[PATCH 8/9] libs: Import vkd3d 1.2.
Zebediah Figura
zfigura at codeweavers.com
Mon Nov 29 11:01:21 CST 2021
The source is unchanged, with one exception: the #include of "vulkan/vulkan.h"
in vkd3d.h is changed to "wine/vulkan.h". I could not find an easy way to avoid
this.
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
configure.ac | 3 +
dlls/vkd3d-shader/Makefile.in | 14 +
dlls/vkd3d-shader/config.h | 156 +
dlls/vkd3d-shader/libvkd3d-shader-wine.spec | 15 +
dlls/vkd3d/Makefile.in | 16 +
dlls/vkd3d/config.h | 156 +
dlls/vkd3d/include/config.h.in | 156 +
dlls/vkd3d/include/private/list.h | 234 +
dlls/vkd3d/include/private/rbtree.h | 378 +
dlls/vkd3d/include/private/vkd3d_common.h | 186 +
dlls/vkd3d/include/private/vkd3d_debug.h | 118 +
dlls/vkd3d/include/private/vkd3d_memory.h | 60 +
dlls/vkd3d/include/private/vkd3d_test.h | 410 +
dlls/vkd3d/include/private/vkd3d_utf8.h | 26 +
dlls/vkd3d/include/private/vkd3d_version.h | 1 +
dlls/vkd3d/include/vkd3d.h | 243 +
dlls/vkd3d/include/vkd3d_d3d12.h | 7749 ++++++++++++++
dlls/vkd3d/include/vkd3d_d3d12.idl | 2547 +++++
dlls/vkd3d/include/vkd3d_d3d12sdklayers.h | 228 +
dlls/vkd3d/include/vkd3d_d3d12sdklayers.idl | 43 +
dlls/vkd3d/include/vkd3d_d3dcommon.h | 296 +
dlls/vkd3d/include/vkd3d_d3dcommon.idl | 95 +
dlls/vkd3d/include/vkd3d_dxgi.h | 1237 +++
dlls/vkd3d/include/vkd3d_dxgi.idl | 154 +
dlls/vkd3d/include/vkd3d_dxgi1_2.h | 751 ++
dlls/vkd3d/include/vkd3d_dxgi1_2.idl | 100 +
dlls/vkd3d/include/vkd3d_dxgi1_3.h | 732 ++
dlls/vkd3d/include/vkd3d_dxgi1_3.idl | 50 +
dlls/vkd3d/include/vkd3d_dxgi1_4.h | 796 ++
dlls/vkd3d/include/vkd3d_dxgi1_4.idl | 47 +
dlls/vkd3d/include/vkd3d_dxgibase.h | 49 +
dlls/vkd3d/include/vkd3d_dxgibase.idl | 34 +
dlls/vkd3d/include/vkd3d_dxgiformat.h | 156 +
dlls/vkd3d/include/vkd3d_dxgiformat.idl | 139 +
dlls/vkd3d/include/vkd3d_dxgitype.h | 57 +
dlls/vkd3d/include/vkd3d_dxgitype.idl | 41 +
dlls/vkd3d/include/vkd3d_shader.h | 1502 +++
dlls/vkd3d/include/vkd3d_types.h | 60 +
dlls/vkd3d/include/vkd3d_unknown.idl | 55 +
dlls/vkd3d/include/vkd3d_utils.h | 61 +
dlls/vkd3d/include/vkd3d_windows.h | 281 +
dlls/vkd3d/libs/vkd3d-common/debug.c | 363 +
dlls/vkd3d/libs/vkd3d-common/memory.c | 48 +
dlls/vkd3d/libs/vkd3d-common/utf8.c | 164 +
dlls/vkd3d/libs/vkd3d-shader/checksum.c | 301 +
dlls/vkd3d/libs/vkd3d-shader/dxbc.c | 3659 +++++++
.../libs/vkd3d-shader/libvkd3d-shader.pc.in | 10 +
dlls/vkd3d/libs/vkd3d-shader/spirv.c | 9281 +++++++++++++++++
dlls/vkd3d/libs/vkd3d-shader/trace.c | 1602 +++
dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader.map | 21 +
.../libs/vkd3d-shader/vkd3d_shader_main.c | 1091 ++
.../libs/vkd3d-shader/vkd3d_shader_private.h | 989 ++
.../libs/vkd3d-utils/libvkd3d-utils.pc.in | 10 +
dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils.map | 17 +
.../vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c | 234 +
.../libs/vkd3d-utils/vkd3d_utils_private.h | 39 +
dlls/vkd3d/libs/vkd3d/command.c | 6461 ++++++++++++
dlls/vkd3d/libs/vkd3d/device.c | 3857 +++++++
dlls/vkd3d/libs/vkd3d/libvkd3d.pc.in | 10 +
dlls/vkd3d/libs/vkd3d/resource.c | 4092 ++++++++
dlls/vkd3d/libs/vkd3d/state.c | 3020 ++++++
dlls/vkd3d/libs/vkd3d/utils.c | 1080 ++
dlls/vkd3d/libs/vkd3d/vkd3d.map | 27 +
dlls/vkd3d/libs/vkd3d/vkd3d_main.c | 641 ++
dlls/vkd3d/libs/vkd3d/vkd3d_private.h | 1372 +++
dlls/vkd3d/libs/vkd3d/vkd3d_shaders.h | 388 +
dlls/vkd3d/libs/vkd3d/vulkan_procs.h | 212 +
dlls/vkd3d/libvkd3d-wine.spec | 20 +
68 files changed, 58441 insertions(+)
create mode 100644 dlls/vkd3d-shader/Makefile.in
create mode 100644 dlls/vkd3d-shader/config.h
create mode 100644 dlls/vkd3d-shader/libvkd3d-shader-wine.spec
create mode 100644 dlls/vkd3d/Makefile.in
create mode 100644 dlls/vkd3d/config.h
create mode 100644 dlls/vkd3d/include/config.h.in
create mode 100644 dlls/vkd3d/include/private/list.h
create mode 100644 dlls/vkd3d/include/private/rbtree.h
create mode 100644 dlls/vkd3d/include/private/vkd3d_common.h
create mode 100644 dlls/vkd3d/include/private/vkd3d_debug.h
create mode 100644 dlls/vkd3d/include/private/vkd3d_memory.h
create mode 100644 dlls/vkd3d/include/private/vkd3d_test.h
create mode 100644 dlls/vkd3d/include/private/vkd3d_utf8.h
create mode 100644 dlls/vkd3d/include/private/vkd3d_version.h
create mode 100644 dlls/vkd3d/include/vkd3d.h
create mode 100644 dlls/vkd3d/include/vkd3d_d3d12.h
create mode 100644 dlls/vkd3d/include/vkd3d_d3d12.idl
create mode 100644 dlls/vkd3d/include/vkd3d_d3d12sdklayers.h
create mode 100644 dlls/vkd3d/include/vkd3d_d3d12sdklayers.idl
create mode 100644 dlls/vkd3d/include/vkd3d_d3dcommon.h
create mode 100644 dlls/vkd3d/include/vkd3d_d3dcommon.idl
create mode 100644 dlls/vkd3d/include/vkd3d_dxgi.h
create mode 100644 dlls/vkd3d/include/vkd3d_dxgi.idl
create mode 100644 dlls/vkd3d/include/vkd3d_dxgi1_2.h
create mode 100644 dlls/vkd3d/include/vkd3d_dxgi1_2.idl
create mode 100644 dlls/vkd3d/include/vkd3d_dxgi1_3.h
create mode 100644 dlls/vkd3d/include/vkd3d_dxgi1_3.idl
create mode 100644 dlls/vkd3d/include/vkd3d_dxgi1_4.h
create mode 100644 dlls/vkd3d/include/vkd3d_dxgi1_4.idl
create mode 100644 dlls/vkd3d/include/vkd3d_dxgibase.h
create mode 100644 dlls/vkd3d/include/vkd3d_dxgibase.idl
create mode 100644 dlls/vkd3d/include/vkd3d_dxgiformat.h
create mode 100644 dlls/vkd3d/include/vkd3d_dxgiformat.idl
create mode 100644 dlls/vkd3d/include/vkd3d_dxgitype.h
create mode 100644 dlls/vkd3d/include/vkd3d_dxgitype.idl
create mode 100644 dlls/vkd3d/include/vkd3d_shader.h
create mode 100644 dlls/vkd3d/include/vkd3d_types.h
create mode 100644 dlls/vkd3d/include/vkd3d_unknown.idl
create mode 100644 dlls/vkd3d/include/vkd3d_utils.h
create mode 100644 dlls/vkd3d/include/vkd3d_windows.h
create mode 100644 dlls/vkd3d/libs/vkd3d-common/debug.c
create mode 100644 dlls/vkd3d/libs/vkd3d-common/memory.c
create mode 100644 dlls/vkd3d/libs/vkd3d-common/utf8.c
create mode 100644 dlls/vkd3d/libs/vkd3d-shader/checksum.c
create mode 100644 dlls/vkd3d/libs/vkd3d-shader/dxbc.c
create mode 100644 dlls/vkd3d/libs/vkd3d-shader/libvkd3d-shader.pc.in
create mode 100644 dlls/vkd3d/libs/vkd3d-shader/spirv.c
create mode 100644 dlls/vkd3d/libs/vkd3d-shader/trace.c
create mode 100644 dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader.map
create mode 100644 dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
create mode 100644 dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
create mode 100644 dlls/vkd3d/libs/vkd3d-utils/libvkd3d-utils.pc.in
create mode 100644 dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils.map
create mode 100644 dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c
create mode 100644 dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils_private.h
create mode 100644 dlls/vkd3d/libs/vkd3d/command.c
create mode 100644 dlls/vkd3d/libs/vkd3d/device.c
create mode 100644 dlls/vkd3d/libs/vkd3d/libvkd3d.pc.in
create mode 100644 dlls/vkd3d/libs/vkd3d/resource.c
create mode 100644 dlls/vkd3d/libs/vkd3d/state.c
create mode 100644 dlls/vkd3d/libs/vkd3d/utils.c
create mode 100644 dlls/vkd3d/libs/vkd3d/vkd3d.map
create mode 100644 dlls/vkd3d/libs/vkd3d/vkd3d_main.c
create mode 100644 dlls/vkd3d/libs/vkd3d/vkd3d_private.h
create mode 100644 dlls/vkd3d/libs/vkd3d/vkd3d_shaders.h
create mode 100644 dlls/vkd3d/libs/vkd3d/vulkan_procs.h
create mode 100644 dlls/vkd3d/libvkd3d-wine.spec
diff --git a/configure.ac b/configure.ac
index ff393285c0b..af8c34da130 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1161,6 +1161,7 @@ WINE_EXTLIB_FLAGS(MPG123, mpg123, mpg123, "-I\$(top_srcdir)/libs/mpg123/src/libm
WINE_EXTLIB_FLAGS(PNG, png, "png \$(ZLIB_PE_LIBS)", "-I\$(top_srcdir)/libs/png")
WINE_EXTLIB_FLAGS(PTHREAD, pthread, pthread, "-I\$(top_srcdir)/libs/winpthreads/include")
WINE_EXTLIB_FLAGS(TIFF, tiff, tiff, "-I\$(top_srcdir)/libs/tiff/libtiff")
+WINE_EXTLIB_FLAGS(VKD3D, vkd3d, vkd3d-wine, "-I\$(top_srcdir)/dlls/vkd3d/include")
WINE_EXTLIB_FLAGS(XML2, xml2, xml2, "-I\$(top_srcdir)/libs/xml2/include -DLIBXML_STATIC")
WINE_EXTLIB_FLAGS(XSLT, xslt, xslt, "-I\$(top_srcdir)/libs/xslt -DLIBXSLT_STATIC")
WINE_EXTLIB_FLAGS(ZLIB, zlib, z, "-I\$(top_srcdir)/libs/zlib -DFAR= -DZ_SOLO")
@@ -3517,6 +3518,8 @@ WINE_CONFIG_MAKEFILE(dlls/version/tests)
WINE_CONFIG_MAKEFILE(dlls/vga)
WINE_CONFIG_MAKEFILE(dlls/virtdisk)
WINE_CONFIG_MAKEFILE(dlls/virtdisk/tests)
+WINE_CONFIG_MAKEFILE(dlls/vkd3d)
+WINE_CONFIG_MAKEFILE(dlls/vkd3d-shader)
WINE_CONFIG_MAKEFILE(dlls/vmm.vxd,enable_win16)
WINE_CONFIG_MAKEFILE(dlls/vnbt.vxd,enable_win16)
WINE_CONFIG_MAKEFILE(dlls/vnetbios.vxd,enable_win16)
diff --git a/dlls/vkd3d-shader/Makefile.in b/dlls/vkd3d-shader/Makefile.in
new file mode 100644
index 00000000000..31dbb324675
--- /dev/null
+++ b/dlls/vkd3d-shader/Makefile.in
@@ -0,0 +1,14 @@
+EXTLIB = libvkd3d-shader-wine.dll
+IMPORTLIB = vkd3d-shader-wine
+EXTRAINCL = -I$(srcdir)/../vkd3d/include -I$(srcdir)/../vkd3d/include/private -I../../libs/spirv-headers
+PARENTSRC = ../vkd3d
+
+C_SRCS = \
+ libs/vkd3d-common/debug.c \
+ libs/vkd3d-common/memory.c \
+ libs/vkd3d-common/utf8.c \
+ libs/vkd3d-shader/checksum.c \
+ libs/vkd3d-shader/dxbc.c \
+ libs/vkd3d-shader/spirv.c \
+ libs/vkd3d-shader/trace.c \
+ libs/vkd3d-shader/vkd3d_shader_main.c
diff --git a/dlls/vkd3d-shader/config.h b/dlls/vkd3d-shader/config.h
new file mode 100644
index 00000000000..3c629956372
--- /dev/null
+++ b/dlls/vkd3d-shader/config.h
@@ -0,0 +1,156 @@
+/* include/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have __builtin_clz. */
+#define HAVE_BUILTIN_CLZ 1
+
+/* Define to 1 if you have __builtin_popcount. */
+#define HAVE_BUILTIN_POPCOUNT 1
+
+/* Define to 1 if you have the declaration of `program_invocation_name', and
+ to 0 if you don't. */
+#undef HAVE_DECL_PROGRAM_INVOCATION_NAME
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the `pthread_setname_np' function. */
+#undef HAVE_PTHREAD_SETNAME_NP
+
+/* Define to 1 if you have the one-argument variant of pthread_setname_np().
+ */
+#undef HAVE_PTHREAD_SETNAME_NP_1
+
+/* Define to 1 if you have the two-argument variant of pthread_setname_np().
+ */
+#undef HAVE_PTHREAD_SETNAME_NP_2
+
+/* Define to 1 if you have SPIRV-Tools. */
+#undef HAVE_SPIRV_TOOLS
+
+/* Define to 1 if you have the <spirv/unified1/GLSL.std.450.h> header file. */
+#define HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H 1
+
+/* Define to 1 if you have the <spirv/unified1/spirv.h> header file. */
+#define HAVE_SPIRV_UNIFIED1_SPIRV_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have __sync_add_and_fetch. */
+#define HAVE_SYNC_ADD_AND_FETCH 1
+
+/* Define to 1 if you have __sync_sub_and_fetch. */
+#define HAVE_SYNC_SUB_AND_FETCH 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <vulkan/GLSL.std.450.h> header file. */
+#undef HAVE_VULKAN_GLSL_STD_450_H
+
+/* Define to 1 if you have the <vulkan/spirv.h> header file. */
+#undef HAVE_VULKAN_SPIRV_H
+
+/* Define to 1 if you have the <vulkan/vulkan.h> header file. */
+#undef HAVE_VULKAN_VULKAN_H
+
+/* Define to 1 if you have libxcb. */
+#undef HAVE_XCB
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#undef LT_OBJDIR
+
+/* Name of package */
+#define PACKAGE "vkd3d"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "vkd3d"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "vkd3d 1.2"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "vkd3d"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.2"
+
+/* Define to the soname of the libMoltenVK library. */
+#undef SONAME_LIBMOLTENVK
+
+/* Define to the soname of the libvulkan library. */
+#define SONAME_LIBVULKAN "vulkan-1.dll"
+
+/* Define to the soname of the libvulkan-1 library. */
+#define SONAME_LIBVULKAN_1 "vulkan-1.dll"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Version number of package */
+#define VERSION "1.2"
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
diff --git a/dlls/vkd3d-shader/libvkd3d-shader-wine.spec b/dlls/vkd3d-shader/libvkd3d-shader-wine.spec
new file mode 100644
index 00000000000..f9b6ec2951d
--- /dev/null
+++ b/dlls/vkd3d-shader/libvkd3d-shader-wine.spec
@@ -0,0 +1,15 @@
+@ cdecl vkd3d_shader_compile(ptr ptr ptr)
+@ cdecl vkd3d_shader_convert_root_signature(ptr long ptr)
+@ cdecl vkd3d_shader_find_signature_element(ptr ptr long long)
+@ cdecl vkd3d_shader_free_messages(ptr)
+@ cdecl vkd3d_shader_free_root_signature(ptr)
+@ cdecl vkd3d_shader_free_scan_descriptor_info(ptr)
+@ cdecl vkd3d_shader_free_shader_code(ptr)
+@ cdecl vkd3d_shader_free_shader_signature(ptr)
+@ cdecl vkd3d_shader_get_supported_source_types(ptr)
+@ cdecl vkd3d_shader_get_supported_target_types(long ptr)
+@ cdecl vkd3d_shader_get_version(ptr ptr)
+@ cdecl vkd3d_shader_parse_input_signature(ptr ptr ptr)
+@ cdecl vkd3d_shader_parse_root_signature(ptr ptr ptr)
+@ cdecl vkd3d_shader_scan(ptr ptr)
+@ cdecl vkd3d_shader_serialize_root_signature(ptr ptr ptr)
diff --git a/dlls/vkd3d/Makefile.in b/dlls/vkd3d/Makefile.in
new file mode 100644
index 00000000000..1171b63ef94
--- /dev/null
+++ b/dlls/vkd3d/Makefile.in
@@ -0,0 +1,16 @@
+EXTLIB = libvkd3d-wine.dll
+IMPORTLIB = vkd3d-wine
+IMPORTS = vkd3d-shader-wine $(PTHREAD_PE_LIBS)
+EXTRAINCL = -I$(srcdir)/include -I$(srcdir)/include/private $(PTHREAD_PE_CFLAGS)
+EXTRADEFS = -DCONST_VTABLE -DWINE_NO_NAMELESS_EXTENSION -DPATH_MAX=4096
+
+C_SRCS = \
+ libs/vkd3d/command.c \
+ libs/vkd3d/device.c \
+ libs/vkd3d/resource.c \
+ libs/vkd3d/state.c \
+ libs/vkd3d/utils.c \
+ libs/vkd3d/vkd3d_main.c \
+ libs/vkd3d-common/debug.c \
+ libs/vkd3d-common/memory.c \
+ libs/vkd3d-common/utf8.c
diff --git a/dlls/vkd3d/config.h b/dlls/vkd3d/config.h
new file mode 100644
index 00000000000..855d52d5be4
--- /dev/null
+++ b/dlls/vkd3d/config.h
@@ -0,0 +1,156 @@
+/* include/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have __builtin_clz. */
+#define HAVE_BUILTIN_CLZ 1
+
+/* Define to 1 if you have __builtin_popcount. */
+#define HAVE_BUILTIN_POPCOUNT 1
+
+/* Define to 1 if you have the declaration of `program_invocation_name', and
+ to 0 if you don't. */
+#undef HAVE_DECL_PROGRAM_INVOCATION_NAME
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the `pthread_setname_np' function. */
+#undef HAVE_PTHREAD_SETNAME_NP
+
+/* Define to 1 if you have the one-argument variant of pthread_setname_np().
+ */
+#undef HAVE_PTHREAD_SETNAME_NP_1
+
+/* Define to 1 if you have the two-argument variant of pthread_setname_np().
+ */
+#undef HAVE_PTHREAD_SETNAME_NP_2
+
+/* Define to 1 if you have SPIRV-Tools. */
+#undef HAVE_SPIRV_TOOLS
+
+/* Define to 1 if you have the <spirv/unified1/GLSL.std.450.h> header file. */
+#define HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H 1
+
+/* Define to 1 if you have the <spirv/unified1/spirv.h> header file. */
+#define HAVE_SPIRV_UNIFIED1_SPIRV_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have __sync_add_and_fetch. */
+#define HAVE_SYNC_ADD_AND_FETCH 1
+
+/* Define to 1 if you have __sync_sub_and_fetch. */
+#define HAVE_SYNC_SUB_AND_FETCH 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <vulkan/GLSL.std.450.h> header file. */
+#undef HAVE_VULKAN_GLSL_STD_450_H
+
+/* Define to 1 if you have the <vulkan/spirv.h> header file. */
+#undef HAVE_VULKAN_SPIRV_H
+
+/* Define to 1 if you have the <vulkan/vulkan.h> header file. */
+#undef HAVE_VULKAN_VULKAN_H
+
+/* Define to 1 if you have libxcb. */
+#undef HAVE_XCB
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#undef LT_OBJDIR
+
+/* Name of package */
+#define PACKAGE "vkd3d"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "vkd3d"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "vkd3d 1.2"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "vkd3d"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.2"
+
+/* Define to the soname of the libMoltenVK library. */
+#undef SONAME_LIBMOLTENVK
+
+/* Define to the soname of the libvulkan library. */
+#define SONAME_LIBVULKAN "vulkan-1.dll"
+
+/* Define to the soname of the libvulkan-1 library. */
+#define SONAME_LIBVULKAN_1 "vulkan-1.dll"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+
+/* Version number of package */
+#define VERSION "1.2"
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
diff --git a/dlls/vkd3d/include/config.h.in b/dlls/vkd3d/include/config.h.in
new file mode 100644
index 00000000000..2496eed1096
--- /dev/null
+++ b/dlls/vkd3d/include/config.h.in
@@ -0,0 +1,156 @@
+/* include/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have __builtin_clz. */
+#undef HAVE_BUILTIN_CLZ
+
+/* Define to 1 if you have __builtin_popcount. */
+#undef HAVE_BUILTIN_POPCOUNT
+
+/* Define to 1 if you have the declaration of `program_invocation_name', and
+ to 0 if you don't. */
+#undef HAVE_DECL_PROGRAM_INVOCATION_NAME
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the `pthread_setname_np' function. */
+#undef HAVE_PTHREAD_SETNAME_NP
+
+/* Define to 1 if you have the one-argument variant of pthread_setname_np().
+ */
+#undef HAVE_PTHREAD_SETNAME_NP_1
+
+/* Define to 1 if you have the two-argument variant of pthread_setname_np().
+ */
+#undef HAVE_PTHREAD_SETNAME_NP_2
+
+/* Define to 1 if you have SPIRV-Tools. */
+#undef HAVE_SPIRV_TOOLS
+
+/* Define to 1 if you have the <spirv/unified1/GLSL.std.450.h> header file. */
+#undef HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H
+
+/* Define to 1 if you have the <spirv/unified1/spirv.h> header file. */
+#undef HAVE_SPIRV_UNIFIED1_SPIRV_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have __sync_add_and_fetch. */
+#undef HAVE_SYNC_ADD_AND_FETCH
+
+/* Define to 1 if you have __sync_sub_and_fetch. */
+#undef HAVE_SYNC_SUB_AND_FETCH
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <vulkan/GLSL.std.450.h> header file. */
+#undef HAVE_VULKAN_GLSL_STD_450_H
+
+/* Define to 1 if you have the <vulkan/spirv.h> header file. */
+#undef HAVE_VULKAN_SPIRV_H
+
+/* Define to 1 if you have the <vulkan/vulkan.h> header file. */
+#undef HAVE_VULKAN_VULKAN_H
+
+/* Define to 1 if you have libxcb. */
+#undef HAVE_XCB
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#undef LT_OBJDIR
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to the soname of the libMoltenVK library. */
+#undef SONAME_LIBMOLTENVK
+
+/* Define to the soname of the libvulkan library. */
+#undef SONAME_LIBVULKAN
+
+/* Define to the soname of the libvulkan-1 library. */
+#undef SONAME_LIBVULKAN_1
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
diff --git a/dlls/vkd3d/include/private/list.h b/dlls/vkd3d/include/private/list.h
new file mode 100644
index 00000000000..b4d681fe0f3
--- /dev/null
+++ b/dlls/vkd3d/include/private/list.h
@@ -0,0 +1,234 @@
+/*
+ * Linked lists support
+ *
+ * Copyright (C) 2002 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_SERVER_LIST_H
+#define __WINE_SERVER_LIST_H
+
+#include <stddef.h>
+
+struct list
+{
+ struct list *next;
+ struct list *prev;
+};
+
+/* Define a list like so:
+ *
+ * struct gadget
+ * {
+ * struct list entry; <-- doesn't have to be the first item in the struct
+ * int a, b;
+ * };
+ *
+ * static struct list global_gadgets = LIST_INIT( global_gadgets );
+ *
+ * or
+ *
+ * struct some_global_thing
+ * {
+ * struct list gadgets;
+ * };
+ *
+ * list_init( &some_global_thing->gadgets );
+ *
+ * Manipulate it like this:
+ *
+ * list_add_head( &global_gadgets, &new_gadget->entry );
+ * list_remove( &new_gadget->entry );
+ * list_add_after( &some_random_gadget->entry, &new_gadget->entry );
+ *
+ * And to iterate over it:
+ *
+ * struct gadget *gadget;
+ * LIST_FOR_EACH_ENTRY( gadget, &global_gadgets, struct gadget, entry )
+ * {
+ * ...
+ * }
+ *
+ */
+
+/* add an element after the specified one */
+static inline void list_add_after( struct list *elem, struct list *to_add )
+{
+ to_add->next = elem->next;
+ to_add->prev = elem;
+ elem->next->prev = to_add;
+ elem->next = to_add;
+}
+
+/* add an element before the specified one */
+static inline void list_add_before( struct list *elem, struct list *to_add )
+{
+ to_add->next = elem;
+ to_add->prev = elem->prev;
+ elem->prev->next = to_add;
+ elem->prev = to_add;
+}
+
+/* add element at the head of the list */
+static inline void list_add_head( struct list *list, struct list *elem )
+{
+ list_add_after( list, elem );
+}
+
+/* add element at the tail of the list */
+static inline void list_add_tail( struct list *list, struct list *elem )
+{
+ list_add_before( list, elem );
+}
+
+/* remove an element from its list */
+static inline void list_remove( struct list *elem )
+{
+ elem->next->prev = elem->prev;
+ elem->prev->next = elem->next;
+}
+
+/* get the next element */
+static inline struct list *list_next( const struct list *list, const struct list *elem )
+{
+ struct list *ret = elem->next;
+ if (elem->next == list) ret = NULL;
+ return ret;
+}
+
+/* get the previous element */
+static inline struct list *list_prev( const struct list *list, const struct list *elem )
+{
+ struct list *ret = elem->prev;
+ if (elem->prev == list) ret = NULL;
+ return ret;
+}
+
+/* get the first element */
+static inline struct list *list_head( const struct list *list )
+{
+ return list_next( list, list );
+}
+
+/* get the last element */
+static inline struct list *list_tail( const struct list *list )
+{
+ return list_prev( list, list );
+}
+
+/* check if a list is empty */
+static inline int list_empty( const struct list *list )
+{
+ return list->next == list;
+}
+
+/* initialize a list */
+static inline void list_init( struct list *list )
+{
+ list->next = list->prev = list;
+}
+
+/* count the elements of a list */
+static inline unsigned int list_count( const struct list *list )
+{
+ unsigned count = 0;
+ const struct list *ptr;
+ for (ptr = list->next; ptr != list; ptr = ptr->next) count++;
+ return count;
+}
+
+/* move all elements from src to the tail of dst */
+static inline void list_move_tail( struct list *dst, struct list *src )
+{
+ if (list_empty(src)) return;
+
+ dst->prev->next = src->next;
+ src->next->prev = dst->prev;
+ dst->prev = src->prev;
+ src->prev->next = dst;
+ list_init(src);
+}
+
+/* move all elements from src to the head of dst */
+static inline void list_move_head( struct list *dst, struct list *src )
+{
+ if (list_empty(src)) return;
+
+ dst->next->prev = src->prev;
+ src->prev->next = dst->next;
+ dst->next = src->next;
+ src->next->prev = dst;
+ list_init(src);
+}
+
+/* iterate through the list */
+#define LIST_FOR_EACH(cursor,list) \
+ for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)
+
+/* iterate through the list, with safety against removal */
+#define LIST_FOR_EACH_SAFE(cursor, cursor2, list) \
+ for ((cursor) = (list)->next, (cursor2) = (cursor)->next; \
+ (cursor) != (list); \
+ (cursor) = (cursor2), (cursor2) = (cursor)->next)
+
+/* iterate through the list using a list entry */
+#define LIST_FOR_EACH_ENTRY(elem, list, type, field) \
+ for ((elem) = LIST_ENTRY((list)->next, type, field); \
+ &(elem)->field != (list); \
+ (elem) = LIST_ENTRY((elem)->field.next, type, field))
+
+/* iterate through the list using a list entry, with safety against removal */
+#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field) \
+ for ((cursor) = LIST_ENTRY((list)->next, type, field), \
+ (cursor2) = LIST_ENTRY((cursor)->field.next, type, field); \
+ &(cursor)->field != (list); \
+ (cursor) = (cursor2), \
+ (cursor2) = LIST_ENTRY((cursor)->field.next, type, field))
+
+/* iterate through the list in reverse order */
+#define LIST_FOR_EACH_REV(cursor,list) \
+ for ((cursor) = (list)->prev; (cursor) != (list); (cursor) = (cursor)->prev)
+
+/* iterate through the list in reverse order, with safety against removal */
+#define LIST_FOR_EACH_SAFE_REV(cursor, cursor2, list) \
+ for ((cursor) = (list)->prev, (cursor2) = (cursor)->prev; \
+ (cursor) != (list); \
+ (cursor) = (cursor2), (cursor2) = (cursor)->prev)
+
+/* iterate through the list in reverse order using a list entry */
+#define LIST_FOR_EACH_ENTRY_REV(elem, list, type, field) \
+ for ((elem) = LIST_ENTRY((list)->prev, type, field); \
+ &(elem)->field != (list); \
+ (elem) = LIST_ENTRY((elem)->field.prev, type, field))
+
+/* iterate through the list in reverse order using a list entry, with safety against removal */
+#define LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, list, type, field) \
+ for ((cursor) = LIST_ENTRY((list)->prev, type, field), \
+ (cursor2) = LIST_ENTRY((cursor)->field.prev, type, field); \
+ &(cursor)->field != (list); \
+ (cursor) = (cursor2), \
+ (cursor2) = LIST_ENTRY((cursor)->field.prev, type, field))
+
+/* macros for statically initialized lists */
+#undef LIST_INIT
+#define LIST_INIT(list) { &(list), &(list) }
+
+/* get pointer to object containing list element */
+#undef LIST_ENTRY
+#define LIST_ENTRY(elem, type, field) \
+ ((type *)((char *)(elem) - offsetof(type, field)))
+
+#endif /* __WINE_SERVER_LIST_H */
diff --git a/dlls/vkd3d/include/private/rbtree.h b/dlls/vkd3d/include/private/rbtree.h
new file mode 100644
index 00000000000..b4993da3ce5
--- /dev/null
+++ b/dlls/vkd3d/include/private/rbtree.h
@@ -0,0 +1,378 @@
+/*
+ * Red-black search tree support
+ *
+ * Copyright 2009 Henri Verbeet
+ * Copyright 2009 Andrew Riedi
+ * Copyright 2016 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_WINE_RBTREE_H
+#define __WINE_WINE_RBTREE_H
+
+#define RB_ENTRY_VALUE(element, type, field) \
+ ((type *)((char *)(element) - offsetof(type, field)))
+
+struct rb_entry
+{
+ struct rb_entry *parent;
+ struct rb_entry *left;
+ struct rb_entry *right;
+ unsigned int flags;
+};
+
+typedef int (*rb_compare_func)(const void *key, const struct rb_entry *entry);
+
+struct rb_tree
+{
+ rb_compare_func compare;
+ struct rb_entry *root;
+};
+
+typedef void (rb_traverse_func)(struct rb_entry *entry, void *context);
+
+#define RB_FLAG_RED 0x1
+
+static inline int rb_is_red(struct rb_entry *entry)
+{
+ return entry && (entry->flags & RB_FLAG_RED);
+}
+
+static inline void rb_rotate_left(struct rb_tree *tree, struct rb_entry *e)
+{
+ struct rb_entry *right = e->right;
+
+ if (!e->parent)
+ tree->root = right;
+ else if (e->parent->left == e)
+ e->parent->left = right;
+ else
+ e->parent->right = right;
+
+ e->right = right->left;
+ if (e->right) e->right->parent = e;
+ right->left = e;
+ right->parent = e->parent;
+ e->parent = right;
+}
+
+static inline void rb_rotate_right(struct rb_tree *tree, struct rb_entry *e)
+{
+ struct rb_entry *left = e->left;
+
+ if (!e->parent)
+ tree->root = left;
+ else if (e->parent->left == e)
+ e->parent->left = left;
+ else
+ e->parent->right = left;
+
+ e->left = left->right;
+ if (e->left) e->left->parent = e;
+ left->right = e;
+ left->parent = e->parent;
+ e->parent = left;
+}
+
+static inline void rb_flip_color(struct rb_entry *entry)
+{
+ entry->flags ^= RB_FLAG_RED;
+ entry->left->flags ^= RB_FLAG_RED;
+ entry->right->flags ^= RB_FLAG_RED;
+}
+
+static inline struct rb_entry *rb_head(struct rb_entry *iter)
+{
+ if (!iter) return NULL;
+ while (iter->left) iter = iter->left;
+ return iter;
+}
+
+static inline struct rb_entry *rb_next(struct rb_entry *iter)
+{
+ if (iter->right) return rb_head(iter->right);
+ while (iter->parent && iter->parent->right == iter) iter = iter->parent;
+ return iter->parent;
+}
+
+static inline struct rb_entry *rb_postorder_head(struct rb_entry *iter)
+{
+ if (!iter) return NULL;
+
+ for (;;) {
+ while (iter->left) iter = iter->left;
+ if (!iter->right) return iter;
+ iter = iter->right;
+ }
+}
+
+static inline struct rb_entry *rb_postorder_next(struct rb_entry *iter)
+{
+ if (!iter->parent) return NULL;
+ if (iter == iter->parent->right || !iter->parent->right) return iter->parent;
+ return rb_postorder_head(iter->parent->right);
+}
+
+/* iterate through the tree */
+#define RB_FOR_EACH(cursor, tree) \
+ for ((cursor) = rb_head((tree)->root); (cursor); (cursor) = rb_next(cursor))
+
+/* iterate through the tree using a tree entry */
+#define RB_FOR_EACH_ENTRY(elem, tree, type, field) \
+ for ((elem) = RB_ENTRY_VALUE(rb_head((tree)->root), type, field); \
+ &(elem)->field; \
+ (elem) = RB_ENTRY_VALUE(rb_next(&elem->field), type, field))
+
+/* iterate through the tree using using postorder, making it safe to free the entry */
+#define RB_FOR_EACH_DESTRUCTOR(cursor, cursor2, tree) \
+ for ((cursor) = rb_postorder_head((tree)->root); \
+ (cursor) && (((cursor2) = rb_postorder_next(cursor)) || 1); \
+ (cursor) = (cursor2))
+
+/* iterate through the tree using a tree entry and postorder, making it safe to free the entry */
+#define RB_FOR_EACH_ENTRY_DESTRUCTOR(elem, elem2, tree, type, field) \
+ for ((elem) = RB_ENTRY_VALUE(rb_postorder_head((tree)->root), type, field); \
+ &(elem)->field \
+ && (((elem2) = RB_ENTRY_VALUE(rb_postorder_next(&(elem)->field), type, field)) || 1); \
+ (elem) = (elem2))
+
+
+static inline void rb_postorder(struct rb_tree *tree, rb_traverse_func *callback, void *context)
+{
+ struct rb_entry *iter, *next;
+ RB_FOR_EACH_DESTRUCTOR(iter, next, tree) callback(iter, context);
+}
+
+static inline void rb_init(struct rb_tree *tree, rb_compare_func compare)
+{
+ tree->compare = compare;
+ tree->root = NULL;
+}
+
+static inline void rb_for_each_entry(struct rb_tree *tree, rb_traverse_func *callback, void *context)
+{
+ struct rb_entry *iter;
+ RB_FOR_EACH(iter, tree) callback(iter, context);
+}
+
+static inline void rb_clear(struct rb_tree *tree, rb_traverse_func *callback, void *context)
+{
+ /* Note that we use postorder here because the callback will likely free the entry. */
+ if (callback) rb_postorder(tree, callback, context);
+ tree->root = NULL;
+}
+
+static inline void rb_destroy(struct rb_tree *tree, rb_traverse_func *callback, void *context)
+{
+ rb_clear(tree, callback, context);
+}
+
+static inline struct rb_entry *rb_get(const struct rb_tree *tree, const void *key)
+{
+ struct rb_entry *entry = tree->root;
+ while (entry)
+ {
+ int c = tree->compare(key, entry);
+ if (!c) return entry;
+ entry = c < 0 ? entry->left : entry->right;
+ }
+ return NULL;
+}
+
+static inline int rb_put(struct rb_tree *tree, const void *key, struct rb_entry *entry)
+{
+ struct rb_entry **iter = &tree->root, *parent = tree->root;
+
+ while (*iter)
+ {
+ int c;
+
+ parent = *iter;
+ c = tree->compare(key, parent);
+ if (!c) return -1;
+ else if (c < 0) iter = &parent->left;
+ else iter = &parent->right;
+ }
+
+ entry->flags = RB_FLAG_RED;
+ entry->parent = parent;
+ entry->left = NULL;
+ entry->right = NULL;
+ *iter = entry;
+
+ while (rb_is_red(entry->parent))
+ {
+ if (entry->parent == entry->parent->parent->left)
+ {
+ if (rb_is_red(entry->parent->parent->right))
+ {
+ rb_flip_color(entry->parent->parent);
+ entry = entry->parent->parent;
+ }
+ else
+ {
+ if (entry == entry->parent->right)
+ {
+ entry = entry->parent;
+ rb_rotate_left(tree, entry);
+ }
+ entry->parent->flags &= ~RB_FLAG_RED;
+ entry->parent->parent->flags |= RB_FLAG_RED;
+ rb_rotate_right(tree, entry->parent->parent);
+ }
+ }
+ else
+ {
+ if (rb_is_red(entry->parent->parent->left))
+ {
+ rb_flip_color(entry->parent->parent);
+ entry = entry->parent->parent;
+ }
+ else
+ {
+ if (entry == entry->parent->left)
+ {
+ entry = entry->parent;
+ rb_rotate_right(tree, entry);
+ }
+ entry->parent->flags &= ~RB_FLAG_RED;
+ entry->parent->parent->flags |= RB_FLAG_RED;
+ rb_rotate_left(tree, entry->parent->parent);
+ }
+ }
+ }
+
+ tree->root->flags &= ~RB_FLAG_RED;
+
+ return 0;
+}
+
+static inline void rb_remove(struct rb_tree *tree, struct rb_entry *entry)
+{
+ struct rb_entry *iter, *child, *parent, *w;
+ int need_fixup;
+
+ if (entry->right && entry->left)
+ for(iter = entry->right; iter->left; iter = iter->left);
+ else
+ iter = entry;
+
+ child = iter->left ? iter->left : iter->right;
+
+ if (!iter->parent)
+ tree->root = child;
+ else if (iter == iter->parent->left)
+ iter->parent->left = child;
+ else
+ iter->parent->right = child;
+
+ if (child) child->parent = iter->parent;
+ parent = iter->parent;
+
+ need_fixup = !rb_is_red(iter);
+
+ if (entry != iter)
+ {
+ *iter = *entry;
+ if (!iter->parent)
+ tree->root = iter;
+ else if (entry == iter->parent->left)
+ iter->parent->left = iter;
+ else
+ iter->parent->right = iter;
+
+ if (iter->right) iter->right->parent = iter;
+ if (iter->left) iter->left->parent = iter;
+ if (parent == entry) parent = iter;
+ }
+
+ if (need_fixup)
+ {
+ while (parent && !rb_is_red(child))
+ {
+ if (child == parent->left)
+ {
+ w = parent->right;
+ if (rb_is_red(w))
+ {
+ w->flags &= ~RB_FLAG_RED;
+ parent->flags |= RB_FLAG_RED;
+ rb_rotate_left(tree, parent);
+ w = parent->right;
+ }
+ if (rb_is_red(w->left) || rb_is_red(w->right))
+ {
+ if (!rb_is_red(w->right))
+ {
+ w->left->flags &= ~RB_FLAG_RED;
+ w->flags |= RB_FLAG_RED;
+ rb_rotate_right(tree, w);
+ w = parent->right;
+ }
+ w->flags = (w->flags & ~RB_FLAG_RED) | (parent->flags & RB_FLAG_RED);
+ parent->flags &= ~RB_FLAG_RED;
+ if (w->right)
+ w->right->flags &= ~RB_FLAG_RED;
+ rb_rotate_left(tree, parent);
+ child = NULL;
+ break;
+ }
+ }
+ else
+ {
+ w = parent->left;
+ if (rb_is_red(w))
+ {
+ w->flags &= ~RB_FLAG_RED;
+ parent->flags |= RB_FLAG_RED;
+ rb_rotate_right(tree, parent);
+ w = parent->left;
+ }
+ if (rb_is_red(w->left) || rb_is_red(w->right))
+ {
+ if (!rb_is_red(w->left))
+ {
+ w->right->flags &= ~RB_FLAG_RED;
+ w->flags |= RB_FLAG_RED;
+ rb_rotate_left(tree, w);
+ w = parent->left;
+ }
+ w->flags = (w->flags & ~RB_FLAG_RED) | (parent->flags & RB_FLAG_RED);
+ parent->flags &= ~RB_FLAG_RED;
+ if (w->left)
+ w->left->flags &= ~RB_FLAG_RED;
+ rb_rotate_right(tree, parent);
+ child = NULL;
+ break;
+ }
+ }
+ w->flags |= RB_FLAG_RED;
+ child = parent;
+ parent = child->parent;
+ }
+ if (child) child->flags &= ~RB_FLAG_RED;
+ }
+
+ if (tree->root) tree->root->flags &= ~RB_FLAG_RED;
+}
+
+static inline void rb_remove_key(struct rb_tree *tree, const void *key)
+{
+ struct rb_entry *entry = rb_get(tree, key);
+ if (entry) rb_remove(tree, entry);
+}
+
+#endif /* __WINE_WINE_RBTREE_H */
diff --git a/dlls/vkd3d/include/private/vkd3d_common.h b/dlls/vkd3d/include/private/vkd3d_common.h
new file mode 100644
index 00000000000..ac217e9eec0
--- /dev/null
+++ b/dlls/vkd3d/include/private/vkd3d_common.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_COMMON_H
+#define __VKD3D_COMMON_H
+
+#include "config.h"
+#include "vkd3d_windows.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdbool.h>
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+#endif
+
+#define DIV_ROUND_UP(a, b) ((a) % (b) == 0 ? (a) / (b) : (a) / (b) + 1)
+
+#define STATIC_ASSERT(e) extern void __VKD3D_STATIC_ASSERT__(int [(e) ? 1 : -1])
+
+#define MEMBER_SIZE(t, m) sizeof(((t *)0)->m)
+
+static inline size_t align(size_t addr, size_t alignment)
+{
+ return (addr + (alignment - 1)) & ~(alignment - 1);
+}
+
+#ifdef __GNUC__
+# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args)))
+# define VKD3D_UNUSED __attribute__((unused))
+#else
+# define VKD3D_PRINTF_FUNC(fmt, args)
+# define VKD3D_UNUSED
+#endif /* __GNUC__ */
+
+static inline unsigned int vkd3d_popcount(unsigned int v)
+{
+#ifdef _MSC_VER
+ return __popcnt(v);
+#elif defined(HAVE_BUILTIN_POPCOUNT)
+ return __builtin_popcount(v);
+#else
+ v -= (v >> 1) & 0x55555555;
+ v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+ return (((v + (v >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
+#endif
+}
+
+static inline bool vkd3d_bitmask_is_contiguous(unsigned int mask)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; i < sizeof(mask) * CHAR_BIT; ++i)
+ {
+ if (mask & (1u << i))
+ ++j;
+ else if (j)
+ break;
+ }
+
+ return vkd3d_popcount(mask) == j;
+}
+
+/* Undefined for x == 0. */
+static inline unsigned int vkd3d_log2i(unsigned int x)
+{
+#ifdef _MSC_VER
+ /* _BitScanReverse returns the index of the highest set bit,
+ * unlike clz which is 31 - index. */
+ unsigned long result;
+ _BitScanReverse(&result, x);
+ return (unsigned int)result;
+#elif defined(HAVE_BUILTIN_CLZ)
+ return __builtin_clz(x) ^ 0x1f;
+#else
+ static const unsigned int l[] =
+ {
+ ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ };
+ unsigned int i;
+
+ return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24
+ : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
+#endif
+}
+
+static inline int ascii_isupper(int c)
+{
+ return 'A' <= c && c <= 'Z';
+}
+
+static inline int ascii_tolower(int c)
+{
+ return ascii_isupper(c) ? c - 'A' + 'a' : c;
+}
+
+static inline int ascii_strcasecmp(const char *a, const char *b)
+{
+ int c_a, c_b;
+
+ do
+ {
+ c_a = ascii_tolower(*a++);
+ c_b = ascii_tolower(*b++);
+ } while (c_a == c_b && c_a != '\0');
+
+ return c_a - c_b;
+}
+
+#ifndef _WIN32
+# if HAVE_SYNC_ADD_AND_FETCH
+static inline LONG InterlockedIncrement(LONG volatile *x)
+{
+ return __sync_add_and_fetch(x, 1);
+}
+# else
+# error "InterlockedIncrement() not implemented for this platform"
+# endif /* HAVE_SYNC_ADD_AND_FETCH */
+
+# if HAVE_SYNC_SUB_AND_FETCH
+static inline LONG InterlockedDecrement(LONG volatile *x)
+{
+ return __sync_sub_and_fetch(x, 1);
+}
+# else
+# error "InterlockedDecrement() not implemented for this platform"
+# endif
+#endif /* _WIN32 */
+
+#if HAVE_SYNC_ADD_AND_FETCH
+# define atomic_add_fetch(ptr, val) __sync_add_and_fetch(ptr, val)
+#elif defined(_MSC_VER)
+/* InterlockedAdd returns value after increment, like add_and_fetch. */
+# define atomic_add_fetch(ptr, val) InterlockedAdd(ptr, val)
+#else
+# error "atomic_add_fetch() not implemented for this platform"
+#endif /* HAVE_SYNC_ADD_AND_FETCH */
+
+static inline void vkd3d_parse_version(const char *version, int *major, int *minor)
+{
+ *major = atoi(version);
+
+ while (isdigit(*version))
+ ++version;
+ if (*version == '.')
+ ++version;
+
+ *minor = atoi(version);
+}
+
+#endif /* __VKD3D_COMMON_H */
diff --git a/dlls/vkd3d/include/private/vkd3d_debug.h b/dlls/vkd3d/include/private/vkd3d_debug.h
new file mode 100644
index 00000000000..c37c841ae0a
--- /dev/null
+++ b/dlls/vkd3d/include/private/vkd3d_debug.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_DEBUG_H
+#define __VKD3D_DEBUG_H
+
+#include "vkd3d_common.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef VKD3D_NO_TRACE_MESSAGES
+#define TRACE(args...) do { } while (0)
+#define TRACE_ON() (false)
+#endif
+
+#ifdef VKD3D_NO_DEBUG_MESSAGES
+#define WARN(args...) do { } while (0)
+#define FIXME(args...) do { } while (0)
+#endif
+
+enum vkd3d_dbg_level
+{
+ VKD3D_DBG_LEVEL_NONE,
+ VKD3D_DBG_LEVEL_ERR,
+ VKD3D_DBG_LEVEL_FIXME,
+ VKD3D_DBG_LEVEL_WARN,
+ VKD3D_DBG_LEVEL_TRACE,
+};
+
+enum vkd3d_dbg_level vkd3d_dbg_get_level(void) DECLSPEC_HIDDEN;
+
+void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function,
+ const char *fmt, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN;
+
+const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2) DECLSPEC_HIDDEN;
+const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args) DECLSPEC_HIDDEN;
+const char *debugstr_a(const char *str) DECLSPEC_HIDDEN;
+const char *debugstr_w(const WCHAR *wstr, size_t wchar_size) DECLSPEC_HIDDEN;
+
+#define VKD3D_DBG_LOG(level) \
+ do { \
+ const enum vkd3d_dbg_level vkd3d_dbg_level = VKD3D_DBG_LEVEL_##level; \
+ VKD3D_DBG_PRINTF
+
+#define VKD3D_DBG_LOG_ONCE(first_time_level, level) \
+ do { \
+ static bool vkd3d_dbg_next_time; \
+ const enum vkd3d_dbg_level vkd3d_dbg_level = vkd3d_dbg_next_time \
+ ? VKD3D_DBG_LEVEL_##level : VKD3D_DBG_LEVEL_##first_time_level; \
+ vkd3d_dbg_next_time = true; \
+ VKD3D_DBG_PRINTF
+
+#define VKD3D_DBG_PRINTF(...) \
+ vkd3d_dbg_printf(vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); } while (0)
+
+#ifndef TRACE
+#define TRACE VKD3D_DBG_LOG(TRACE)
+#endif
+
+#ifndef WARN
+#define WARN VKD3D_DBG_LOG(WARN)
+#endif
+
+#ifndef FIXME
+#define FIXME VKD3D_DBG_LOG(FIXME)
+#endif
+
+#define ERR VKD3D_DBG_LOG(ERR)
+
+#ifndef TRACE_ON
+#define TRACE_ON() (vkd3d_dbg_get_level() == VKD3D_DBG_LEVEL_TRACE)
+#endif
+
+#define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN)
+
+#define VKD3D_DEBUG_ENV_NAME(name) const char *vkd3d_dbg_env_name = name
+
+static inline const char *debugstr_guid(const GUID *guid)
+{
+ if (!guid)
+ return "(null)";
+
+ return vkd3d_dbg_sprintf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ (unsigned long)guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
+ guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
+ guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+}
+
+unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value) DECLSPEC_HIDDEN;
+
+struct vkd3d_debug_option
+{
+ const char *name;
+ uint64_t flag;
+};
+
+bool vkd3d_debug_list_has_member(const char *string, const char *member) DECLSPEC_HIDDEN;
+uint64_t vkd3d_parse_debug_options(const char *string,
+ const struct vkd3d_debug_option *options, unsigned int option_count) DECLSPEC_HIDDEN;
+
+#endif /* __VKD3D_DEBUG_H */
diff --git a/dlls/vkd3d/include/private/vkd3d_memory.h b/dlls/vkd3d/include/private/vkd3d_memory.h
new file mode 100644
index 00000000000..df93abf5257
--- /dev/null
+++ b/dlls/vkd3d/include/private/vkd3d_memory.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_MEMORY_H
+#define __VKD3D_MEMORY_H
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "vkd3d_debug.h"
+
+static inline void *vkd3d_malloc(size_t size)
+{
+ void *ptr;
+ if (!(ptr = malloc(size)))
+ ERR("Out of memory.\n");
+ return ptr;
+}
+
+static inline void *vkd3d_realloc(void *ptr, size_t size)
+{
+ if (!(ptr = realloc(ptr, size)))
+ ERR("Out of memory.\n");
+ return ptr;
+}
+
+static inline void *vkd3d_calloc(size_t count, size_t size)
+{
+ void *ptr;
+ assert(count <= ~(size_t)0 / size);
+ if (!(ptr = calloc(count, size)))
+ ERR("Out of memory.\n");
+ return ptr;
+}
+
+static inline void vkd3d_free(void *ptr)
+{
+ free(ptr);
+}
+
+bool vkd3d_array_reserve(void **elements, size_t *capacity,
+ size_t element_count, size_t element_size) DECLSPEC_HIDDEN;
+
+#endif /* __VKD3D_MEMORY_H */
diff --git a/dlls/vkd3d/include/private/vkd3d_test.h b/dlls/vkd3d/include/private/vkd3d_test.h
new file mode 100644
index 00000000000..6b8763ddeb7
--- /dev/null
+++ b/dlls/vkd3d/include/private/vkd3d_test.h
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_TEST_H
+#define __VKD3D_TEST_H
+
+#include "vkd3d_common.h"
+#include <assert.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void vkd3d_test_main(int argc, char **argv);
+static const char *vkd3d_test_name;
+static const char *vkd3d_test_platform = "other";
+
+static void vkd3d_test_start_todo(bool is_todo);
+static int vkd3d_test_loop_todo(void);
+static void vkd3d_test_end_todo(void);
+
+#define START_TEST(name) \
+ static const char *vkd3d_test_name = #name; \
+ static void vkd3d_test_main(int argc, char **argv)
+
+/*
+ * Use assert_that() for conditions that should always be true.
+ * todo_if() and bug_if() do not influence assert_that().
+ */
+#define assert_that assert_that_(__LINE__)
+
+#define ok ok_(__LINE__)
+
+#define skip skip_(__LINE__)
+
+#define trace trace_(__LINE__)
+
+#define assert_that_(line) \
+ do { \
+ unsigned int vkd3d_line = line; \
+ VKD3D_TEST_ASSERT_THAT
+
+#define VKD3D_TEST_ASSERT_THAT(...) \
+ vkd3d_test_assert_that(vkd3d_line, __VA_ARGS__); } while (0)
+
+#define ok_(line) \
+ do { \
+ unsigned int vkd3d_line = line; \
+ VKD3D_TEST_OK
+
+#define VKD3D_TEST_OK(...) \
+ vkd3d_test_ok(vkd3d_line, __VA_ARGS__); } while (0)
+
+#define todo_(line) \
+ do { \
+ unsigned int vkd3d_line = line; \
+ VKD3D_TEST_TODO
+
+#define VKD3D_TEST_TODO(...) \
+ vkd3d_test_todo(vkd3d_line, __VA_ARGS__); } while (0)
+
+#define skip_(line) \
+ do { \
+ unsigned int vkd3d_line = line; \
+ VKD3D_TEST_SKIP
+
+#define VKD3D_TEST_SKIP(...) \
+ vkd3d_test_skip(vkd3d_line, __VA_ARGS__); } while (0)
+
+#define trace_(line) \
+ do { \
+ unsigned int vkd3d_line = line; \
+ VKD3D_TEST_TRACE
+
+#define VKD3D_TEST_TRACE(...) \
+ vkd3d_test_trace(vkd3d_line, __VA_ARGS__); } while (0)
+
+#define todo_if(is_todo) \
+ for (vkd3d_test_start_todo(is_todo); vkd3d_test_loop_todo(); vkd3d_test_end_todo())
+
+#define bug_if(is_bug) \
+ for (vkd3d_test_start_bug(is_bug); vkd3d_test_loop_bug(); vkd3d_test_end_bug())
+
+#define todo todo_if(true)
+
+static struct
+{
+ LONG success_count;
+ LONG failure_count;
+ LONG skip_count;
+ LONG todo_count;
+ LONG todo_success_count;
+ LONG bug_count;
+
+ unsigned int debug_level;
+
+ unsigned int todo_level;
+ bool todo_do_loop;
+
+ unsigned int bug_level;
+ bool bug_do_loop;
+ bool bug_enabled;
+
+ const char *test_name_filter;
+ char context[1024];
+} vkd3d_test_state;
+
+static bool
+vkd3d_test_platform_is_windows(void)
+{
+ return !strcmp(vkd3d_test_platform, "windows");
+}
+
+static inline bool
+broken(bool condition)
+{
+ return condition && vkd3d_test_platform_is_windows();
+}
+
+static void
+vkd3d_test_check_assert_that(unsigned int line, bool result, const char *fmt, va_list args)
+{
+ if (result)
+ {
+ InterlockedIncrement(&vkd3d_test_state.success_count);
+ if (vkd3d_test_state.debug_level > 1)
+ printf("%s:%d%s: Test succeeded.\n", vkd3d_test_name, line, vkd3d_test_state.context);
+ }
+ else
+ {
+ InterlockedIncrement(&vkd3d_test_state.failure_count);
+ printf("%s:%d%s: Test failed: ", vkd3d_test_name, line, vkd3d_test_state.context);
+ vprintf(fmt, args);
+ }
+}
+
+static void VKD3D_PRINTF_FUNC(3, 4) VKD3D_UNUSED
+vkd3d_test_assert_that(unsigned int line, bool result, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vkd3d_test_check_assert_that(line, result, fmt, args);
+ va_end(args);
+}
+
+static void
+vkd3d_test_check_ok(unsigned int line, bool result, const char *fmt, va_list args)
+{
+ bool is_todo = vkd3d_test_state.todo_level && !vkd3d_test_platform_is_windows();
+ bool is_bug = vkd3d_test_state.bug_level && !vkd3d_test_platform_is_windows();
+
+ if (is_bug && vkd3d_test_state.bug_enabled)
+ {
+ InterlockedIncrement(&vkd3d_test_state.bug_count);
+ if (is_todo)
+ result = !result;
+ if (result)
+ printf("%s:%d%s: Fixed bug: ", vkd3d_test_name, line, vkd3d_test_state.context);
+ else
+ printf("%s:%d%s: Bug: ", vkd3d_test_name, line, vkd3d_test_state.context);
+ vprintf(fmt, args);
+ }
+ else if (is_todo)
+ {
+ if (result)
+ {
+ InterlockedIncrement(&vkd3d_test_state.todo_success_count);
+ printf("%s:%d%s: Todo succeeded: ", vkd3d_test_name, line, vkd3d_test_state.context);
+ }
+ else
+ {
+ InterlockedIncrement(&vkd3d_test_state.todo_count);
+ printf("%s:%d%s: Todo: ", vkd3d_test_name, line, vkd3d_test_state.context);
+ }
+ vprintf(fmt, args);
+ }
+ else
+ {
+ vkd3d_test_check_assert_that(line, result, fmt, args);
+ }
+}
+
+static void VKD3D_PRINTF_FUNC(3, 4) VKD3D_UNUSED
+vkd3d_test_ok(unsigned int line, bool result, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vkd3d_test_check_ok(line, result, fmt, args);
+ va_end(args);
+}
+
+static void VKD3D_PRINTF_FUNC(2, 3) VKD3D_UNUSED
+vkd3d_test_skip(unsigned int line, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ printf("%s:%d%s: Test skipped: ", vkd3d_test_name, line, vkd3d_test_state.context);
+ vprintf(fmt, args);
+ va_end(args);
+ InterlockedIncrement(&vkd3d_test_state.skip_count);
+}
+
+static void VKD3D_PRINTF_FUNC(2, 3) VKD3D_UNUSED
+vkd3d_test_trace(unsigned int line, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ printf("%s:%d%s: ", vkd3d_test_name, line, vkd3d_test_state.context);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+static void VKD3D_PRINTF_FUNC(1, 2) VKD3D_UNUSED
+vkd3d_test_debug(const char *fmt, ...)
+{
+ char buffer[512];
+ va_list args;
+ int size;
+
+ size = snprintf(buffer, sizeof(buffer), "%s: ", vkd3d_test_name);
+ if (0 < size && size < sizeof(buffer))
+ {
+ va_start(args, fmt);
+ vsnprintf(buffer + size, sizeof(buffer) - size, fmt, args);
+ va_end(args);
+ }
+ buffer[sizeof(buffer) - 1] = '\0';
+
+#ifdef _WIN32
+ OutputDebugStringA(buffer);
+#endif
+
+ if (vkd3d_test_state.debug_level > 0)
+ printf("%s\n", buffer);
+}
+
+int main(int argc, char **argv)
+{
+ const char *test_filter = getenv("VKD3D_TEST_FILTER");
+ const char *debug_level = getenv("VKD3D_TEST_DEBUG");
+ char *test_platform = getenv("VKD3D_TEST_PLATFORM");
+ const char *bug = getenv("VKD3D_TEST_BUG");
+
+ memset(&vkd3d_test_state, 0, sizeof(vkd3d_test_state));
+ vkd3d_test_state.debug_level = debug_level ? atoi(debug_level) : 0;
+ vkd3d_test_state.bug_enabled = bug ? atoi(bug) : true;
+ vkd3d_test_state.test_name_filter = test_filter;
+
+ if (test_platform)
+ {
+ test_platform = strdup(test_platform);
+ vkd3d_test_platform = test_platform;
+ }
+
+ if (vkd3d_test_state.debug_level > 1)
+ printf("Test platform: '%s'.\n", vkd3d_test_platform);
+
+ vkd3d_test_main(argc, argv);
+
+ printf("%s: %lu tests executed (%lu failures, %lu skipped, %lu todo, %lu bugs).\n",
+ vkd3d_test_name,
+ (unsigned long)(vkd3d_test_state.success_count
+ + vkd3d_test_state.failure_count + vkd3d_test_state.todo_count
+ + vkd3d_test_state.todo_success_count),
+ (unsigned long)(vkd3d_test_state.failure_count
+ + vkd3d_test_state.todo_success_count),
+ (unsigned long)vkd3d_test_state.skip_count,
+ (unsigned long)vkd3d_test_state.todo_count,
+ (unsigned long)vkd3d_test_state.bug_count);
+
+ if (test_platform)
+ free(test_platform);
+
+ return vkd3d_test_state.failure_count || vkd3d_test_state.todo_success_count;
+}
+
+#ifdef _WIN32
+static char *vkd3d_test_strdupWtoA(WCHAR *str)
+{
+ char *out;
+ int len;
+
+ if (!(len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL)))
+ return NULL;
+ if (!(out = malloc(len)))
+ return NULL;
+ WideCharToMultiByte(CP_ACP, 0, str, -1, out, len, NULL, NULL);
+
+ return out;
+}
+
+static bool running_under_wine(void)
+{
+ HMODULE module = GetModuleHandleA("ntdll.dll");
+ return module && GetProcAddress(module, "wine_server_call");
+}
+
+int wmain(int argc, WCHAR **wargv)
+{
+ char **argv;
+ int i, ret;
+
+ argv = malloc(argc * sizeof(*argv));
+ assert(argv);
+ for (i = 0; i < argc; ++i)
+ {
+ if (!(argv[i] = vkd3d_test_strdupWtoA(wargv[i])))
+ break;
+ }
+ assert(i == argc);
+
+ vkd3d_test_platform = running_under_wine() ? "wine" : "windows";
+
+ ret = main(argc, argv);
+
+ for (i = 0; i < argc; ++i)
+ free(argv[i]);
+ free(argv);
+
+ return ret;
+}
+#endif /* _WIN32 */
+
+typedef void (*vkd3d_test_pfn)(void);
+
+static inline void vkd3d_run_test(const char *name, vkd3d_test_pfn test_pfn)
+{
+ if (vkd3d_test_state.test_name_filter && !strstr(name, vkd3d_test_state.test_name_filter))
+ return;
+
+ vkd3d_test_debug("%s", name);
+ test_pfn();
+}
+
+static inline void vkd3d_test_start_todo(bool is_todo)
+{
+ vkd3d_test_state.todo_level = (vkd3d_test_state.todo_level << 1) | is_todo;
+ vkd3d_test_state.todo_do_loop = true;
+}
+
+static inline int vkd3d_test_loop_todo(void)
+{
+ bool do_loop = vkd3d_test_state.todo_do_loop;
+ vkd3d_test_state.todo_do_loop = false;
+ return do_loop;
+}
+
+static inline void vkd3d_test_end_todo(void)
+{
+ vkd3d_test_state.todo_level >>= 1;
+}
+
+static inline void vkd3d_test_start_bug(bool is_bug)
+{
+ vkd3d_test_state.bug_level = (vkd3d_test_state.bug_level << 1) | is_bug;
+ vkd3d_test_state.bug_do_loop = true;
+}
+
+static inline int vkd3d_test_loop_bug(void)
+{
+ bool do_loop = vkd3d_test_state.bug_do_loop;
+ vkd3d_test_state.bug_do_loop = false;
+ return do_loop;
+}
+
+static inline void vkd3d_test_end_bug(void)
+{
+ vkd3d_test_state.bug_level >>= 1;
+}
+
+static inline void vkd3d_test_set_context(const char *fmt, ...)
+{
+ va_list args;
+
+ if (!fmt)
+ {
+ vkd3d_test_state.context[0] = '\0';
+ return;
+ }
+
+ vkd3d_test_state.context[0] = ':';
+ va_start(args, fmt);
+ vsnprintf(&vkd3d_test_state.context[1], sizeof(vkd3d_test_state.context) - 1, fmt, args);
+ va_end(args);
+ vkd3d_test_state.context[sizeof(vkd3d_test_state.context) - 1] = '\0';
+}
+
+#define run_test(test_pfn) \
+ vkd3d_run_test(#test_pfn, test_pfn)
+
+#endif /* __VKD3D_TEST_H */
diff --git a/dlls/vkd3d/include/private/vkd3d_utf8.h b/dlls/vkd3d/include/private/vkd3d_utf8.h
new file mode 100644
index 00000000000..ab32884b216
--- /dev/null
+++ b/dlls/vkd3d/include/private/vkd3d_utf8.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 Zhiyi Zhang for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_UTF8_H
+#define __VKD3D_UTF8_H
+
+#include "vkd3d_common.h"
+
+char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t wchar_size) DECLSPEC_HIDDEN;
+
+#endif /* __VKD3D_UTF8_H */
diff --git a/dlls/vkd3d/include/private/vkd3d_version.h b/dlls/vkd3d/include/private/vkd3d_version.h
new file mode 100644
index 00000000000..7dd2f25d609
--- /dev/null
+++ b/dlls/vkd3d/include/private/vkd3d_version.h
@@ -0,0 +1 @@
+#define VKD3D_VCS_ID ""
diff --git a/dlls/vkd3d/include/vkd3d.h b/dlls/vkd3d/include/vkd3d.h
new file mode 100644
index 00000000000..db1d5cdf607
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_H
+#define __VKD3D_H
+
+#include <vkd3d_types.h>
+
+#ifndef VKD3D_NO_WIN32_TYPES
+# include <vkd3d_windows.h>
+# include <vkd3d_d3d12.h>
+#endif /* VKD3D_NO_WIN32_TYPES */
+
+#ifndef VKD3D_NO_VULKAN_H
+# include <wine/vulkan.h>
+#endif /* VKD3D_NO_VULKAN_H */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+enum vkd3d_structure_type
+{
+ /* 1.0 */
+ VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO,
+
+ /* 1.1 */
+ VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO,
+
+ /* 1.2 */
+ VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO,
+ VKD3D_STRUCTURE_TYPE_APPLICATION_INFO,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE),
+};
+
+enum vkd3d_api_version
+{
+ VKD3D_API_VERSION_1_0,
+ VKD3D_API_VERSION_1_1,
+ VKD3D_API_VERSION_1_2,
+};
+
+typedef HRESULT (*PFN_vkd3d_signal_event)(HANDLE event);
+
+typedef void * (*PFN_vkd3d_thread)(void *data);
+
+typedef void * (*PFN_vkd3d_create_thread)(PFN_vkd3d_thread thread_main, void *data);
+typedef HRESULT (*PFN_vkd3d_join_thread)(void *thread);
+
+struct vkd3d_instance;
+
+struct vkd3d_instance_create_info
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+
+ PFN_vkd3d_signal_event pfn_signal_event;
+ PFN_vkd3d_create_thread pfn_create_thread;
+ PFN_vkd3d_join_thread pfn_join_thread;
+ size_t wchar_size;
+
+ /* If set to NULL, libvkd3d loads libvulkan. */
+ PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr;
+
+ const char * const *instance_extensions;
+ uint32_t instance_extension_count;
+};
+
+/* Extends vkd3d_instance_create_info. Available since 1.1. */
+struct vkd3d_optional_instance_extensions_info
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+
+ const char * const *extensions;
+ uint32_t extension_count;
+};
+
+/* Extends vkd3d_instance_create_info. Available since 1.2. */
+struct vkd3d_application_info
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+
+ const char *application_name;
+ uint32_t application_version;
+
+ const char *engine_name; /* "vkd3d" if NULL */
+ uint32_t engine_version; /* vkd3d version if engine_name is NULL */
+
+ enum vkd3d_api_version api_version;
+};
+
+struct vkd3d_device_create_info
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+
+ D3D_FEATURE_LEVEL minimum_feature_level;
+
+ struct vkd3d_instance *instance;
+ const struct vkd3d_instance_create_info *instance_create_info;
+
+ VkPhysicalDevice vk_physical_device;
+
+ const char * const *device_extensions;
+ uint32_t device_extension_count;
+
+ IUnknown *parent;
+ LUID adapter_luid;
+};
+
+/* Extends vkd3d_device_create_info. Available since 1.2. */
+struct vkd3d_optional_device_extensions_info
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+
+ const char * const *extensions;
+ uint32_t extension_count;
+};
+
+/* vkd3d_image_resource_create_info flags */
+#define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
+#define VKD3D_RESOURCE_PRESENT_STATE_TRANSITION 0x00000002
+
+struct vkd3d_image_resource_create_info
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+
+ VkImage vk_image;
+ D3D12_RESOURCE_DESC desc;
+ unsigned int flags;
+ D3D12_RESOURCE_STATES present_state;
+};
+
+#ifndef VKD3D_NO_PROTOTYPES
+
+HRESULT vkd3d_create_instance(const struct vkd3d_instance_create_info *create_info,
+ struct vkd3d_instance **instance);
+ULONG vkd3d_instance_decref(struct vkd3d_instance *instance);
+VkInstance vkd3d_instance_get_vk_instance(struct vkd3d_instance *instance);
+ULONG vkd3d_instance_incref(struct vkd3d_instance *instance);
+
+HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
+ REFIID iid, void **device);
+IUnknown *vkd3d_get_device_parent(ID3D12Device *device);
+VkDevice vkd3d_get_vk_device(ID3D12Device *device);
+VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device);
+struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device);
+
+uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue);
+VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue);
+void vkd3d_release_vk_queue(ID3D12CommandQueue *queue);
+
+HRESULT vkd3d_create_image_resource(ID3D12Device *device,
+ const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource);
+ULONG vkd3d_resource_decref(ID3D12Resource *resource);
+ULONG vkd3d_resource_incref(ID3D12Resource *resource);
+
+HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc,
+ D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
+HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_size,
+ REFIID iid, void **deserializer);
+
+VkFormat vkd3d_get_vk_format(DXGI_FORMAT format);
+
+/* 1.1 */
+DXGI_FORMAT vkd3d_get_dxgi_format(VkFormat format);
+
+/* 1.2 */
+HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
+ ID3DBlob **blob, ID3DBlob **error_blob);
+HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZE_T data_size,
+ REFIID iid, void **deserializer);
+
+#endif /* VKD3D_NO_PROTOTYPES */
+
+/*
+ * Function pointer typedefs for vkd3d functions.
+ */
+typedef HRESULT (*PFN_vkd3d_create_instance)(const struct vkd3d_instance_create_info *create_info,
+ struct vkd3d_instance **instance);
+typedef ULONG (*PFN_vkd3d_instance_decref)(struct vkd3d_instance *instance);
+typedef VkInstance (*PFN_vkd3d_instance_get_vk_instance)(struct vkd3d_instance *instance);
+typedef ULONG (*PFN_vkd3d_instance_incref)(struct vkd3d_instance *instance);
+
+typedef HRESULT (*PFN_vkd3d_create_device)(const struct vkd3d_device_create_info *create_info,
+ REFIID iid, void **device);
+typedef IUnknown * (*PFN_vkd3d_get_device_parent)(ID3D12Device *device);
+typedef VkDevice (*PFN_vkd3d_get_vk_device)(ID3D12Device *device);
+typedef VkPhysicalDevice (*PFN_vkd3d_get_vk_physical_device)(ID3D12Device *device);
+typedef struct vkd3d_instance * (*PFN_vkd3d_instance_from_device)(ID3D12Device *device);
+
+typedef uint32_t (*PFN_vkd3d_get_vk_queue_family_index)(ID3D12CommandQueue *queue);
+typedef VkQueue (*PFN_vkd3d_acquire_vk_queue)(ID3D12CommandQueue *queue);
+typedef void (*PFN_vkd3d_release_vk_queue)(ID3D12CommandQueue *queue);
+
+typedef HRESULT (*PFN_vkd3d_create_image_resource)(ID3D12Device *device,
+ const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource);
+typedef ULONG (*PFN_vkd3d_resource_decref)(ID3D12Resource *resource);
+typedef ULONG (*PFN_vkd3d_resource_incref)(ID3D12Resource *resource);
+
+typedef HRESULT (*PFN_vkd3d_serialize_root_signature)(const D3D12_ROOT_SIGNATURE_DESC *desc,
+ D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
+typedef HRESULT (*PFN_vkd3d_create_root_signature_deserializer)(const void *data, SIZE_T data_size,
+ REFIID iid, void **deserializer);
+
+typedef VkFormat (*PFN_vkd3d_get_vk_format)(DXGI_FORMAT format);
+
+/* 1.1 */
+typedef DXGI_FORMAT (*PFN_vkd3d_get_dxgi_format)(VkFormat format);
+
+/* 1.2 */
+typedef HRESULT (*PFN_vkd3d_serialize_versioned_root_signature)(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
+ ID3DBlob **blob, ID3DBlob **error_blob);
+typedef HRESULT (*PFN_vkd3d_create_versioned_root_signature_deserializer)(const void *data, SIZE_T data_size,
+ REFIID iid, void **deserializer);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __VKD3D_H */
diff --git a/dlls/vkd3d/include/vkd3d_d3d12.h b/dlls/vkd3d/include/vkd3d_d3d12.h
new file mode 100644
index 00000000000..f1036f56b99
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_d3d12.h
@@ -0,0 +1,7749 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_d3d12.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_d3d12_h__
+#define __vkd3d_d3d12_h__
+
+/* Forward declarations */
+
+#ifndef __ID3D12Object_FWD_DEFINED__
+#define __ID3D12Object_FWD_DEFINED__
+typedef interface ID3D12Object ID3D12Object;
+#ifdef __cplusplus
+interface ID3D12Object;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12DeviceChild_FWD_DEFINED__
+#define __ID3D12DeviceChild_FWD_DEFINED__
+typedef interface ID3D12DeviceChild ID3D12DeviceChild;
+#ifdef __cplusplus
+interface ID3D12DeviceChild;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Pageable_FWD_DEFINED__
+#define __ID3D12Pageable_FWD_DEFINED__
+typedef interface ID3D12Pageable ID3D12Pageable;
+#ifdef __cplusplus
+interface ID3D12Pageable;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Heap_FWD_DEFINED__
+#define __ID3D12Heap_FWD_DEFINED__
+typedef interface ID3D12Heap ID3D12Heap;
+#ifdef __cplusplus
+interface ID3D12Heap;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Resource_FWD_DEFINED__
+#define __ID3D12Resource_FWD_DEFINED__
+typedef interface ID3D12Resource ID3D12Resource;
+#ifdef __cplusplus
+interface ID3D12Resource;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12CommandList_FWD_DEFINED__
+#define __ID3D12CommandList_FWD_DEFINED__
+typedef interface ID3D12CommandList ID3D12CommandList;
+#ifdef __cplusplus
+interface ID3D12CommandList;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12DescriptorHeap_FWD_DEFINED__
+#define __ID3D12DescriptorHeap_FWD_DEFINED__
+typedef interface ID3D12DescriptorHeap ID3D12DescriptorHeap;
+#ifdef __cplusplus
+interface ID3D12DescriptorHeap;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12QueryHeap_FWD_DEFINED__
+#define __ID3D12QueryHeap_FWD_DEFINED__
+typedef interface ID3D12QueryHeap ID3D12QueryHeap;
+#ifdef __cplusplus
+interface ID3D12QueryHeap;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12CommandSignature_FWD_DEFINED__
+#define __ID3D12CommandSignature_FWD_DEFINED__
+typedef interface ID3D12CommandSignature ID3D12CommandSignature;
+#ifdef __cplusplus
+interface ID3D12CommandSignature;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12GraphicsCommandList_FWD_DEFINED__
+#define __ID3D12GraphicsCommandList_FWD_DEFINED__
+typedef interface ID3D12GraphicsCommandList ID3D12GraphicsCommandList;
+#ifdef __cplusplus
+interface ID3D12GraphicsCommandList;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12GraphicsCommandList1_FWD_DEFINED__
+#define __ID3D12GraphicsCommandList1_FWD_DEFINED__
+typedef interface ID3D12GraphicsCommandList1 ID3D12GraphicsCommandList1;
+#ifdef __cplusplus
+interface ID3D12GraphicsCommandList1;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12GraphicsCommandList2_FWD_DEFINED__
+#define __ID3D12GraphicsCommandList2_FWD_DEFINED__
+typedef interface ID3D12GraphicsCommandList2 ID3D12GraphicsCommandList2;
+#ifdef __cplusplus
+interface ID3D12GraphicsCommandList2;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12CommandQueue_FWD_DEFINED__
+#define __ID3D12CommandQueue_FWD_DEFINED__
+typedef interface ID3D12CommandQueue ID3D12CommandQueue;
+#ifdef __cplusplus
+interface ID3D12CommandQueue;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12RootSignature_FWD_DEFINED__
+#define __ID3D12RootSignature_FWD_DEFINED__
+typedef interface ID3D12RootSignature ID3D12RootSignature;
+#ifdef __cplusplus
+interface ID3D12RootSignature;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12PipelineState_FWD_DEFINED__
+#define __ID3D12PipelineState_FWD_DEFINED__
+typedef interface ID3D12PipelineState ID3D12PipelineState;
+#ifdef __cplusplus
+interface ID3D12PipelineState;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Fence_FWD_DEFINED__
+#define __ID3D12Fence_FWD_DEFINED__
+typedef interface ID3D12Fence ID3D12Fence;
+#ifdef __cplusplus
+interface ID3D12Fence;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12CommandAllocator_FWD_DEFINED__
+#define __ID3D12CommandAllocator_FWD_DEFINED__
+typedef interface ID3D12CommandAllocator ID3D12CommandAllocator;
+#ifdef __cplusplus
+interface ID3D12CommandAllocator;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Device_FWD_DEFINED__
+#define __ID3D12Device_FWD_DEFINED__
+typedef interface ID3D12Device ID3D12Device;
+#ifdef __cplusplus
+interface ID3D12Device;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Device1_FWD_DEFINED__
+#define __ID3D12Device1_FWD_DEFINED__
+typedef interface ID3D12Device1 ID3D12Device1;
+#ifdef __cplusplus
+interface ID3D12Device1;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12RootSignatureDeserializer_FWD_DEFINED__
+#define __ID3D12RootSignatureDeserializer_FWD_DEFINED__
+typedef interface ID3D12RootSignatureDeserializer ID3D12RootSignatureDeserializer;
+#ifdef __cplusplus
+interface ID3D12RootSignatureDeserializer;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12VersionedRootSignatureDeserializer_FWD_DEFINED__
+#define __ID3D12VersionedRootSignatureDeserializer_FWD_DEFINED__
+typedef interface ID3D12VersionedRootSignatureDeserializer ID3D12VersionedRootSignatureDeserializer;
+#ifdef __cplusplus
+interface ID3D12VersionedRootSignatureDeserializer;
+#endif /* __cplusplus */
+#endif
+
+/* Headers for imported files */
+
+#include <vkd3d_windows.h>
+#include <vkd3d_dxgibase.h>
+#include <vkd3d_d3dcommon.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _D3D12_CONSTANTS
+#define _D3D12_CONSTANTS
+#define D3D12_CS_TGSM_REGISTER_COUNT (8192)
+
+#define D3D12_MAX_ROOT_COST (64)
+
+#define D3D12_VIEWPORT_BOUNDS_MAX (32767)
+
+#define D3D12_VIEWPORT_BOUNDS_MIN (-32768)
+
+#define D3D12_COMMONSHADER_CONSTANT_BUFFER_REGISTER_COUNT (15)
+
+#define D3D12_APPEND_ALIGNED_ELEMENT (0xffffffff)
+
+#define D3D12_DEFAULT_BLEND_FACTOR_ALPHA (1.0f)
+#define D3D12_DEFAULT_BLEND_FACTOR_BLUE (1.0f)
+#define D3D12_DEFAULT_BLEND_FACTOR_GREEN (1.0f)
+#define D3D12_DEFAULT_BLEND_FACTOR_RED (1.0f)
+#define D3D12_DEFAULT_DEPTH_BIAS (0)
+
+#define D3D12_DEFAULT_DEPTH_BIAS_CLAMP (0.0f)
+#define D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS (0.0f)
+#define D3D12_DEFAULT_STENCIL_READ_MASK (0xff)
+
+#define D3D12_DEFAULT_STENCIL_WRITE_MASK (0xff)
+
+#define D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND (0xffffffff)
+
+#define D3D12_FLOAT32_MAX (3.402823466e+38f)
+#define D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT (32)
+
+#define D3D12_UAV_SLOT_COUNT (64)
+
+#define D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT (4096)
+
+#define D3D12_REQ_IMMEDIATE_CONSTANT_BUFFER_ELEMENT_COUNT (4096)
+
+#define D3D12_REQ_MIP_LEVELS (15)
+
+#define D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION (2048)
+
+#define D3D12_REQ_TEXTURE1D_U_DIMENSION (16384)
+
+#define D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION (2048)
+
+#define D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION (16384)
+
+#define D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION (2048)
+
+#define D3D12_REQ_TEXTURECUBE_DIMENSION (16384)
+
+#define D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES (0xffffffff)
+
+#define D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT (8)
+
+#define D3D12_SO_BUFFER_MAX_STRIDE_IN_BYTES (2048)
+
+#define D3D12_SO_BUFFER_SLOT_COUNT (4)
+
+#define D3D12_SO_DDI_REGISTER_INDEX_DENOTING_GAP (0xffffffff)
+
+#define D3D12_SO_NO_RASTERIZED_STREAM (0xffffffff)
+
+#define D3D12_SO_OUTPUT_COMPONENT_COUNT (128)
+
+#define D3D12_SO_STREAM_COUNT (4)
+
+#define D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT (256)
+
+#define D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT (4194304)
+
+#define D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT (65536)
+
+#define D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT (16)
+
+#define D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT (65536)
+
+#define D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT (4096)
+
+#define D3D12_STANDARD_MAXIMUM_ELEMENT_ALIGNMENT_BYTE_MULTIPLE (4)
+
+#define D3D12_TEXTURE_DATA_PITCH_ALIGNMENT (256)
+
+#define D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT (512)
+
+#define D3D12_UAV_COUNTER_PLACEMENT_ALIGNMENT (4096)
+
+#define D3D12_VS_INPUT_REGISTER_COUNT (32)
+
+#define D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE (16)
+
+#endif
+#define D3D12_SHADER_COMPONENT_MAPPING_MASK (0x7)
+
+#define D3D12_SHADER_COMPONENT_MAPPING_SHIFT (3)
+
+#define D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES (1 << (D3D12_SHADER_COMPONENT_MAPPING_SHIFT * 4))
+
+typedef enum D3D12_SHADER_MIN_PRECISION_SUPPORT {
+ D3D12_SHADER_MIN_PRECISION_SUPPORT_NONE = 0x0,
+ D3D12_SHADER_MIN_PRECISION_SUPPORT_10_BIT = 0x1,
+ D3D12_SHADER_MIN_PRECISION_SUPPORT_16_BIT = 0x2
+} D3D12_SHADER_MIN_PRECISION_SUPPORT;
+typedef enum D3D12_TILED_RESOURCES_TIER {
+ D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED = 0,
+ D3D12_TILED_RESOURCES_TIER_1 = 1,
+ D3D12_TILED_RESOURCES_TIER_2 = 2,
+ D3D12_TILED_RESOURCES_TIER_3 = 3
+} D3D12_TILED_RESOURCES_TIER;
+typedef enum D3D12_RESOURCE_BINDING_TIER {
+ D3D12_RESOURCE_BINDING_TIER_1 = 1,
+ D3D12_RESOURCE_BINDING_TIER_2 = 2,
+ D3D12_RESOURCE_BINDING_TIER_3 = 3
+} D3D12_RESOURCE_BINDING_TIER;
+typedef enum D3D12_CONSERVATIVE_RASTERIZATION_TIER {
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED = 0,
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER_1 = 1,
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER_2 = 2,
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER_3 = 3
+} D3D12_CONSERVATIVE_RASTERIZATION_TIER;
+typedef enum D3D12_CROSS_NODE_SHARING_TIER {
+ D3D12_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED = 0,
+ D3D12_CROSS_NODE_SHARING_TIER_1_EMULATED = 1,
+ D3D12_CROSS_NODE_SHARING_TIER_1 = 2,
+ D3D12_CROSS_NODE_SHARING_TIER_2 = 3
+} D3D12_CROSS_NODE_SHARING_TIER;
+typedef enum D3D12_RESOURCE_HEAP_TIER {
+ D3D12_RESOURCE_HEAP_TIER_1 = 1,
+ D3D12_RESOURCE_HEAP_TIER_2 = 2
+} D3D12_RESOURCE_HEAP_TIER;
+typedef enum D3D12_FORMAT_SUPPORT1 {
+ D3D12_FORMAT_SUPPORT1_NONE = 0x0,
+ D3D12_FORMAT_SUPPORT1_BUFFER = 0x1,
+ D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER = 0x2,
+ D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER = 0x4,
+ D3D12_FORMAT_SUPPORT1_SO_BUFFER = 0x8,
+ D3D12_FORMAT_SUPPORT1_TEXTURE1D = 0x10,
+ D3D12_FORMAT_SUPPORT1_TEXTURE2D = 0x20,
+ D3D12_FORMAT_SUPPORT1_TEXTURE3D = 0x40,
+ D3D12_FORMAT_SUPPORT1_TEXTURECUBE = 0x80,
+ D3D12_FORMAT_SUPPORT1_SHADER_LOAD = 0x100,
+ D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE = 0x200,
+ D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_COMPARISON = 0x400,
+ D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_MONO_TEXT = 0x800,
+ D3D12_FORMAT_SUPPORT1_MIP = 0x1000,
+ D3D12_FORMAT_SUPPORT1_RENDER_TARGET = 0x4000,
+ D3D12_FORMAT_SUPPORT1_BLENDABLE = 0x8000,
+ D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL = 0x10000,
+ D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE = 0x40000,
+ D3D12_FORMAT_SUPPORT1_DISPLAY = 0x80000,
+ D3D12_FORMAT_SUPPORT1_CAST_WITHIN_BIT_LAYOUT = 0x100000,
+ D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET = 0x200000,
+ D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD = 0x400000,
+ D3D12_FORMAT_SUPPORT1_SHADER_GATHER = 0x800000,
+ D3D12_FORMAT_SUPPORT1_BACK_BUFFER_CAST = 0x1000000,
+ D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW = 0x2000000,
+ D3D12_FORMAT_SUPPORT1_SHADER_GATHER_COMPARISON = 0x4000000,
+ D3D12_FORMAT_SUPPORT1_DECODER_OUTPUT = 0x8000000,
+ D3D12_FORMAT_SUPPORT1_VIDEO_PROCESSOR_OUTPUT = 0x10000000,
+ D3D12_FORMAT_SUPPORT1_VIDEO_PROCESSOR_INPUT = 0x20000000,
+ D3D12_FORMAT_SUPPORT1_VIDEO_ENCODER = 0x40000000
+} D3D12_FORMAT_SUPPORT1;
+typedef enum D3D12_FORMAT_SUPPORT2 {
+ D3D12_FORMAT_SUPPORT2_NONE = 0x0,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_ADD = 0x1,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS = 0x2,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 0x4,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE = 0x8,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX = 0x10,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 0x20,
+ D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD = 0x40,
+ D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE = 0x80,
+ D3D12_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP = 0x100,
+ D3D12_FORMAT_SUPPORT2_TILED = 0x200,
+ D3D12_FORMAT_SUPPORT2_MULTIPLANE_OVERLAY = 0x4000
+} D3D12_FORMAT_SUPPORT2;
+typedef enum D3D12_WRITEBUFFERIMMEDIATE_MODE {
+ D3D12_WRITEBUFFERIMMEDIATE_MODE_DEFAULT = 0x0,
+ D3D12_WRITEBUFFERIMMEDIATE_MODE_MARKER_IN = 0x1,
+ D3D12_WRITEBUFFERIMMEDIATE_MODE_MARKER_OUT = 0x2
+} D3D12_WRITEBUFFERIMMEDIATE_MODE;
+typedef enum D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER {
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED = 0x0,
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_1 = 0x1,
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_2 = 0x2
+} D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER;
+typedef enum D3D12_SHADER_CACHE_SUPPORT_FLAGS {
+ D3D12_SHADER_CACHE_SUPPORT_NONE = 0x0,
+ D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO = 0x1,
+ D3D12_SHADER_CACHE_SUPPORT_LIBRARY = 0x2,
+ D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_INPROC_CACHE = 0x4,
+ D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_DISK_CACHE = 0x8
+} D3D12_SHADER_CACHE_SUPPORT_FLAGS;
+typedef enum D3D12_COMMAND_LIST_SUPPORT_FLAGS {
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE = 0x0,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_DIRECT = 0x1,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_BUNDLE = 0x2,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_COMPUTE = 0x4,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_COPY = 0x8,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_DECODE = 0x10,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_PROCESS = 0x20,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_ENCODE = 0x40
+} D3D12_COMMAND_LIST_SUPPORT_FLAGS;
+typedef enum D3D12_VIEW_INSTANCING_TIER {
+ D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED = 0x0,
+ D3D12_VIEW_INSTANCING_TIER_1 = 0x1,
+ D3D12_VIEW_INSTANCING_TIER_2 = 0x2,
+ D3D12_VIEW_INSTANCING_TIER_3 = 0x3
+} D3D12_VIEW_INSTANCING_TIER;
+typedef enum D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER {
+ D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_0 = 0x0,
+ D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_1 = 0x1
+} D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER;
+typedef enum D3D12_HEAP_SERIALIZATION_TIER {
+ D3D12_HEAP_SERIALIZATION_TIER_0 = 0x0,
+ D3D12_HEAP_SERIALIZATION_TIER_10 = 0xa
+} D3D12_HEAP_SERIALIZATION_TIER;
+typedef enum D3D12_RENDER_PASS_TIER {
+ D3D12_RENDER_PASS_TIER_0 = 0x0,
+ D3D12_RENDER_PASS_TIER_1 = 0x1,
+ D3D12_RENDER_PASS_TIER_2 = 0x2
+} D3D12_RENDER_PASS_TIER;
+typedef enum D3D12_RAYTRACING_TIER {
+ D3D12_RAYTRACING_TIER_NOT_SUPPORTED = 0x0,
+ D3D12_RAYTRACING_TIER_1_0 = 0xa
+} D3D12_RAYTRACING_TIER;
+#ifndef __ID3D12Fence_FWD_DEFINED__
+#define __ID3D12Fence_FWD_DEFINED__
+typedef interface ID3D12Fence ID3D12Fence;
+#ifdef __cplusplus
+interface ID3D12Fence;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12RootSignature_FWD_DEFINED__
+#define __ID3D12RootSignature_FWD_DEFINED__
+typedef interface ID3D12RootSignature ID3D12RootSignature;
+#ifdef __cplusplus
+interface ID3D12RootSignature;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Heap_FWD_DEFINED__
+#define __ID3D12Heap_FWD_DEFINED__
+typedef interface ID3D12Heap ID3D12Heap;
+#ifdef __cplusplus
+interface ID3D12Heap;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12DescriptorHeap_FWD_DEFINED__
+#define __ID3D12DescriptorHeap_FWD_DEFINED__
+typedef interface ID3D12DescriptorHeap ID3D12DescriptorHeap;
+#ifdef __cplusplus
+interface ID3D12DescriptorHeap;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Resource_FWD_DEFINED__
+#define __ID3D12Resource_FWD_DEFINED__
+typedef interface ID3D12Resource ID3D12Resource;
+#ifdef __cplusplus
+interface ID3D12Resource;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12CommandAllocator_FWD_DEFINED__
+#define __ID3D12CommandAllocator_FWD_DEFINED__
+typedef interface ID3D12CommandAllocator ID3D12CommandAllocator;
+#ifdef __cplusplus
+interface ID3D12CommandAllocator;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12GraphicsCommandList_FWD_DEFINED__
+#define __ID3D12GraphicsCommandList_FWD_DEFINED__
+typedef interface ID3D12GraphicsCommandList ID3D12GraphicsCommandList;
+#ifdef __cplusplus
+interface ID3D12GraphicsCommandList;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12CommandQueue_FWD_DEFINED__
+#define __ID3D12CommandQueue_FWD_DEFINED__
+typedef interface ID3D12CommandQueue ID3D12CommandQueue;
+#ifdef __cplusplus
+interface ID3D12CommandQueue;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12PipelineState_FWD_DEFINED__
+#define __ID3D12PipelineState_FWD_DEFINED__
+typedef interface ID3D12PipelineState ID3D12PipelineState;
+#ifdef __cplusplus
+interface ID3D12PipelineState;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Device_FWD_DEFINED__
+#define __ID3D12Device_FWD_DEFINED__
+typedef interface ID3D12Device ID3D12Device;
+#ifdef __cplusplus
+interface ID3D12Device;
+#endif /* __cplusplus */
+#endif
+
+typedef RECT D3D12_RECT;
+typedef struct D3D12_BOX {
+ UINT left;
+ UINT top;
+ UINT front;
+ UINT right;
+ UINT bottom;
+ UINT back;
+} D3D12_BOX;
+typedef struct D3D12_VIEWPORT {
+ FLOAT TopLeftX;
+ FLOAT TopLeftY;
+ FLOAT Width;
+ FLOAT Height;
+ FLOAT MinDepth;
+ FLOAT MaxDepth;
+} D3D12_VIEWPORT;
+typedef struct D3D12_RANGE {
+ SIZE_T Begin;
+ SIZE_T End;
+} D3D12_RANGE;
+typedef struct D3D12_RANGE_UINT64 {
+ UINT64 Begin;
+ UINT64 End;
+} D3D12_RANGE_UINT64;
+typedef struct D3D12_SUBRESOURCE_RANGE_UINT64 {
+ UINT Subresource;
+ D3D12_RANGE_UINT64 Range;
+} D3D12_SUBRESOURCE_RANGE_UINT64;
+typedef struct D3D12_RESOURCE_ALLOCATION_INFO {
+ UINT64 SizeInBytes;
+ UINT64 Alignment;
+} D3D12_RESOURCE_ALLOCATION_INFO;
+typedef struct D3D12_DRAW_ARGUMENTS {
+ UINT VertexCountPerInstance;
+ UINT InstanceCount;
+ UINT StartVertexLocation;
+ UINT StartInstanceLocation;
+} D3D12_DRAW_ARGUMENTS;
+typedef struct D3D12_DRAW_INDEXED_ARGUMENTS {
+ UINT IndexCountPerInstance;
+ UINT InstanceCount;
+ UINT StartIndexLocation;
+ INT BaseVertexLocation;
+ UINT StartInstanceLocation;
+} D3D12_DRAW_INDEXED_ARGUMENTS;
+typedef struct D3D12_DISPATCH_ARGUMENTS {
+ UINT ThreadGroupCountX;
+ UINT ThreadGroupCountY;
+ UINT ThreadGroupCountZ;
+} D3D12_DISPATCH_ARGUMENTS;
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS {
+ BOOL DoublePrecisionFloatShaderOps;
+ BOOL OutputMergerLogicOp;
+ D3D12_SHADER_MIN_PRECISION_SUPPORT MinPrecisionSupport;
+ D3D12_TILED_RESOURCES_TIER TiledResourcesTier;
+ D3D12_RESOURCE_BINDING_TIER ResourceBindingTier;
+ BOOL PSSpecifiedStencilRefSupported;
+ BOOL TypedUAVLoadAdditionalFormats;
+ BOOL ROVsSupported;
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER ConservativeRasterizationTier;
+ UINT MaxGPUVirtualAddressBitsPerResource;
+ BOOL StandardSwizzle64KBSupported;
+ D3D12_CROSS_NODE_SHARING_TIER CrossNodeSharingTier;
+ BOOL CrossAdapterRowMajorTextureSupported;
+ BOOL VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation;
+ D3D12_RESOURCE_HEAP_TIER ResourceHeapTier;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS;
+typedef struct D3D12_FEATURE_DATA_FORMAT_SUPPORT {
+ DXGI_FORMAT Format;
+ D3D12_FORMAT_SUPPORT1 Support1;
+ D3D12_FORMAT_SUPPORT2 Support2;
+} D3D12_FEATURE_DATA_FORMAT_SUPPORT;
+typedef enum D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS {
+ D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE = 0x0,
+ D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE = 0x1
+} D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS;
+typedef struct D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS {
+ DXGI_FORMAT Format;
+ UINT SampleCount;
+ D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS Flags;
+ UINT NumQualityLevels;
+} D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS;
+typedef enum D3D12_HEAP_TYPE {
+ D3D12_HEAP_TYPE_DEFAULT = 1,
+ D3D12_HEAP_TYPE_UPLOAD = 2,
+ D3D12_HEAP_TYPE_READBACK = 3,
+ D3D12_HEAP_TYPE_CUSTOM = 4
+} D3D12_HEAP_TYPE;
+typedef enum D3D12_CPU_PAGE_PROPERTY {
+ D3D12_CPU_PAGE_PROPERTY_UNKNOWN = 0,
+ D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE = 1,
+ D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE = 2,
+ D3D12_CPU_PAGE_PROPERTY_WRITE_BACK = 3
+} D3D12_CPU_PAGE_PROPERTY;
+typedef enum D3D12_MEMORY_POOL {
+ D3D12_MEMORY_POOL_UNKNOWN = 0,
+ D3D12_MEMORY_POOL_L0 = 1,
+ D3D12_MEMORY_POOL_L1 = 2
+} D3D12_MEMORY_POOL;
+typedef struct D3D12_HEAP_PROPERTIES {
+ D3D12_HEAP_TYPE Type;
+ D3D12_CPU_PAGE_PROPERTY CPUPageProperty;
+ D3D12_MEMORY_POOL MemoryPoolPreference;
+ UINT CreationNodeMask;
+ UINT VisibleNodeMask;
+} D3D12_HEAP_PROPERTIES;
+typedef enum D3D12_HEAP_FLAGS {
+ D3D12_HEAP_FLAG_NONE = 0x0,
+ D3D12_HEAP_FLAG_SHARED = 0x1,
+ D3D12_HEAP_FLAG_DENY_BUFFERS = 0x4,
+ D3D12_HEAP_FLAG_ALLOW_DISPLAY = 0x8,
+ D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER = 0x20,
+ D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES = 0x40,
+ D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES = 0x80,
+ D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0x0,
+ D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS = 0xc0,
+ D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES = 0x44,
+ D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES = 0x84
+} D3D12_HEAP_FLAGS;
+typedef struct D3D12_HEAP_DESC {
+ UINT64 SizeInBytes;
+ D3D12_HEAP_PROPERTIES Properties;
+ UINT64 Alignment;
+ D3D12_HEAP_FLAGS Flags;
+} D3D12_HEAP_DESC;
+typedef struct D3D12_TILED_RESOURCE_COORDINATE {
+ UINT X;
+ UINT Y;
+ UINT Z;
+ UINT Subresource;
+} D3D12_TILED_RESOURCE_COORDINATE;
+typedef struct D3D12_TILE_REGION_SIZE {
+ UINT NumTiles;
+ BOOL UseBox;
+ UINT Width;
+ UINT16 Height;
+ UINT16 Depth;
+} D3D12_TILE_REGION_SIZE;
+typedef struct D3D12_SUBRESOURCE_TILING {
+ UINT WidthInTiles;
+ UINT16 HeightInTiles;
+ UINT16 DepthInTiles;
+ UINT StartTileIndexInOverallResource;
+} D3D12_SUBRESOURCE_TILING;
+typedef struct D3D12_TILE_SHAPE {
+ UINT WidthInTexels;
+ UINT HeightInTexels;
+ UINT DepthInTexels;
+} D3D12_TILE_SHAPE;
+typedef struct D3D12_SHADER_BYTECODE {
+ const void *pShaderBytecode;
+ SIZE_T BytecodeLength;
+} D3D12_SHADER_BYTECODE;
+typedef struct D3D12_DEPTH_STENCIL_VALUE {
+ FLOAT Depth;
+ UINT8 Stencil;
+} D3D12_DEPTH_STENCIL_VALUE;
+typedef struct D3D12_CLEAR_VALUE {
+ DXGI_FORMAT Format;
+ __C89_NAMELESS union {
+ FLOAT Color[4];
+ D3D12_DEPTH_STENCIL_VALUE DepthStencil;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_CLEAR_VALUE;
+typedef struct D3D12_PACKED_MIP_INFO {
+ UINT8 NumStandardMips;
+ UINT8 NumPackedMips;
+ UINT NumTilesForPackedMips;
+ UINT StartTileIndexInOverallResource;
+} D3D12_PACKED_MIP_INFO;
+typedef enum D3D12_RESOURCE_STATES {
+ D3D12_RESOURCE_STATE_COMMON = 0,
+ D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER = 0x1,
+ D3D12_RESOURCE_STATE_INDEX_BUFFER = 0x2,
+ D3D12_RESOURCE_STATE_RENDER_TARGET = 0x4,
+ D3D12_RESOURCE_STATE_UNORDERED_ACCESS = 0x8,
+ D3D12_RESOURCE_STATE_DEPTH_WRITE = 0x10,
+ D3D12_RESOURCE_STATE_DEPTH_READ = 0x20,
+ D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE = 0x40,
+ D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE = 0x80,
+ D3D12_RESOURCE_STATE_STREAM_OUT = 0x100,
+ D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT = 0x200,
+ D3D12_RESOURCE_STATE_COPY_DEST = 0x400,
+ D3D12_RESOURCE_STATE_COPY_SOURCE = 0x800,
+ D3D12_RESOURCE_STATE_RESOLVE_DEST = 0x1000,
+ D3D12_RESOURCE_STATE_RESOLVE_SOURCE = 0x2000,
+ D3D12_RESOURCE_STATE_GENERIC_READ = ((((0x1 | 0x2) | 0x40) | 0x80) | 0x200) | 0x800,
+ D3D12_RESOURCE_STATE_PRESENT = 0x0,
+ D3D12_RESOURCE_STATE_PREDICATION = 0x200
+} D3D12_RESOURCE_STATES;
+DEFINE_ENUM_FLAG_OPERATORS(D3D12_RESOURCE_STATES);
+typedef enum D3D12_RESOURCE_BARRIER_TYPE {
+ D3D12_RESOURCE_BARRIER_TYPE_TRANSITION = 0,
+ D3D12_RESOURCE_BARRIER_TYPE_ALIASING = 1,
+ D3D12_RESOURCE_BARRIER_TYPE_UAV = 2
+} D3D12_RESOURCE_BARRIER_TYPE;
+typedef enum D3D12_RESOURCE_BARRIER_FLAGS {
+ D3D12_RESOURCE_BARRIER_FLAG_NONE = 0x0,
+ D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY = 0x1,
+ D3D12_RESOURCE_BARRIER_FLAG_END_ONLY = 0x2
+} D3D12_RESOURCE_BARRIER_FLAGS;
+typedef struct D3D12_RESOURCE_TRANSITION_BARRIER {
+ ID3D12Resource *pResource;
+ UINT Subresource;
+ D3D12_RESOURCE_STATES StateBefore;
+ D3D12_RESOURCE_STATES StateAfter;
+} D3D12_RESOURCE_TRANSITION_BARRIER;
+typedef struct D3D12_RESOURCE_ALIASING_BARRIER_ALIASING {
+ ID3D12Resource *pResourceBefore;
+ ID3D12Resource *pResourceAfter;
+} D3D12_RESOURCE_ALIASING_BARRIER;
+typedef struct D3D12_RESOURCE_UAV_BARRIER {
+ ID3D12Resource *pResource;
+} D3D12_RESOURCE_UAV_BARRIER;
+typedef struct D3D12_RESOURCE_BARRIER {
+ D3D12_RESOURCE_BARRIER_TYPE Type;
+ D3D12_RESOURCE_BARRIER_FLAGS Flags;
+ __C89_NAMELESS union {
+ D3D12_RESOURCE_TRANSITION_BARRIER Transition;
+ D3D12_RESOURCE_ALIASING_BARRIER Aliasing;
+ D3D12_RESOURCE_UAV_BARRIER UAV;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_RESOURCE_BARRIER;
+typedef enum D3D12_RESOURCE_DIMENSION {
+ D3D12_RESOURCE_DIMENSION_UNKNOWN = 0,
+ D3D12_RESOURCE_DIMENSION_BUFFER = 1,
+ D3D12_RESOURCE_DIMENSION_TEXTURE1D = 2,
+ D3D12_RESOURCE_DIMENSION_TEXTURE2D = 3,
+ D3D12_RESOURCE_DIMENSION_TEXTURE3D = 4
+} D3D12_RESOURCE_DIMENSION;
+typedef enum D3D12_TEXTURE_LAYOUT {
+ D3D12_TEXTURE_LAYOUT_UNKNOWN = 0,
+ D3D12_TEXTURE_LAYOUT_ROW_MAJOR = 1,
+ D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE = 2,
+ D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE = 3
+} D3D12_TEXTURE_LAYOUT;
+typedef enum D3D12_RESOURCE_FLAGS {
+ D3D12_RESOURCE_FLAG_NONE = 0x0,
+ D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET = 0x1,
+ D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL = 0x2,
+ D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS = 0x4,
+ D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE = 0x8,
+ D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER = 0x10,
+ D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS = 0x20
+} D3D12_RESOURCE_FLAGS;
+DEFINE_ENUM_FLAG_OPERATORS(D3D12_RESOURCE_FLAGS);
+typedef struct D3D12_RESOURCE_DESC {
+ D3D12_RESOURCE_DIMENSION Dimension;
+ UINT64 Alignment;
+ UINT64 Width;
+ UINT Height;
+ UINT16 DepthOrArraySize;
+ UINT16 MipLevels;
+ DXGI_FORMAT Format;
+ DXGI_SAMPLE_DESC SampleDesc;
+ D3D12_TEXTURE_LAYOUT Layout;
+ D3D12_RESOURCE_FLAGS Flags;
+} D3D12_RESOURCE_DESC;
+typedef enum D3D12_RESOLVE_MODE {
+ D3D12_RESOLVE_MODE_DECOMPRESS = 0,
+ D3D12_RESOLVE_MODE_MIN = 1,
+ D3D12_RESOLVE_MODE_MAX = 2,
+ D3D12_RESOLVE_MODE_AVERAGE = 3
+} D3D12_RESOLVE_MODE;
+typedef struct D3D12_SAMPLE_POSITION {
+ INT8 X;
+ INT8 Y;
+} D3D12_SAMPLE_POSITION;
+typedef enum D3D12_TEXTURE_COPY_TYPE {
+ D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX = 0,
+ D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT = 1
+} D3D12_TEXTURE_COPY_TYPE;
+typedef struct D3D12_SUBRESOURCE_FOOTPRINT {
+ DXGI_FORMAT Format;
+ UINT Width;
+ UINT Height;
+ UINT Depth;
+ UINT RowPitch;
+} D3D12_SUBRESOURCE_FOOTPRINT;
+typedef struct D3D12_PLACED_SUBRESOURCE_FOOTPRINT {
+ UINT64 Offset;
+ D3D12_SUBRESOURCE_FOOTPRINT Footprint;
+} D3D12_PLACED_SUBRESOURCE_FOOTPRINT;
+typedef struct D3D12_TEXTURE_COPY_LOCATION {
+ ID3D12Resource *pResource;
+ D3D12_TEXTURE_COPY_TYPE Type;
+ __C89_NAMELESS union {
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT PlacedFootprint;
+ UINT SubresourceIndex;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_TEXTURE_COPY_LOCATION;
+typedef enum D3D12_DESCRIPTOR_RANGE_TYPE {
+ D3D12_DESCRIPTOR_RANGE_TYPE_SRV = 0,
+ D3D12_DESCRIPTOR_RANGE_TYPE_UAV = 1,
+ D3D12_DESCRIPTOR_RANGE_TYPE_CBV = 2,
+ D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER = 3
+} D3D12_DESCRIPTOR_RANGE_TYPE;
+typedef struct D3D12_DESCRIPTOR_RANGE {
+ D3D12_DESCRIPTOR_RANGE_TYPE RangeType;
+ UINT NumDescriptors;
+ UINT BaseShaderRegister;
+ UINT RegisterSpace;
+ UINT OffsetInDescriptorsFromTableStart;
+} D3D12_DESCRIPTOR_RANGE;
+typedef enum D3D12_DESCRIPTOR_RANGE_FLAGS {
+ D3D12_DESCRIPTOR_RANGE_FLAG_NONE = 0x0,
+ D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE = 0x1,
+ D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2,
+ D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
+ D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8
+} D3D12_DESCRIPTOR_RANGE_FLAGS;
+typedef struct D3D12_DESCRIPTOR_RANGE1 {
+ D3D12_DESCRIPTOR_RANGE_TYPE RangeType;
+ UINT NumDescriptors;
+ UINT BaseShaderRegister;
+ UINT RegisterSpace;
+ D3D12_DESCRIPTOR_RANGE_FLAGS Flags;
+ UINT OffsetInDescriptorsFromTableStart;
+} D3D12_DESCRIPTOR_RANGE1;
+typedef struct D3D12_ROOT_DESCRIPTOR_TABLE {
+ UINT NumDescriptorRanges;
+ const D3D12_DESCRIPTOR_RANGE *pDescriptorRanges;
+} D3D12_ROOT_DESCRIPTOR_TABLE;
+typedef struct D3D12_ROOT_DESCRIPTOR_TABLE1 {
+ UINT NumDescriptorRanges;
+ const D3D12_DESCRIPTOR_RANGE1 *pDescriptorRanges;
+} D3D12_ROOT_DESCRIPTOR_TABLE1;
+typedef struct D3D12_ROOT_CONSTANTS {
+ UINT ShaderRegister;
+ UINT RegisterSpace;
+ UINT Num32BitValues;
+} D3D12_ROOT_CONSTANTS;
+typedef struct D3D12_ROOT_DESCRIPTOR {
+ UINT ShaderRegister;
+ UINT RegisterSpace;
+} D3D12_ROOT_DESCRIPTOR;
+typedef enum D3D12_ROOT_DESCRIPTOR_FLAGS {
+ D3D12_ROOT_DESCRIPTOR_FLAG_NONE = 0x0,
+ D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE = 0x2,
+ D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
+ D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC = 0x8
+} D3D12_ROOT_DESCRIPTOR_FLAGS;
+typedef struct D3D12_ROOT_DESCRIPTOR1 {
+ UINT ShaderRegister;
+ UINT RegisterSpace;
+ D3D12_ROOT_DESCRIPTOR_FLAGS Flags;
+} D3D12_ROOT_DESCRIPTOR1;
+typedef enum D3D12_ROOT_PARAMETER_TYPE {
+ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE = 0,
+ D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS = 1,
+ D3D12_ROOT_PARAMETER_TYPE_CBV = 2,
+ D3D12_ROOT_PARAMETER_TYPE_SRV = 3,
+ D3D12_ROOT_PARAMETER_TYPE_UAV = 4
+} D3D12_ROOT_PARAMETER_TYPE;
+typedef enum D3D12_SHADER_VISIBILITY {
+ D3D12_SHADER_VISIBILITY_ALL = 0,
+ D3D12_SHADER_VISIBILITY_VERTEX = 1,
+ D3D12_SHADER_VISIBILITY_HULL = 2,
+ D3D12_SHADER_VISIBILITY_DOMAIN = 3,
+ D3D12_SHADER_VISIBILITY_GEOMETRY = 4,
+ D3D12_SHADER_VISIBILITY_PIXEL = 5
+} D3D12_SHADER_VISIBILITY;
+typedef struct D3D12_ROOT_PARAMETER {
+ D3D12_ROOT_PARAMETER_TYPE ParameterType;
+ __C89_NAMELESS union {
+ D3D12_ROOT_DESCRIPTOR_TABLE DescriptorTable;
+ D3D12_ROOT_CONSTANTS Constants;
+ D3D12_ROOT_DESCRIPTOR Descriptor;
+ } __C89_NAMELESSUNIONNAME;
+ D3D12_SHADER_VISIBILITY ShaderVisibility;
+} D3D12_ROOT_PARAMETER;
+typedef struct D3D12_ROOT_PARAMETER1 {
+ D3D12_ROOT_PARAMETER_TYPE ParameterType;
+ __C89_NAMELESS union {
+ D3D12_ROOT_DESCRIPTOR_TABLE1 DescriptorTable;
+ D3D12_ROOT_CONSTANTS Constants;
+ D3D12_ROOT_DESCRIPTOR1 Descriptor;
+ } __C89_NAMELESSUNIONNAME;
+ D3D12_SHADER_VISIBILITY ShaderVisibility;
+} D3D12_ROOT_PARAMETER1;
+typedef enum D3D12_STATIC_BORDER_COLOR {
+ D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK = 0,
+ D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK = 1,
+ D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE = 2
+} D3D12_STATIC_BORDER_COLOR;
+typedef enum D3D12_FILTER {
+ D3D12_FILTER_MIN_MAG_MIP_POINT = 0x0,
+ D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR = 0x1,
+ D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x4,
+ D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x5,
+ D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT = 0x10,
+ D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11,
+ D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14,
+ D3D12_FILTER_MIN_MAG_MIP_LINEAR = 0x15,
+ D3D12_FILTER_ANISOTROPIC = 0x55,
+ D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT = 0x80,
+ D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x81,
+ D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x84,
+ D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR = 0x85,
+ D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT = 0x90,
+ D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x91,
+ D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x94,
+ D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR = 0x95,
+ D3D12_FILTER_COMPARISON_ANISOTROPIC = 0xd5,
+ D3D12_FILTER_MINIMUM_MIN_MAG_MIP_POINT = 0x100,
+ D3D12_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x101,
+ D3D12_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x104,
+ D3D12_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR = 0x105,
+ D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT = 0x110,
+ D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x111,
+ D3D12_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x114,
+ D3D12_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR = 0x115,
+ D3D12_FILTER_MINIMUM_ANISOTROPIC = 0x155,
+ D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_POINT = 0x180,
+ D3D12_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x181,
+ D3D12_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x184,
+ D3D12_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR = 0x185,
+ D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT = 0x190,
+ D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x191,
+ D3D12_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x194,
+ D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR = 0x195,
+ D3D12_FILTER_MAXIMUM_ANISOTROPIC = 0x1d5
+} D3D12_FILTER;
+typedef enum D3D12_FILTER_TYPE {
+ D3D12_FILTER_TYPE_POINT = 0,
+ D3D12_FILTER_TYPE_LINEAR = 1
+} D3D12_FILTER_TYPE;
+#define D3D12_MIP_FILTER_SHIFT (0)
+
+#define D3D12_MAG_FILTER_SHIFT (2)
+
+#define D3D12_MIN_FILTER_SHIFT (4)
+
+#define D3D12_FILTER_TYPE_MASK (0x3)
+
+#define D3D12_ANISOTROPIC_FILTERING_BIT (0x40)
+
+typedef enum D3D12_FILTER_REDUCTION_TYPE {
+ D3D12_FILTER_REDUCTION_TYPE_STANDARD = 0,
+ D3D12_FILTER_REDUCTION_TYPE_COMPARISON = 1,
+ D3D12_FILTER_REDUCTION_TYPE_MINIMUM = 2,
+ D3D12_FILTER_REDUCTION_TYPE_MAXIMUM = 3
+} D3D12_FILTER_REDUCTION_TYPE;
+#define D3D12_FILTER_REDUCTION_TYPE_MASK (0x3)
+
+#define D3D12_FILTER_REDUCTION_TYPE_SHIFT (7)
+
+#define D3D12_DECODE_MAG_FILTER(filter) \
+ ((D3D12_FILTER_TYPE)(((filter) >> D3D12_MAG_FILTER_SHIFT) & D3D12_FILTER_TYPE_MASK))
+#define D3D12_DECODE_MIN_FILTER(filter) \
+ ((D3D12_FILTER_TYPE)(((filter) >> D3D12_MIN_FILTER_SHIFT) & D3D12_FILTER_TYPE_MASK))
+#define D3D12_DECODE_MIP_FILTER(filter) \
+ ((D3D12_FILTER_TYPE)(((filter) >> D3D12_MIP_FILTER_SHIFT) & D3D12_FILTER_TYPE_MASK))
+#define D3D12_DECODE_IS_ANISOTROPIC_FILTER(filter) \
+ (((filter) & D3D12_ANISOTROPIC_FILTERING_BIT) \
+ && (D3D12_DECODE_MIN_FILTER(filter) == D3D12_FILTER_TYPE_LINEAR) \
+ && (D3D12_DECODE_MAG_FILTER(filter) == D3D12_FILTER_TYPE_LINEAR) \
+ && (D3D12_DECODE_MIP_FILTER(filter) == D3D12_FILTER_TYPE_LINEAR))
+#define D3D12_DECODE_FILTER_REDUCTION(filter) \
+ ((D3D12_FILTER_REDUCTION_TYPE)(((filter) >> D3D12_FILTER_REDUCTION_TYPE_SHIFT) \
+ & D3D12_FILTER_REDUCTION_TYPE_MASK))
+#define D3D12_DECODE_IS_COMPARISON_FILTER(filter) \
+ (D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_COMPARISON)
+typedef enum D3D12_TEXTURE_ADDRESS_MODE {
+ D3D12_TEXTURE_ADDRESS_MODE_WRAP = 1,
+ D3D12_TEXTURE_ADDRESS_MODE_MIRROR = 2,
+ D3D12_TEXTURE_ADDRESS_MODE_CLAMP = 3,
+ D3D12_TEXTURE_ADDRESS_MODE_BORDER = 4,
+ D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE = 5
+} D3D12_TEXTURE_ADDRESS_MODE;
+typedef enum D3D12_COMPARISON_FUNC {
+ D3D12_COMPARISON_FUNC_NEVER = 1,
+ D3D12_COMPARISON_FUNC_LESS = 2,
+ D3D12_COMPARISON_FUNC_EQUAL = 3,
+ D3D12_COMPARISON_FUNC_LESS_EQUAL = 4,
+ D3D12_COMPARISON_FUNC_GREATER = 5,
+ D3D12_COMPARISON_FUNC_NOT_EQUAL = 6,
+ D3D12_COMPARISON_FUNC_GREATER_EQUAL = 7,
+ D3D12_COMPARISON_FUNC_ALWAYS = 8
+} D3D12_COMPARISON_FUNC;
+typedef struct D3D12_STATIC_SAMPLER_DESC {
+ D3D12_FILTER Filter;
+ D3D12_TEXTURE_ADDRESS_MODE AddressU;
+ D3D12_TEXTURE_ADDRESS_MODE AddressV;
+ D3D12_TEXTURE_ADDRESS_MODE AddressW;
+ FLOAT MipLODBias;
+ UINT MaxAnisotropy;
+ D3D12_COMPARISON_FUNC ComparisonFunc;
+ D3D12_STATIC_BORDER_COLOR BorderColor;
+ FLOAT MinLOD;
+ FLOAT MaxLOD;
+ UINT ShaderRegister;
+ UINT RegisterSpace;
+ D3D12_SHADER_VISIBILITY ShaderVisibility;
+} D3D12_STATIC_SAMPLER_DESC;
+typedef enum D3D12_ROOT_SIGNATURE_FLAGS {
+ D3D12_ROOT_SIGNATURE_FLAG_NONE = 0x0,
+ D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0x1,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS = 0x2,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS = 0x4,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS = 0x8,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS = 0x10,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20,
+ D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT = 0x40
+} D3D12_ROOT_SIGNATURE_FLAGS;
+typedef struct D3D12_ROOT_SIGNATURE_DESC {
+ UINT NumParameters;
+ const D3D12_ROOT_PARAMETER *pParameters;
+ UINT NumStaticSamplers;
+ const D3D12_STATIC_SAMPLER_DESC *pStaticSamplers;
+ D3D12_ROOT_SIGNATURE_FLAGS Flags;
+} D3D12_ROOT_SIGNATURE_DESC;
+typedef struct D3D12_ROOT_SIGNATURE_DESC1 {
+ UINT NumParameters;
+ const D3D12_ROOT_PARAMETER1 *pParameters;
+ UINT NumStaticSamplers;
+ const D3D12_STATIC_SAMPLER_DESC *pStaticSamplers;
+ D3D12_ROOT_SIGNATURE_FLAGS Flags;
+} D3D12_ROOT_SIGNATURE_DESC1;
+typedef enum D3D_ROOT_SIGNATURE_VERSION {
+ D3D_ROOT_SIGNATURE_VERSION_1 = 0x1,
+ D3D_ROOT_SIGNATURE_VERSION_1_0 = 0x1,
+ D3D_ROOT_SIGNATURE_VERSION_1_1 = 0x2
+} D3D_ROOT_SIGNATURE_VERSION;
+typedef struct D3D12_VERSIONED_ROOT_SIGNATURE_DESC {
+ D3D_ROOT_SIGNATURE_VERSION Version;
+ __C89_NAMELESS union {
+ D3D12_ROOT_SIGNATURE_DESC Desc_1_0;
+ D3D12_ROOT_SIGNATURE_DESC1 Desc_1_1;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_VERSIONED_ROOT_SIGNATURE_DESC;
+typedef enum D3D12_DESCRIPTOR_HEAP_TYPE {
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV = 0,
+ D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER = 1,
+ D3D12_DESCRIPTOR_HEAP_TYPE_RTV = 2,
+ D3D12_DESCRIPTOR_HEAP_TYPE_DSV = 3,
+ D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES = 4
+} D3D12_DESCRIPTOR_HEAP_TYPE;
+typedef enum D3D12_DESCRIPTOR_HEAP_FLAGS {
+ D3D12_DESCRIPTOR_HEAP_FLAG_NONE = 0x0,
+ D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE = 0x1
+} D3D12_DESCRIPTOR_HEAP_FLAGS;
+typedef struct D3D12_DESCRIPTOR_HEAP_DESC {
+ D3D12_DESCRIPTOR_HEAP_TYPE Type;
+ UINT NumDescriptors;
+ D3D12_DESCRIPTOR_HEAP_FLAGS Flags;
+ UINT NodeMask;
+} D3D12_DESCRIPTOR_HEAP_DESC;
+typedef UINT64 D3D12_GPU_VIRTUAL_ADDRESS;
+typedef struct D3D12_CONSTANT_BUFFER_VIEW_DESC {
+ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
+ UINT SizeInBytes;
+} D3D12_CONSTANT_BUFFER_VIEW_DESC;
+typedef enum D3D12_SRV_DIMENSION {
+ D3D12_SRV_DIMENSION_UNKNOWN = 0,
+ D3D12_SRV_DIMENSION_BUFFER = 1,
+ D3D12_SRV_DIMENSION_TEXTURE1D = 2,
+ D3D12_SRV_DIMENSION_TEXTURE1DARRAY = 3,
+ D3D12_SRV_DIMENSION_TEXTURE2D = 4,
+ D3D12_SRV_DIMENSION_TEXTURE2DARRAY = 5,
+ D3D12_SRV_DIMENSION_TEXTURE2DMS = 6,
+ D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY = 7,
+ D3D12_SRV_DIMENSION_TEXTURE3D = 8,
+ D3D12_SRV_DIMENSION_TEXTURECUBE = 9,
+ D3D12_SRV_DIMENSION_TEXTURECUBEARRAY = 10
+} D3D12_SRV_DIMENSION;
+typedef enum D3D12_BUFFER_SRV_FLAGS {
+ D3D12_BUFFER_SRV_FLAG_NONE = 0x0,
+ D3D12_BUFFER_SRV_FLAG_RAW = 0x1
+} D3D12_BUFFER_SRV_FLAGS;
+typedef enum D3D12_SHADER_COMPONENT_MAPPING {
+ D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0 = 0,
+ D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1 = 1,
+ D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2 = 2,
+ D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3 = 3,
+ D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0 = 4,
+ D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1 = 5
+} D3D12_SHADER_COMPONENT_MAPPING;
+#define D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(x, y, z, w) \
+ (((x) & D3D12_SHADER_COMPONENT_MAPPING_MASK) \
+ | (((y) & D3D12_SHADER_COMPONENT_MAPPING_MASK) << D3D12_SHADER_COMPONENT_MAPPING_SHIFT) \
+ | (((z) & D3D12_SHADER_COMPONENT_MAPPING_MASK) << (D3D12_SHADER_COMPONENT_MAPPING_SHIFT * 2)) \
+ | (((w) & D3D12_SHADER_COMPONENT_MAPPING_MASK) << (D3D12_SHADER_COMPONENT_MAPPING_SHIFT * 3)) \
+ | D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES)
+#define D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(0, 1, 2, 3)
+#define D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(i, mapping) \
+ ((D3D12_SHADER_COMPONENT_MAPPING)(mapping >> (i * D3D12_SHADER_COMPONENT_MAPPING_SHIFT) \
+ & D3D12_SHADER_COMPONENT_MAPPING_MASK))
+typedef struct D3D12_BUFFER_SRV {
+ UINT64 FirstElement;
+ UINT NumElements;
+ UINT StructureByteStride;
+ D3D12_BUFFER_SRV_FLAGS Flags;
+} D3D12_BUFFER_SRV;
+typedef struct D3D12_TEX1D_SRV {
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX1D_SRV;
+typedef struct D3D12_TEX1D_ARRAY_SRV {
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX1D_ARRAY_SRV;
+typedef struct D3D12_TEX2D_SRV {
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ UINT PlaneSlice;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX2D_SRV;
+typedef struct D3D12_TEX2D_ARRAY_SRV {
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+ UINT PlaneSlice;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX2D_ARRAY_SRV;
+typedef struct D3D12_TEX2DMS_SRV {
+ UINT UnusedField_NothingToDefine;
+} D3D12_TEX2DMS_SRV;
+typedef struct D3D12_TEX2DMS_ARRAY_SRV {
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX2DMS_ARRAY_SRV;
+typedef struct D3D12_TEX3D_SRV {
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX3D_SRV;
+typedef struct D3D12_TEXCUBE_SRV {
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEXCUBE_SRV;
+typedef struct D3D12_TEXCUBE_ARRAY_SRV {
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ UINT First2DArrayFace;
+ UINT NumCubes;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEXCUBE_ARRAY_SRV;
+typedef struct D3D12_SHADER_RESOURCE_VIEW_DESC {
+ DXGI_FORMAT Format;
+ D3D12_SRV_DIMENSION ViewDimension;
+ UINT Shader4ComponentMapping;
+ __C89_NAMELESS union {
+ D3D12_BUFFER_SRV Buffer;
+ D3D12_TEX1D_SRV Texture1D;
+ D3D12_TEX1D_ARRAY_SRV Texture1DArray;
+ D3D12_TEX2D_SRV Texture2D;
+ D3D12_TEX2D_ARRAY_SRV Texture2DArray;
+ D3D12_TEX2DMS_SRV Texture2DMS;
+ D3D12_TEX2DMS_ARRAY_SRV Texture2DMSArray;
+ D3D12_TEX3D_SRV Texture3D;
+ D3D12_TEXCUBE_SRV TextureCube;
+ D3D12_TEXCUBE_ARRAY_SRV TextureCubeArray;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_SHADER_RESOURCE_VIEW_DESC;
+typedef enum D3D12_UAV_DIMENSION {
+ D3D12_UAV_DIMENSION_UNKNOWN = 0,
+ D3D12_UAV_DIMENSION_BUFFER = 1,
+ D3D12_UAV_DIMENSION_TEXTURE1D = 2,
+ D3D12_UAV_DIMENSION_TEXTURE1DARRAY = 3,
+ D3D12_UAV_DIMENSION_TEXTURE2D = 4,
+ D3D12_UAV_DIMENSION_TEXTURE2DARRAY = 5,
+ D3D12_UAV_DIMENSION_TEXTURE3D = 8
+} D3D12_UAV_DIMENSION;
+typedef enum D3D12_BUFFER_UAV_FLAGS {
+ D3D12_BUFFER_UAV_FLAG_NONE = 0x0,
+ D3D12_BUFFER_UAV_FLAG_RAW = 0x1
+} D3D12_BUFFER_UAV_FLAGS;
+typedef struct D3D12_BUFFER_UAV {
+ UINT64 FirstElement;
+ UINT NumElements;
+ UINT StructureByteStride;
+ UINT64 CounterOffsetInBytes;
+ D3D12_BUFFER_UAV_FLAGS Flags;
+} D3D12_BUFFER_UAV;
+typedef struct D3D12_TEX1D_UAV {
+ UINT MipSlice;
+} D3D12_TEX1D_UAV;
+typedef struct D3D12_TEX1D_ARRAY_UAV {
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX1D_ARRAY_UAV;
+typedef struct D3D12_TEX2D_UAV {
+ UINT MipSlice;
+ UINT PlaneSlice;
+} D3D12_TEX2D_UAV;
+typedef struct D3D12_TEX2D_ARRAY_UAV {
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+ UINT PlaneSlice;
+} D3D12_TEX2D_ARRAY_UAV;
+typedef struct D3D12_TEX3D_UAV {
+ UINT MipSlice;
+ UINT FirstWSlice;
+ UINT WSize;
+} D3D12_TEX3D_UAV;
+typedef struct D3D12_UNORDERED_ACCESS_VIEW_DESC {
+ DXGI_FORMAT Format;
+ D3D12_UAV_DIMENSION ViewDimension;
+ __C89_NAMELESS union {
+ D3D12_BUFFER_UAV Buffer;
+ D3D12_TEX1D_UAV Texture1D;
+ D3D12_TEX1D_ARRAY_UAV Texture1DArray;
+ D3D12_TEX2D_UAV Texture2D;
+ D3D12_TEX2D_ARRAY_UAV Texture2DArray;
+ D3D12_TEX3D_UAV Texture3D;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_UNORDERED_ACCESS_VIEW_DESC;
+typedef enum D3D12_RTV_DIMENSION {
+ D3D12_RTV_DIMENSION_UNKNOWN = 0,
+ D3D12_RTV_DIMENSION_BUFFER = 1,
+ D3D12_RTV_DIMENSION_TEXTURE1D = 2,
+ D3D12_RTV_DIMENSION_TEXTURE1DARRAY = 3,
+ D3D12_RTV_DIMENSION_TEXTURE2D = 4,
+ D3D12_RTV_DIMENSION_TEXTURE2DARRAY = 5,
+ D3D12_RTV_DIMENSION_TEXTURE2DMS = 6,
+ D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY = 7,
+ D3D12_RTV_DIMENSION_TEXTURE3D = 8
+} D3D12_RTV_DIMENSION;
+typedef struct D3D12_BUFFER_RTV {
+ UINT64 FirstElement;
+ UINT NumElements;
+} D3D12_BUFFER_RTV;
+typedef struct D3D12_TEX1D_RTV {
+ UINT MipSlice;
+} D3D12_TEX1D_RTV;
+typedef struct D3D12_TEX1D_ARRAY_RTV {
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX1D_ARRAY_RTV;
+typedef struct D3D12_TEX2D_RTV {
+ UINT MipSlice;
+ UINT PlaneSlice;
+} D3D12_TEX2D_RTV;
+typedef struct D3D12_TEX2D_ARRAY_RTV {
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+ UINT PlaneSlice;
+} D3D12_TEX2D_ARRAY_RTV;
+typedef struct D3D12_TEX2DMS_RTV {
+ UINT UnusedField_NothingToDefine;
+} D3D12_TEX2DMS_RTV;
+typedef struct D3D12_TEX2DMS_ARRAY_RTV {
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX2DMS_ARRAY_RTV;
+typedef struct D3D12_TEX3D_RTV {
+ UINT MipSlice;
+ UINT FirstWSlice;
+ UINT WSize;
+} D3D12_TEX3D_RTV;
+typedef struct D3D12_RENDER_TARGET_VIEW_DESC {
+ DXGI_FORMAT Format;
+ D3D12_RTV_DIMENSION ViewDimension;
+ __C89_NAMELESS union {
+ D3D12_BUFFER_RTV Buffer;
+ D3D12_TEX1D_RTV Texture1D;
+ D3D12_TEX1D_ARRAY_RTV Texture1DArray;
+ D3D12_TEX2D_RTV Texture2D;
+ D3D12_TEX2D_ARRAY_RTV Texture2DArray;
+ D3D12_TEX2DMS_RTV Texture2DMS;
+ D3D12_TEX2DMS_ARRAY_RTV Texture2DMSArray;
+ D3D12_TEX3D_RTV Texture3D;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_RENDER_TARGET_VIEW_DESC;
+typedef enum D3D12_DSV_DIMENSION {
+ D3D12_DSV_DIMENSION_UNKNOWN = 0,
+ D3D12_DSV_DIMENSION_TEXTURE1D = 1,
+ D3D12_DSV_DIMENSION_TEXTURE1DARRAY = 2,
+ D3D12_DSV_DIMENSION_TEXTURE2D = 3,
+ D3D12_DSV_DIMENSION_TEXTURE2DARRAY = 4,
+ D3D12_DSV_DIMENSION_TEXTURE2DMS = 5,
+ D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY = 6
+} D3D12_DSV_DIMENSION;
+typedef enum D3D12_DSV_FLAGS {
+ D3D12_DSV_FLAG_NONE = 0x0,
+ D3D12_DSV_FLAG_READ_ONLY_DEPTH = 0x1,
+ D3D12_DSV_FLAG_READ_ONLY_STENCIL = 0x2
+} D3D12_DSV_FLAGS;
+DEFINE_ENUM_FLAG_OPERATORS(D3D12_DSV_FLAGS);
+typedef struct D3D12_TEX1D_DSV {
+ UINT MipSlice;
+} D3D12_TEX1D_DSV;
+typedef struct D3D12_TEX1D_ARRAY_DSV {
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX1D_ARRAY_DSV;
+typedef struct D3D12_TEX2D_DSV {
+ UINT MipSlice;
+} D3D12_TEX2D_DSV;
+typedef struct D3D12_TEX2D_ARRAY_DSV {
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX2D_ARRAY_DSV;
+typedef struct D3D12_TEX2DMS_DSV {
+ UINT UnusedField_NothingToDefine;
+} D3D12_TEX2DMS_DSV;
+typedef struct D3D12_TEX2DMS_ARRAY_DSV {
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX2DMS_ARRAY_DSV;
+typedef struct D3D12_DEPTH_STENCIL_VIEW_DESC {
+ DXGI_FORMAT Format;
+ D3D12_DSV_DIMENSION ViewDimension;
+ D3D12_DSV_FLAGS Flags;
+ __C89_NAMELESS union {
+ D3D12_TEX1D_DSV Texture1D;
+ D3D12_TEX1D_ARRAY_DSV Texture1DArray;
+ D3D12_TEX2D_DSV Texture2D;
+ D3D12_TEX2D_ARRAY_DSV Texture2DArray;
+ D3D12_TEX2DMS_DSV Texture2DMS;
+ D3D12_TEX2DMS_ARRAY_DSV Texture2DMSArray;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_DEPTH_STENCIL_VIEW_DESC;
+typedef struct D3D12_SAMPLER_DESC {
+ D3D12_FILTER Filter;
+ D3D12_TEXTURE_ADDRESS_MODE AddressU;
+ D3D12_TEXTURE_ADDRESS_MODE AddressV;
+ D3D12_TEXTURE_ADDRESS_MODE AddressW;
+ FLOAT MipLODBias;
+ UINT MaxAnisotropy;
+ D3D12_COMPARISON_FUNC ComparisonFunc;
+ FLOAT BorderColor[4];
+ FLOAT MinLOD;
+ FLOAT MaxLOD;
+} D3D12_SAMPLER_DESC;
+typedef struct D3D12_CPU_DESCRIPTOR_HANDLE {
+ SIZE_T ptr;
+} D3D12_CPU_DESCRIPTOR_HANDLE;
+typedef struct D3D12_GPU_DESCRIPTOR_HANDLE {
+ UINT64 ptr;
+} D3D12_GPU_DESCRIPTOR_HANDLE;
+typedef enum D3D12_STENCIL_OP {
+ D3D12_STENCIL_OP_KEEP = 1,
+ D3D12_STENCIL_OP_ZERO = 2,
+ D3D12_STENCIL_OP_REPLACE = 3,
+ D3D12_STENCIL_OP_INCR_SAT = 4,
+ D3D12_STENCIL_OP_DECR_SAT = 5,
+ D3D12_STENCIL_OP_INVERT = 6,
+ D3D12_STENCIL_OP_INCR = 7,
+ D3D12_STENCIL_OP_DECR = 8
+} D3D12_STENCIL_OP;
+typedef struct D3D12_DEPTH_STENCILOP_DESC {
+ D3D12_STENCIL_OP StencilFailOp;
+ D3D12_STENCIL_OP StencilDepthFailOp;
+ D3D12_STENCIL_OP StencilPassOp;
+ D3D12_COMPARISON_FUNC StencilFunc;
+} D3D12_DEPTH_STENCILOP_DESC;
+typedef enum D3D12_DEPTH_WRITE_MASK {
+ D3D12_DEPTH_WRITE_MASK_ZERO = 0,
+ D3D12_DEPTH_WRITE_MASK_ALL = 1
+} D3D12_DEPTH_WRITE_MASK;
+typedef struct D3D12_DEPTH_STENCIL_DESC {
+ BOOL DepthEnable;
+ D3D12_DEPTH_WRITE_MASK DepthWriteMask;
+ D3D12_COMPARISON_FUNC DepthFunc;
+ BOOL StencilEnable;
+ UINT8 StencilReadMask;
+ UINT8 StencilWriteMask;
+ D3D12_DEPTH_STENCILOP_DESC FrontFace;
+ D3D12_DEPTH_STENCILOP_DESC BackFace;
+} D3D12_DEPTH_STENCIL_DESC;
+typedef enum D3D12_BLEND {
+ D3D12_BLEND_ZERO = 1,
+ D3D12_BLEND_ONE = 2,
+ D3D12_BLEND_SRC_COLOR = 3,
+ D3D12_BLEND_INV_SRC_COLOR = 4,
+ D3D12_BLEND_SRC_ALPHA = 5,
+ D3D12_BLEND_INV_SRC_ALPHA = 6,
+ D3D12_BLEND_DEST_ALPHA = 7,
+ D3D12_BLEND_INV_DEST_ALPHA = 8,
+ D3D12_BLEND_DEST_COLOR = 9,
+ D3D12_BLEND_INV_DEST_COLOR = 10,
+ D3D12_BLEND_SRC_ALPHA_SAT = 11,
+ D3D12_BLEND_BLEND_FACTOR = 14,
+ D3D12_BLEND_INV_BLEND_FACTOR = 15,
+ D3D12_BLEND_SRC1_COLOR = 16,
+ D3D12_BLEND_INV_SRC1_COLOR = 17,
+ D3D12_BLEND_SRC1_ALPHA = 18,
+ D3D12_BLEND_INV_SRC1_ALPHA = 19
+} D3D12_BLEND;
+typedef enum D3D12_BLEND_OP {
+ D3D12_BLEND_OP_ADD = 1,
+ D3D12_BLEND_OP_SUBTRACT = 2,
+ D3D12_BLEND_OP_REV_SUBTRACT = 3,
+ D3D12_BLEND_OP_MIN = 4,
+ D3D12_BLEND_OP_MAX = 5
+} D3D12_BLEND_OP;
+typedef enum D3D12_LOGIC_OP {
+ D3D12_LOGIC_OP_CLEAR = 0,
+ D3D12_LOGIC_OP_SET = 1,
+ D3D12_LOGIC_OP_COPY = 2,
+ D3D12_LOGIC_OP_COPY_INVERTED = 3,
+ D3D12_LOGIC_OP_NOOP = 4
+} D3D12_LOGIC_OP;
+typedef enum D3D12_COLOR_WRITE_ENABLE {
+ D3D12_COLOR_WRITE_ENABLE_RED = 0x1,
+ D3D12_COLOR_WRITE_ENABLE_GREEN = 0x2,
+ D3D12_COLOR_WRITE_ENABLE_BLUE = 0x4,
+ D3D12_COLOR_WRITE_ENABLE_ALPHA = 0x8,
+ D3D12_COLOR_WRITE_ENABLE_ALL = ((D3D12_COLOR_WRITE_ENABLE_RED | D3D12_COLOR_WRITE_ENABLE_GREEN) | D3D12_COLOR_WRITE_ENABLE_BLUE) | D3D12_COLOR_WRITE_ENABLE_ALPHA
+} D3D12_COLOR_WRITE_ENABLE;
+typedef struct D3D12_RENDER_TARGET_BLEND_DESC {
+ BOOL BlendEnable;
+ BOOL LogicOpEnable;
+ D3D12_BLEND SrcBlend;
+ D3D12_BLEND DestBlend;
+ D3D12_BLEND_OP BlendOp;
+ D3D12_BLEND SrcBlendAlpha;
+ D3D12_BLEND DestBlendAlpha;
+ D3D12_BLEND_OP BlendOpAlpha;
+ D3D12_LOGIC_OP LogicOp;
+ UINT8 RenderTargetWriteMask;
+} D3D12_RENDER_TARGET_BLEND_DESC;
+typedef struct D3D12_BLEND_DESC {
+ BOOL AlphaToCoverageEnable;
+ BOOL IndependentBlendEnable;
+ D3D12_RENDER_TARGET_BLEND_DESC RenderTarget[8];
+} D3D12_BLEND_DESC;
+typedef enum D3D12_FILL_MODE {
+ D3D12_FILL_MODE_WIREFRAME = 2,
+ D3D12_FILL_MODE_SOLID = 3
+} D3D12_FILL_MODE;
+typedef enum D3D12_CULL_MODE {
+ D3D12_CULL_MODE_NONE = 1,
+ D3D12_CULL_MODE_FRONT = 2,
+ D3D12_CULL_MODE_BACK = 3
+} D3D12_CULL_MODE;
+typedef enum D3D12_CONSERVATIVE_RASTERIZATION_MODE {
+ D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF = 0,
+ D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON = 1
+} D3D12_CONSERVATIVE_RASTERIZATION_MODE;
+typedef struct D3D12_RASTERIZER_DESC {
+ D3D12_FILL_MODE FillMode;
+ D3D12_CULL_MODE CullMode;
+ BOOL FrontCounterClockwise;
+ INT DepthBias;
+ FLOAT DepthBiasClamp;
+ FLOAT SlopeScaledDepthBias;
+ BOOL DepthClipEnable;
+ BOOL MultisampleEnable;
+ BOOL AntialiasedLineEnable;
+ UINT ForcedSampleCount;
+ D3D12_CONSERVATIVE_RASTERIZATION_MODE ConservativeRaster;
+} D3D12_RASTERIZER_DESC;
+typedef struct D3D12_SO_DECLARATION_ENTRY {
+ UINT Stream;
+ const char *SemanticName;
+ UINT SemanticIndex;
+ BYTE StartComponent;
+ BYTE ComponentCount;
+ BYTE OutputSlot;
+} D3D12_SO_DECLARATION_ENTRY;
+typedef struct D3D12_STREAM_OUTPUT_DESC {
+ const D3D12_SO_DECLARATION_ENTRY *pSODeclaration;
+ UINT NumEntries;
+ const UINT *pBufferStrides;
+ UINT NumStrides;
+ UINT RasterizedStream;
+} D3D12_STREAM_OUTPUT_DESC;
+typedef enum D3D12_INPUT_CLASSIFICATION {
+ D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA = 0,
+ D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA = 1
+} D3D12_INPUT_CLASSIFICATION;
+typedef struct D3D12_INPUT_ELEMENT_DESC {
+ const char *SemanticName;
+ UINT SemanticIndex;
+ DXGI_FORMAT Format;
+ UINT InputSlot;
+ UINT AlignedByteOffset;
+ D3D12_INPUT_CLASSIFICATION InputSlotClass;
+ UINT InstanceDataStepRate;
+} D3D12_INPUT_ELEMENT_DESC;
+typedef struct D3D12_INPUT_LAYOUT_DESC {
+ const D3D12_INPUT_ELEMENT_DESC *pInputElementDescs;
+ UINT NumElements;
+} D3D12_INPUT_LAYOUT_DESC;
+typedef enum D3D12_INDEX_BUFFER_STRIP_CUT_VALUE {
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED = 0,
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF = 1,
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF = 2
+} D3D12_INDEX_BUFFER_STRIP_CUT_VALUE;
+typedef D3D_PRIMITIVE_TOPOLOGY D3D12_PRIMITIVE_TOPOLOGY;
+typedef enum D3D12_PRIMITIVE_TOPOLOGY_TYPE {
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED = 0,
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT = 1,
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE = 2,
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE = 3,
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH = 4
+} D3D12_PRIMITIVE_TOPOLOGY_TYPE;
+typedef struct D3D12_CACHED_PIPELINE_STATE {
+ const void *pCachedBlob;
+ SIZE_T CachedBlobSizeInBytes;
+} D3D12_CACHED_PIPELINE_STATE;
+typedef enum D3D12_PIPELINE_STATE_FLAGS {
+ D3D12_PIPELINE_STATE_FLAG_NONE = 0x0,
+ D3D12_PIPELINE_STATE_FLAG_DEBUG = 0x1
+} D3D12_PIPELINE_STATE_FLAGS;
+typedef struct D3D12_GRAPHICS_PIPELINE_STATE_DESC {
+ ID3D12RootSignature *pRootSignature;
+ D3D12_SHADER_BYTECODE VS;
+ D3D12_SHADER_BYTECODE PS;
+ D3D12_SHADER_BYTECODE DS;
+ D3D12_SHADER_BYTECODE HS;
+ D3D12_SHADER_BYTECODE GS;
+ D3D12_STREAM_OUTPUT_DESC StreamOutput;
+ D3D12_BLEND_DESC BlendState;
+ UINT SampleMask;
+ D3D12_RASTERIZER_DESC RasterizerState;
+ D3D12_DEPTH_STENCIL_DESC DepthStencilState;
+ D3D12_INPUT_LAYOUT_DESC InputLayout;
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue;
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;
+ UINT NumRenderTargets;
+ DXGI_FORMAT RTVFormats[8];
+ DXGI_FORMAT DSVFormat;
+ DXGI_SAMPLE_DESC SampleDesc;
+ UINT NodeMask;
+ D3D12_CACHED_PIPELINE_STATE CachedPSO;
+ D3D12_PIPELINE_STATE_FLAGS Flags;
+} D3D12_GRAPHICS_PIPELINE_STATE_DESC;
+typedef struct D3D12_COMPUTE_PIPELINE_STATE_DESC {
+ ID3D12RootSignature *pRootSignature;
+ D3D12_SHADER_BYTECODE CS;
+ UINT NodeMask;
+ D3D12_CACHED_PIPELINE_STATE CachedPSO;
+ D3D12_PIPELINE_STATE_FLAGS Flags;
+} D3D12_COMPUTE_PIPELINE_STATE_DESC;
+typedef enum D3D12_COMMAND_LIST_TYPE {
+ D3D12_COMMAND_LIST_TYPE_DIRECT = 0,
+ D3D12_COMMAND_LIST_TYPE_BUNDLE = 1,
+ D3D12_COMMAND_LIST_TYPE_COMPUTE = 2,
+ D3D12_COMMAND_LIST_TYPE_COPY = 3
+} D3D12_COMMAND_LIST_TYPE;
+typedef enum D3D12_COMMAND_QUEUE_PRIORITY {
+ D3D12_COMMAND_QUEUE_PRIORITY_NORMAL = 0,
+ D3D12_COMMAND_QUEUE_PRIORITY_HIGH = 100,
+ D3D12_COMMAND_QUEUE_PRIORITY_GLOBAL_REALTIME = 10000
+} D3D12_COMMAND_QUEUE_PRIORITY;
+typedef enum D3D12_COMMAND_QUEUE_FLAGS {
+ D3D12_COMMAND_QUEUE_FLAG_NONE = 0x0,
+ D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT = 0x1
+} D3D12_COMMAND_QUEUE_FLAGS;
+typedef struct D3D12_COMMAND_QUEUE_DESC {
+ D3D12_COMMAND_LIST_TYPE Type;
+ INT Priority;
+ D3D12_COMMAND_QUEUE_FLAGS Flags;
+ UINT NodeMask;
+} D3D12_COMMAND_QUEUE_DESC;
+typedef struct D3D12_FEATURE_DATA_ARCHITECTURE {
+ UINT NodeIndex;
+ BOOL TileBasedRenderer;
+ BOOL UMA;
+ BOOL CacheCoherentUMA;
+} D3D12_FEATURE_DATA_ARCHITECTURE;
+typedef struct D3D12_FEATURE_DATA_FORMAT_INFO {
+ DXGI_FORMAT Format;
+ UINT8 PlaneCount;
+} D3D12_FEATURE_DATA_FORMAT_INFO;
+typedef struct D3D12_FEATURE_DATA_FEATURE_LEVELS {
+ UINT NumFeatureLevels;
+ const D3D_FEATURE_LEVEL *pFeatureLevelsRequested;
+ D3D_FEATURE_LEVEL MaxSupportedFeatureLevel;
+} D3D12_FEATURE_DATA_FEATURE_LEVELS;
+typedef struct D3D12_FEATURE_DATA_ROOT_SIGNATURE {
+ D3D_ROOT_SIGNATURE_VERSION HighestVersion;
+} D3D12_FEATURE_DATA_ROOT_SIGNATURE;
+typedef struct D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT {
+ UINT MaxGPUVirtualAddressBitsPerResource;
+ UINT MaxGPUVirtualAddressBitsPerProcess;
+} D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT;
+typedef enum D3D_SHADER_MODEL {
+ D3D_SHADER_MODEL_5_1 = 0x51,
+ D3D_SHADER_MODEL_6_0 = 0x60
+} D3D_SHADER_MODEL;
+typedef struct D3D12_FEATURE_DATA_SHADER_MODEL {
+ D3D_SHADER_MODEL HighestShaderModel;
+} D3D12_FEATURE_DATA_SHADER_MODEL;
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS1 {
+ BOOL WaveOps;
+ UINT WaveLaneCountMin;
+ UINT WaveLaneCountMax;
+ UINT TotalLaneCount;
+ BOOL ExpandedComputeResourceStates;
+ BOOL Int64ShaderOps;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS1;
+typedef struct D3D12_FEATURE_DATA_ARCHITECTURE1 {
+ UINT NodeIndex;
+ BOOL TileBasedRenderer;
+ BOOL UMA;
+ BOOL CacheCoherentUMA;
+ BOOL IsolatedMMU;
+} D3D12_FEATURE_DATA_ARCHITECTURE1;
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS2 {
+ BOOL DepthBoundsTestSupported;
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER ProgrammableSamplePositionsTier;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS2;
+typedef struct D3D12_FEATURE_DATA_SHADER_CACHE {
+ D3D12_SHADER_CACHE_SUPPORT_FLAGS SupportFlags;
+} D3D12_FEATURE_DATA_SHADER_CACHE;
+typedef struct D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY {
+ D3D12_COMMAND_LIST_TYPE CommandListType;
+ UINT Priority;
+ BOOL PriorityForTypeIsSupported;
+} D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY;
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS3 {
+ BOOL CopyQueueTimestampQueriesSupported;
+ BOOL CastingFullyTypedFormatSupported;
+ D3D12_COMMAND_LIST_SUPPORT_FLAGS WriteBufferImmediateSupportFlags;
+ D3D12_VIEW_INSTANCING_TIER ViewInstancingTier;
+ BOOL BarycentricsSupported;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS3;
+typedef struct D3D12_FEATURE_DATA_EXISTING_HEAPS {
+ BOOL Supported;
+} D3D12_FEATURE_DATA_EXISTING_HEAPS;
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS4 {
+ BOOL MSAA64KBAlignedTextureSupported;
+ D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER SharedResourceCompatibilityTier;
+ BOOL Native16BitShaderOpsSupported;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS4;
+typedef struct D3D12_FEATURE_DATA_SERIALIZATION {
+ UINT NodeIndex;
+ D3D12_HEAP_SERIALIZATION_TIER HeapSerializationTier;
+} D3D12_FEATURE_DATA_SERIALIZATION;
+typedef struct D3D12_FEATURE_DATA_CROSS_NODE {
+ D3D12_CROSS_NODE_SHARING_TIER SharingTier;
+ BOOL AtomicShaderInstructions;
+} D3D12_FEATURE_DATA_CROSS_NODE;
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS5 {
+ BOOL SRVOnlyTiledResourceTier3;
+ D3D12_RENDER_PASS_TIER RenderPassesTier;
+ D3D12_RAYTRACING_TIER RaytracingTier;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS5;
+typedef enum D3D12_FEATURE {
+ D3D12_FEATURE_D3D12_OPTIONS = 0,
+ D3D12_FEATURE_ARCHITECTURE = 1,
+ D3D12_FEATURE_FEATURE_LEVELS = 2,
+ D3D12_FEATURE_FORMAT_SUPPORT = 3,
+ D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS = 4,
+ D3D12_FEATURE_FORMAT_INFO = 5,
+ D3D12_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT = 6,
+ D3D12_FEATURE_SHADER_MODEL = 7,
+ D3D12_FEATURE_D3D12_OPTIONS1 = 8,
+ D3D12_FEATURE_ROOT_SIGNATURE = 12,
+ D3D12_FEATURE_ARCHITECTURE1 = 16,
+ D3D12_FEATURE_D3D12_OPTIONS2 = 18,
+ D3D12_FEATURE_SHADER_CACHE = 19,
+ D3D12_FEATURE_COMMAND_QUEUE_PRIORITY = 20,
+ D3D12_FEATURE_D3D12_OPTIONS3 = 21,
+ D3D12_FEATURE_EXISTING_HEAPS = 22,
+ D3D12_FEATURE_D3D12_OPTIONS4 = 23,
+ D3D12_FEATURE_SERIALIZATION = 24,
+ D3D12_FEATURE_CROSS_NODE = 25,
+ D3D12_FEATURE_D3D12_OPTIONS5 = 27
+} D3D12_FEATURE;
+typedef struct D3D12_MEMCPY_DEST {
+ void *pData;
+ SIZE_T RowPitch;
+ SIZE_T SlicePitch;
+} D3D12_MEMCPY_DEST;
+typedef struct D3D12_SUBRESOURCE_DATA {
+ const void *pData;
+ LONG_PTR RowPitch;
+ LONG_PTR SlicePitch;
+} D3D12_SUBRESOURCE_DATA;
+typedef enum D3D12_MULTIPLE_FENCE_WAIT_FLAGS {
+ D3D12_MULTIPLE_FENCE_WAIT_FLAG_NONE = 0x0,
+ D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY = 0x1,
+ D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL = 0x0
+} D3D12_MULTIPLE_FENCE_WAIT_FLAGS;
+DEFINE_ENUM_FLAG_OPERATORS(D3D12_MULTIPLE_FENCE_WAIT_FLAGS);
+typedef enum D3D12_RESIDENCY_PRIORITY {
+ D3D12_RESIDENCY_PRIORITY_MINIMUM = 0x28000000,
+ D3D12_RESIDENCY_PRIORITY_LOW = 0x50000000,
+ D3D12_RESIDENCY_PRIORITY_NORMAL = 0x78000000,
+ D3D12_RESIDENCY_PRIORITY_HIGH = 0xa0010000,
+ D3D12_RESIDENCY_PRIORITY_MAXIMUM = 0xc8000000
+} D3D12_RESIDENCY_PRIORITY;
+typedef struct D3D12_WRITEBUFFERIMMEDIATE_PARAMETER {
+ D3D12_GPU_VIRTUAL_ADDRESS Dest;
+ UINT32 Value;
+} D3D12_WRITEBUFFERIMMEDIATE_PARAMETER;
+/*****************************************************************************
+ * ID3D12Object interface
+ */
+#ifndef __ID3D12Object_INTERFACE_DEFINED__
+#define __ID3D12Object_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Object, 0xc4fec28f, 0x7966, 0x4e95, 0x9f,0x94, 0xf4,0x31,0xcb,0x56,0xc3,0xb8);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("c4fec28f-7966-4e95-9f94-f431cb56c3b8")
+ID3D12Object : public IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE GetPrivateData(
+ REFGUID guid,
+ UINT *data_size,
+ void *data) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetPrivateData(
+ REFGUID guid,
+ UINT data_size,
+ const void *data) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
+ REFGUID guid,
+ const IUnknown *data) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetName(
+ const WCHAR *name) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Object, 0xc4fec28f, 0x7966, 0x4e95, 0x9f,0x94, 0xf4,0x31,0xcb,0x56,0xc3,0xb8)
+#endif
+#else
+typedef struct ID3D12ObjectVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Object *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Object *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Object *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12Object *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12Object *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12Object *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12Object *This,
+ const WCHAR *name);
+
+ END_INTERFACE
+} ID3D12ObjectVtbl;
+
+interface ID3D12Object {
+ CONST_VTBL ID3D12ObjectVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Object_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Object_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Object_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12Object_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12Object_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12Object_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12Object_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Object_QueryInterface(ID3D12Object* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Object_AddRef(ID3D12Object* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Object_Release(ID3D12Object* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12Object_GetPrivateData(ID3D12Object* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Object_SetPrivateData(ID3D12Object* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Object_SetPrivateDataInterface(ID3D12Object* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12Object_SetName(ID3D12Object* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Object_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12DeviceChild interface
+ */
+#ifndef __ID3D12DeviceChild_INTERFACE_DEFINED__
+#define __ID3D12DeviceChild_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12DeviceChild, 0x905db94b, 0xa00c, 0x4140, 0x9d,0xf5, 0x2b,0x64,0xca,0x9e,0xa3,0x57);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("905db94b-a00c-4140-9df5-2b64ca9ea357")
+ID3D12DeviceChild : public ID3D12Object
+{
+ virtual HRESULT STDMETHODCALLTYPE GetDevice(
+ REFIID riid,
+ void **device) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12DeviceChild, 0x905db94b, 0xa00c, 0x4140, 0x9d,0xf5, 0x2b,0x64,0xca,0x9e,0xa3,0x57)
+#endif
+#else
+typedef struct ID3D12DeviceChildVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12DeviceChild *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12DeviceChild *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12DeviceChild *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12DeviceChild *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12DeviceChild *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12DeviceChild *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12DeviceChild *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12DeviceChild *This,
+ REFIID riid,
+ void **device);
+
+ END_INTERFACE
+} ID3D12DeviceChildVtbl;
+
+interface ID3D12DeviceChild {
+ CONST_VTBL ID3D12DeviceChildVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12DeviceChild_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12DeviceChild_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12DeviceChild_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12DeviceChild_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12DeviceChild_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12DeviceChild_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12DeviceChild_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12DeviceChild_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12DeviceChild_QueryInterface(ID3D12DeviceChild* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12DeviceChild_AddRef(ID3D12DeviceChild* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12DeviceChild_Release(ID3D12DeviceChild* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12DeviceChild_GetPrivateData(ID3D12DeviceChild* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12DeviceChild_SetPrivateData(ID3D12DeviceChild* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12DeviceChild_SetPrivateDataInterface(ID3D12DeviceChild* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12DeviceChild_SetName(ID3D12DeviceChild* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12DeviceChild_GetDevice(ID3D12DeviceChild* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12DeviceChild_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12Pageable interface
+ */
+#ifndef __ID3D12Pageable_INTERFACE_DEFINED__
+#define __ID3D12Pageable_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Pageable, 0x63ee58fb, 0x1268, 0x4835, 0x86,0xda, 0xf0,0x08,0xce,0x62,0xf0,0xd6);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("63ee58fb-1268-4835-86da-f008ce62f0d6")
+ID3D12Pageable : public ID3D12DeviceChild
+{
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Pageable, 0x63ee58fb, 0x1268, 0x4835, 0x86,0xda, 0xf0,0x08,0xce,0x62,0xf0,0xd6)
+#endif
+#else
+typedef struct ID3D12PageableVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Pageable *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Pageable *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Pageable *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12Pageable *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12Pageable *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12Pageable *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12Pageable *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12Pageable *This,
+ REFIID riid,
+ void **device);
+
+ END_INTERFACE
+} ID3D12PageableVtbl;
+
+interface ID3D12Pageable {
+ CONST_VTBL ID3D12PageableVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Pageable_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Pageable_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Pageable_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12Pageable_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12Pageable_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12Pageable_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12Pageable_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12Pageable_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Pageable_QueryInterface(ID3D12Pageable* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Pageable_AddRef(ID3D12Pageable* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Pageable_Release(ID3D12Pageable* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12Pageable_GetPrivateData(ID3D12Pageable* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Pageable_SetPrivateData(ID3D12Pageable* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Pageable_SetPrivateDataInterface(ID3D12Pageable* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12Pageable_SetName(ID3D12Pageable* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12Pageable_GetDevice(ID3D12Pageable* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Pageable_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12Heap interface
+ */
+#ifndef __ID3D12Heap_INTERFACE_DEFINED__
+#define __ID3D12Heap_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Heap, 0x6b3b2502, 0x6e51, 0x45b3, 0x90,0xee, 0x98,0x84,0x26,0x5e,0x8d,0xf3);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("6b3b2502-6e51-45b3-90ee-9884265e8df3")
+ID3D12Heap : public ID3D12Pageable
+{
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual D3D12_HEAP_DESC* STDMETHODCALLTYPE GetDesc(
+ D3D12_HEAP_DESC *__ret) = 0;
+ D3D12_HEAP_DESC STDMETHODCALLTYPE GetDesc(
+ )
+ {
+ D3D12_HEAP_DESC __ret;
+ return *GetDesc(&__ret);
+ }
+#else
+ virtual D3D12_HEAP_DESC STDMETHODCALLTYPE GetDesc(
+ ) = 0;
+#endif
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Heap, 0x6b3b2502, 0x6e51, 0x45b3, 0x90,0xee, 0x98,0x84,0x26,0x5e,0x8d,0xf3)
+#endif
+#else
+typedef struct ID3D12HeapVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Heap *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Heap *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Heap *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12Heap *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12Heap *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12Heap *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12Heap *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12Heap *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12Heap methods ***/
+ D3D12_HEAP_DESC * (STDMETHODCALLTYPE *GetDesc)(
+ ID3D12Heap *This,
+ D3D12_HEAP_DESC *__ret);
+
+ END_INTERFACE
+} ID3D12HeapVtbl;
+
+interface ID3D12Heap {
+ CONST_VTBL ID3D12HeapVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Heap_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Heap_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Heap_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12Heap_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12Heap_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12Heap_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12Heap_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12Heap_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12Heap methods ***/
+#define ID3D12Heap_GetDesc(This) ID3D12Heap_GetDesc_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Heap_QueryInterface(ID3D12Heap* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Heap_AddRef(ID3D12Heap* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Heap_Release(ID3D12Heap* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12Heap_GetPrivateData(ID3D12Heap* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Heap_SetPrivateData(ID3D12Heap* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Heap_SetPrivateDataInterface(ID3D12Heap* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12Heap_SetName(ID3D12Heap* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12Heap_GetDevice(ID3D12Heap* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12Heap methods ***/
+static FORCEINLINE D3D12_HEAP_DESC ID3D12Heap_GetDesc(ID3D12Heap* This) {
+ D3D12_HEAP_DESC __ret;
+ return *This->lpVtbl->GetDesc(This,&__ret);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Heap_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12Resource interface
+ */
+#ifndef __ID3D12Resource_INTERFACE_DEFINED__
+#define __ID3D12Resource_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Resource, 0x696442be, 0xa72e, 0x4059, 0xbc,0x79, 0x5b,0x5c,0x98,0x04,0x0f,0xad);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("696442be-a72e-4059-bc79-5b5c98040fad")
+ID3D12Resource : public ID3D12Pageable
+{
+ virtual HRESULT STDMETHODCALLTYPE Map(
+ UINT sub_resource,
+ const D3D12_RANGE *read_range,
+ void **data) = 0;
+
+ virtual void STDMETHODCALLTYPE Unmap(
+ UINT sub_resource,
+ const D3D12_RANGE *written_range) = 0;
+
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual D3D12_RESOURCE_DESC* STDMETHODCALLTYPE GetDesc(
+ D3D12_RESOURCE_DESC *__ret) = 0;
+ D3D12_RESOURCE_DESC STDMETHODCALLTYPE GetDesc(
+ )
+ {
+ D3D12_RESOURCE_DESC __ret;
+ return *GetDesc(&__ret);
+ }
+#else
+ virtual D3D12_RESOURCE_DESC STDMETHODCALLTYPE GetDesc(
+ ) = 0;
+#endif
+
+ virtual D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE GetGPUVirtualAddress(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteToSubresource(
+ UINT dst_sub_resource,
+ const D3D12_BOX *dst_box,
+ const void *src_data,
+ UINT src_row_pitch,
+ UINT src_slice_pitch) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ReadFromSubresource(
+ void *dst_data,
+ UINT dst_row_pitch,
+ UINT dst_slice_pitch,
+ UINT src_sub_resource,
+ const D3D12_BOX *src_box) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHeapProperties(
+ D3D12_HEAP_PROPERTIES *heap_properties,
+ D3D12_HEAP_FLAGS *flags) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Resource, 0x696442be, 0xa72e, 0x4059, 0xbc,0x79, 0x5b,0x5c,0x98,0x04,0x0f,0xad)
+#endif
+#else
+typedef struct ID3D12ResourceVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Resource *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Resource *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Resource *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12Resource *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12Resource *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12Resource *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12Resource *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12Resource *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12Resource methods ***/
+ HRESULT (STDMETHODCALLTYPE *Map)(
+ ID3D12Resource *This,
+ UINT sub_resource,
+ const D3D12_RANGE *read_range,
+ void **data);
+
+ void (STDMETHODCALLTYPE *Unmap)(
+ ID3D12Resource *This,
+ UINT sub_resource,
+ const D3D12_RANGE *written_range);
+
+ D3D12_RESOURCE_DESC * (STDMETHODCALLTYPE *GetDesc)(
+ ID3D12Resource *This,
+ D3D12_RESOURCE_DESC *__ret);
+
+ D3D12_GPU_VIRTUAL_ADDRESS (STDMETHODCALLTYPE *GetGPUVirtualAddress)(
+ ID3D12Resource *This);
+
+ HRESULT (STDMETHODCALLTYPE *WriteToSubresource)(
+ ID3D12Resource *This,
+ UINT dst_sub_resource,
+ const D3D12_BOX *dst_box,
+ const void *src_data,
+ UINT src_row_pitch,
+ UINT src_slice_pitch);
+
+ HRESULT (STDMETHODCALLTYPE *ReadFromSubresource)(
+ ID3D12Resource *This,
+ void *dst_data,
+ UINT dst_row_pitch,
+ UINT dst_slice_pitch,
+ UINT src_sub_resource,
+ const D3D12_BOX *src_box);
+
+ HRESULT (STDMETHODCALLTYPE *GetHeapProperties)(
+ ID3D12Resource *This,
+ D3D12_HEAP_PROPERTIES *heap_properties,
+ D3D12_HEAP_FLAGS *flags);
+
+ END_INTERFACE
+} ID3D12ResourceVtbl;
+
+interface ID3D12Resource {
+ CONST_VTBL ID3D12ResourceVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Resource_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Resource_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Resource_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12Resource_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12Resource_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12Resource_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12Resource_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12Resource_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12Resource methods ***/
+#define ID3D12Resource_Map(This,sub_resource,read_range,data) (This)->lpVtbl->Map(This,sub_resource,read_range,data)
+#define ID3D12Resource_Unmap(This,sub_resource,written_range) (This)->lpVtbl->Unmap(This,sub_resource,written_range)
+#define ID3D12Resource_GetDesc(This) ID3D12Resource_GetDesc_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#define ID3D12Resource_GetGPUVirtualAddress(This) (This)->lpVtbl->GetGPUVirtualAddress(This)
+#define ID3D12Resource_WriteToSubresource(This,dst_sub_resource,dst_box,src_data,src_row_pitch,src_slice_pitch) (This)->lpVtbl->WriteToSubresource(This,dst_sub_resource,dst_box,src_data,src_row_pitch,src_slice_pitch)
+#define ID3D12Resource_ReadFromSubresource(This,dst_data,dst_row_pitch,dst_slice_pitch,src_sub_resource,src_box) (This)->lpVtbl->ReadFromSubresource(This,dst_data,dst_row_pitch,dst_slice_pitch,src_sub_resource,src_box)
+#define ID3D12Resource_GetHeapProperties(This,heap_properties,flags) (This)->lpVtbl->GetHeapProperties(This,heap_properties,flags)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Resource_QueryInterface(ID3D12Resource* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Resource_AddRef(ID3D12Resource* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Resource_Release(ID3D12Resource* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12Resource_GetPrivateData(ID3D12Resource* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Resource_SetPrivateData(ID3D12Resource* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Resource_SetPrivateDataInterface(ID3D12Resource* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12Resource_SetName(ID3D12Resource* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12Resource_GetDevice(ID3D12Resource* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12Resource methods ***/
+static FORCEINLINE HRESULT ID3D12Resource_Map(ID3D12Resource* This,UINT sub_resource,const D3D12_RANGE *read_range,void **data) {
+ return This->lpVtbl->Map(This,sub_resource,read_range,data);
+}
+static FORCEINLINE void ID3D12Resource_Unmap(ID3D12Resource* This,UINT sub_resource,const D3D12_RANGE *written_range) {
+ This->lpVtbl->Unmap(This,sub_resource,written_range);
+}
+static FORCEINLINE D3D12_RESOURCE_DESC ID3D12Resource_GetDesc(ID3D12Resource* This) {
+ D3D12_RESOURCE_DESC __ret;
+ return *This->lpVtbl->GetDesc(This,&__ret);
+}
+static FORCEINLINE D3D12_GPU_VIRTUAL_ADDRESS ID3D12Resource_GetGPUVirtualAddress(ID3D12Resource* This) {
+ return This->lpVtbl->GetGPUVirtualAddress(This);
+}
+static FORCEINLINE HRESULT ID3D12Resource_WriteToSubresource(ID3D12Resource* This,UINT dst_sub_resource,const D3D12_BOX *dst_box,const void *src_data,UINT src_row_pitch,UINT src_slice_pitch) {
+ return This->lpVtbl->WriteToSubresource(This,dst_sub_resource,dst_box,src_data,src_row_pitch,src_slice_pitch);
+}
+static FORCEINLINE HRESULT ID3D12Resource_ReadFromSubresource(ID3D12Resource* This,void *dst_data,UINT dst_row_pitch,UINT dst_slice_pitch,UINT src_sub_resource,const D3D12_BOX *src_box) {
+ return This->lpVtbl->ReadFromSubresource(This,dst_data,dst_row_pitch,dst_slice_pitch,src_sub_resource,src_box);
+}
+static FORCEINLINE HRESULT ID3D12Resource_GetHeapProperties(ID3D12Resource* This,D3D12_HEAP_PROPERTIES *heap_properties,D3D12_HEAP_FLAGS *flags) {
+ return This->lpVtbl->GetHeapProperties(This,heap_properties,flags);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Resource_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12CommandList interface
+ */
+#ifndef __ID3D12CommandList_INTERFACE_DEFINED__
+#define __ID3D12CommandList_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12CommandList, 0x7116d91c, 0xe7e4, 0x47ce, 0xb8,0xc6, 0xec,0x81,0x68,0xf4,0x37,0xe5);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("7116d91c-e7e4-47ce-b8c6-ec8168f437e5")
+ID3D12CommandList : public ID3D12DeviceChild
+{
+ virtual D3D12_COMMAND_LIST_TYPE STDMETHODCALLTYPE GetType(
+ ) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12CommandList, 0x7116d91c, 0xe7e4, 0x47ce, 0xb8,0xc6, 0xec,0x81,0x68,0xf4,0x37,0xe5)
+#endif
+#else
+typedef struct ID3D12CommandListVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12CommandList *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12CommandList *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12CommandList *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12CommandList *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12CommandList *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12CommandList *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12CommandList *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12CommandList *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12CommandList methods ***/
+ D3D12_COMMAND_LIST_TYPE (STDMETHODCALLTYPE *GetType)(
+ ID3D12CommandList *This);
+
+ END_INTERFACE
+} ID3D12CommandListVtbl;
+
+interface ID3D12CommandList {
+ CONST_VTBL ID3D12CommandListVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12CommandList_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12CommandList_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12CommandList_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12CommandList_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12CommandList_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12CommandList_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12CommandList_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12CommandList_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12CommandList methods ***/
+#define ID3D12CommandList_GetType(This) (This)->lpVtbl->GetType(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12CommandList_QueryInterface(ID3D12CommandList* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12CommandList_AddRef(ID3D12CommandList* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12CommandList_Release(ID3D12CommandList* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12CommandList_GetPrivateData(ID3D12CommandList* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandList_SetPrivateData(ID3D12CommandList* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandList_SetPrivateDataInterface(ID3D12CommandList* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandList_SetName(ID3D12CommandList* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12CommandList_GetDevice(ID3D12CommandList* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12CommandList methods ***/
+static FORCEINLINE D3D12_COMMAND_LIST_TYPE ID3D12CommandList_GetType(ID3D12CommandList* This) {
+ return This->lpVtbl->GetType(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12CommandList_INTERFACE_DEFINED__ */
+
+typedef enum D3D12_TILE_COPY_FLAGS {
+ D3D12_TILE_COPY_FLAG_NONE = 0x0,
+ D3D12_TILE_COPY_FLAG_NO_HAZARD = 0x1,
+ D3D12_TILE_COPY_FLAG_LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE = 0x2,
+ D3D12_TILE_COPY_FLAG_SWIZZLED_TILED_RESOURCE_TO_LINEAR_BUFFER = 0x4
+} D3D12_TILE_COPY_FLAGS;
+typedef struct D3D12_INDEX_BUFFER_VIEW {
+ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
+ UINT SizeInBytes;
+ DXGI_FORMAT Format;
+} D3D12_INDEX_BUFFER_VIEW;
+typedef struct D3D12_VERTEX_BUFFER_VIEW {
+ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
+ UINT SizeInBytes;
+ UINT StrideInBytes;
+} D3D12_VERTEX_BUFFER_VIEW;
+typedef struct D3D12_STREAM_OUTPUT_BUFFER_VIEW {
+ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
+ UINT64 SizeInBytes;
+ D3D12_GPU_VIRTUAL_ADDRESS BufferFilledSizeLocation;
+} D3D12_STREAM_OUTPUT_BUFFER_VIEW;
+typedef enum D3D12_CLEAR_FLAGS {
+ D3D12_CLEAR_FLAG_DEPTH = 0x1,
+ D3D12_CLEAR_FLAG_STENCIL = 0x2
+} D3D12_CLEAR_FLAGS;
+DEFINE_ENUM_FLAG_OPERATORS(D3D12_CLEAR_FLAGS);
+typedef struct D3D12_DISCARD_REGION {
+ UINT NumRects;
+ const D3D12_RECT *pRects;
+ UINT FirstSubresource;
+ UINT NumSubresources;
+} D3D12_DISCARD_REGION;
+typedef enum D3D12_QUERY_TYPE {
+ D3D12_QUERY_TYPE_OCCLUSION = 0,
+ D3D12_QUERY_TYPE_BINARY_OCCLUSION = 1,
+ D3D12_QUERY_TYPE_TIMESTAMP = 2,
+ D3D12_QUERY_TYPE_PIPELINE_STATISTICS = 3,
+ D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 = 4,
+ D3D12_QUERY_TYPE_SO_STATISTICS_STREAM1 = 5,
+ D3D12_QUERY_TYPE_SO_STATISTICS_STREAM2 = 6,
+ D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3 = 7
+} D3D12_QUERY_TYPE;
+typedef struct D3D12_QUERY_DATA_PIPELINE_STATISTICS {
+ UINT64 IAVertices;
+ UINT64 IAPrimitives;
+ UINT64 VSInvocations;
+ UINT64 GSInvocations;
+ UINT64 GSPrimitives;
+ UINT64 CInvocations;
+ UINT64 CPrimitives;
+ UINT64 PSInvocations;
+ UINT64 HSInvocations;
+ UINT64 DSInvocations;
+ UINT64 CSInvocations;
+} D3D12_QUERY_DATA_PIPELINE_STATISTICS;
+typedef struct D3D12_QUERY_DATA_SO_STATISTICS {
+ UINT64 NumPrimitivesWritten;
+ UINT64 PrimitivesStorageNeeded;
+} D3D12_QUERY_DATA_SO_STATISTICS;
+typedef enum D3D12_PREDICATION_OP {
+ D3D12_PREDICATION_OP_EQUAL_ZERO = 0,
+ D3D12_PREDICATION_OP_NOT_EQUAL_ZERO = 1
+} D3D12_PREDICATION_OP;
+/*****************************************************************************
+ * ID3D12DescriptorHeap interface
+ */
+#ifndef __ID3D12DescriptorHeap_INTERFACE_DEFINED__
+#define __ID3D12DescriptorHeap_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12DescriptorHeap, 0x8efb471d, 0x616c, 0x4f49, 0x90,0xf7, 0x12,0x7b,0xb7,0x63,0xfa,0x51);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("8efb471d-616c-4f49-90f7-127bb763fa51")
+ID3D12DescriptorHeap : public ID3D12Pageable
+{
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual D3D12_DESCRIPTOR_HEAP_DESC* STDMETHODCALLTYPE GetDesc(
+ D3D12_DESCRIPTOR_HEAP_DESC *__ret) = 0;
+ D3D12_DESCRIPTOR_HEAP_DESC STDMETHODCALLTYPE GetDesc(
+ )
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC __ret;
+ return *GetDesc(&__ret);
+ }
+#else
+ virtual D3D12_DESCRIPTOR_HEAP_DESC STDMETHODCALLTYPE GetDesc(
+ ) = 0;
+#endif
+
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE* STDMETHODCALLTYPE GetCPUDescriptorHandleForHeapStart(
+ D3D12_CPU_DESCRIPTOR_HANDLE *__ret) = 0;
+ D3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetCPUDescriptorHandleForHeapStart(
+ )
+ {
+ D3D12_CPU_DESCRIPTOR_HANDLE __ret;
+ return *GetCPUDescriptorHandleForHeapStart(&__ret);
+ }
+#else
+ virtual D3D12_CPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetCPUDescriptorHandleForHeapStart(
+ ) = 0;
+#endif
+
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual D3D12_GPU_DESCRIPTOR_HANDLE* STDMETHODCALLTYPE GetGPUDescriptorHandleForHeapStart(
+ D3D12_GPU_DESCRIPTOR_HANDLE *__ret) = 0;
+ D3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetGPUDescriptorHandleForHeapStart(
+ )
+ {
+ D3D12_GPU_DESCRIPTOR_HANDLE __ret;
+ return *GetGPUDescriptorHandleForHeapStart(&__ret);
+ }
+#else
+ virtual D3D12_GPU_DESCRIPTOR_HANDLE STDMETHODCALLTYPE GetGPUDescriptorHandleForHeapStart(
+ ) = 0;
+#endif
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12DescriptorHeap, 0x8efb471d, 0x616c, 0x4f49, 0x90,0xf7, 0x12,0x7b,0xb7,0x63,0xfa,0x51)
+#endif
+#else
+typedef struct ID3D12DescriptorHeapVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12DescriptorHeap *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12DescriptorHeap *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12DescriptorHeap *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12DescriptorHeap *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12DescriptorHeap *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12DescriptorHeap *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12DescriptorHeap *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12DescriptorHeap *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12DescriptorHeap methods ***/
+ D3D12_DESCRIPTOR_HEAP_DESC * (STDMETHODCALLTYPE *GetDesc)(
+ ID3D12DescriptorHeap *This,
+ D3D12_DESCRIPTOR_HEAP_DESC *__ret);
+
+ D3D12_CPU_DESCRIPTOR_HANDLE * (STDMETHODCALLTYPE *GetCPUDescriptorHandleForHeapStart)(
+ ID3D12DescriptorHeap *This,
+ D3D12_CPU_DESCRIPTOR_HANDLE *__ret);
+
+ D3D12_GPU_DESCRIPTOR_HANDLE * (STDMETHODCALLTYPE *GetGPUDescriptorHandleForHeapStart)(
+ ID3D12DescriptorHeap *This,
+ D3D12_GPU_DESCRIPTOR_HANDLE *__ret);
+
+ END_INTERFACE
+} ID3D12DescriptorHeapVtbl;
+
+interface ID3D12DescriptorHeap {
+ CONST_VTBL ID3D12DescriptorHeapVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12DescriptorHeap_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12DescriptorHeap_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12DescriptorHeap_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12DescriptorHeap_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12DescriptorHeap_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12DescriptorHeap_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12DescriptorHeap_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12DescriptorHeap_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12DescriptorHeap methods ***/
+#define ID3D12DescriptorHeap_GetDesc(This) ID3D12DescriptorHeap_GetDesc_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#define ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(This) ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#define ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(This) ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12DescriptorHeap_QueryInterface(ID3D12DescriptorHeap* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12DescriptorHeap_AddRef(ID3D12DescriptorHeap* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12DescriptorHeap_Release(ID3D12DescriptorHeap* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12DescriptorHeap_GetPrivateData(ID3D12DescriptorHeap* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12DescriptorHeap_SetPrivateData(ID3D12DescriptorHeap* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12DescriptorHeap_SetPrivateDataInterface(ID3D12DescriptorHeap* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12DescriptorHeap_SetName(ID3D12DescriptorHeap* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12DescriptorHeap_GetDevice(ID3D12DescriptorHeap* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12DescriptorHeap methods ***/
+static FORCEINLINE D3D12_DESCRIPTOR_HEAP_DESC ID3D12DescriptorHeap_GetDesc(ID3D12DescriptorHeap* This) {
+ D3D12_DESCRIPTOR_HEAP_DESC __ret;
+ return *This->lpVtbl->GetDesc(This,&__ret);
+}
+static FORCEINLINE D3D12_CPU_DESCRIPTOR_HANDLE ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap* This) {
+ D3D12_CPU_DESCRIPTOR_HANDLE __ret;
+ return *This->lpVtbl->GetCPUDescriptorHandleForHeapStart(This,&__ret);
+}
+static FORCEINLINE D3D12_GPU_DESCRIPTOR_HANDLE ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap* This) {
+ D3D12_GPU_DESCRIPTOR_HANDLE __ret;
+ return *This->lpVtbl->GetGPUDescriptorHandleForHeapStart(This,&__ret);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12DescriptorHeap_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12QueryHeap interface
+ */
+#ifndef __ID3D12QueryHeap_INTERFACE_DEFINED__
+#define __ID3D12QueryHeap_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12QueryHeap, 0x0d9658ae, 0xed45, 0x469e, 0xa6,0x1d, 0x97,0x0e,0xc5,0x83,0xca,0xb4);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("0d9658ae-ed45-469e-a61d-970ec583cab4")
+ID3D12QueryHeap : public ID3D12Pageable
+{
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12QueryHeap, 0x0d9658ae, 0xed45, 0x469e, 0xa6,0x1d, 0x97,0x0e,0xc5,0x83,0xca,0xb4)
+#endif
+#else
+typedef struct ID3D12QueryHeapVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12QueryHeap *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12QueryHeap *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12QueryHeap *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12QueryHeap *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12QueryHeap *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12QueryHeap *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12QueryHeap *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12QueryHeap *This,
+ REFIID riid,
+ void **device);
+
+ END_INTERFACE
+} ID3D12QueryHeapVtbl;
+
+interface ID3D12QueryHeap {
+ CONST_VTBL ID3D12QueryHeapVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12QueryHeap_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12QueryHeap_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12QueryHeap_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12QueryHeap_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12QueryHeap_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12QueryHeap_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12QueryHeap_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12QueryHeap_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12QueryHeap_QueryInterface(ID3D12QueryHeap* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12QueryHeap_AddRef(ID3D12QueryHeap* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12QueryHeap_Release(ID3D12QueryHeap* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12QueryHeap_GetPrivateData(ID3D12QueryHeap* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12QueryHeap_SetPrivateData(ID3D12QueryHeap* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12QueryHeap_SetPrivateDataInterface(ID3D12QueryHeap* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12QueryHeap_SetName(ID3D12QueryHeap* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12QueryHeap_GetDevice(ID3D12QueryHeap* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12QueryHeap_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12CommandSignature interface
+ */
+#ifndef __ID3D12CommandSignature_INTERFACE_DEFINED__
+#define __ID3D12CommandSignature_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12CommandSignature, 0xc36a797c, 0xec80, 0x4f0a, 0x89,0x85, 0xa7,0xb2,0x47,0x50,0x82,0xd1);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("c36a797c-ec80-4f0a-8985-a7b2475082d1")
+ID3D12CommandSignature : public ID3D12Pageable
+{
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12CommandSignature, 0xc36a797c, 0xec80, 0x4f0a, 0x89,0x85, 0xa7,0xb2,0x47,0x50,0x82,0xd1)
+#endif
+#else
+typedef struct ID3D12CommandSignatureVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12CommandSignature *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12CommandSignature *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12CommandSignature *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12CommandSignature *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12CommandSignature *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12CommandSignature *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12CommandSignature *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12CommandSignature *This,
+ REFIID riid,
+ void **device);
+
+ END_INTERFACE
+} ID3D12CommandSignatureVtbl;
+
+interface ID3D12CommandSignature {
+ CONST_VTBL ID3D12CommandSignatureVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12CommandSignature_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12CommandSignature_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12CommandSignature_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12CommandSignature_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12CommandSignature_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12CommandSignature_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12CommandSignature_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12CommandSignature_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12CommandSignature_QueryInterface(ID3D12CommandSignature* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12CommandSignature_AddRef(ID3D12CommandSignature* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12CommandSignature_Release(ID3D12CommandSignature* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12CommandSignature_GetPrivateData(ID3D12CommandSignature* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandSignature_SetPrivateData(ID3D12CommandSignature* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandSignature_SetPrivateDataInterface(ID3D12CommandSignature* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandSignature_SetName(ID3D12CommandSignature* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12CommandSignature_GetDevice(ID3D12CommandSignature* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12CommandSignature_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12GraphicsCommandList interface
+ */
+#ifndef __ID3D12GraphicsCommandList_INTERFACE_DEFINED__
+#define __ID3D12GraphicsCommandList_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12GraphicsCommandList, 0x5b160d0f, 0xac1b, 0x4185, 0x8b,0xa8, 0xb3,0xae,0x42,0xa5,0xa4,0x55);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("5b160d0f-ac1b-4185-8ba8-b3ae42a5a455")
+ID3D12GraphicsCommandList : public ID3D12CommandList
+{
+ virtual HRESULT STDMETHODCALLTYPE Close(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Reset(
+ ID3D12CommandAllocator *allocator,
+ ID3D12PipelineState *initial_state) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ClearState(
+ ID3D12PipelineState *pipeline_state) = 0;
+
+ virtual void STDMETHODCALLTYPE DrawInstanced(
+ UINT vertex_count_per_instance,
+ UINT instance_count,
+ UINT start_vertex_location,
+ UINT start_instance_location) = 0;
+
+ virtual void STDMETHODCALLTYPE DrawIndexedInstanced(
+ UINT index_count_per_instance,
+ UINT instance_count,
+ UINT start_vertex_location,
+ INT base_vertex_location,
+ UINT start_instance_location) = 0;
+
+ virtual void STDMETHODCALLTYPE Dispatch(
+ UINT x,
+ UINT u,
+ UINT z) = 0;
+
+ virtual void STDMETHODCALLTYPE CopyBufferRegion(
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT64 byte_count) = 0;
+
+ virtual void STDMETHODCALLTYPE CopyTextureRegion(
+ const D3D12_TEXTURE_COPY_LOCATION *dst,
+ UINT dst_x,
+ UINT dst_y,
+ UINT dst_z,
+ const D3D12_TEXTURE_COPY_LOCATION *src,
+ const D3D12_BOX *src_box) = 0;
+
+ virtual void STDMETHODCALLTYPE CopyResource(
+ ID3D12Resource *dst_resource,
+ ID3D12Resource *src_resource) = 0;
+
+ virtual void STDMETHODCALLTYPE CopyTiles(
+ ID3D12Resource *tiled_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *tile_region_size,
+ ID3D12Resource *buffer,
+ UINT64 buffer_offset,
+ D3D12_TILE_COPY_FLAGS flags) = 0;
+
+ virtual void STDMETHODCALLTYPE ResolveSubresource(
+ ID3D12Resource *dst_resource,
+ UINT dst_sub_resource,
+ ID3D12Resource *src_resource,
+ UINT src_sub_resource,
+ DXGI_FORMAT format) = 0;
+
+ virtual void STDMETHODCALLTYPE IASetPrimitiveTopology(
+ D3D12_PRIMITIVE_TOPOLOGY primitive_topology) = 0;
+
+ virtual void STDMETHODCALLTYPE RSSetViewports(
+ UINT viewport_count,
+ const D3D12_VIEWPORT *viewports) = 0;
+
+ virtual void STDMETHODCALLTYPE RSSetScissorRects(
+ UINT rect_count,
+ const D3D12_RECT *rects) = 0;
+
+ virtual void STDMETHODCALLTYPE OMSetBlendFactor(
+ const FLOAT blend_factor[4]) = 0;
+
+ virtual void STDMETHODCALLTYPE OMSetStencilRef(
+ UINT stencil_ref) = 0;
+
+ virtual void STDMETHODCALLTYPE SetPipelineState(
+ ID3D12PipelineState *pipeline_state) = 0;
+
+ virtual void STDMETHODCALLTYPE ResourceBarrier(
+ UINT barrier_count,
+ const D3D12_RESOURCE_BARRIER *barriers) = 0;
+
+ virtual void STDMETHODCALLTYPE ExecuteBundle(
+ ID3D12GraphicsCommandList *command_list) = 0;
+
+ virtual void STDMETHODCALLTYPE SetDescriptorHeaps(
+ UINT heap_count,
+ ID3D12DescriptorHeap *const *heaps) = 0;
+
+ virtual void STDMETHODCALLTYPE SetComputeRootSignature(
+ ID3D12RootSignature *root_signature) = 0;
+
+ virtual void STDMETHODCALLTYPE SetGraphicsRootSignature(
+ ID3D12RootSignature *root_signature) = 0;
+
+ virtual void STDMETHODCALLTYPE SetComputeRootDescriptorTable(
+ UINT root_parameter_index,
+ D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE SetGraphicsRootDescriptorTable(
+ UINT root_parameter_index,
+ D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE SetComputeRoot32BitConstant(
+ UINT root_parameter_index,
+ UINT data,
+ UINT dst_offset) = 0;
+
+ virtual void STDMETHODCALLTYPE SetGraphicsRoot32BitConstant(
+ UINT root_parameter_index,
+ UINT data,
+ UINT dst_offset) = 0;
+
+ virtual void STDMETHODCALLTYPE SetComputeRoot32BitConstants(
+ UINT root_parameter_index,
+ UINT constant_count,
+ const void *data,
+ UINT dst_offset) = 0;
+
+ virtual void STDMETHODCALLTYPE SetGraphicsRoot32BitConstants(
+ UINT root_parameter_index,
+ UINT constant_count,
+ const void *data,
+ UINT dst_offset) = 0;
+
+ virtual void STDMETHODCALLTYPE SetComputeRootConstantBufferView(
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address) = 0;
+
+ virtual void STDMETHODCALLTYPE SetGraphicsRootConstantBufferView(
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address) = 0;
+
+ virtual void STDMETHODCALLTYPE SetComputeRootShaderResourceView(
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address) = 0;
+
+ virtual void STDMETHODCALLTYPE SetGraphicsRootShaderResourceView(
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address) = 0;
+
+ virtual void STDMETHODCALLTYPE SetComputeRootUnorderedAccessView(
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address) = 0;
+
+ virtual void STDMETHODCALLTYPE SetGraphicsRootUnorderedAccessView(
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address) = 0;
+
+ virtual void STDMETHODCALLTYPE IASetIndexBuffer(
+ const D3D12_INDEX_BUFFER_VIEW *view) = 0;
+
+ virtual void STDMETHODCALLTYPE IASetVertexBuffers(
+ UINT start_slot,
+ UINT view_count,
+ const D3D12_VERTEX_BUFFER_VIEW *views) = 0;
+
+ virtual void STDMETHODCALLTYPE SOSetTargets(
+ UINT start_slot,
+ UINT view_count,
+ const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views) = 0;
+
+ virtual void STDMETHODCALLTYPE OMSetRenderTargets(
+ UINT render_target_descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,
+ BOOL single_descriptor_handle,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE ClearDepthStencilView(
+ D3D12_CPU_DESCRIPTOR_HANDLE dsv,
+ D3D12_CLEAR_FLAGS flags,
+ FLOAT depth,
+ UINT8 stencil,
+ UINT rect_count,
+ const D3D12_RECT *rects) = 0;
+
+ virtual void STDMETHODCALLTYPE ClearRenderTargetView(
+ D3D12_CPU_DESCRIPTOR_HANDLE rtv,
+ const FLOAT color[4],
+ UINT rect_count,
+ const D3D12_RECT *rects) = 0;
+
+ virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewUint(
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,
+ ID3D12Resource *resource,
+ const UINT values[4],
+ UINT rect_count,
+ const D3D12_RECT *rects) = 0;
+
+ virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat(
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,
+ ID3D12Resource *resource,
+ const float values[4],
+ UINT rect_count,
+ const D3D12_RECT *rects) = 0;
+
+ virtual void STDMETHODCALLTYPE DiscardResource(
+ ID3D12Resource *resource,
+ const D3D12_DISCARD_REGION *region) = 0;
+
+ virtual void STDMETHODCALLTYPE BeginQuery(
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT index) = 0;
+
+ virtual void STDMETHODCALLTYPE EndQuery(
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT index) = 0;
+
+ virtual void STDMETHODCALLTYPE ResolveQueryData(
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT start_index,
+ UINT query_count,
+ ID3D12Resource *dst_buffer,
+ UINT64 aligned_dst_buffer_offset) = 0;
+
+ virtual void STDMETHODCALLTYPE SetPredication(
+ ID3D12Resource *buffer,
+ UINT64 aligned_buffer_offset,
+ D3D12_PREDICATION_OP operation) = 0;
+
+ virtual void STDMETHODCALLTYPE SetMarker(
+ UINT metadata,
+ const void *data,
+ UINT size) = 0;
+
+ virtual void STDMETHODCALLTYPE BeginEvent(
+ UINT metadata,
+ const void *data,
+ UINT size) = 0;
+
+ virtual void STDMETHODCALLTYPE EndEvent(
+ ) = 0;
+
+ virtual void STDMETHODCALLTYPE ExecuteIndirect(
+ ID3D12CommandSignature *command_signature,
+ UINT max_command_count,
+ ID3D12Resource *arg_buffer,
+ UINT64 arg_buffer_offset,
+ ID3D12Resource *count_buffer,
+ UINT64 count_buffer_offset) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12GraphicsCommandList, 0x5b160d0f, 0xac1b, 0x4185, 0x8b,0xa8, 0xb3,0xae,0x42,0xa5,0xa4,0x55)
+#endif
+#else
+typedef struct ID3D12GraphicsCommandListVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12GraphicsCommandList *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12GraphicsCommandList *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12GraphicsCommandList *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12GraphicsCommandList *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12GraphicsCommandList *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12GraphicsCommandList *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12GraphicsCommandList *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12GraphicsCommandList *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12CommandList methods ***/
+ D3D12_COMMAND_LIST_TYPE (STDMETHODCALLTYPE *GetType)(
+ ID3D12GraphicsCommandList *This);
+
+ /*** ID3D12GraphicsCommandList methods ***/
+ HRESULT (STDMETHODCALLTYPE *Close)(
+ ID3D12GraphicsCommandList *This);
+
+ HRESULT (STDMETHODCALLTYPE *Reset)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12CommandAllocator *allocator,
+ ID3D12PipelineState *initial_state);
+
+ HRESULT (STDMETHODCALLTYPE *ClearState)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12PipelineState *pipeline_state);
+
+ void (STDMETHODCALLTYPE *DrawInstanced)(
+ ID3D12GraphicsCommandList *This,
+ UINT vertex_count_per_instance,
+ UINT instance_count,
+ UINT start_vertex_location,
+ UINT start_instance_location);
+
+ void (STDMETHODCALLTYPE *DrawIndexedInstanced)(
+ ID3D12GraphicsCommandList *This,
+ UINT index_count_per_instance,
+ UINT instance_count,
+ UINT start_vertex_location,
+ INT base_vertex_location,
+ UINT start_instance_location);
+
+ void (STDMETHODCALLTYPE *Dispatch)(
+ ID3D12GraphicsCommandList *This,
+ UINT x,
+ UINT u,
+ UINT z);
+
+ void (STDMETHODCALLTYPE *CopyBufferRegion)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT64 byte_count);
+
+ void (STDMETHODCALLTYPE *CopyTextureRegion)(
+ ID3D12GraphicsCommandList *This,
+ const D3D12_TEXTURE_COPY_LOCATION *dst,
+ UINT dst_x,
+ UINT dst_y,
+ UINT dst_z,
+ const D3D12_TEXTURE_COPY_LOCATION *src,
+ const D3D12_BOX *src_box);
+
+ void (STDMETHODCALLTYPE *CopyResource)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12Resource *dst_resource,
+ ID3D12Resource *src_resource);
+
+ void (STDMETHODCALLTYPE *CopyTiles)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12Resource *tiled_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *tile_region_size,
+ ID3D12Resource *buffer,
+ UINT64 buffer_offset,
+ D3D12_TILE_COPY_FLAGS flags);
+
+ void (STDMETHODCALLTYPE *ResolveSubresource)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12Resource *dst_resource,
+ UINT dst_sub_resource,
+ ID3D12Resource *src_resource,
+ UINT src_sub_resource,
+ DXGI_FORMAT format);
+
+ void (STDMETHODCALLTYPE *IASetPrimitiveTopology)(
+ ID3D12GraphicsCommandList *This,
+ D3D12_PRIMITIVE_TOPOLOGY primitive_topology);
+
+ void (STDMETHODCALLTYPE *RSSetViewports)(
+ ID3D12GraphicsCommandList *This,
+ UINT viewport_count,
+ const D3D12_VIEWPORT *viewports);
+
+ void (STDMETHODCALLTYPE *RSSetScissorRects)(
+ ID3D12GraphicsCommandList *This,
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *OMSetBlendFactor)(
+ ID3D12GraphicsCommandList *This,
+ const FLOAT blend_factor[4]);
+
+ void (STDMETHODCALLTYPE *OMSetStencilRef)(
+ ID3D12GraphicsCommandList *This,
+ UINT stencil_ref);
+
+ void (STDMETHODCALLTYPE *SetPipelineState)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12PipelineState *pipeline_state);
+
+ void (STDMETHODCALLTYPE *ResourceBarrier)(
+ ID3D12GraphicsCommandList *This,
+ UINT barrier_count,
+ const D3D12_RESOURCE_BARRIER *barriers);
+
+ void (STDMETHODCALLTYPE *ExecuteBundle)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12GraphicsCommandList *command_list);
+
+ void (STDMETHODCALLTYPE *SetDescriptorHeaps)(
+ ID3D12GraphicsCommandList *This,
+ UINT heap_count,
+ ID3D12DescriptorHeap *const *heaps);
+
+ void (STDMETHODCALLTYPE *SetComputeRootSignature)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12RootSignature *root_signature);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootSignature)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12RootSignature *root_signature);
+
+ void (STDMETHODCALLTYPE *SetComputeRootDescriptorTable)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootDescriptorTable)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor);
+
+ void (STDMETHODCALLTYPE *SetComputeRoot32BitConstant)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ UINT data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRoot32BitConstant)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ UINT data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetComputeRoot32BitConstants)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ UINT constant_count,
+ const void *data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRoot32BitConstants)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ UINT constant_count,
+ const void *data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetComputeRootConstantBufferView)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootConstantBufferView)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetComputeRootShaderResourceView)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootShaderResourceView)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetComputeRootUnorderedAccessView)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootUnorderedAccessView)(
+ ID3D12GraphicsCommandList *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *IASetIndexBuffer)(
+ ID3D12GraphicsCommandList *This,
+ const D3D12_INDEX_BUFFER_VIEW *view);
+
+ void (STDMETHODCALLTYPE *IASetVertexBuffers)(
+ ID3D12GraphicsCommandList *This,
+ UINT start_slot,
+ UINT view_count,
+ const D3D12_VERTEX_BUFFER_VIEW *views);
+
+ void (STDMETHODCALLTYPE *SOSetTargets)(
+ ID3D12GraphicsCommandList *This,
+ UINT start_slot,
+ UINT view_count,
+ const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views);
+
+ void (STDMETHODCALLTYPE *OMSetRenderTargets)(
+ ID3D12GraphicsCommandList *This,
+ UINT render_target_descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,
+ BOOL single_descriptor_handle,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor);
+
+ void (STDMETHODCALLTYPE *ClearDepthStencilView)(
+ ID3D12GraphicsCommandList *This,
+ D3D12_CPU_DESCRIPTOR_HANDLE dsv,
+ D3D12_CLEAR_FLAGS flags,
+ FLOAT depth,
+ UINT8 stencil,
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearRenderTargetView)(
+ ID3D12GraphicsCommandList *This,
+ D3D12_CPU_DESCRIPTOR_HANDLE rtv,
+ const FLOAT color[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearUnorderedAccessViewUint)(
+ ID3D12GraphicsCommandList *This,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,
+ ID3D12Resource *resource,
+ const UINT values[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearUnorderedAccessViewFloat)(
+ ID3D12GraphicsCommandList *This,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,
+ ID3D12Resource *resource,
+ const float values[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *DiscardResource)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12Resource *resource,
+ const D3D12_DISCARD_REGION *region);
+
+ void (STDMETHODCALLTYPE *BeginQuery)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT index);
+
+ void (STDMETHODCALLTYPE *EndQuery)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT index);
+
+ void (STDMETHODCALLTYPE *ResolveQueryData)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT start_index,
+ UINT query_count,
+ ID3D12Resource *dst_buffer,
+ UINT64 aligned_dst_buffer_offset);
+
+ void (STDMETHODCALLTYPE *SetPredication)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12Resource *buffer,
+ UINT64 aligned_buffer_offset,
+ D3D12_PREDICATION_OP operation);
+
+ void (STDMETHODCALLTYPE *SetMarker)(
+ ID3D12GraphicsCommandList *This,
+ UINT metadata,
+ const void *data,
+ UINT size);
+
+ void (STDMETHODCALLTYPE *BeginEvent)(
+ ID3D12GraphicsCommandList *This,
+ UINT metadata,
+ const void *data,
+ UINT size);
+
+ void (STDMETHODCALLTYPE *EndEvent)(
+ ID3D12GraphicsCommandList *This);
+
+ void (STDMETHODCALLTYPE *ExecuteIndirect)(
+ ID3D12GraphicsCommandList *This,
+ ID3D12CommandSignature *command_signature,
+ UINT max_command_count,
+ ID3D12Resource *arg_buffer,
+ UINT64 arg_buffer_offset,
+ ID3D12Resource *count_buffer,
+ UINT64 count_buffer_offset);
+
+ END_INTERFACE
+} ID3D12GraphicsCommandListVtbl;
+
+interface ID3D12GraphicsCommandList {
+ CONST_VTBL ID3D12GraphicsCommandListVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12GraphicsCommandList_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12GraphicsCommandList_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12GraphicsCommandList_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12GraphicsCommandList_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12GraphicsCommandList_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12GraphicsCommandList_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12GraphicsCommandList_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12GraphicsCommandList_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12CommandList methods ***/
+#define ID3D12GraphicsCommandList_GetType(This) (This)->lpVtbl->GetType(This)
+/*** ID3D12GraphicsCommandList methods ***/
+#define ID3D12GraphicsCommandList_Close(This) (This)->lpVtbl->Close(This)
+#define ID3D12GraphicsCommandList_Reset(This,allocator,initial_state) (This)->lpVtbl->Reset(This,allocator,initial_state)
+#define ID3D12GraphicsCommandList_ClearState(This,pipeline_state) (This)->lpVtbl->ClearState(This,pipeline_state)
+#define ID3D12GraphicsCommandList_DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location) (This)->lpVtbl->DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location)
+#define ID3D12GraphicsCommandList_DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location) (This)->lpVtbl->DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location)
+#define ID3D12GraphicsCommandList_Dispatch(This,x,u,z) (This)->lpVtbl->Dispatch(This,x,u,z)
+#define ID3D12GraphicsCommandList_CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count) (This)->lpVtbl->CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count)
+#define ID3D12GraphicsCommandList_CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box) (This)->lpVtbl->CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box)
+#define ID3D12GraphicsCommandList_CopyResource(This,dst_resource,src_resource) (This)->lpVtbl->CopyResource(This,dst_resource,src_resource)
+#define ID3D12GraphicsCommandList_CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags) (This)->lpVtbl->CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags)
+#define ID3D12GraphicsCommandList_ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format) (This)->lpVtbl->ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format)
+#define ID3D12GraphicsCommandList_IASetPrimitiveTopology(This,primitive_topology) (This)->lpVtbl->IASetPrimitiveTopology(This,primitive_topology)
+#define ID3D12GraphicsCommandList_RSSetViewports(This,viewport_count,viewports) (This)->lpVtbl->RSSetViewports(This,viewport_count,viewports)
+#define ID3D12GraphicsCommandList_RSSetScissorRects(This,rect_count,rects) (This)->lpVtbl->RSSetScissorRects(This,rect_count,rects)
+#define ID3D12GraphicsCommandList_OMSetBlendFactor(This,blend_factor) (This)->lpVtbl->OMSetBlendFactor(This,blend_factor)
+#define ID3D12GraphicsCommandList_OMSetStencilRef(This,stencil_ref) (This)->lpVtbl->OMSetStencilRef(This,stencil_ref)
+#define ID3D12GraphicsCommandList_SetPipelineState(This,pipeline_state) (This)->lpVtbl->SetPipelineState(This,pipeline_state)
+#define ID3D12GraphicsCommandList_ResourceBarrier(This,barrier_count,barriers) (This)->lpVtbl->ResourceBarrier(This,barrier_count,barriers)
+#define ID3D12GraphicsCommandList_ExecuteBundle(This,command_list) (This)->lpVtbl->ExecuteBundle(This,command_list)
+#define ID3D12GraphicsCommandList_SetDescriptorHeaps(This,heap_count,heaps) (This)->lpVtbl->SetDescriptorHeaps(This,heap_count,heaps)
+#define ID3D12GraphicsCommandList_SetComputeRootSignature(This,root_signature) (This)->lpVtbl->SetComputeRootSignature(This,root_signature)
+#define ID3D12GraphicsCommandList_SetGraphicsRootSignature(This,root_signature) (This)->lpVtbl->SetGraphicsRootSignature(This,root_signature)
+#define ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor) (This)->lpVtbl->SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor)
+#define ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor) (This)->lpVtbl->SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor)
+#define ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset) (This)->lpVtbl->SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset)
+#define ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset) (This)->lpVtbl->SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset)
+#define ID3D12GraphicsCommandList_SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset) (This)->lpVtbl->SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset)
+#define ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset) (This)->lpVtbl->SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset)
+#define ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootConstantBufferView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootConstantBufferView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList_SetComputeRootShaderResourceView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootShaderResourceView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootShaderResourceView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootUnorderedAccessView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList_SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList_IASetIndexBuffer(This,view) (This)->lpVtbl->IASetIndexBuffer(This,view)
+#define ID3D12GraphicsCommandList_IASetVertexBuffers(This,start_slot,view_count,views) (This)->lpVtbl->IASetVertexBuffers(This,start_slot,view_count,views)
+#define ID3D12GraphicsCommandList_SOSetTargets(This,start_slot,view_count,views) (This)->lpVtbl->SOSetTargets(This,start_slot,view_count,views)
+#define ID3D12GraphicsCommandList_OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor) (This)->lpVtbl->OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor)
+#define ID3D12GraphicsCommandList_ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects) (This)->lpVtbl->ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects)
+#define ID3D12GraphicsCommandList_ClearRenderTargetView(This,rtv,color,rect_count,rects) (This)->lpVtbl->ClearRenderTargetView(This,rtv,color,rect_count,rects)
+#define ID3D12GraphicsCommandList_ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects) (This)->lpVtbl->ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects)
+#define ID3D12GraphicsCommandList_ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects) (This)->lpVtbl->ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects)
+#define ID3D12GraphicsCommandList_DiscardResource(This,resource,region) (This)->lpVtbl->DiscardResource(This,resource,region)
+#define ID3D12GraphicsCommandList_BeginQuery(This,heap,type,index) (This)->lpVtbl->BeginQuery(This,heap,type,index)
+#define ID3D12GraphicsCommandList_EndQuery(This,heap,type,index) (This)->lpVtbl->EndQuery(This,heap,type,index)
+#define ID3D12GraphicsCommandList_ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset) (This)->lpVtbl->ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset)
+#define ID3D12GraphicsCommandList_SetPredication(This,buffer,aligned_buffer_offset,operation) (This)->lpVtbl->SetPredication(This,buffer,aligned_buffer_offset,operation)
+#define ID3D12GraphicsCommandList_SetMarker(This,metadata,data,size) (This)->lpVtbl->SetMarker(This,metadata,data,size)
+#define ID3D12GraphicsCommandList_BeginEvent(This,metadata,data,size) (This)->lpVtbl->BeginEvent(This,metadata,data,size)
+#define ID3D12GraphicsCommandList_EndEvent(This) (This)->lpVtbl->EndEvent(This)
+#define ID3D12GraphicsCommandList_ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset) (This)->lpVtbl->ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_QueryInterface(ID3D12GraphicsCommandList* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12GraphicsCommandList_AddRef(ID3D12GraphicsCommandList* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12GraphicsCommandList_Release(ID3D12GraphicsCommandList* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_GetPrivateData(ID3D12GraphicsCommandList* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_SetPrivateData(ID3D12GraphicsCommandList* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_SetPrivateDataInterface(ID3D12GraphicsCommandList* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_SetName(ID3D12GraphicsCommandList* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_GetDevice(ID3D12GraphicsCommandList* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12CommandList methods ***/
+static FORCEINLINE D3D12_COMMAND_LIST_TYPE ID3D12GraphicsCommandList_GetType(ID3D12GraphicsCommandList* This) {
+ return This->lpVtbl->GetType(This);
+}
+/*** ID3D12GraphicsCommandList methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_Close(ID3D12GraphicsCommandList* This) {
+ return This->lpVtbl->Close(This);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_Reset(ID3D12GraphicsCommandList* This,ID3D12CommandAllocator *allocator,ID3D12PipelineState *initial_state) {
+ return This->lpVtbl->Reset(This,allocator,initial_state);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList_ClearState(ID3D12GraphicsCommandList* This,ID3D12PipelineState *pipeline_state) {
+ return This->lpVtbl->ClearState(This,pipeline_state);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_DrawInstanced(ID3D12GraphicsCommandList* This,UINT vertex_count_per_instance,UINT instance_count,UINT start_vertex_location,UINT start_instance_location) {
+ This->lpVtbl->DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_DrawIndexedInstanced(ID3D12GraphicsCommandList* This,UINT index_count_per_instance,UINT instance_count,UINT start_vertex_location,INT base_vertex_location,UINT start_instance_location) {
+ This->lpVtbl->DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_Dispatch(ID3D12GraphicsCommandList* This,UINT x,UINT u,UINT z) {
+ This->lpVtbl->Dispatch(This,x,u,z);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_CopyBufferRegion(ID3D12GraphicsCommandList* This,ID3D12Resource *dst_buffer,UINT64 dst_offset,ID3D12Resource *src_buffer,UINT64 src_offset,UINT64 byte_count) {
+ This->lpVtbl->CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_CopyTextureRegion(ID3D12GraphicsCommandList* This,const D3D12_TEXTURE_COPY_LOCATION *dst,UINT dst_x,UINT dst_y,UINT dst_z,const D3D12_TEXTURE_COPY_LOCATION *src,const D3D12_BOX *src_box) {
+ This->lpVtbl->CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_CopyResource(ID3D12GraphicsCommandList* This,ID3D12Resource *dst_resource,ID3D12Resource *src_resource) {
+ This->lpVtbl->CopyResource(This,dst_resource,src_resource);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_CopyTiles(ID3D12GraphicsCommandList* This,ID3D12Resource *tiled_resource,const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,const D3D12_TILE_REGION_SIZE *tile_region_size,ID3D12Resource *buffer,UINT64 buffer_offset,D3D12_TILE_COPY_FLAGS flags) {
+ This->lpVtbl->CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ResolveSubresource(ID3D12GraphicsCommandList* This,ID3D12Resource *dst_resource,UINT dst_sub_resource,ID3D12Resource *src_resource,UINT src_sub_resource,DXGI_FORMAT format) {
+ This->lpVtbl->ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_IASetPrimitiveTopology(ID3D12GraphicsCommandList* This,D3D12_PRIMITIVE_TOPOLOGY primitive_topology) {
+ This->lpVtbl->IASetPrimitiveTopology(This,primitive_topology);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_RSSetViewports(ID3D12GraphicsCommandList* This,UINT viewport_count,const D3D12_VIEWPORT *viewports) {
+ This->lpVtbl->RSSetViewports(This,viewport_count,viewports);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_RSSetScissorRects(ID3D12GraphicsCommandList* This,UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->RSSetScissorRects(This,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_OMSetBlendFactor(ID3D12GraphicsCommandList* This,const FLOAT blend_factor[4]) {
+ This->lpVtbl->OMSetBlendFactor(This,blend_factor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_OMSetStencilRef(ID3D12GraphicsCommandList* This,UINT stencil_ref) {
+ This->lpVtbl->OMSetStencilRef(This,stencil_ref);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetPipelineState(ID3D12GraphicsCommandList* This,ID3D12PipelineState *pipeline_state) {
+ This->lpVtbl->SetPipelineState(This,pipeline_state);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ResourceBarrier(ID3D12GraphicsCommandList* This,UINT barrier_count,const D3D12_RESOURCE_BARRIER *barriers) {
+ This->lpVtbl->ResourceBarrier(This,barrier_count,barriers);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ExecuteBundle(ID3D12GraphicsCommandList* This,ID3D12GraphicsCommandList *command_list) {
+ This->lpVtbl->ExecuteBundle(This,command_list);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetDescriptorHeaps(ID3D12GraphicsCommandList* This,UINT heap_count,ID3D12DescriptorHeap *const *heaps) {
+ This->lpVtbl->SetDescriptorHeaps(This,heap_count,heaps);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetComputeRootSignature(ID3D12GraphicsCommandList* This,ID3D12RootSignature *root_signature) {
+ This->lpVtbl->SetComputeRootSignature(This,root_signature);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetGraphicsRootSignature(ID3D12GraphicsCommandList* This,ID3D12RootSignature *root_signature) {
+ This->lpVtbl->SetGraphicsRootSignature(This,root_signature);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(ID3D12GraphicsCommandList* This,UINT root_parameter_index,D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor) {
+ This->lpVtbl->SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(ID3D12GraphicsCommandList* This,UINT root_parameter_index,D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor) {
+ This->lpVtbl->SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(ID3D12GraphicsCommandList* This,UINT root_parameter_index,UINT data,UINT dst_offset) {
+ This->lpVtbl->SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstant(ID3D12GraphicsCommandList* This,UINT root_parameter_index,UINT data,UINT dst_offset) {
+ This->lpVtbl->SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetComputeRoot32BitConstants(ID3D12GraphicsCommandList* This,UINT root_parameter_index,UINT constant_count,const void *data,UINT dst_offset) {
+ This->lpVtbl->SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(ID3D12GraphicsCommandList* This,UINT root_parameter_index,UINT constant_count,const void *data,UINT dst_offset) {
+ This->lpVtbl->SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(ID3D12GraphicsCommandList* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootConstantBufferView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(ID3D12GraphicsCommandList* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootConstantBufferView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetComputeRootShaderResourceView(ID3D12GraphicsCommandList* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootShaderResourceView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(ID3D12GraphicsCommandList* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootShaderResourceView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(ID3D12GraphicsCommandList* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootUnorderedAccessView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetGraphicsRootUnorderedAccessView(ID3D12GraphicsCommandList* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_IASetIndexBuffer(ID3D12GraphicsCommandList* This,const D3D12_INDEX_BUFFER_VIEW *view) {
+ This->lpVtbl->IASetIndexBuffer(This,view);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_IASetVertexBuffers(ID3D12GraphicsCommandList* This,UINT start_slot,UINT view_count,const D3D12_VERTEX_BUFFER_VIEW *views) {
+ This->lpVtbl->IASetVertexBuffers(This,start_slot,view_count,views);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SOSetTargets(ID3D12GraphicsCommandList* This,UINT start_slot,UINT view_count,const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views) {
+ This->lpVtbl->SOSetTargets(This,start_slot,view_count,views);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_OMSetRenderTargets(ID3D12GraphicsCommandList* This,UINT render_target_descriptor_count,const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,BOOL single_descriptor_handle,const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor) {
+ This->lpVtbl->OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ClearDepthStencilView(ID3D12GraphicsCommandList* This,D3D12_CPU_DESCRIPTOR_HANDLE dsv,D3D12_CLEAR_FLAGS flags,FLOAT depth,UINT8 stencil,UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ClearRenderTargetView(ID3D12GraphicsCommandList* This,D3D12_CPU_DESCRIPTOR_HANDLE rtv,const FLOAT color[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearRenderTargetView(This,rtv,color,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ClearUnorderedAccessViewUint(ID3D12GraphicsCommandList* This,D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,ID3D12Resource *resource,const UINT values[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList* This,D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,ID3D12Resource *resource,const float values[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_DiscardResource(ID3D12GraphicsCommandList* This,ID3D12Resource *resource,const D3D12_DISCARD_REGION *region) {
+ This->lpVtbl->DiscardResource(This,resource,region);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_BeginQuery(ID3D12GraphicsCommandList* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT index) {
+ This->lpVtbl->BeginQuery(This,heap,type,index);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_EndQuery(ID3D12GraphicsCommandList* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT index) {
+ This->lpVtbl->EndQuery(This,heap,type,index);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ResolveQueryData(ID3D12GraphicsCommandList* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT start_index,UINT query_count,ID3D12Resource *dst_buffer,UINT64 aligned_dst_buffer_offset) {
+ This->lpVtbl->ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetPredication(ID3D12GraphicsCommandList* This,ID3D12Resource *buffer,UINT64 aligned_buffer_offset,D3D12_PREDICATION_OP operation) {
+ This->lpVtbl->SetPredication(This,buffer,aligned_buffer_offset,operation);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_SetMarker(ID3D12GraphicsCommandList* This,UINT metadata,const void *data,UINT size) {
+ This->lpVtbl->SetMarker(This,metadata,data,size);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_BeginEvent(ID3D12GraphicsCommandList* This,UINT metadata,const void *data,UINT size) {
+ This->lpVtbl->BeginEvent(This,metadata,data,size);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_EndEvent(ID3D12GraphicsCommandList* This) {
+ This->lpVtbl->EndEvent(This);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList_ExecuteIndirect(ID3D12GraphicsCommandList* This,ID3D12CommandSignature *command_signature,UINT max_command_count,ID3D12Resource *arg_buffer,UINT64 arg_buffer_offset,ID3D12Resource *count_buffer,UINT64 count_buffer_offset) {
+ This->lpVtbl->ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12GraphicsCommandList_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12GraphicsCommandList1 interface
+ */
+#ifndef __ID3D12GraphicsCommandList1_INTERFACE_DEFINED__
+#define __ID3D12GraphicsCommandList1_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12GraphicsCommandList1, 0x553103fb, 0x1fe7, 0x4557, 0xbb,0x38, 0x94,0x6d,0x7d,0x0e,0x7c,0xa7);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("553103fb-1fe7-4557-bb38-946d7d0e7ca7")
+ID3D12GraphicsCommandList1 : public ID3D12GraphicsCommandList
+{
+ virtual void STDMETHODCALLTYPE AtomicCopyBufferUINT(
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT dependent_resource_count,
+ ID3D12Resource *const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) = 0;
+
+ virtual void STDMETHODCALLTYPE AtomicCopyBufferUINT64(
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT dependent_resource_count,
+ ID3D12Resource *const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) = 0;
+
+ virtual void STDMETHODCALLTYPE OMSetDepthBounds(
+ FLOAT min,
+ FLOAT max) = 0;
+
+ virtual void STDMETHODCALLTYPE SetSamplePositions(
+ UINT sample_count,
+ UINT pixel_count,
+ D3D12_SAMPLE_POSITION *sample_positions) = 0;
+
+ virtual void STDMETHODCALLTYPE ResolveSubresourceRegion(
+ ID3D12Resource *dst_resource,
+ UINT dst_sub_resource_idx,
+ UINT dst_x,
+ UINT dst_y,
+ ID3D12Resource *src_resource,
+ UINT src_sub_resource_idx,
+ D3D12_RECT *src_rect,
+ DXGI_FORMAT format,
+ D3D12_RESOLVE_MODE mode) = 0;
+
+ virtual void STDMETHODCALLTYPE SetViewInstanceMask(
+ UINT mask) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12GraphicsCommandList1, 0x553103fb, 0x1fe7, 0x4557, 0xbb,0x38, 0x94,0x6d,0x7d,0x0e,0x7c,0xa7)
+#endif
+#else
+typedef struct ID3D12GraphicsCommandList1Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12GraphicsCommandList1 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12GraphicsCommandList1 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12GraphicsCommandList1 *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12GraphicsCommandList1 *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12GraphicsCommandList1 *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12GraphicsCommandList1 *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12GraphicsCommandList1 *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12GraphicsCommandList1 *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12CommandList methods ***/
+ D3D12_COMMAND_LIST_TYPE (STDMETHODCALLTYPE *GetType)(
+ ID3D12GraphicsCommandList1 *This);
+
+ /*** ID3D12GraphicsCommandList methods ***/
+ HRESULT (STDMETHODCALLTYPE *Close)(
+ ID3D12GraphicsCommandList1 *This);
+
+ HRESULT (STDMETHODCALLTYPE *Reset)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12CommandAllocator *allocator,
+ ID3D12PipelineState *initial_state);
+
+ HRESULT (STDMETHODCALLTYPE *ClearState)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12PipelineState *pipeline_state);
+
+ void (STDMETHODCALLTYPE *DrawInstanced)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT vertex_count_per_instance,
+ UINT instance_count,
+ UINT start_vertex_location,
+ UINT start_instance_location);
+
+ void (STDMETHODCALLTYPE *DrawIndexedInstanced)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT index_count_per_instance,
+ UINT instance_count,
+ UINT start_vertex_location,
+ INT base_vertex_location,
+ UINT start_instance_location);
+
+ void (STDMETHODCALLTYPE *Dispatch)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT x,
+ UINT u,
+ UINT z);
+
+ void (STDMETHODCALLTYPE *CopyBufferRegion)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT64 byte_count);
+
+ void (STDMETHODCALLTYPE *CopyTextureRegion)(
+ ID3D12GraphicsCommandList1 *This,
+ const D3D12_TEXTURE_COPY_LOCATION *dst,
+ UINT dst_x,
+ UINT dst_y,
+ UINT dst_z,
+ const D3D12_TEXTURE_COPY_LOCATION *src,
+ const D3D12_BOX *src_box);
+
+ void (STDMETHODCALLTYPE *CopyResource)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *dst_resource,
+ ID3D12Resource *src_resource);
+
+ void (STDMETHODCALLTYPE *CopyTiles)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *tiled_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *tile_region_size,
+ ID3D12Resource *buffer,
+ UINT64 buffer_offset,
+ D3D12_TILE_COPY_FLAGS flags);
+
+ void (STDMETHODCALLTYPE *ResolveSubresource)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *dst_resource,
+ UINT dst_sub_resource,
+ ID3D12Resource *src_resource,
+ UINT src_sub_resource,
+ DXGI_FORMAT format);
+
+ void (STDMETHODCALLTYPE *IASetPrimitiveTopology)(
+ ID3D12GraphicsCommandList1 *This,
+ D3D12_PRIMITIVE_TOPOLOGY primitive_topology);
+
+ void (STDMETHODCALLTYPE *RSSetViewports)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT viewport_count,
+ const D3D12_VIEWPORT *viewports);
+
+ void (STDMETHODCALLTYPE *RSSetScissorRects)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *OMSetBlendFactor)(
+ ID3D12GraphicsCommandList1 *This,
+ const FLOAT blend_factor[4]);
+
+ void (STDMETHODCALLTYPE *OMSetStencilRef)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT stencil_ref);
+
+ void (STDMETHODCALLTYPE *SetPipelineState)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12PipelineState *pipeline_state);
+
+ void (STDMETHODCALLTYPE *ResourceBarrier)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT barrier_count,
+ const D3D12_RESOURCE_BARRIER *barriers);
+
+ void (STDMETHODCALLTYPE *ExecuteBundle)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12GraphicsCommandList *command_list);
+
+ void (STDMETHODCALLTYPE *SetDescriptorHeaps)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT heap_count,
+ ID3D12DescriptorHeap *const *heaps);
+
+ void (STDMETHODCALLTYPE *SetComputeRootSignature)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12RootSignature *root_signature);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootSignature)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12RootSignature *root_signature);
+
+ void (STDMETHODCALLTYPE *SetComputeRootDescriptorTable)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootDescriptorTable)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor);
+
+ void (STDMETHODCALLTYPE *SetComputeRoot32BitConstant)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ UINT data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRoot32BitConstant)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ UINT data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetComputeRoot32BitConstants)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ UINT constant_count,
+ const void *data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRoot32BitConstants)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ UINT constant_count,
+ const void *data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetComputeRootConstantBufferView)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootConstantBufferView)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetComputeRootShaderResourceView)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootShaderResourceView)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetComputeRootUnorderedAccessView)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootUnorderedAccessView)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *IASetIndexBuffer)(
+ ID3D12GraphicsCommandList1 *This,
+ const D3D12_INDEX_BUFFER_VIEW *view);
+
+ void (STDMETHODCALLTYPE *IASetVertexBuffers)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT start_slot,
+ UINT view_count,
+ const D3D12_VERTEX_BUFFER_VIEW *views);
+
+ void (STDMETHODCALLTYPE *SOSetTargets)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT start_slot,
+ UINT view_count,
+ const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views);
+
+ void (STDMETHODCALLTYPE *OMSetRenderTargets)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT render_target_descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,
+ BOOL single_descriptor_handle,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor);
+
+ void (STDMETHODCALLTYPE *ClearDepthStencilView)(
+ ID3D12GraphicsCommandList1 *This,
+ D3D12_CPU_DESCRIPTOR_HANDLE dsv,
+ D3D12_CLEAR_FLAGS flags,
+ FLOAT depth,
+ UINT8 stencil,
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearRenderTargetView)(
+ ID3D12GraphicsCommandList1 *This,
+ D3D12_CPU_DESCRIPTOR_HANDLE rtv,
+ const FLOAT color[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearUnorderedAccessViewUint)(
+ ID3D12GraphicsCommandList1 *This,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,
+ ID3D12Resource *resource,
+ const UINT values[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearUnorderedAccessViewFloat)(
+ ID3D12GraphicsCommandList1 *This,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,
+ ID3D12Resource *resource,
+ const float values[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *DiscardResource)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *resource,
+ const D3D12_DISCARD_REGION *region);
+
+ void (STDMETHODCALLTYPE *BeginQuery)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT index);
+
+ void (STDMETHODCALLTYPE *EndQuery)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT index);
+
+ void (STDMETHODCALLTYPE *ResolveQueryData)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT start_index,
+ UINT query_count,
+ ID3D12Resource *dst_buffer,
+ UINT64 aligned_dst_buffer_offset);
+
+ void (STDMETHODCALLTYPE *SetPredication)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *buffer,
+ UINT64 aligned_buffer_offset,
+ D3D12_PREDICATION_OP operation);
+
+ void (STDMETHODCALLTYPE *SetMarker)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT metadata,
+ const void *data,
+ UINT size);
+
+ void (STDMETHODCALLTYPE *BeginEvent)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT metadata,
+ const void *data,
+ UINT size);
+
+ void (STDMETHODCALLTYPE *EndEvent)(
+ ID3D12GraphicsCommandList1 *This);
+
+ void (STDMETHODCALLTYPE *ExecuteIndirect)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12CommandSignature *command_signature,
+ UINT max_command_count,
+ ID3D12Resource *arg_buffer,
+ UINT64 arg_buffer_offset,
+ ID3D12Resource *count_buffer,
+ UINT64 count_buffer_offset);
+
+ /*** ID3D12GraphicsCommandList1 methods ***/
+ void (STDMETHODCALLTYPE *AtomicCopyBufferUINT)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT dependent_resource_count,
+ ID3D12Resource *const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges);
+
+ void (STDMETHODCALLTYPE *AtomicCopyBufferUINT64)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT dependent_resource_count,
+ ID3D12Resource *const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges);
+
+ void (STDMETHODCALLTYPE *OMSetDepthBounds)(
+ ID3D12GraphicsCommandList1 *This,
+ FLOAT min,
+ FLOAT max);
+
+ void (STDMETHODCALLTYPE *SetSamplePositions)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT sample_count,
+ UINT pixel_count,
+ D3D12_SAMPLE_POSITION *sample_positions);
+
+ void (STDMETHODCALLTYPE *ResolveSubresourceRegion)(
+ ID3D12GraphicsCommandList1 *This,
+ ID3D12Resource *dst_resource,
+ UINT dst_sub_resource_idx,
+ UINT dst_x,
+ UINT dst_y,
+ ID3D12Resource *src_resource,
+ UINT src_sub_resource_idx,
+ D3D12_RECT *src_rect,
+ DXGI_FORMAT format,
+ D3D12_RESOLVE_MODE mode);
+
+ void (STDMETHODCALLTYPE *SetViewInstanceMask)(
+ ID3D12GraphicsCommandList1 *This,
+ UINT mask);
+
+ END_INTERFACE
+} ID3D12GraphicsCommandList1Vtbl;
+
+interface ID3D12GraphicsCommandList1 {
+ CONST_VTBL ID3D12GraphicsCommandList1Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12GraphicsCommandList1_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12GraphicsCommandList1_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12GraphicsCommandList1_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12GraphicsCommandList1_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12GraphicsCommandList1_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12GraphicsCommandList1_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12GraphicsCommandList1_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12GraphicsCommandList1_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12CommandList methods ***/
+#define ID3D12GraphicsCommandList1_GetType(This) (This)->lpVtbl->GetType(This)
+/*** ID3D12GraphicsCommandList methods ***/
+#define ID3D12GraphicsCommandList1_Close(This) (This)->lpVtbl->Close(This)
+#define ID3D12GraphicsCommandList1_Reset(This,allocator,initial_state) (This)->lpVtbl->Reset(This,allocator,initial_state)
+#define ID3D12GraphicsCommandList1_ClearState(This,pipeline_state) (This)->lpVtbl->ClearState(This,pipeline_state)
+#define ID3D12GraphicsCommandList1_DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location) (This)->lpVtbl->DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location)
+#define ID3D12GraphicsCommandList1_DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location) (This)->lpVtbl->DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location)
+#define ID3D12GraphicsCommandList1_Dispatch(This,x,u,z) (This)->lpVtbl->Dispatch(This,x,u,z)
+#define ID3D12GraphicsCommandList1_CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count) (This)->lpVtbl->CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count)
+#define ID3D12GraphicsCommandList1_CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box) (This)->lpVtbl->CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box)
+#define ID3D12GraphicsCommandList1_CopyResource(This,dst_resource,src_resource) (This)->lpVtbl->CopyResource(This,dst_resource,src_resource)
+#define ID3D12GraphicsCommandList1_CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags) (This)->lpVtbl->CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags)
+#define ID3D12GraphicsCommandList1_ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format) (This)->lpVtbl->ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format)
+#define ID3D12GraphicsCommandList1_IASetPrimitiveTopology(This,primitive_topology) (This)->lpVtbl->IASetPrimitiveTopology(This,primitive_topology)
+#define ID3D12GraphicsCommandList1_RSSetViewports(This,viewport_count,viewports) (This)->lpVtbl->RSSetViewports(This,viewport_count,viewports)
+#define ID3D12GraphicsCommandList1_RSSetScissorRects(This,rect_count,rects) (This)->lpVtbl->RSSetScissorRects(This,rect_count,rects)
+#define ID3D12GraphicsCommandList1_OMSetBlendFactor(This,blend_factor) (This)->lpVtbl->OMSetBlendFactor(This,blend_factor)
+#define ID3D12GraphicsCommandList1_OMSetStencilRef(This,stencil_ref) (This)->lpVtbl->OMSetStencilRef(This,stencil_ref)
+#define ID3D12GraphicsCommandList1_SetPipelineState(This,pipeline_state) (This)->lpVtbl->SetPipelineState(This,pipeline_state)
+#define ID3D12GraphicsCommandList1_ResourceBarrier(This,barrier_count,barriers) (This)->lpVtbl->ResourceBarrier(This,barrier_count,barriers)
+#define ID3D12GraphicsCommandList1_ExecuteBundle(This,command_list) (This)->lpVtbl->ExecuteBundle(This,command_list)
+#define ID3D12GraphicsCommandList1_SetDescriptorHeaps(This,heap_count,heaps) (This)->lpVtbl->SetDescriptorHeaps(This,heap_count,heaps)
+#define ID3D12GraphicsCommandList1_SetComputeRootSignature(This,root_signature) (This)->lpVtbl->SetComputeRootSignature(This,root_signature)
+#define ID3D12GraphicsCommandList1_SetGraphicsRootSignature(This,root_signature) (This)->lpVtbl->SetGraphicsRootSignature(This,root_signature)
+#define ID3D12GraphicsCommandList1_SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor) (This)->lpVtbl->SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor)
+#define ID3D12GraphicsCommandList1_SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor) (This)->lpVtbl->SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor)
+#define ID3D12GraphicsCommandList1_SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset) (This)->lpVtbl->SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset)
+#define ID3D12GraphicsCommandList1_SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset) (This)->lpVtbl->SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset)
+#define ID3D12GraphicsCommandList1_SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset) (This)->lpVtbl->SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset)
+#define ID3D12GraphicsCommandList1_SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset) (This)->lpVtbl->SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset)
+#define ID3D12GraphicsCommandList1_SetComputeRootConstantBufferView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootConstantBufferView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList1_SetGraphicsRootConstantBufferView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootConstantBufferView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList1_SetComputeRootShaderResourceView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootShaderResourceView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList1_SetGraphicsRootShaderResourceView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootShaderResourceView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList1_SetComputeRootUnorderedAccessView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootUnorderedAccessView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList1_SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList1_IASetIndexBuffer(This,view) (This)->lpVtbl->IASetIndexBuffer(This,view)
+#define ID3D12GraphicsCommandList1_IASetVertexBuffers(This,start_slot,view_count,views) (This)->lpVtbl->IASetVertexBuffers(This,start_slot,view_count,views)
+#define ID3D12GraphicsCommandList1_SOSetTargets(This,start_slot,view_count,views) (This)->lpVtbl->SOSetTargets(This,start_slot,view_count,views)
+#define ID3D12GraphicsCommandList1_OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor) (This)->lpVtbl->OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor)
+#define ID3D12GraphicsCommandList1_ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects) (This)->lpVtbl->ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects)
+#define ID3D12GraphicsCommandList1_ClearRenderTargetView(This,rtv,color,rect_count,rects) (This)->lpVtbl->ClearRenderTargetView(This,rtv,color,rect_count,rects)
+#define ID3D12GraphicsCommandList1_ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects) (This)->lpVtbl->ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects)
+#define ID3D12GraphicsCommandList1_ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects) (This)->lpVtbl->ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects)
+#define ID3D12GraphicsCommandList1_DiscardResource(This,resource,region) (This)->lpVtbl->DiscardResource(This,resource,region)
+#define ID3D12GraphicsCommandList1_BeginQuery(This,heap,type,index) (This)->lpVtbl->BeginQuery(This,heap,type,index)
+#define ID3D12GraphicsCommandList1_EndQuery(This,heap,type,index) (This)->lpVtbl->EndQuery(This,heap,type,index)
+#define ID3D12GraphicsCommandList1_ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset) (This)->lpVtbl->ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset)
+#define ID3D12GraphicsCommandList1_SetPredication(This,buffer,aligned_buffer_offset,operation) (This)->lpVtbl->SetPredication(This,buffer,aligned_buffer_offset,operation)
+#define ID3D12GraphicsCommandList1_SetMarker(This,metadata,data,size) (This)->lpVtbl->SetMarker(This,metadata,data,size)
+#define ID3D12GraphicsCommandList1_BeginEvent(This,metadata,data,size) (This)->lpVtbl->BeginEvent(This,metadata,data,size)
+#define ID3D12GraphicsCommandList1_EndEvent(This) (This)->lpVtbl->EndEvent(This)
+#define ID3D12GraphicsCommandList1_ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset) (This)->lpVtbl->ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset)
+/*** ID3D12GraphicsCommandList1 methods ***/
+#define ID3D12GraphicsCommandList1_AtomicCopyBufferUINT(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges) (This)->lpVtbl->AtomicCopyBufferUINT(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges)
+#define ID3D12GraphicsCommandList1_AtomicCopyBufferUINT64(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges) (This)->lpVtbl->AtomicCopyBufferUINT64(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges)
+#define ID3D12GraphicsCommandList1_OMSetDepthBounds(This,min,max) (This)->lpVtbl->OMSetDepthBounds(This,min,max)
+#define ID3D12GraphicsCommandList1_SetSamplePositions(This,sample_count,pixel_count,sample_positions) (This)->lpVtbl->SetSamplePositions(This,sample_count,pixel_count,sample_positions)
+#define ID3D12GraphicsCommandList1_ResolveSubresourceRegion(This,dst_resource,dst_sub_resource_idx,dst_x,dst_y,src_resource,src_sub_resource_idx,src_rect,format,mode) (This)->lpVtbl->ResolveSubresourceRegion(This,dst_resource,dst_sub_resource_idx,dst_x,dst_y,src_resource,src_sub_resource_idx,src_rect,format,mode)
+#define ID3D12GraphicsCommandList1_SetViewInstanceMask(This,mask) (This)->lpVtbl->SetViewInstanceMask(This,mask)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_QueryInterface(ID3D12GraphicsCommandList1* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12GraphicsCommandList1_AddRef(ID3D12GraphicsCommandList1* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12GraphicsCommandList1_Release(ID3D12GraphicsCommandList1* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_GetPrivateData(ID3D12GraphicsCommandList1* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_SetPrivateData(ID3D12GraphicsCommandList1* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_SetPrivateDataInterface(ID3D12GraphicsCommandList1* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_SetName(ID3D12GraphicsCommandList1* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_GetDevice(ID3D12GraphicsCommandList1* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12CommandList methods ***/
+static FORCEINLINE D3D12_COMMAND_LIST_TYPE ID3D12GraphicsCommandList1_GetType(ID3D12GraphicsCommandList1* This) {
+ return This->lpVtbl->GetType(This);
+}
+/*** ID3D12GraphicsCommandList methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_Close(ID3D12GraphicsCommandList1* This) {
+ return This->lpVtbl->Close(This);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_Reset(ID3D12GraphicsCommandList1* This,ID3D12CommandAllocator *allocator,ID3D12PipelineState *initial_state) {
+ return This->lpVtbl->Reset(This,allocator,initial_state);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList1_ClearState(ID3D12GraphicsCommandList1* This,ID3D12PipelineState *pipeline_state) {
+ return This->lpVtbl->ClearState(This,pipeline_state);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_DrawInstanced(ID3D12GraphicsCommandList1* This,UINT vertex_count_per_instance,UINT instance_count,UINT start_vertex_location,UINT start_instance_location) {
+ This->lpVtbl->DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_DrawIndexedInstanced(ID3D12GraphicsCommandList1* This,UINT index_count_per_instance,UINT instance_count,UINT start_vertex_location,INT base_vertex_location,UINT start_instance_location) {
+ This->lpVtbl->DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_Dispatch(ID3D12GraphicsCommandList1* This,UINT x,UINT u,UINT z) {
+ This->lpVtbl->Dispatch(This,x,u,z);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_CopyBufferRegion(ID3D12GraphicsCommandList1* This,ID3D12Resource *dst_buffer,UINT64 dst_offset,ID3D12Resource *src_buffer,UINT64 src_offset,UINT64 byte_count) {
+ This->lpVtbl->CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_CopyTextureRegion(ID3D12GraphicsCommandList1* This,const D3D12_TEXTURE_COPY_LOCATION *dst,UINT dst_x,UINT dst_y,UINT dst_z,const D3D12_TEXTURE_COPY_LOCATION *src,const D3D12_BOX *src_box) {
+ This->lpVtbl->CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_CopyResource(ID3D12GraphicsCommandList1* This,ID3D12Resource *dst_resource,ID3D12Resource *src_resource) {
+ This->lpVtbl->CopyResource(This,dst_resource,src_resource);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_CopyTiles(ID3D12GraphicsCommandList1* This,ID3D12Resource *tiled_resource,const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,const D3D12_TILE_REGION_SIZE *tile_region_size,ID3D12Resource *buffer,UINT64 buffer_offset,D3D12_TILE_COPY_FLAGS flags) {
+ This->lpVtbl->CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ResolveSubresource(ID3D12GraphicsCommandList1* This,ID3D12Resource *dst_resource,UINT dst_sub_resource,ID3D12Resource *src_resource,UINT src_sub_resource,DXGI_FORMAT format) {
+ This->lpVtbl->ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_IASetPrimitiveTopology(ID3D12GraphicsCommandList1* This,D3D12_PRIMITIVE_TOPOLOGY primitive_topology) {
+ This->lpVtbl->IASetPrimitiveTopology(This,primitive_topology);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_RSSetViewports(ID3D12GraphicsCommandList1* This,UINT viewport_count,const D3D12_VIEWPORT *viewports) {
+ This->lpVtbl->RSSetViewports(This,viewport_count,viewports);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_RSSetScissorRects(ID3D12GraphicsCommandList1* This,UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->RSSetScissorRects(This,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_OMSetBlendFactor(ID3D12GraphicsCommandList1* This,const FLOAT blend_factor[4]) {
+ This->lpVtbl->OMSetBlendFactor(This,blend_factor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_OMSetStencilRef(ID3D12GraphicsCommandList1* This,UINT stencil_ref) {
+ This->lpVtbl->OMSetStencilRef(This,stencil_ref);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetPipelineState(ID3D12GraphicsCommandList1* This,ID3D12PipelineState *pipeline_state) {
+ This->lpVtbl->SetPipelineState(This,pipeline_state);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ResourceBarrier(ID3D12GraphicsCommandList1* This,UINT barrier_count,const D3D12_RESOURCE_BARRIER *barriers) {
+ This->lpVtbl->ResourceBarrier(This,barrier_count,barriers);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ExecuteBundle(ID3D12GraphicsCommandList1* This,ID3D12GraphicsCommandList *command_list) {
+ This->lpVtbl->ExecuteBundle(This,command_list);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetDescriptorHeaps(ID3D12GraphicsCommandList1* This,UINT heap_count,ID3D12DescriptorHeap *const *heaps) {
+ This->lpVtbl->SetDescriptorHeaps(This,heap_count,heaps);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetComputeRootSignature(ID3D12GraphicsCommandList1* This,ID3D12RootSignature *root_signature) {
+ This->lpVtbl->SetComputeRootSignature(This,root_signature);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetGraphicsRootSignature(ID3D12GraphicsCommandList1* This,ID3D12RootSignature *root_signature) {
+ This->lpVtbl->SetGraphicsRootSignature(This,root_signature);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetComputeRootDescriptorTable(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor) {
+ This->lpVtbl->SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetGraphicsRootDescriptorTable(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor) {
+ This->lpVtbl->SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetComputeRoot32BitConstant(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,UINT data,UINT dst_offset) {
+ This->lpVtbl->SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetGraphicsRoot32BitConstant(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,UINT data,UINT dst_offset) {
+ This->lpVtbl->SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetComputeRoot32BitConstants(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,UINT constant_count,const void *data,UINT dst_offset) {
+ This->lpVtbl->SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetGraphicsRoot32BitConstants(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,UINT constant_count,const void *data,UINT dst_offset) {
+ This->lpVtbl->SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetComputeRootConstantBufferView(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootConstantBufferView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetGraphicsRootConstantBufferView(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootConstantBufferView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetComputeRootShaderResourceView(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootShaderResourceView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetGraphicsRootShaderResourceView(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootShaderResourceView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetComputeRootUnorderedAccessView(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootUnorderedAccessView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetGraphicsRootUnorderedAccessView(ID3D12GraphicsCommandList1* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_IASetIndexBuffer(ID3D12GraphicsCommandList1* This,const D3D12_INDEX_BUFFER_VIEW *view) {
+ This->lpVtbl->IASetIndexBuffer(This,view);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_IASetVertexBuffers(ID3D12GraphicsCommandList1* This,UINT start_slot,UINT view_count,const D3D12_VERTEX_BUFFER_VIEW *views) {
+ This->lpVtbl->IASetVertexBuffers(This,start_slot,view_count,views);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SOSetTargets(ID3D12GraphicsCommandList1* This,UINT start_slot,UINT view_count,const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views) {
+ This->lpVtbl->SOSetTargets(This,start_slot,view_count,views);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_OMSetRenderTargets(ID3D12GraphicsCommandList1* This,UINT render_target_descriptor_count,const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,BOOL single_descriptor_handle,const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor) {
+ This->lpVtbl->OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ClearDepthStencilView(ID3D12GraphicsCommandList1* This,D3D12_CPU_DESCRIPTOR_HANDLE dsv,D3D12_CLEAR_FLAGS flags,FLOAT depth,UINT8 stencil,UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ClearRenderTargetView(ID3D12GraphicsCommandList1* This,D3D12_CPU_DESCRIPTOR_HANDLE rtv,const FLOAT color[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearRenderTargetView(This,rtv,color,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ClearUnorderedAccessViewUint(ID3D12GraphicsCommandList1* This,D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,ID3D12Resource *resource,const UINT values[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList1* This,D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,ID3D12Resource *resource,const float values[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_DiscardResource(ID3D12GraphicsCommandList1* This,ID3D12Resource *resource,const D3D12_DISCARD_REGION *region) {
+ This->lpVtbl->DiscardResource(This,resource,region);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_BeginQuery(ID3D12GraphicsCommandList1* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT index) {
+ This->lpVtbl->BeginQuery(This,heap,type,index);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_EndQuery(ID3D12GraphicsCommandList1* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT index) {
+ This->lpVtbl->EndQuery(This,heap,type,index);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ResolveQueryData(ID3D12GraphicsCommandList1* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT start_index,UINT query_count,ID3D12Resource *dst_buffer,UINT64 aligned_dst_buffer_offset) {
+ This->lpVtbl->ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetPredication(ID3D12GraphicsCommandList1* This,ID3D12Resource *buffer,UINT64 aligned_buffer_offset,D3D12_PREDICATION_OP operation) {
+ This->lpVtbl->SetPredication(This,buffer,aligned_buffer_offset,operation);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetMarker(ID3D12GraphicsCommandList1* This,UINT metadata,const void *data,UINT size) {
+ This->lpVtbl->SetMarker(This,metadata,data,size);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_BeginEvent(ID3D12GraphicsCommandList1* This,UINT metadata,const void *data,UINT size) {
+ This->lpVtbl->BeginEvent(This,metadata,data,size);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_EndEvent(ID3D12GraphicsCommandList1* This) {
+ This->lpVtbl->EndEvent(This);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ExecuteIndirect(ID3D12GraphicsCommandList1* This,ID3D12CommandSignature *command_signature,UINT max_command_count,ID3D12Resource *arg_buffer,UINT64 arg_buffer_offset,ID3D12Resource *count_buffer,UINT64 count_buffer_offset) {
+ This->lpVtbl->ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset);
+}
+/*** ID3D12GraphicsCommandList1 methods ***/
+static FORCEINLINE void ID3D12GraphicsCommandList1_AtomicCopyBufferUINT(ID3D12GraphicsCommandList1* This,ID3D12Resource *dst_buffer,UINT64 dst_offset,ID3D12Resource *src_buffer,UINT64 src_offset,UINT dependent_resource_count,ID3D12Resource *const *dependent_resources,const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) {
+ This->lpVtbl->AtomicCopyBufferUINT(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_AtomicCopyBufferUINT64(ID3D12GraphicsCommandList1* This,ID3D12Resource *dst_buffer,UINT64 dst_offset,ID3D12Resource *src_buffer,UINT64 src_offset,UINT dependent_resource_count,ID3D12Resource *const *dependent_resources,const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) {
+ This->lpVtbl->AtomicCopyBufferUINT64(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_OMSetDepthBounds(ID3D12GraphicsCommandList1* This,FLOAT min,FLOAT max) {
+ This->lpVtbl->OMSetDepthBounds(This,min,max);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetSamplePositions(ID3D12GraphicsCommandList1* This,UINT sample_count,UINT pixel_count,D3D12_SAMPLE_POSITION *sample_positions) {
+ This->lpVtbl->SetSamplePositions(This,sample_count,pixel_count,sample_positions);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_ResolveSubresourceRegion(ID3D12GraphicsCommandList1* This,ID3D12Resource *dst_resource,UINT dst_sub_resource_idx,UINT dst_x,UINT dst_y,ID3D12Resource *src_resource,UINT src_sub_resource_idx,D3D12_RECT *src_rect,DXGI_FORMAT format,D3D12_RESOLVE_MODE mode) {
+ This->lpVtbl->ResolveSubresourceRegion(This,dst_resource,dst_sub_resource_idx,dst_x,dst_y,src_resource,src_sub_resource_idx,src_rect,format,mode);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList1_SetViewInstanceMask(ID3D12GraphicsCommandList1* This,UINT mask) {
+ This->lpVtbl->SetViewInstanceMask(This,mask);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12GraphicsCommandList1_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12GraphicsCommandList2 interface
+ */
+#ifndef __ID3D12GraphicsCommandList2_INTERFACE_DEFINED__
+#define __ID3D12GraphicsCommandList2_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12GraphicsCommandList2, 0x38c3e585, 0xff17, 0x412c, 0x91,0x50, 0x4f,0xc6,0xf9,0xd7,0x2a,0x28);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("38c3e585-ff17-412c-9150-4fc6f9d72a28")
+ID3D12GraphicsCommandList2 : public ID3D12GraphicsCommandList1
+{
+ virtual void STDMETHODCALLTYPE WriteBufferImmediate(
+ UINT count,
+ const D3D12_WRITEBUFFERIMMEDIATE_PARAMETER *parameters,
+ const D3D12_WRITEBUFFERIMMEDIATE_MODE *modes) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12GraphicsCommandList2, 0x38c3e585, 0xff17, 0x412c, 0x91,0x50, 0x4f,0xc6,0xf9,0xd7,0x2a,0x28)
+#endif
+#else
+typedef struct ID3D12GraphicsCommandList2Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12GraphicsCommandList2 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12GraphicsCommandList2 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12GraphicsCommandList2 *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12GraphicsCommandList2 *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12GraphicsCommandList2 *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12GraphicsCommandList2 *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12GraphicsCommandList2 *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12GraphicsCommandList2 *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12CommandList methods ***/
+ D3D12_COMMAND_LIST_TYPE (STDMETHODCALLTYPE *GetType)(
+ ID3D12GraphicsCommandList2 *This);
+
+ /*** ID3D12GraphicsCommandList methods ***/
+ HRESULT (STDMETHODCALLTYPE *Close)(
+ ID3D12GraphicsCommandList2 *This);
+
+ HRESULT (STDMETHODCALLTYPE *Reset)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12CommandAllocator *allocator,
+ ID3D12PipelineState *initial_state);
+
+ HRESULT (STDMETHODCALLTYPE *ClearState)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12PipelineState *pipeline_state);
+
+ void (STDMETHODCALLTYPE *DrawInstanced)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT vertex_count_per_instance,
+ UINT instance_count,
+ UINT start_vertex_location,
+ UINT start_instance_location);
+
+ void (STDMETHODCALLTYPE *DrawIndexedInstanced)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT index_count_per_instance,
+ UINT instance_count,
+ UINT start_vertex_location,
+ INT base_vertex_location,
+ UINT start_instance_location);
+
+ void (STDMETHODCALLTYPE *Dispatch)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT x,
+ UINT u,
+ UINT z);
+
+ void (STDMETHODCALLTYPE *CopyBufferRegion)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT64 byte_count);
+
+ void (STDMETHODCALLTYPE *CopyTextureRegion)(
+ ID3D12GraphicsCommandList2 *This,
+ const D3D12_TEXTURE_COPY_LOCATION *dst,
+ UINT dst_x,
+ UINT dst_y,
+ UINT dst_z,
+ const D3D12_TEXTURE_COPY_LOCATION *src,
+ const D3D12_BOX *src_box);
+
+ void (STDMETHODCALLTYPE *CopyResource)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *dst_resource,
+ ID3D12Resource *src_resource);
+
+ void (STDMETHODCALLTYPE *CopyTiles)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *tiled_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *tile_region_size,
+ ID3D12Resource *buffer,
+ UINT64 buffer_offset,
+ D3D12_TILE_COPY_FLAGS flags);
+
+ void (STDMETHODCALLTYPE *ResolveSubresource)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *dst_resource,
+ UINT dst_sub_resource,
+ ID3D12Resource *src_resource,
+ UINT src_sub_resource,
+ DXGI_FORMAT format);
+
+ void (STDMETHODCALLTYPE *IASetPrimitiveTopology)(
+ ID3D12GraphicsCommandList2 *This,
+ D3D12_PRIMITIVE_TOPOLOGY primitive_topology);
+
+ void (STDMETHODCALLTYPE *RSSetViewports)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT viewport_count,
+ const D3D12_VIEWPORT *viewports);
+
+ void (STDMETHODCALLTYPE *RSSetScissorRects)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *OMSetBlendFactor)(
+ ID3D12GraphicsCommandList2 *This,
+ const FLOAT blend_factor[4]);
+
+ void (STDMETHODCALLTYPE *OMSetStencilRef)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT stencil_ref);
+
+ void (STDMETHODCALLTYPE *SetPipelineState)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12PipelineState *pipeline_state);
+
+ void (STDMETHODCALLTYPE *ResourceBarrier)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT barrier_count,
+ const D3D12_RESOURCE_BARRIER *barriers);
+
+ void (STDMETHODCALLTYPE *ExecuteBundle)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12GraphicsCommandList *command_list);
+
+ void (STDMETHODCALLTYPE *SetDescriptorHeaps)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT heap_count,
+ ID3D12DescriptorHeap *const *heaps);
+
+ void (STDMETHODCALLTYPE *SetComputeRootSignature)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12RootSignature *root_signature);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootSignature)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12RootSignature *root_signature);
+
+ void (STDMETHODCALLTYPE *SetComputeRootDescriptorTable)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootDescriptorTable)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor);
+
+ void (STDMETHODCALLTYPE *SetComputeRoot32BitConstant)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ UINT data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRoot32BitConstant)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ UINT data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetComputeRoot32BitConstants)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ UINT constant_count,
+ const void *data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRoot32BitConstants)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ UINT constant_count,
+ const void *data,
+ UINT dst_offset);
+
+ void (STDMETHODCALLTYPE *SetComputeRootConstantBufferView)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootConstantBufferView)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetComputeRootShaderResourceView)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootShaderResourceView)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetComputeRootUnorderedAccessView)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *SetGraphicsRootUnorderedAccessView)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT root_parameter_index,
+ D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void (STDMETHODCALLTYPE *IASetIndexBuffer)(
+ ID3D12GraphicsCommandList2 *This,
+ const D3D12_INDEX_BUFFER_VIEW *view);
+
+ void (STDMETHODCALLTYPE *IASetVertexBuffers)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT start_slot,
+ UINT view_count,
+ const D3D12_VERTEX_BUFFER_VIEW *views);
+
+ void (STDMETHODCALLTYPE *SOSetTargets)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT start_slot,
+ UINT view_count,
+ const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views);
+
+ void (STDMETHODCALLTYPE *OMSetRenderTargets)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT render_target_descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,
+ BOOL single_descriptor_handle,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor);
+
+ void (STDMETHODCALLTYPE *ClearDepthStencilView)(
+ ID3D12GraphicsCommandList2 *This,
+ D3D12_CPU_DESCRIPTOR_HANDLE dsv,
+ D3D12_CLEAR_FLAGS flags,
+ FLOAT depth,
+ UINT8 stencil,
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearRenderTargetView)(
+ ID3D12GraphicsCommandList2 *This,
+ D3D12_CPU_DESCRIPTOR_HANDLE rtv,
+ const FLOAT color[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearUnorderedAccessViewUint)(
+ ID3D12GraphicsCommandList2 *This,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,
+ ID3D12Resource *resource,
+ const UINT values[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *ClearUnorderedAccessViewFloat)(
+ ID3D12GraphicsCommandList2 *This,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,
+ ID3D12Resource *resource,
+ const float values[4],
+ UINT rect_count,
+ const D3D12_RECT *rects);
+
+ void (STDMETHODCALLTYPE *DiscardResource)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *resource,
+ const D3D12_DISCARD_REGION *region);
+
+ void (STDMETHODCALLTYPE *BeginQuery)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT index);
+
+ void (STDMETHODCALLTYPE *EndQuery)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT index);
+
+ void (STDMETHODCALLTYPE *ResolveQueryData)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12QueryHeap *heap,
+ D3D12_QUERY_TYPE type,
+ UINT start_index,
+ UINT query_count,
+ ID3D12Resource *dst_buffer,
+ UINT64 aligned_dst_buffer_offset);
+
+ void (STDMETHODCALLTYPE *SetPredication)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *buffer,
+ UINT64 aligned_buffer_offset,
+ D3D12_PREDICATION_OP operation);
+
+ void (STDMETHODCALLTYPE *SetMarker)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT metadata,
+ const void *data,
+ UINT size);
+
+ void (STDMETHODCALLTYPE *BeginEvent)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT metadata,
+ const void *data,
+ UINT size);
+
+ void (STDMETHODCALLTYPE *EndEvent)(
+ ID3D12GraphicsCommandList2 *This);
+
+ void (STDMETHODCALLTYPE *ExecuteIndirect)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12CommandSignature *command_signature,
+ UINT max_command_count,
+ ID3D12Resource *arg_buffer,
+ UINT64 arg_buffer_offset,
+ ID3D12Resource *count_buffer,
+ UINT64 count_buffer_offset);
+
+ /*** ID3D12GraphicsCommandList1 methods ***/
+ void (STDMETHODCALLTYPE *AtomicCopyBufferUINT)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT dependent_resource_count,
+ ID3D12Resource *const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges);
+
+ void (STDMETHODCALLTYPE *AtomicCopyBufferUINT64)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *dst_buffer,
+ UINT64 dst_offset,
+ ID3D12Resource *src_buffer,
+ UINT64 src_offset,
+ UINT dependent_resource_count,
+ ID3D12Resource *const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges);
+
+ void (STDMETHODCALLTYPE *OMSetDepthBounds)(
+ ID3D12GraphicsCommandList2 *This,
+ FLOAT min,
+ FLOAT max);
+
+ void (STDMETHODCALLTYPE *SetSamplePositions)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT sample_count,
+ UINT pixel_count,
+ D3D12_SAMPLE_POSITION *sample_positions);
+
+ void (STDMETHODCALLTYPE *ResolveSubresourceRegion)(
+ ID3D12GraphicsCommandList2 *This,
+ ID3D12Resource *dst_resource,
+ UINT dst_sub_resource_idx,
+ UINT dst_x,
+ UINT dst_y,
+ ID3D12Resource *src_resource,
+ UINT src_sub_resource_idx,
+ D3D12_RECT *src_rect,
+ DXGI_FORMAT format,
+ D3D12_RESOLVE_MODE mode);
+
+ void (STDMETHODCALLTYPE *SetViewInstanceMask)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT mask);
+
+ /*** ID3D12GraphicsCommandList2 methods ***/
+ void (STDMETHODCALLTYPE *WriteBufferImmediate)(
+ ID3D12GraphicsCommandList2 *This,
+ UINT count,
+ const D3D12_WRITEBUFFERIMMEDIATE_PARAMETER *parameters,
+ const D3D12_WRITEBUFFERIMMEDIATE_MODE *modes);
+
+ END_INTERFACE
+} ID3D12GraphicsCommandList2Vtbl;
+
+interface ID3D12GraphicsCommandList2 {
+ CONST_VTBL ID3D12GraphicsCommandList2Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12GraphicsCommandList2_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12GraphicsCommandList2_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12GraphicsCommandList2_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12GraphicsCommandList2_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12GraphicsCommandList2_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12GraphicsCommandList2_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12GraphicsCommandList2_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12GraphicsCommandList2_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12CommandList methods ***/
+#define ID3D12GraphicsCommandList2_GetType(This) (This)->lpVtbl->GetType(This)
+/*** ID3D12GraphicsCommandList methods ***/
+#define ID3D12GraphicsCommandList2_Close(This) (This)->lpVtbl->Close(This)
+#define ID3D12GraphicsCommandList2_Reset(This,allocator,initial_state) (This)->lpVtbl->Reset(This,allocator,initial_state)
+#define ID3D12GraphicsCommandList2_ClearState(This,pipeline_state) (This)->lpVtbl->ClearState(This,pipeline_state)
+#define ID3D12GraphicsCommandList2_DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location) (This)->lpVtbl->DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location)
+#define ID3D12GraphicsCommandList2_DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location) (This)->lpVtbl->DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location)
+#define ID3D12GraphicsCommandList2_Dispatch(This,x,u,z) (This)->lpVtbl->Dispatch(This,x,u,z)
+#define ID3D12GraphicsCommandList2_CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count) (This)->lpVtbl->CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count)
+#define ID3D12GraphicsCommandList2_CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box) (This)->lpVtbl->CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box)
+#define ID3D12GraphicsCommandList2_CopyResource(This,dst_resource,src_resource) (This)->lpVtbl->CopyResource(This,dst_resource,src_resource)
+#define ID3D12GraphicsCommandList2_CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags) (This)->lpVtbl->CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags)
+#define ID3D12GraphicsCommandList2_ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format) (This)->lpVtbl->ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format)
+#define ID3D12GraphicsCommandList2_IASetPrimitiveTopology(This,primitive_topology) (This)->lpVtbl->IASetPrimitiveTopology(This,primitive_topology)
+#define ID3D12GraphicsCommandList2_RSSetViewports(This,viewport_count,viewports) (This)->lpVtbl->RSSetViewports(This,viewport_count,viewports)
+#define ID3D12GraphicsCommandList2_RSSetScissorRects(This,rect_count,rects) (This)->lpVtbl->RSSetScissorRects(This,rect_count,rects)
+#define ID3D12GraphicsCommandList2_OMSetBlendFactor(This,blend_factor) (This)->lpVtbl->OMSetBlendFactor(This,blend_factor)
+#define ID3D12GraphicsCommandList2_OMSetStencilRef(This,stencil_ref) (This)->lpVtbl->OMSetStencilRef(This,stencil_ref)
+#define ID3D12GraphicsCommandList2_SetPipelineState(This,pipeline_state) (This)->lpVtbl->SetPipelineState(This,pipeline_state)
+#define ID3D12GraphicsCommandList2_ResourceBarrier(This,barrier_count,barriers) (This)->lpVtbl->ResourceBarrier(This,barrier_count,barriers)
+#define ID3D12GraphicsCommandList2_ExecuteBundle(This,command_list) (This)->lpVtbl->ExecuteBundle(This,command_list)
+#define ID3D12GraphicsCommandList2_SetDescriptorHeaps(This,heap_count,heaps) (This)->lpVtbl->SetDescriptorHeaps(This,heap_count,heaps)
+#define ID3D12GraphicsCommandList2_SetComputeRootSignature(This,root_signature) (This)->lpVtbl->SetComputeRootSignature(This,root_signature)
+#define ID3D12GraphicsCommandList2_SetGraphicsRootSignature(This,root_signature) (This)->lpVtbl->SetGraphicsRootSignature(This,root_signature)
+#define ID3D12GraphicsCommandList2_SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor) (This)->lpVtbl->SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor)
+#define ID3D12GraphicsCommandList2_SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor) (This)->lpVtbl->SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor)
+#define ID3D12GraphicsCommandList2_SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset) (This)->lpVtbl->SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset)
+#define ID3D12GraphicsCommandList2_SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset) (This)->lpVtbl->SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset)
+#define ID3D12GraphicsCommandList2_SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset) (This)->lpVtbl->SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset)
+#define ID3D12GraphicsCommandList2_SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset) (This)->lpVtbl->SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset)
+#define ID3D12GraphicsCommandList2_SetComputeRootConstantBufferView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootConstantBufferView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList2_SetGraphicsRootConstantBufferView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootConstantBufferView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList2_SetComputeRootShaderResourceView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootShaderResourceView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList2_SetGraphicsRootShaderResourceView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootShaderResourceView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList2_SetComputeRootUnorderedAccessView(This,root_parameter_index,address) (This)->lpVtbl->SetComputeRootUnorderedAccessView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList2_SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address) (This)->lpVtbl->SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address)
+#define ID3D12GraphicsCommandList2_IASetIndexBuffer(This,view) (This)->lpVtbl->IASetIndexBuffer(This,view)
+#define ID3D12GraphicsCommandList2_IASetVertexBuffers(This,start_slot,view_count,views) (This)->lpVtbl->IASetVertexBuffers(This,start_slot,view_count,views)
+#define ID3D12GraphicsCommandList2_SOSetTargets(This,start_slot,view_count,views) (This)->lpVtbl->SOSetTargets(This,start_slot,view_count,views)
+#define ID3D12GraphicsCommandList2_OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor) (This)->lpVtbl->OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor)
+#define ID3D12GraphicsCommandList2_ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects) (This)->lpVtbl->ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects)
+#define ID3D12GraphicsCommandList2_ClearRenderTargetView(This,rtv,color,rect_count,rects) (This)->lpVtbl->ClearRenderTargetView(This,rtv,color,rect_count,rects)
+#define ID3D12GraphicsCommandList2_ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects) (This)->lpVtbl->ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects)
+#define ID3D12GraphicsCommandList2_ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects) (This)->lpVtbl->ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects)
+#define ID3D12GraphicsCommandList2_DiscardResource(This,resource,region) (This)->lpVtbl->DiscardResource(This,resource,region)
+#define ID3D12GraphicsCommandList2_BeginQuery(This,heap,type,index) (This)->lpVtbl->BeginQuery(This,heap,type,index)
+#define ID3D12GraphicsCommandList2_EndQuery(This,heap,type,index) (This)->lpVtbl->EndQuery(This,heap,type,index)
+#define ID3D12GraphicsCommandList2_ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset) (This)->lpVtbl->ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset)
+#define ID3D12GraphicsCommandList2_SetPredication(This,buffer,aligned_buffer_offset,operation) (This)->lpVtbl->SetPredication(This,buffer,aligned_buffer_offset,operation)
+#define ID3D12GraphicsCommandList2_SetMarker(This,metadata,data,size) (This)->lpVtbl->SetMarker(This,metadata,data,size)
+#define ID3D12GraphicsCommandList2_BeginEvent(This,metadata,data,size) (This)->lpVtbl->BeginEvent(This,metadata,data,size)
+#define ID3D12GraphicsCommandList2_EndEvent(This) (This)->lpVtbl->EndEvent(This)
+#define ID3D12GraphicsCommandList2_ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset) (This)->lpVtbl->ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset)
+/*** ID3D12GraphicsCommandList1 methods ***/
+#define ID3D12GraphicsCommandList2_AtomicCopyBufferUINT(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges) (This)->lpVtbl->AtomicCopyBufferUINT(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges)
+#define ID3D12GraphicsCommandList2_AtomicCopyBufferUINT64(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges) (This)->lpVtbl->AtomicCopyBufferUINT64(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges)
+#define ID3D12GraphicsCommandList2_OMSetDepthBounds(This,min,max) (This)->lpVtbl->OMSetDepthBounds(This,min,max)
+#define ID3D12GraphicsCommandList2_SetSamplePositions(This,sample_count,pixel_count,sample_positions) (This)->lpVtbl->SetSamplePositions(This,sample_count,pixel_count,sample_positions)
+#define ID3D12GraphicsCommandList2_ResolveSubresourceRegion(This,dst_resource,dst_sub_resource_idx,dst_x,dst_y,src_resource,src_sub_resource_idx,src_rect,format,mode) (This)->lpVtbl->ResolveSubresourceRegion(This,dst_resource,dst_sub_resource_idx,dst_x,dst_y,src_resource,src_sub_resource_idx,src_rect,format,mode)
+#define ID3D12GraphicsCommandList2_SetViewInstanceMask(This,mask) (This)->lpVtbl->SetViewInstanceMask(This,mask)
+/*** ID3D12GraphicsCommandList2 methods ***/
+#define ID3D12GraphicsCommandList2_WriteBufferImmediate(This,count,parameters,modes) (This)->lpVtbl->WriteBufferImmediate(This,count,parameters,modes)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_QueryInterface(ID3D12GraphicsCommandList2* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12GraphicsCommandList2_AddRef(ID3D12GraphicsCommandList2* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12GraphicsCommandList2_Release(ID3D12GraphicsCommandList2* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_GetPrivateData(ID3D12GraphicsCommandList2* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_SetPrivateData(ID3D12GraphicsCommandList2* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_SetPrivateDataInterface(ID3D12GraphicsCommandList2* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_SetName(ID3D12GraphicsCommandList2* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_GetDevice(ID3D12GraphicsCommandList2* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12CommandList methods ***/
+static FORCEINLINE D3D12_COMMAND_LIST_TYPE ID3D12GraphicsCommandList2_GetType(ID3D12GraphicsCommandList2* This) {
+ return This->lpVtbl->GetType(This);
+}
+/*** ID3D12GraphicsCommandList methods ***/
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_Close(ID3D12GraphicsCommandList2* This) {
+ return This->lpVtbl->Close(This);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_Reset(ID3D12GraphicsCommandList2* This,ID3D12CommandAllocator *allocator,ID3D12PipelineState *initial_state) {
+ return This->lpVtbl->Reset(This,allocator,initial_state);
+}
+static FORCEINLINE HRESULT ID3D12GraphicsCommandList2_ClearState(ID3D12GraphicsCommandList2* This,ID3D12PipelineState *pipeline_state) {
+ return This->lpVtbl->ClearState(This,pipeline_state);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_DrawInstanced(ID3D12GraphicsCommandList2* This,UINT vertex_count_per_instance,UINT instance_count,UINT start_vertex_location,UINT start_instance_location) {
+ This->lpVtbl->DrawInstanced(This,vertex_count_per_instance,instance_count,start_vertex_location,start_instance_location);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_DrawIndexedInstanced(ID3D12GraphicsCommandList2* This,UINT index_count_per_instance,UINT instance_count,UINT start_vertex_location,INT base_vertex_location,UINT start_instance_location) {
+ This->lpVtbl->DrawIndexedInstanced(This,index_count_per_instance,instance_count,start_vertex_location,base_vertex_location,start_instance_location);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_Dispatch(ID3D12GraphicsCommandList2* This,UINT x,UINT u,UINT z) {
+ This->lpVtbl->Dispatch(This,x,u,z);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_CopyBufferRegion(ID3D12GraphicsCommandList2* This,ID3D12Resource *dst_buffer,UINT64 dst_offset,ID3D12Resource *src_buffer,UINT64 src_offset,UINT64 byte_count) {
+ This->lpVtbl->CopyBufferRegion(This,dst_buffer,dst_offset,src_buffer,src_offset,byte_count);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_CopyTextureRegion(ID3D12GraphicsCommandList2* This,const D3D12_TEXTURE_COPY_LOCATION *dst,UINT dst_x,UINT dst_y,UINT dst_z,const D3D12_TEXTURE_COPY_LOCATION *src,const D3D12_BOX *src_box) {
+ This->lpVtbl->CopyTextureRegion(This,dst,dst_x,dst_y,dst_z,src,src_box);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_CopyResource(ID3D12GraphicsCommandList2* This,ID3D12Resource *dst_resource,ID3D12Resource *src_resource) {
+ This->lpVtbl->CopyResource(This,dst_resource,src_resource);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_CopyTiles(ID3D12GraphicsCommandList2* This,ID3D12Resource *tiled_resource,const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,const D3D12_TILE_REGION_SIZE *tile_region_size,ID3D12Resource *buffer,UINT64 buffer_offset,D3D12_TILE_COPY_FLAGS flags) {
+ This->lpVtbl->CopyTiles(This,tiled_resource,tile_region_start_coordinate,tile_region_size,buffer,buffer_offset,flags);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ResolveSubresource(ID3D12GraphicsCommandList2* This,ID3D12Resource *dst_resource,UINT dst_sub_resource,ID3D12Resource *src_resource,UINT src_sub_resource,DXGI_FORMAT format) {
+ This->lpVtbl->ResolveSubresource(This,dst_resource,dst_sub_resource,src_resource,src_sub_resource,format);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_IASetPrimitiveTopology(ID3D12GraphicsCommandList2* This,D3D12_PRIMITIVE_TOPOLOGY primitive_topology) {
+ This->lpVtbl->IASetPrimitiveTopology(This,primitive_topology);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_RSSetViewports(ID3D12GraphicsCommandList2* This,UINT viewport_count,const D3D12_VIEWPORT *viewports) {
+ This->lpVtbl->RSSetViewports(This,viewport_count,viewports);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_RSSetScissorRects(ID3D12GraphicsCommandList2* This,UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->RSSetScissorRects(This,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_OMSetBlendFactor(ID3D12GraphicsCommandList2* This,const FLOAT blend_factor[4]) {
+ This->lpVtbl->OMSetBlendFactor(This,blend_factor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_OMSetStencilRef(ID3D12GraphicsCommandList2* This,UINT stencil_ref) {
+ This->lpVtbl->OMSetStencilRef(This,stencil_ref);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetPipelineState(ID3D12GraphicsCommandList2* This,ID3D12PipelineState *pipeline_state) {
+ This->lpVtbl->SetPipelineState(This,pipeline_state);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ResourceBarrier(ID3D12GraphicsCommandList2* This,UINT barrier_count,const D3D12_RESOURCE_BARRIER *barriers) {
+ This->lpVtbl->ResourceBarrier(This,barrier_count,barriers);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ExecuteBundle(ID3D12GraphicsCommandList2* This,ID3D12GraphicsCommandList *command_list) {
+ This->lpVtbl->ExecuteBundle(This,command_list);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetDescriptorHeaps(ID3D12GraphicsCommandList2* This,UINT heap_count,ID3D12DescriptorHeap *const *heaps) {
+ This->lpVtbl->SetDescriptorHeaps(This,heap_count,heaps);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetComputeRootSignature(ID3D12GraphicsCommandList2* This,ID3D12RootSignature *root_signature) {
+ This->lpVtbl->SetComputeRootSignature(This,root_signature);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetGraphicsRootSignature(ID3D12GraphicsCommandList2* This,ID3D12RootSignature *root_signature) {
+ This->lpVtbl->SetGraphicsRootSignature(This,root_signature);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetComputeRootDescriptorTable(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor) {
+ This->lpVtbl->SetComputeRootDescriptorTable(This,root_parameter_index,base_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetGraphicsRootDescriptorTable(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor) {
+ This->lpVtbl->SetGraphicsRootDescriptorTable(This,root_parameter_index,base_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetComputeRoot32BitConstant(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,UINT data,UINT dst_offset) {
+ This->lpVtbl->SetComputeRoot32BitConstant(This,root_parameter_index,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetGraphicsRoot32BitConstant(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,UINT data,UINT dst_offset) {
+ This->lpVtbl->SetGraphicsRoot32BitConstant(This,root_parameter_index,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetComputeRoot32BitConstants(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,UINT constant_count,const void *data,UINT dst_offset) {
+ This->lpVtbl->SetComputeRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetGraphicsRoot32BitConstants(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,UINT constant_count,const void *data,UINT dst_offset) {
+ This->lpVtbl->SetGraphicsRoot32BitConstants(This,root_parameter_index,constant_count,data,dst_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetComputeRootConstantBufferView(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootConstantBufferView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetGraphicsRootConstantBufferView(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootConstantBufferView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetComputeRootShaderResourceView(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootShaderResourceView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetGraphicsRootShaderResourceView(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootShaderResourceView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetComputeRootUnorderedAccessView(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetComputeRootUnorderedAccessView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetGraphicsRootUnorderedAccessView(ID3D12GraphicsCommandList2* This,UINT root_parameter_index,D3D12_GPU_VIRTUAL_ADDRESS address) {
+ This->lpVtbl->SetGraphicsRootUnorderedAccessView(This,root_parameter_index,address);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_IASetIndexBuffer(ID3D12GraphicsCommandList2* This,const D3D12_INDEX_BUFFER_VIEW *view) {
+ This->lpVtbl->IASetIndexBuffer(This,view);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_IASetVertexBuffers(ID3D12GraphicsCommandList2* This,UINT start_slot,UINT view_count,const D3D12_VERTEX_BUFFER_VIEW *views) {
+ This->lpVtbl->IASetVertexBuffers(This,start_slot,view_count,views);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SOSetTargets(ID3D12GraphicsCommandList2* This,UINT start_slot,UINT view_count,const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views) {
+ This->lpVtbl->SOSetTargets(This,start_slot,view_count,views);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_OMSetRenderTargets(ID3D12GraphicsCommandList2* This,UINT render_target_descriptor_count,const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,BOOL single_descriptor_handle,const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor) {
+ This->lpVtbl->OMSetRenderTargets(This,render_target_descriptor_count,render_target_descriptors,single_descriptor_handle,depth_stencil_descriptor);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ClearDepthStencilView(ID3D12GraphicsCommandList2* This,D3D12_CPU_DESCRIPTOR_HANDLE dsv,D3D12_CLEAR_FLAGS flags,FLOAT depth,UINT8 stencil,UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearDepthStencilView(This,dsv,flags,depth,stencil,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ClearRenderTargetView(ID3D12GraphicsCommandList2* This,D3D12_CPU_DESCRIPTOR_HANDLE rtv,const FLOAT color[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearRenderTargetView(This,rtv,color,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ClearUnorderedAccessViewUint(ID3D12GraphicsCommandList2* This,D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,ID3D12Resource *resource,const UINT values[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearUnorderedAccessViewUint(This,gpu_handle,cpu_handle,resource,values,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList2* This,D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle,ID3D12Resource *resource,const float values[4],UINT rect_count,const D3D12_RECT *rects) {
+ This->lpVtbl->ClearUnorderedAccessViewFloat(This,gpu_handle,cpu_handle,resource,values,rect_count,rects);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_DiscardResource(ID3D12GraphicsCommandList2* This,ID3D12Resource *resource,const D3D12_DISCARD_REGION *region) {
+ This->lpVtbl->DiscardResource(This,resource,region);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_BeginQuery(ID3D12GraphicsCommandList2* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT index) {
+ This->lpVtbl->BeginQuery(This,heap,type,index);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_EndQuery(ID3D12GraphicsCommandList2* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT index) {
+ This->lpVtbl->EndQuery(This,heap,type,index);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ResolveQueryData(ID3D12GraphicsCommandList2* This,ID3D12QueryHeap *heap,D3D12_QUERY_TYPE type,UINT start_index,UINT query_count,ID3D12Resource *dst_buffer,UINT64 aligned_dst_buffer_offset) {
+ This->lpVtbl->ResolveQueryData(This,heap,type,start_index,query_count,dst_buffer,aligned_dst_buffer_offset);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetPredication(ID3D12GraphicsCommandList2* This,ID3D12Resource *buffer,UINT64 aligned_buffer_offset,D3D12_PREDICATION_OP operation) {
+ This->lpVtbl->SetPredication(This,buffer,aligned_buffer_offset,operation);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetMarker(ID3D12GraphicsCommandList2* This,UINT metadata,const void *data,UINT size) {
+ This->lpVtbl->SetMarker(This,metadata,data,size);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_BeginEvent(ID3D12GraphicsCommandList2* This,UINT metadata,const void *data,UINT size) {
+ This->lpVtbl->BeginEvent(This,metadata,data,size);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_EndEvent(ID3D12GraphicsCommandList2* This) {
+ This->lpVtbl->EndEvent(This);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ExecuteIndirect(ID3D12GraphicsCommandList2* This,ID3D12CommandSignature *command_signature,UINT max_command_count,ID3D12Resource *arg_buffer,UINT64 arg_buffer_offset,ID3D12Resource *count_buffer,UINT64 count_buffer_offset) {
+ This->lpVtbl->ExecuteIndirect(This,command_signature,max_command_count,arg_buffer,arg_buffer_offset,count_buffer,count_buffer_offset);
+}
+/*** ID3D12GraphicsCommandList1 methods ***/
+static FORCEINLINE void ID3D12GraphicsCommandList2_AtomicCopyBufferUINT(ID3D12GraphicsCommandList2* This,ID3D12Resource *dst_buffer,UINT64 dst_offset,ID3D12Resource *src_buffer,UINT64 src_offset,UINT dependent_resource_count,ID3D12Resource *const *dependent_resources,const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) {
+ This->lpVtbl->AtomicCopyBufferUINT(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_AtomicCopyBufferUINT64(ID3D12GraphicsCommandList2* This,ID3D12Resource *dst_buffer,UINT64 dst_offset,ID3D12Resource *src_buffer,UINT64 src_offset,UINT dependent_resource_count,ID3D12Resource *const *dependent_resources,const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) {
+ This->lpVtbl->AtomicCopyBufferUINT64(This,dst_buffer,dst_offset,src_buffer,src_offset,dependent_resource_count,dependent_resources,dependent_sub_resource_ranges);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_OMSetDepthBounds(ID3D12GraphicsCommandList2* This,FLOAT min,FLOAT max) {
+ This->lpVtbl->OMSetDepthBounds(This,min,max);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetSamplePositions(ID3D12GraphicsCommandList2* This,UINT sample_count,UINT pixel_count,D3D12_SAMPLE_POSITION *sample_positions) {
+ This->lpVtbl->SetSamplePositions(This,sample_count,pixel_count,sample_positions);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_ResolveSubresourceRegion(ID3D12GraphicsCommandList2* This,ID3D12Resource *dst_resource,UINT dst_sub_resource_idx,UINT dst_x,UINT dst_y,ID3D12Resource *src_resource,UINT src_sub_resource_idx,D3D12_RECT *src_rect,DXGI_FORMAT format,D3D12_RESOLVE_MODE mode) {
+ This->lpVtbl->ResolveSubresourceRegion(This,dst_resource,dst_sub_resource_idx,dst_x,dst_y,src_resource,src_sub_resource_idx,src_rect,format,mode);
+}
+static FORCEINLINE void ID3D12GraphicsCommandList2_SetViewInstanceMask(ID3D12GraphicsCommandList2* This,UINT mask) {
+ This->lpVtbl->SetViewInstanceMask(This,mask);
+}
+/*** ID3D12GraphicsCommandList2 methods ***/
+static FORCEINLINE void ID3D12GraphicsCommandList2_WriteBufferImmediate(ID3D12GraphicsCommandList2* This,UINT count,const D3D12_WRITEBUFFERIMMEDIATE_PARAMETER *parameters,const D3D12_WRITEBUFFERIMMEDIATE_MODE *modes) {
+ This->lpVtbl->WriteBufferImmediate(This,count,parameters,modes);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12GraphicsCommandList2_INTERFACE_DEFINED__ */
+
+typedef enum D3D12_TILE_RANGE_FLAGS {
+ D3D12_TILE_RANGE_FLAG_NONE = 0x0,
+ D3D12_TILE_RANGE_FLAG_NULL = 0x1,
+ D3D12_TILE_RANGE_FLAG_SKIP = 0x2,
+ D3D12_TILE_RANGE_FLAG_REUSE_SINGLE_TILE = 0x4
+} D3D12_TILE_RANGE_FLAGS;
+typedef enum D3D12_TILE_MAPPING_FLAGS {
+ D3D12_TILE_MAPPING_FLAG_NONE = 0x0,
+ D3D12_TILE_MAPPING_FLAG_NO_HAZARD = 0x1
+} D3D12_TILE_MAPPING_FLAGS;
+/*****************************************************************************
+ * ID3D12CommandQueue interface
+ */
+#ifndef __ID3D12CommandQueue_INTERFACE_DEFINED__
+#define __ID3D12CommandQueue_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12CommandQueue, 0x0ec870a6, 0x5d7e, 0x4c22, 0x8c,0xfc, 0x5b,0xaa,0xe0,0x76,0x16,0xed);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("0ec870a6-5d7e-4c22-8cfc-5baae07616ed")
+ID3D12CommandQueue : public ID3D12Pageable
+{
+ virtual void STDMETHODCALLTYPE UpdateTileMappings(
+ ID3D12Resource *resource,
+ UINT region_count,
+ const D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates,
+ const D3D12_TILE_REGION_SIZE *region_sizes,
+ UINT range_count,
+ const D3D12_TILE_RANGE_FLAGS *range_flags,
+ UINT *heap_range_offsets,
+ UINT *range_tile_counts,
+ D3D12_TILE_MAPPING_FLAGS flags) = 0;
+
+ virtual void STDMETHODCALLTYPE CopyTileMappings(
+ ID3D12Resource *dst_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *dst_region_start_coordinate,
+ ID3D12Resource *src_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *src_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *region_size,
+ D3D12_TILE_MAPPING_FLAGS flags) = 0;
+
+ virtual void STDMETHODCALLTYPE ExecuteCommandLists(
+ UINT command_list_count,
+ ID3D12CommandList *const *command_lists) = 0;
+
+ virtual void STDMETHODCALLTYPE SetMarker(
+ UINT metadata,
+ const void *data,
+ UINT size) = 0;
+
+ virtual void STDMETHODCALLTYPE BeginEvent(
+ UINT metadata,
+ const void *data,
+ UINT size) = 0;
+
+ virtual void STDMETHODCALLTYPE EndEvent(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Signal(
+ ID3D12Fence *fence,
+ UINT64 value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Wait(
+ ID3D12Fence *fence,
+ UINT64 value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimestampFrequency(
+ UINT64 *frequency) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetClockCalibration(
+ UINT64 *gpu_timestamp,
+ UINT64 *cpu_timestamp) = 0;
+
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual D3D12_COMMAND_QUEUE_DESC* STDMETHODCALLTYPE GetDesc(
+ D3D12_COMMAND_QUEUE_DESC *__ret) = 0;
+ D3D12_COMMAND_QUEUE_DESC STDMETHODCALLTYPE GetDesc(
+ )
+ {
+ D3D12_COMMAND_QUEUE_DESC __ret;
+ return *GetDesc(&__ret);
+ }
+#else
+ virtual D3D12_COMMAND_QUEUE_DESC STDMETHODCALLTYPE GetDesc(
+ ) = 0;
+#endif
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12CommandQueue, 0x0ec870a6, 0x5d7e, 0x4c22, 0x8c,0xfc, 0x5b,0xaa,0xe0,0x76,0x16,0xed)
+#endif
+#else
+typedef struct ID3D12CommandQueueVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12CommandQueue *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12CommandQueue *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12CommandQueue *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12CommandQueue *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12CommandQueue *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12CommandQueue *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12CommandQueue *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12CommandQueue *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12CommandQueue methods ***/
+ void (STDMETHODCALLTYPE *UpdateTileMappings)(
+ ID3D12CommandQueue *This,
+ ID3D12Resource *resource,
+ UINT region_count,
+ const D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates,
+ const D3D12_TILE_REGION_SIZE *region_sizes,
+ UINT range_count,
+ const D3D12_TILE_RANGE_FLAGS *range_flags,
+ UINT *heap_range_offsets,
+ UINT *range_tile_counts,
+ D3D12_TILE_MAPPING_FLAGS flags);
+
+ void (STDMETHODCALLTYPE *CopyTileMappings)(
+ ID3D12CommandQueue *This,
+ ID3D12Resource *dst_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *dst_region_start_coordinate,
+ ID3D12Resource *src_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *src_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *region_size,
+ D3D12_TILE_MAPPING_FLAGS flags);
+
+ void (STDMETHODCALLTYPE *ExecuteCommandLists)(
+ ID3D12CommandQueue *This,
+ UINT command_list_count,
+ ID3D12CommandList *const *command_lists);
+
+ void (STDMETHODCALLTYPE *SetMarker)(
+ ID3D12CommandQueue *This,
+ UINT metadata,
+ const void *data,
+ UINT size);
+
+ void (STDMETHODCALLTYPE *BeginEvent)(
+ ID3D12CommandQueue *This,
+ UINT metadata,
+ const void *data,
+ UINT size);
+
+ void (STDMETHODCALLTYPE *EndEvent)(
+ ID3D12CommandQueue *This);
+
+ HRESULT (STDMETHODCALLTYPE *Signal)(
+ ID3D12CommandQueue *This,
+ ID3D12Fence *fence,
+ UINT64 value);
+
+ HRESULT (STDMETHODCALLTYPE *Wait)(
+ ID3D12CommandQueue *This,
+ ID3D12Fence *fence,
+ UINT64 value);
+
+ HRESULT (STDMETHODCALLTYPE *GetTimestampFrequency)(
+ ID3D12CommandQueue *This,
+ UINT64 *frequency);
+
+ HRESULT (STDMETHODCALLTYPE *GetClockCalibration)(
+ ID3D12CommandQueue *This,
+ UINT64 *gpu_timestamp,
+ UINT64 *cpu_timestamp);
+
+ D3D12_COMMAND_QUEUE_DESC * (STDMETHODCALLTYPE *GetDesc)(
+ ID3D12CommandQueue *This,
+ D3D12_COMMAND_QUEUE_DESC *__ret);
+
+ END_INTERFACE
+} ID3D12CommandQueueVtbl;
+
+interface ID3D12CommandQueue {
+ CONST_VTBL ID3D12CommandQueueVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12CommandQueue_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12CommandQueue_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12CommandQueue_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12CommandQueue_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12CommandQueue_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12CommandQueue_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12CommandQueue_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12CommandQueue_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12CommandQueue methods ***/
+#define ID3D12CommandQueue_UpdateTileMappings(This,resource,region_count,region_start_coordinates,region_sizes,range_count,range_flags,heap_range_offsets,range_tile_counts,flags) (This)->lpVtbl->UpdateTileMappings(This,resource,region_count,region_start_coordinates,region_sizes,range_count,range_flags,heap_range_offsets,range_tile_counts,flags)
+#define ID3D12CommandQueue_CopyTileMappings(This,dst_resource,dst_region_start_coordinate,src_resource,src_region_start_coordinate,region_size,flags) (This)->lpVtbl->CopyTileMappings(This,dst_resource,dst_region_start_coordinate,src_resource,src_region_start_coordinate,region_size,flags)
+#define ID3D12CommandQueue_ExecuteCommandLists(This,command_list_count,command_lists) (This)->lpVtbl->ExecuteCommandLists(This,command_list_count,command_lists)
+#define ID3D12CommandQueue_SetMarker(This,metadata,data,size) (This)->lpVtbl->SetMarker(This,metadata,data,size)
+#define ID3D12CommandQueue_BeginEvent(This,metadata,data,size) (This)->lpVtbl->BeginEvent(This,metadata,data,size)
+#define ID3D12CommandQueue_EndEvent(This) (This)->lpVtbl->EndEvent(This)
+#define ID3D12CommandQueue_Signal(This,fence,value) (This)->lpVtbl->Signal(This,fence,value)
+#define ID3D12CommandQueue_Wait(This,fence,value) (This)->lpVtbl->Wait(This,fence,value)
+#define ID3D12CommandQueue_GetTimestampFrequency(This,frequency) (This)->lpVtbl->GetTimestampFrequency(This,frequency)
+#define ID3D12CommandQueue_GetClockCalibration(This,gpu_timestamp,cpu_timestamp) (This)->lpVtbl->GetClockCalibration(This,gpu_timestamp,cpu_timestamp)
+#define ID3D12CommandQueue_GetDesc(This) ID3D12CommandQueue_GetDesc_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12CommandQueue_QueryInterface(ID3D12CommandQueue* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12CommandQueue_AddRef(ID3D12CommandQueue* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12CommandQueue_Release(ID3D12CommandQueue* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12CommandQueue_GetPrivateData(ID3D12CommandQueue* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandQueue_SetPrivateData(ID3D12CommandQueue* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandQueue_SetPrivateDataInterface(ID3D12CommandQueue* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandQueue_SetName(ID3D12CommandQueue* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12CommandQueue_GetDevice(ID3D12CommandQueue* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12CommandQueue methods ***/
+static FORCEINLINE void ID3D12CommandQueue_UpdateTileMappings(ID3D12CommandQueue* This,ID3D12Resource *resource,UINT region_count,const D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates,const D3D12_TILE_REGION_SIZE *region_sizes,UINT range_count,const D3D12_TILE_RANGE_FLAGS *range_flags,UINT *heap_range_offsets,UINT *range_tile_counts,D3D12_TILE_MAPPING_FLAGS flags) {
+ This->lpVtbl->UpdateTileMappings(This,resource,region_count,region_start_coordinates,region_sizes,range_count,range_flags,heap_range_offsets,range_tile_counts,flags);
+}
+static FORCEINLINE void ID3D12CommandQueue_CopyTileMappings(ID3D12CommandQueue* This,ID3D12Resource *dst_resource,const D3D12_TILED_RESOURCE_COORDINATE *dst_region_start_coordinate,ID3D12Resource *src_resource,const D3D12_TILED_RESOURCE_COORDINATE *src_region_start_coordinate,const D3D12_TILE_REGION_SIZE *region_size,D3D12_TILE_MAPPING_FLAGS flags) {
+ This->lpVtbl->CopyTileMappings(This,dst_resource,dst_region_start_coordinate,src_resource,src_region_start_coordinate,region_size,flags);
+}
+static FORCEINLINE void ID3D12CommandQueue_ExecuteCommandLists(ID3D12CommandQueue* This,UINT command_list_count,ID3D12CommandList *const *command_lists) {
+ This->lpVtbl->ExecuteCommandLists(This,command_list_count,command_lists);
+}
+static FORCEINLINE void ID3D12CommandQueue_SetMarker(ID3D12CommandQueue* This,UINT metadata,const void *data,UINT size) {
+ This->lpVtbl->SetMarker(This,metadata,data,size);
+}
+static FORCEINLINE void ID3D12CommandQueue_BeginEvent(ID3D12CommandQueue* This,UINT metadata,const void *data,UINT size) {
+ This->lpVtbl->BeginEvent(This,metadata,data,size);
+}
+static FORCEINLINE void ID3D12CommandQueue_EndEvent(ID3D12CommandQueue* This) {
+ This->lpVtbl->EndEvent(This);
+}
+static FORCEINLINE HRESULT ID3D12CommandQueue_Signal(ID3D12CommandQueue* This,ID3D12Fence *fence,UINT64 value) {
+ return This->lpVtbl->Signal(This,fence,value);
+}
+static FORCEINLINE HRESULT ID3D12CommandQueue_Wait(ID3D12CommandQueue* This,ID3D12Fence *fence,UINT64 value) {
+ return This->lpVtbl->Wait(This,fence,value);
+}
+static FORCEINLINE HRESULT ID3D12CommandQueue_GetTimestampFrequency(ID3D12CommandQueue* This,UINT64 *frequency) {
+ return This->lpVtbl->GetTimestampFrequency(This,frequency);
+}
+static FORCEINLINE HRESULT ID3D12CommandQueue_GetClockCalibration(ID3D12CommandQueue* This,UINT64 *gpu_timestamp,UINT64 *cpu_timestamp) {
+ return This->lpVtbl->GetClockCalibration(This,gpu_timestamp,cpu_timestamp);
+}
+static FORCEINLINE D3D12_COMMAND_QUEUE_DESC ID3D12CommandQueue_GetDesc(ID3D12CommandQueue* This) {
+ D3D12_COMMAND_QUEUE_DESC __ret;
+ return *This->lpVtbl->GetDesc(This,&__ret);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12CommandQueue_INTERFACE_DEFINED__ */
+
+typedef enum D3D12_FENCE_FLAGS {
+ D3D12_FENCE_FLAG_NONE = 0x0,
+ D3D12_FENCE_FLAG_SHARED = 0x1,
+ D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER = 0x2
+} D3D12_FENCE_FLAGS;
+typedef enum D3D12_QUERY_HEAP_TYPE {
+ D3D12_QUERY_HEAP_TYPE_OCCLUSION = 0,
+ D3D12_QUERY_HEAP_TYPE_TIMESTAMP = 1,
+ D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS = 2,
+ D3D12_QUERY_HEAP_TYPE_SO_STATISTICS = 3
+} D3D12_QUERY_HEAP_TYPE;
+typedef struct D3D12_QUERY_HEAP_DESC {
+ D3D12_QUERY_HEAP_TYPE Type;
+ UINT Count;
+ UINT NodeMask;
+} D3D12_QUERY_HEAP_DESC;
+typedef enum D3D12_INDIRECT_ARGUMENT_TYPE {
+ D3D12_INDIRECT_ARGUMENT_TYPE_DRAW = 0,
+ D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED = 1,
+ D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH = 2,
+ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW = 3,
+ D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW = 4,
+ D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT = 5,
+ D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW = 6,
+ D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW = 7,
+ D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW = 8
+} D3D12_INDIRECT_ARGUMENT_TYPE;
+typedef struct D3D12_INDIRECT_ARGUMENT_DESC {
+ D3D12_INDIRECT_ARGUMENT_TYPE Type;
+ __C89_NAMELESS union {
+ struct {
+ UINT Slot;
+ } VertexBuffer;
+ struct {
+ UINT RootParameterIndex;
+ UINT DestOffsetIn32BitValues;
+ UINT Num32BitValuesToSet;
+ } Constant;
+ struct {
+ UINT RootParameterIndex;
+ } ConstantBufferView;
+ struct {
+ UINT RootParameterIndex;
+ } ShaderResourceView;
+ struct {
+ UINT RootParameterIndex;
+ } UnorderedAccessView;
+ } __C89_NAMELESSUNIONNAME;
+} D3D12_INDIRECT_ARGUMENT_DESC;
+typedef struct D3D12_COMMAND_SIGNATURE_DESC {
+ UINT ByteStride;
+ UINT NumArgumentDescs;
+ const D3D12_INDIRECT_ARGUMENT_DESC *pArgumentDescs;
+ UINT NodeMask;
+} D3D12_COMMAND_SIGNATURE_DESC;
+/*****************************************************************************
+ * ID3D12RootSignature interface
+ */
+#ifndef __ID3D12RootSignature_INTERFACE_DEFINED__
+#define __ID3D12RootSignature_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12RootSignature, 0xc54a6b66, 0x72df, 0x4ee8, 0x8b,0xe5, 0xa9,0x46,0xa1,0x42,0x92,0x14);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("c54a6b66-72df-4ee8-8be5-a946a1429214")
+ID3D12RootSignature : public ID3D12DeviceChild
+{
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12RootSignature, 0xc54a6b66, 0x72df, 0x4ee8, 0x8b,0xe5, 0xa9,0x46,0xa1,0x42,0x92,0x14)
+#endif
+#else
+typedef struct ID3D12RootSignatureVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12RootSignature *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12RootSignature *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12RootSignature *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12RootSignature *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12RootSignature *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12RootSignature *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12RootSignature *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12RootSignature *This,
+ REFIID riid,
+ void **device);
+
+ END_INTERFACE
+} ID3D12RootSignatureVtbl;
+
+interface ID3D12RootSignature {
+ CONST_VTBL ID3D12RootSignatureVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12RootSignature_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12RootSignature_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12RootSignature_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12RootSignature_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12RootSignature_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12RootSignature_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12RootSignature_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12RootSignature_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12RootSignature_QueryInterface(ID3D12RootSignature* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12RootSignature_AddRef(ID3D12RootSignature* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12RootSignature_Release(ID3D12RootSignature* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12RootSignature_GetPrivateData(ID3D12RootSignature* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12RootSignature_SetPrivateData(ID3D12RootSignature* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12RootSignature_SetPrivateDataInterface(ID3D12RootSignature* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12RootSignature_SetName(ID3D12RootSignature* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12RootSignature_GetDevice(ID3D12RootSignature* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12RootSignature_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12PipelineState interface
+ */
+#ifndef __ID3D12PipelineState_INTERFACE_DEFINED__
+#define __ID3D12PipelineState_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12PipelineState, 0x765a30f3, 0xf624, 0x4c6f, 0xa8,0x28, 0xac,0xe9,0x48,0x62,0x24,0x45);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("765a30f3-f624-4c6f-a828-ace948622445")
+ID3D12PipelineState : public ID3D12Pageable
+{
+ virtual HRESULT STDMETHODCALLTYPE GetCachedBlob(
+ ID3DBlob **blob) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12PipelineState, 0x765a30f3, 0xf624, 0x4c6f, 0xa8,0x28, 0xac,0xe9,0x48,0x62,0x24,0x45)
+#endif
+#else
+typedef struct ID3D12PipelineStateVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12PipelineState *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12PipelineState *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12PipelineState *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12PipelineState *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12PipelineState *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12PipelineState *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12PipelineState *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12PipelineState *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12PipelineState methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetCachedBlob)(
+ ID3D12PipelineState *This,
+ ID3DBlob **blob);
+
+ END_INTERFACE
+} ID3D12PipelineStateVtbl;
+
+interface ID3D12PipelineState {
+ CONST_VTBL ID3D12PipelineStateVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12PipelineState_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12PipelineState_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12PipelineState_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12PipelineState_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12PipelineState_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12PipelineState_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12PipelineState_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12PipelineState_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12PipelineState methods ***/
+#define ID3D12PipelineState_GetCachedBlob(This,blob) (This)->lpVtbl->GetCachedBlob(This,blob)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12PipelineState_QueryInterface(ID3D12PipelineState* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12PipelineState_AddRef(ID3D12PipelineState* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12PipelineState_Release(ID3D12PipelineState* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12PipelineState_GetPrivateData(ID3D12PipelineState* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12PipelineState_SetPrivateData(ID3D12PipelineState* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12PipelineState_SetPrivateDataInterface(ID3D12PipelineState* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12PipelineState_SetName(ID3D12PipelineState* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12PipelineState_GetDevice(ID3D12PipelineState* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12PipelineState methods ***/
+static FORCEINLINE HRESULT ID3D12PipelineState_GetCachedBlob(ID3D12PipelineState* This,ID3DBlob **blob) {
+ return This->lpVtbl->GetCachedBlob(This,blob);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12PipelineState_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12Fence interface
+ */
+#ifndef __ID3D12Fence_INTERFACE_DEFINED__
+#define __ID3D12Fence_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Fence, 0x0a753dcf, 0xc4d8, 0x4b91, 0xad,0xf6, 0xbe,0x5a,0x60,0xd9,0x5a,0x76);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("0a753dcf-c4d8-4b91-adf6-be5a60d95a76")
+ID3D12Fence : public ID3D12Pageable
+{
+ virtual UINT64 STDMETHODCALLTYPE GetCompletedValue(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetEventOnCompletion(
+ UINT64 value,
+ HANDLE event) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Signal(
+ UINT64 value) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Fence, 0x0a753dcf, 0xc4d8, 0x4b91, 0xad,0xf6, 0xbe,0x5a,0x60,0xd9,0x5a,0x76)
+#endif
+#else
+typedef struct ID3D12FenceVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Fence *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Fence *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Fence *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12Fence *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12Fence *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12Fence *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12Fence *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12Fence *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12Fence methods ***/
+ UINT64 (STDMETHODCALLTYPE *GetCompletedValue)(
+ ID3D12Fence *This);
+
+ HRESULT (STDMETHODCALLTYPE *SetEventOnCompletion)(
+ ID3D12Fence *This,
+ UINT64 value,
+ HANDLE event);
+
+ HRESULT (STDMETHODCALLTYPE *Signal)(
+ ID3D12Fence *This,
+ UINT64 value);
+
+ END_INTERFACE
+} ID3D12FenceVtbl;
+
+interface ID3D12Fence {
+ CONST_VTBL ID3D12FenceVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Fence_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Fence_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Fence_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12Fence_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12Fence_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12Fence_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12Fence_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12Fence_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12Fence methods ***/
+#define ID3D12Fence_GetCompletedValue(This) (This)->lpVtbl->GetCompletedValue(This)
+#define ID3D12Fence_SetEventOnCompletion(This,value,event) (This)->lpVtbl->SetEventOnCompletion(This,value,event)
+#define ID3D12Fence_Signal(This,value) (This)->lpVtbl->Signal(This,value)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Fence_QueryInterface(ID3D12Fence* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Fence_AddRef(ID3D12Fence* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Fence_Release(ID3D12Fence* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12Fence_GetPrivateData(ID3D12Fence* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Fence_SetPrivateData(ID3D12Fence* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Fence_SetPrivateDataInterface(ID3D12Fence* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12Fence_SetName(ID3D12Fence* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12Fence_GetDevice(ID3D12Fence* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12Fence methods ***/
+static FORCEINLINE UINT64 ID3D12Fence_GetCompletedValue(ID3D12Fence* This) {
+ return This->lpVtbl->GetCompletedValue(This);
+}
+static FORCEINLINE HRESULT ID3D12Fence_SetEventOnCompletion(ID3D12Fence* This,UINT64 value,HANDLE event) {
+ return This->lpVtbl->SetEventOnCompletion(This,value,event);
+}
+static FORCEINLINE HRESULT ID3D12Fence_Signal(ID3D12Fence* This,UINT64 value) {
+ return This->lpVtbl->Signal(This,value);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Fence_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12CommandAllocator interface
+ */
+#ifndef __ID3D12CommandAllocator_INTERFACE_DEFINED__
+#define __ID3D12CommandAllocator_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12CommandAllocator, 0x6102dee4, 0xaf59, 0x4b09, 0xb9,0x99, 0xb4,0x4d,0x73,0xf0,0x9b,0x24);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("6102dee4-af59-4b09-b999-b44d73f09b24")
+ID3D12CommandAllocator : public ID3D12Pageable
+{
+ virtual HRESULT STDMETHODCALLTYPE Reset(
+ ) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12CommandAllocator, 0x6102dee4, 0xaf59, 0x4b09, 0xb9,0x99, 0xb4,0x4d,0x73,0xf0,0x9b,0x24)
+#endif
+#else
+typedef struct ID3D12CommandAllocatorVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12CommandAllocator *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12CommandAllocator *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12CommandAllocator *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12CommandAllocator *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12CommandAllocator *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12CommandAllocator *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12CommandAllocator *This,
+ const WCHAR *name);
+
+ /*** ID3D12DeviceChild methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ ID3D12CommandAllocator *This,
+ REFIID riid,
+ void **device);
+
+ /*** ID3D12CommandAllocator methods ***/
+ HRESULT (STDMETHODCALLTYPE *Reset)(
+ ID3D12CommandAllocator *This);
+
+ END_INTERFACE
+} ID3D12CommandAllocatorVtbl;
+
+interface ID3D12CommandAllocator {
+ CONST_VTBL ID3D12CommandAllocatorVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12CommandAllocator_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12CommandAllocator_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12CommandAllocator_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12CommandAllocator_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12CommandAllocator_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12CommandAllocator_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12CommandAllocator_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12DeviceChild methods ***/
+#define ID3D12CommandAllocator_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** ID3D12CommandAllocator methods ***/
+#define ID3D12CommandAllocator_Reset(This) (This)->lpVtbl->Reset(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12CommandAllocator_QueryInterface(ID3D12CommandAllocator* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12CommandAllocator_AddRef(ID3D12CommandAllocator* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12CommandAllocator_Release(ID3D12CommandAllocator* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12CommandAllocator_GetPrivateData(ID3D12CommandAllocator* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandAllocator_SetPrivateData(ID3D12CommandAllocator* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandAllocator_SetPrivateDataInterface(ID3D12CommandAllocator* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12CommandAllocator_SetName(ID3D12CommandAllocator* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12DeviceChild methods ***/
+static FORCEINLINE HRESULT ID3D12CommandAllocator_GetDevice(ID3D12CommandAllocator* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** ID3D12CommandAllocator methods ***/
+static FORCEINLINE HRESULT ID3D12CommandAllocator_Reset(ID3D12CommandAllocator* This) {
+ return This->lpVtbl->Reset(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12CommandAllocator_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12Device interface
+ */
+#ifndef __ID3D12Device_INTERFACE_DEFINED__
+#define __ID3D12Device_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Device, 0x189819f1, 0x1db6, 0x4b57, 0xbe,0x54, 0x18,0x21,0x33,0x9b,0x85,0xf7);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("189819f1-1db6-4b57-be54-1821339b85f7")
+ID3D12Device : public ID3D12Object
+{
+ virtual UINT STDMETHODCALLTYPE GetNodeCount(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateCommandQueue(
+ const D3D12_COMMAND_QUEUE_DESC *desc,
+ REFIID riid,
+ void **command_queue) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateCommandAllocator(
+ D3D12_COMMAND_LIST_TYPE type,
+ REFIID riid,
+ void **command_allocator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateGraphicsPipelineState(
+ const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,
+ REFIID riid,
+ void **pipeline_state) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateComputePipelineState(
+ const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc,
+ REFIID riid,
+ void **pipeline_state) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateCommandList(
+ UINT node_mask,
+ D3D12_COMMAND_LIST_TYPE type,
+ ID3D12CommandAllocator *command_allocator,
+ ID3D12PipelineState *initial_pipeline_state,
+ REFIID riid,
+ void **command_list) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport(
+ D3D12_FEATURE feature,
+ void *feature_data,
+ UINT feature_data_size) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateDescriptorHeap(
+ const D3D12_DESCRIPTOR_HEAP_DESC *desc,
+ REFIID riid,
+ void **descriptor_heap) = 0;
+
+ virtual UINT STDMETHODCALLTYPE GetDescriptorHandleIncrementSize(
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateRootSignature(
+ UINT node_mask,
+ const void *bytecode,
+ SIZE_T bytecode_length,
+ REFIID riid,
+ void **root_signature) = 0;
+
+ virtual void STDMETHODCALLTYPE CreateConstantBufferView(
+ const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE CreateShaderResourceView(
+ ID3D12Resource *resource,
+ const D3D12_SHADER_RESOURCE_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE CreateUnorderedAccessView(
+ ID3D12Resource *resource,
+ ID3D12Resource *counter_resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE CreateRenderTargetView(
+ ID3D12Resource *resource,
+ const D3D12_RENDER_TARGET_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE CreateDepthStencilView(
+ ID3D12Resource *resource,
+ const D3D12_DEPTH_STENCIL_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE CreateSampler(
+ const D3D12_SAMPLER_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor) = 0;
+
+ virtual void STDMETHODCALLTYPE CopyDescriptors(
+ UINT dst_descriptor_range_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *dst_descriptor_range_offsets,
+ const UINT *dst_descriptor_range_sizes,
+ UINT src_descriptor_range_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *src_descriptor_range_offsets,
+ const UINT *src_descriptor_range_sizes,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) = 0;
+
+ virtual void STDMETHODCALLTYPE CopyDescriptorsSimple(
+ UINT descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE dst_descriptor_range_offset,
+ const D3D12_CPU_DESCRIPTOR_HANDLE src_descriptor_range_offset,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) = 0;
+
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual D3D12_RESOURCE_ALLOCATION_INFO* STDMETHODCALLTYPE GetResourceAllocationInfo(
+ D3D12_RESOURCE_ALLOCATION_INFO *__ret,
+ UINT visible_mask,
+ UINT reource_desc_count,
+ const D3D12_RESOURCE_DESC *resource_descs) = 0;
+ D3D12_RESOURCE_ALLOCATION_INFO STDMETHODCALLTYPE GetResourceAllocationInfo(
+ UINT visible_mask,
+ UINT reource_desc_count,
+ const D3D12_RESOURCE_DESC *resource_descs)
+ {
+ D3D12_RESOURCE_ALLOCATION_INFO __ret;
+ return *GetResourceAllocationInfo(&__ret, visible_mask, reource_desc_count, resource_descs);
+ }
+#else
+ virtual D3D12_RESOURCE_ALLOCATION_INFO STDMETHODCALLTYPE GetResourceAllocationInfo(
+ UINT visible_mask,
+ UINT reource_desc_count,
+ const D3D12_RESOURCE_DESC *resource_descs) = 0;
+#endif
+
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual D3D12_HEAP_PROPERTIES* STDMETHODCALLTYPE GetCustomHeapProperties(
+ D3D12_HEAP_PROPERTIES *__ret,
+ UINT node_mask,
+ D3D12_HEAP_TYPE heap_type) = 0;
+ D3D12_HEAP_PROPERTIES STDMETHODCALLTYPE GetCustomHeapProperties(
+ UINT node_mask,
+ D3D12_HEAP_TYPE heap_type)
+ {
+ D3D12_HEAP_PROPERTIES __ret;
+ return *GetCustomHeapProperties(&__ret, node_mask, heap_type);
+ }
+#else
+ virtual D3D12_HEAP_PROPERTIES STDMETHODCALLTYPE GetCustomHeapProperties(
+ UINT node_mask,
+ D3D12_HEAP_TYPE heap_type) = 0;
+#endif
+
+ virtual HRESULT STDMETHODCALLTYPE CreateCommittedResource(
+ const D3D12_HEAP_PROPERTIES *heap_properties,
+ D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateHeap(
+ const D3D12_HEAP_DESC *desc,
+ REFIID riid,
+ void **heap) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreatePlacedResource(
+ ID3D12Heap *heap,
+ UINT64 heap_offset,
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateReservedResource(
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateSharedHandle(
+ ID3D12DeviceChild *object,
+ const SECURITY_ATTRIBUTES *attributes,
+ DWORD access,
+ const WCHAR *name,
+ HANDLE *handle) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE OpenSharedHandle(
+ HANDLE handle,
+ REFIID riid,
+ void **object) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE OpenSharedHandleByName(
+ const WCHAR *name,
+ DWORD access,
+ HANDLE *handle) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MakeResident(
+ UINT object_count,
+ ID3D12Pageable *const *objects) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Evict(
+ UINT object_count,
+ ID3D12Pageable *const *objects) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateFence(
+ UINT64 initial_value,
+ D3D12_FENCE_FLAGS flags,
+ REFIID riid,
+ void **fence) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(
+ ) = 0;
+
+ virtual void STDMETHODCALLTYPE GetCopyableFootprints(
+ const D3D12_RESOURCE_DESC *desc,
+ UINT first_sub_resource,
+ UINT sub_resource_count,
+ UINT64 base_offset,
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts,
+ UINT *row_count,
+ UINT64 *row_size,
+ UINT64 *total_bytes) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateQueryHeap(
+ const D3D12_QUERY_HEAP_DESC *desc,
+ REFIID riid,
+ void **heap) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetStablePowerState(
+ BOOL enable) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateCommandSignature(
+ const D3D12_COMMAND_SIGNATURE_DESC *desc,
+ ID3D12RootSignature *root_signature,
+ REFIID riid,
+ void **command_signature) = 0;
+
+ virtual void STDMETHODCALLTYPE GetResourceTiling(
+ ID3D12Resource *resource,
+ UINT *total_tile_count,
+ D3D12_PACKED_MIP_INFO *packed_mip_info,
+ D3D12_TILE_SHAPE *standard_tile_shape,
+ UINT *sub_resource_tiling_count,
+ UINT first_sub_resource_tiling,
+ D3D12_SUBRESOURCE_TILING *sub_resource_tilings) = 0;
+
+#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS
+ virtual LUID* STDMETHODCALLTYPE GetAdapterLuid(
+ LUID *__ret) = 0;
+ LUID STDMETHODCALLTYPE GetAdapterLuid(
+ )
+ {
+ LUID __ret;
+ return *GetAdapterLuid(&__ret);
+ }
+#else
+ virtual LUID STDMETHODCALLTYPE GetAdapterLuid(
+ ) = 0;
+#endif
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Device, 0x189819f1, 0x1db6, 0x4b57, 0xbe,0x54, 0x18,0x21,0x33,0x9b,0x85,0xf7)
+#endif
+#else
+typedef struct ID3D12DeviceVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Device *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Device *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Device *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12Device *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12Device *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12Device *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12Device *This,
+ const WCHAR *name);
+
+ /*** ID3D12Device methods ***/
+ UINT (STDMETHODCALLTYPE *GetNodeCount)(
+ ID3D12Device *This);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommandQueue)(
+ ID3D12Device *This,
+ const D3D12_COMMAND_QUEUE_DESC *desc,
+ REFIID riid,
+ void **command_queue);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommandAllocator)(
+ ID3D12Device *This,
+ D3D12_COMMAND_LIST_TYPE type,
+ REFIID riid,
+ void **command_allocator);
+
+ HRESULT (STDMETHODCALLTYPE *CreateGraphicsPipelineState)(
+ ID3D12Device *This,
+ const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,
+ REFIID riid,
+ void **pipeline_state);
+
+ HRESULT (STDMETHODCALLTYPE *CreateComputePipelineState)(
+ ID3D12Device *This,
+ const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc,
+ REFIID riid,
+ void **pipeline_state);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommandList)(
+ ID3D12Device *This,
+ UINT node_mask,
+ D3D12_COMMAND_LIST_TYPE type,
+ ID3D12CommandAllocator *command_allocator,
+ ID3D12PipelineState *initial_pipeline_state,
+ REFIID riid,
+ void **command_list);
+
+ HRESULT (STDMETHODCALLTYPE *CheckFeatureSupport)(
+ ID3D12Device *This,
+ D3D12_FEATURE feature,
+ void *feature_data,
+ UINT feature_data_size);
+
+ HRESULT (STDMETHODCALLTYPE *CreateDescriptorHeap)(
+ ID3D12Device *This,
+ const D3D12_DESCRIPTOR_HEAP_DESC *desc,
+ REFIID riid,
+ void **descriptor_heap);
+
+ UINT (STDMETHODCALLTYPE *GetDescriptorHandleIncrementSize)(
+ ID3D12Device *This,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+
+ HRESULT (STDMETHODCALLTYPE *CreateRootSignature)(
+ ID3D12Device *This,
+ UINT node_mask,
+ const void *bytecode,
+ SIZE_T bytecode_length,
+ REFIID riid,
+ void **root_signature);
+
+ void (STDMETHODCALLTYPE *CreateConstantBufferView)(
+ ID3D12Device *This,
+ const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateShaderResourceView)(
+ ID3D12Device *This,
+ ID3D12Resource *resource,
+ const D3D12_SHADER_RESOURCE_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateUnorderedAccessView)(
+ ID3D12Device *This,
+ ID3D12Resource *resource,
+ ID3D12Resource *counter_resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateRenderTargetView)(
+ ID3D12Device *This,
+ ID3D12Resource *resource,
+ const D3D12_RENDER_TARGET_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateDepthStencilView)(
+ ID3D12Device *This,
+ ID3D12Resource *resource,
+ const D3D12_DEPTH_STENCIL_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateSampler)(
+ ID3D12Device *This,
+ const D3D12_SAMPLER_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CopyDescriptors)(
+ ID3D12Device *This,
+ UINT dst_descriptor_range_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *dst_descriptor_range_offsets,
+ const UINT *dst_descriptor_range_sizes,
+ UINT src_descriptor_range_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *src_descriptor_range_offsets,
+ const UINT *src_descriptor_range_sizes,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+
+ void (STDMETHODCALLTYPE *CopyDescriptorsSimple)(
+ ID3D12Device *This,
+ UINT descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE dst_descriptor_range_offset,
+ const D3D12_CPU_DESCRIPTOR_HANDLE src_descriptor_range_offset,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+
+ D3D12_RESOURCE_ALLOCATION_INFO * (STDMETHODCALLTYPE *GetResourceAllocationInfo)(
+ ID3D12Device *This,
+ D3D12_RESOURCE_ALLOCATION_INFO *__ret,
+ UINT visible_mask,
+ UINT reource_desc_count,
+ const D3D12_RESOURCE_DESC *resource_descs);
+
+ D3D12_HEAP_PROPERTIES * (STDMETHODCALLTYPE *GetCustomHeapProperties)(
+ ID3D12Device *This,
+ D3D12_HEAP_PROPERTIES *__ret,
+ UINT node_mask,
+ D3D12_HEAP_TYPE heap_type);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommittedResource)(
+ ID3D12Device *This,
+ const D3D12_HEAP_PROPERTIES *heap_properties,
+ D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource);
+
+ HRESULT (STDMETHODCALLTYPE *CreateHeap)(
+ ID3D12Device *This,
+ const D3D12_HEAP_DESC *desc,
+ REFIID riid,
+ void **heap);
+
+ HRESULT (STDMETHODCALLTYPE *CreatePlacedResource)(
+ ID3D12Device *This,
+ ID3D12Heap *heap,
+ UINT64 heap_offset,
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource);
+
+ HRESULT (STDMETHODCALLTYPE *CreateReservedResource)(
+ ID3D12Device *This,
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSharedHandle)(
+ ID3D12Device *This,
+ ID3D12DeviceChild *object,
+ const SECURITY_ATTRIBUTES *attributes,
+ DWORD access,
+ const WCHAR *name,
+ HANDLE *handle);
+
+ HRESULT (STDMETHODCALLTYPE *OpenSharedHandle)(
+ ID3D12Device *This,
+ HANDLE handle,
+ REFIID riid,
+ void **object);
+
+ HRESULT (STDMETHODCALLTYPE *OpenSharedHandleByName)(
+ ID3D12Device *This,
+ const WCHAR *name,
+ DWORD access,
+ HANDLE *handle);
+
+ HRESULT (STDMETHODCALLTYPE *MakeResident)(
+ ID3D12Device *This,
+ UINT object_count,
+ ID3D12Pageable *const *objects);
+
+ HRESULT (STDMETHODCALLTYPE *Evict)(
+ ID3D12Device *This,
+ UINT object_count,
+ ID3D12Pageable *const *objects);
+
+ HRESULT (STDMETHODCALLTYPE *CreateFence)(
+ ID3D12Device *This,
+ UINT64 initial_value,
+ D3D12_FENCE_FLAGS flags,
+ REFIID riid,
+ void **fence);
+
+ HRESULT (STDMETHODCALLTYPE *GetDeviceRemovedReason)(
+ ID3D12Device *This);
+
+ void (STDMETHODCALLTYPE *GetCopyableFootprints)(
+ ID3D12Device *This,
+ const D3D12_RESOURCE_DESC *desc,
+ UINT first_sub_resource,
+ UINT sub_resource_count,
+ UINT64 base_offset,
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts,
+ UINT *row_count,
+ UINT64 *row_size,
+ UINT64 *total_bytes);
+
+ HRESULT (STDMETHODCALLTYPE *CreateQueryHeap)(
+ ID3D12Device *This,
+ const D3D12_QUERY_HEAP_DESC *desc,
+ REFIID riid,
+ void **heap);
+
+ HRESULT (STDMETHODCALLTYPE *SetStablePowerState)(
+ ID3D12Device *This,
+ BOOL enable);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommandSignature)(
+ ID3D12Device *This,
+ const D3D12_COMMAND_SIGNATURE_DESC *desc,
+ ID3D12RootSignature *root_signature,
+ REFIID riid,
+ void **command_signature);
+
+ void (STDMETHODCALLTYPE *GetResourceTiling)(
+ ID3D12Device *This,
+ ID3D12Resource *resource,
+ UINT *total_tile_count,
+ D3D12_PACKED_MIP_INFO *packed_mip_info,
+ D3D12_TILE_SHAPE *standard_tile_shape,
+ UINT *sub_resource_tiling_count,
+ UINT first_sub_resource_tiling,
+ D3D12_SUBRESOURCE_TILING *sub_resource_tilings);
+
+ LUID * (STDMETHODCALLTYPE *GetAdapterLuid)(
+ ID3D12Device *This,
+ LUID *__ret);
+
+ END_INTERFACE
+} ID3D12DeviceVtbl;
+
+interface ID3D12Device {
+ CONST_VTBL ID3D12DeviceVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Device_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Device_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Device_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12Device_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12Device_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12Device_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12Device_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12Device methods ***/
+#define ID3D12Device_GetNodeCount(This) (This)->lpVtbl->GetNodeCount(This)
+#define ID3D12Device_CreateCommandQueue(This,desc,riid,command_queue) (This)->lpVtbl->CreateCommandQueue(This,desc,riid,command_queue)
+#define ID3D12Device_CreateCommandAllocator(This,type,riid,command_allocator) (This)->lpVtbl->CreateCommandAllocator(This,type,riid,command_allocator)
+#define ID3D12Device_CreateGraphicsPipelineState(This,desc,riid,pipeline_state) (This)->lpVtbl->CreateGraphicsPipelineState(This,desc,riid,pipeline_state)
+#define ID3D12Device_CreateComputePipelineState(This,desc,riid,pipeline_state) (This)->lpVtbl->CreateComputePipelineState(This,desc,riid,pipeline_state)
+#define ID3D12Device_CreateCommandList(This,node_mask,type,command_allocator,initial_pipeline_state,riid,command_list) (This)->lpVtbl->CreateCommandList(This,node_mask,type,command_allocator,initial_pipeline_state,riid,command_list)
+#define ID3D12Device_CheckFeatureSupport(This,feature,feature_data,feature_data_size) (This)->lpVtbl->CheckFeatureSupport(This,feature,feature_data,feature_data_size)
+#define ID3D12Device_CreateDescriptorHeap(This,desc,riid,descriptor_heap) (This)->lpVtbl->CreateDescriptorHeap(This,desc,riid,descriptor_heap)
+#define ID3D12Device_GetDescriptorHandleIncrementSize(This,descriptor_heap_type) (This)->lpVtbl->GetDescriptorHandleIncrementSize(This,descriptor_heap_type)
+#define ID3D12Device_CreateRootSignature(This,node_mask,bytecode,bytecode_length,riid,root_signature) (This)->lpVtbl->CreateRootSignature(This,node_mask,bytecode,bytecode_length,riid,root_signature)
+#define ID3D12Device_CreateConstantBufferView(This,desc,descriptor) (This)->lpVtbl->CreateConstantBufferView(This,desc,descriptor)
+#define ID3D12Device_CreateShaderResourceView(This,resource,desc,descriptor) (This)->lpVtbl->CreateShaderResourceView(This,resource,desc,descriptor)
+#define ID3D12Device_CreateUnorderedAccessView(This,resource,counter_resource,desc,descriptor) (This)->lpVtbl->CreateUnorderedAccessView(This,resource,counter_resource,desc,descriptor)
+#define ID3D12Device_CreateRenderTargetView(This,resource,desc,descriptor) (This)->lpVtbl->CreateRenderTargetView(This,resource,desc,descriptor)
+#define ID3D12Device_CreateDepthStencilView(This,resource,desc,descriptor) (This)->lpVtbl->CreateDepthStencilView(This,resource,desc,descriptor)
+#define ID3D12Device_CreateSampler(This,desc,descriptor) (This)->lpVtbl->CreateSampler(This,desc,descriptor)
+#define ID3D12Device_CopyDescriptors(This,dst_descriptor_range_count,dst_descriptor_range_offsets,dst_descriptor_range_sizes,src_descriptor_range_count,src_descriptor_range_offsets,src_descriptor_range_sizes,descriptor_heap_type) (This)->lpVtbl->CopyDescriptors(This,dst_descriptor_range_count,dst_descriptor_range_offsets,dst_descriptor_range_sizes,src_descriptor_range_count,src_descriptor_range_offsets,src_descriptor_range_sizes,descriptor_heap_type)
+#define ID3D12Device_CopyDescriptorsSimple(This,descriptor_count,dst_descriptor_range_offset,src_descriptor_range_offset,descriptor_heap_type) (This)->lpVtbl->CopyDescriptorsSimple(This,descriptor_count,dst_descriptor_range_offset,src_descriptor_range_offset,descriptor_heap_type)
+#define ID3D12Device_GetResourceAllocationInfo(This,visible_mask,reource_desc_count,resource_descs) ID3D12Device_GetResourceAllocationInfo_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#define ID3D12Device_GetCustomHeapProperties(This,node_mask,heap_type) ID3D12Device_GetCustomHeapProperties_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#define ID3D12Device_CreateCommittedResource(This,heap_properties,heap_flags,desc,initial_state,optimized_clear_value,riid,resource) (This)->lpVtbl->CreateCommittedResource(This,heap_properties,heap_flags,desc,initial_state,optimized_clear_value,riid,resource)
+#define ID3D12Device_CreateHeap(This,desc,riid,heap) (This)->lpVtbl->CreateHeap(This,desc,riid,heap)
+#define ID3D12Device_CreatePlacedResource(This,heap,heap_offset,desc,initial_state,optimized_clear_value,riid,resource) (This)->lpVtbl->CreatePlacedResource(This,heap,heap_offset,desc,initial_state,optimized_clear_value,riid,resource)
+#define ID3D12Device_CreateReservedResource(This,desc,initial_state,optimized_clear_value,riid,resource) (This)->lpVtbl->CreateReservedResource(This,desc,initial_state,optimized_clear_value,riid,resource)
+#define ID3D12Device_CreateSharedHandle(This,object,attributes,access,name,handle) (This)->lpVtbl->CreateSharedHandle(This,object,attributes,access,name,handle)
+#define ID3D12Device_OpenSharedHandle(This,handle,riid,object) (This)->lpVtbl->OpenSharedHandle(This,handle,riid,object)
+#define ID3D12Device_OpenSharedHandleByName(This,name,access,handle) (This)->lpVtbl->OpenSharedHandleByName(This,name,access,handle)
+#define ID3D12Device_MakeResident(This,object_count,objects) (This)->lpVtbl->MakeResident(This,object_count,objects)
+#define ID3D12Device_Evict(This,object_count,objects) (This)->lpVtbl->Evict(This,object_count,objects)
+#define ID3D12Device_CreateFence(This,initial_value,flags,riid,fence) (This)->lpVtbl->CreateFence(This,initial_value,flags,riid,fence)
+#define ID3D12Device_GetDeviceRemovedReason(This) (This)->lpVtbl->GetDeviceRemovedReason(This)
+#define ID3D12Device_GetCopyableFootprints(This,desc,first_sub_resource,sub_resource_count,base_offset,layouts,row_count,row_size,total_bytes) (This)->lpVtbl->GetCopyableFootprints(This,desc,first_sub_resource,sub_resource_count,base_offset,layouts,row_count,row_size,total_bytes)
+#define ID3D12Device_CreateQueryHeap(This,desc,riid,heap) (This)->lpVtbl->CreateQueryHeap(This,desc,riid,heap)
+#define ID3D12Device_SetStablePowerState(This,enable) (This)->lpVtbl->SetStablePowerState(This,enable)
+#define ID3D12Device_CreateCommandSignature(This,desc,root_signature,riid,command_signature) (This)->lpVtbl->CreateCommandSignature(This,desc,root_signature,riid,command_signature)
+#define ID3D12Device_GetResourceTiling(This,resource,total_tile_count,packed_mip_info,standard_tile_shape,sub_resource_tiling_count,first_sub_resource_tiling,sub_resource_tilings) (This)->lpVtbl->GetResourceTiling(This,resource,total_tile_count,packed_mip_info,standard_tile_shape,sub_resource_tiling_count,first_sub_resource_tiling,sub_resource_tilings)
+#define ID3D12Device_GetAdapterLuid(This) ID3D12Device_GetAdapterLuid_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Device_QueryInterface(ID3D12Device* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Device_AddRef(ID3D12Device* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Device_Release(ID3D12Device* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12Device_GetPrivateData(ID3D12Device* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Device_SetPrivateData(ID3D12Device* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Device_SetPrivateDataInterface(ID3D12Device* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12Device_SetName(ID3D12Device* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12Device methods ***/
+static FORCEINLINE UINT ID3D12Device_GetNodeCount(ID3D12Device* This) {
+ return This->lpVtbl->GetNodeCount(This);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateCommandQueue(ID3D12Device* This,const D3D12_COMMAND_QUEUE_DESC *desc,REFIID riid,void **command_queue) {
+ return This->lpVtbl->CreateCommandQueue(This,desc,riid,command_queue);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateCommandAllocator(ID3D12Device* This,D3D12_COMMAND_LIST_TYPE type,REFIID riid,void **command_allocator) {
+ return This->lpVtbl->CreateCommandAllocator(This,type,riid,command_allocator);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateGraphicsPipelineState(ID3D12Device* This,const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,REFIID riid,void **pipeline_state) {
+ return This->lpVtbl->CreateGraphicsPipelineState(This,desc,riid,pipeline_state);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateComputePipelineState(ID3D12Device* This,const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc,REFIID riid,void **pipeline_state) {
+ return This->lpVtbl->CreateComputePipelineState(This,desc,riid,pipeline_state);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateCommandList(ID3D12Device* This,UINT node_mask,D3D12_COMMAND_LIST_TYPE type,ID3D12CommandAllocator *command_allocator,ID3D12PipelineState *initial_pipeline_state,REFIID riid,void **command_list) {
+ return This->lpVtbl->CreateCommandList(This,node_mask,type,command_allocator,initial_pipeline_state,riid,command_list);
+}
+static FORCEINLINE HRESULT ID3D12Device_CheckFeatureSupport(ID3D12Device* This,D3D12_FEATURE feature,void *feature_data,UINT feature_data_size) {
+ return This->lpVtbl->CheckFeatureSupport(This,feature,feature_data,feature_data_size);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateDescriptorHeap(ID3D12Device* This,const D3D12_DESCRIPTOR_HEAP_DESC *desc,REFIID riid,void **descriptor_heap) {
+ return This->lpVtbl->CreateDescriptorHeap(This,desc,riid,descriptor_heap);
+}
+static FORCEINLINE UINT ID3D12Device_GetDescriptorHandleIncrementSize(ID3D12Device* This,D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) {
+ return This->lpVtbl->GetDescriptorHandleIncrementSize(This,descriptor_heap_type);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateRootSignature(ID3D12Device* This,UINT node_mask,const void *bytecode,SIZE_T bytecode_length,REFIID riid,void **root_signature) {
+ return This->lpVtbl->CreateRootSignature(This,node_mask,bytecode,bytecode_length,riid,root_signature);
+}
+static FORCEINLINE void ID3D12Device_CreateConstantBufferView(ID3D12Device* This,const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateConstantBufferView(This,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device_CreateShaderResourceView(ID3D12Device* This,ID3D12Resource *resource,const D3D12_SHADER_RESOURCE_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateShaderResourceView(This,resource,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device_CreateUnorderedAccessView(ID3D12Device* This,ID3D12Resource *resource,ID3D12Resource *counter_resource,const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateUnorderedAccessView(This,resource,counter_resource,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device_CreateRenderTargetView(ID3D12Device* This,ID3D12Resource *resource,const D3D12_RENDER_TARGET_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateRenderTargetView(This,resource,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device_CreateDepthStencilView(ID3D12Device* This,ID3D12Resource *resource,const D3D12_DEPTH_STENCIL_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateDepthStencilView(This,resource,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device_CreateSampler(ID3D12Device* This,const D3D12_SAMPLER_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateSampler(This,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device_CopyDescriptors(ID3D12Device* This,UINT dst_descriptor_range_count,const D3D12_CPU_DESCRIPTOR_HANDLE *dst_descriptor_range_offsets,const UINT *dst_descriptor_range_sizes,UINT src_descriptor_range_count,const D3D12_CPU_DESCRIPTOR_HANDLE *src_descriptor_range_offsets,const UINT *src_descriptor_range_sizes,D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) {
+ This->lpVtbl->CopyDescriptors(This,dst_descriptor_range_count,dst_descriptor_range_offsets,dst_descriptor_range_sizes,src_descriptor_range_count,src_descriptor_range_offsets,src_descriptor_range_sizes,descriptor_heap_type);
+}
+static FORCEINLINE void ID3D12Device_CopyDescriptorsSimple(ID3D12Device* This,UINT descriptor_count,const D3D12_CPU_DESCRIPTOR_HANDLE dst_descriptor_range_offset,const D3D12_CPU_DESCRIPTOR_HANDLE src_descriptor_range_offset,D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) {
+ This->lpVtbl->CopyDescriptorsSimple(This,descriptor_count,dst_descriptor_range_offset,src_descriptor_range_offset,descriptor_heap_type);
+}
+static FORCEINLINE D3D12_RESOURCE_ALLOCATION_INFO ID3D12Device_GetResourceAllocationInfo(ID3D12Device* This,UINT visible_mask,UINT reource_desc_count,const D3D12_RESOURCE_DESC *resource_descs) {
+ D3D12_RESOURCE_ALLOCATION_INFO __ret;
+ return *This->lpVtbl->GetResourceAllocationInfo(This,&__ret,visible_mask,reource_desc_count,resource_descs);
+}
+static FORCEINLINE D3D12_HEAP_PROPERTIES ID3D12Device_GetCustomHeapProperties(ID3D12Device* This,UINT node_mask,D3D12_HEAP_TYPE heap_type) {
+ D3D12_HEAP_PROPERTIES __ret;
+ return *This->lpVtbl->GetCustomHeapProperties(This,&__ret,node_mask,heap_type);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateCommittedResource(ID3D12Device* This,const D3D12_HEAP_PROPERTIES *heap_properties,D3D12_HEAP_FLAGS heap_flags,const D3D12_RESOURCE_DESC *desc,D3D12_RESOURCE_STATES initial_state,const D3D12_CLEAR_VALUE *optimized_clear_value,REFIID riid,void **resource) {
+ return This->lpVtbl->CreateCommittedResource(This,heap_properties,heap_flags,desc,initial_state,optimized_clear_value,riid,resource);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateHeap(ID3D12Device* This,const D3D12_HEAP_DESC *desc,REFIID riid,void **heap) {
+ return This->lpVtbl->CreateHeap(This,desc,riid,heap);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreatePlacedResource(ID3D12Device* This,ID3D12Heap *heap,UINT64 heap_offset,const D3D12_RESOURCE_DESC *desc,D3D12_RESOURCE_STATES initial_state,const D3D12_CLEAR_VALUE *optimized_clear_value,REFIID riid,void **resource) {
+ return This->lpVtbl->CreatePlacedResource(This,heap,heap_offset,desc,initial_state,optimized_clear_value,riid,resource);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateReservedResource(ID3D12Device* This,const D3D12_RESOURCE_DESC *desc,D3D12_RESOURCE_STATES initial_state,const D3D12_CLEAR_VALUE *optimized_clear_value,REFIID riid,void **resource) {
+ return This->lpVtbl->CreateReservedResource(This,desc,initial_state,optimized_clear_value,riid,resource);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateSharedHandle(ID3D12Device* This,ID3D12DeviceChild *object,const SECURITY_ATTRIBUTES *attributes,DWORD access,const WCHAR *name,HANDLE *handle) {
+ return This->lpVtbl->CreateSharedHandle(This,object,attributes,access,name,handle);
+}
+static FORCEINLINE HRESULT ID3D12Device_OpenSharedHandle(ID3D12Device* This,HANDLE handle,REFIID riid,void **object) {
+ return This->lpVtbl->OpenSharedHandle(This,handle,riid,object);
+}
+static FORCEINLINE HRESULT ID3D12Device_OpenSharedHandleByName(ID3D12Device* This,const WCHAR *name,DWORD access,HANDLE *handle) {
+ return This->lpVtbl->OpenSharedHandleByName(This,name,access,handle);
+}
+static FORCEINLINE HRESULT ID3D12Device_MakeResident(ID3D12Device* This,UINT object_count,ID3D12Pageable *const *objects) {
+ return This->lpVtbl->MakeResident(This,object_count,objects);
+}
+static FORCEINLINE HRESULT ID3D12Device_Evict(ID3D12Device* This,UINT object_count,ID3D12Pageable *const *objects) {
+ return This->lpVtbl->Evict(This,object_count,objects);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateFence(ID3D12Device* This,UINT64 initial_value,D3D12_FENCE_FLAGS flags,REFIID riid,void **fence) {
+ return This->lpVtbl->CreateFence(This,initial_value,flags,riid,fence);
+}
+static FORCEINLINE HRESULT ID3D12Device_GetDeviceRemovedReason(ID3D12Device* This) {
+ return This->lpVtbl->GetDeviceRemovedReason(This);
+}
+static FORCEINLINE void ID3D12Device_GetCopyableFootprints(ID3D12Device* This,const D3D12_RESOURCE_DESC *desc,UINT first_sub_resource,UINT sub_resource_count,UINT64 base_offset,D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts,UINT *row_count,UINT64 *row_size,UINT64 *total_bytes) {
+ This->lpVtbl->GetCopyableFootprints(This,desc,first_sub_resource,sub_resource_count,base_offset,layouts,row_count,row_size,total_bytes);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateQueryHeap(ID3D12Device* This,const D3D12_QUERY_HEAP_DESC *desc,REFIID riid,void **heap) {
+ return This->lpVtbl->CreateQueryHeap(This,desc,riid,heap);
+}
+static FORCEINLINE HRESULT ID3D12Device_SetStablePowerState(ID3D12Device* This,BOOL enable) {
+ return This->lpVtbl->SetStablePowerState(This,enable);
+}
+static FORCEINLINE HRESULT ID3D12Device_CreateCommandSignature(ID3D12Device* This,const D3D12_COMMAND_SIGNATURE_DESC *desc,ID3D12RootSignature *root_signature,REFIID riid,void **command_signature) {
+ return This->lpVtbl->CreateCommandSignature(This,desc,root_signature,riid,command_signature);
+}
+static FORCEINLINE void ID3D12Device_GetResourceTiling(ID3D12Device* This,ID3D12Resource *resource,UINT *total_tile_count,D3D12_PACKED_MIP_INFO *packed_mip_info,D3D12_TILE_SHAPE *standard_tile_shape,UINT *sub_resource_tiling_count,UINT first_sub_resource_tiling,D3D12_SUBRESOURCE_TILING *sub_resource_tilings) {
+ This->lpVtbl->GetResourceTiling(This,resource,total_tile_count,packed_mip_info,standard_tile_shape,sub_resource_tiling_count,first_sub_resource_tiling,sub_resource_tilings);
+}
+static FORCEINLINE LUID ID3D12Device_GetAdapterLuid(ID3D12Device* This) {
+ LUID __ret;
+ return *This->lpVtbl->GetAdapterLuid(This,&__ret);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Device_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12Device1 interface
+ */
+#ifndef __ID3D12Device1_INTERFACE_DEFINED__
+#define __ID3D12Device1_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Device1, 0x77acce80, 0x638e, 0x4e65, 0x88,0x95, 0xc1,0xf2,0x33,0x86,0x86,0x3e);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("77acce80-638e-4e65-8895-c1f23386863e")
+ID3D12Device1 : public ID3D12Device
+{
+ virtual HRESULT STDMETHODCALLTYPE CreatePipelineLibrary(
+ const void *blob,
+ SIZE_T blob_size,
+ REFIID iid,
+ void **lib) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetEventOnMultipleFenceCompletion(
+ ID3D12Fence *const *fences,
+ const UINT64 *values,
+ UINT fence_count,
+ D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags,
+ HANDLE event) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetResidencyPriority(
+ UINT object_count,
+ ID3D12Pageable *const *objects,
+ const D3D12_RESIDENCY_PRIORITY *priorities) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Device1, 0x77acce80, 0x638e, 0x4e65, 0x88,0x95, 0xc1,0xf2,0x33,0x86,0x86,0x3e)
+#endif
+#else
+typedef struct ID3D12Device1Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Device1 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Device1 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Device1 *This);
+
+ /*** ID3D12Object methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ ID3D12Device1 *This,
+ REFGUID guid,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ ID3D12Device1 *This,
+ REFGUID guid,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetPrivateDataInterface)(
+ ID3D12Device1 *This,
+ REFGUID guid,
+ const IUnknown *data);
+
+ HRESULT (STDMETHODCALLTYPE *SetName)(
+ ID3D12Device1 *This,
+ const WCHAR *name);
+
+ /*** ID3D12Device methods ***/
+ UINT (STDMETHODCALLTYPE *GetNodeCount)(
+ ID3D12Device1 *This);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommandQueue)(
+ ID3D12Device1 *This,
+ const D3D12_COMMAND_QUEUE_DESC *desc,
+ REFIID riid,
+ void **command_queue);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommandAllocator)(
+ ID3D12Device1 *This,
+ D3D12_COMMAND_LIST_TYPE type,
+ REFIID riid,
+ void **command_allocator);
+
+ HRESULT (STDMETHODCALLTYPE *CreateGraphicsPipelineState)(
+ ID3D12Device1 *This,
+ const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,
+ REFIID riid,
+ void **pipeline_state);
+
+ HRESULT (STDMETHODCALLTYPE *CreateComputePipelineState)(
+ ID3D12Device1 *This,
+ const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc,
+ REFIID riid,
+ void **pipeline_state);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommandList)(
+ ID3D12Device1 *This,
+ UINT node_mask,
+ D3D12_COMMAND_LIST_TYPE type,
+ ID3D12CommandAllocator *command_allocator,
+ ID3D12PipelineState *initial_pipeline_state,
+ REFIID riid,
+ void **command_list);
+
+ HRESULT (STDMETHODCALLTYPE *CheckFeatureSupport)(
+ ID3D12Device1 *This,
+ D3D12_FEATURE feature,
+ void *feature_data,
+ UINT feature_data_size);
+
+ HRESULT (STDMETHODCALLTYPE *CreateDescriptorHeap)(
+ ID3D12Device1 *This,
+ const D3D12_DESCRIPTOR_HEAP_DESC *desc,
+ REFIID riid,
+ void **descriptor_heap);
+
+ UINT (STDMETHODCALLTYPE *GetDescriptorHandleIncrementSize)(
+ ID3D12Device1 *This,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+
+ HRESULT (STDMETHODCALLTYPE *CreateRootSignature)(
+ ID3D12Device1 *This,
+ UINT node_mask,
+ const void *bytecode,
+ SIZE_T bytecode_length,
+ REFIID riid,
+ void **root_signature);
+
+ void (STDMETHODCALLTYPE *CreateConstantBufferView)(
+ ID3D12Device1 *This,
+ const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateShaderResourceView)(
+ ID3D12Device1 *This,
+ ID3D12Resource *resource,
+ const D3D12_SHADER_RESOURCE_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateUnorderedAccessView)(
+ ID3D12Device1 *This,
+ ID3D12Resource *resource,
+ ID3D12Resource *counter_resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateRenderTargetView)(
+ ID3D12Device1 *This,
+ ID3D12Resource *resource,
+ const D3D12_RENDER_TARGET_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateDepthStencilView)(
+ ID3D12Device1 *This,
+ ID3D12Resource *resource,
+ const D3D12_DEPTH_STENCIL_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CreateSampler)(
+ ID3D12Device1 *This,
+ const D3D12_SAMPLER_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void (STDMETHODCALLTYPE *CopyDescriptors)(
+ ID3D12Device1 *This,
+ UINT dst_descriptor_range_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *dst_descriptor_range_offsets,
+ const UINT *dst_descriptor_range_sizes,
+ UINT src_descriptor_range_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *src_descriptor_range_offsets,
+ const UINT *src_descriptor_range_sizes,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+
+ void (STDMETHODCALLTYPE *CopyDescriptorsSimple)(
+ ID3D12Device1 *This,
+ UINT descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE dst_descriptor_range_offset,
+ const D3D12_CPU_DESCRIPTOR_HANDLE src_descriptor_range_offset,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+
+ D3D12_RESOURCE_ALLOCATION_INFO * (STDMETHODCALLTYPE *GetResourceAllocationInfo)(
+ ID3D12Device1 *This,
+ D3D12_RESOURCE_ALLOCATION_INFO *__ret,
+ UINT visible_mask,
+ UINT reource_desc_count,
+ const D3D12_RESOURCE_DESC *resource_descs);
+
+ D3D12_HEAP_PROPERTIES * (STDMETHODCALLTYPE *GetCustomHeapProperties)(
+ ID3D12Device1 *This,
+ D3D12_HEAP_PROPERTIES *__ret,
+ UINT node_mask,
+ D3D12_HEAP_TYPE heap_type);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommittedResource)(
+ ID3D12Device1 *This,
+ const D3D12_HEAP_PROPERTIES *heap_properties,
+ D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource);
+
+ HRESULT (STDMETHODCALLTYPE *CreateHeap)(
+ ID3D12Device1 *This,
+ const D3D12_HEAP_DESC *desc,
+ REFIID riid,
+ void **heap);
+
+ HRESULT (STDMETHODCALLTYPE *CreatePlacedResource)(
+ ID3D12Device1 *This,
+ ID3D12Heap *heap,
+ UINT64 heap_offset,
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource);
+
+ HRESULT (STDMETHODCALLTYPE *CreateReservedResource)(
+ ID3D12Device1 *This,
+ const D3D12_RESOURCE_DESC *desc,
+ D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid,
+ void **resource);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSharedHandle)(
+ ID3D12Device1 *This,
+ ID3D12DeviceChild *object,
+ const SECURITY_ATTRIBUTES *attributes,
+ DWORD access,
+ const WCHAR *name,
+ HANDLE *handle);
+
+ HRESULT (STDMETHODCALLTYPE *OpenSharedHandle)(
+ ID3D12Device1 *This,
+ HANDLE handle,
+ REFIID riid,
+ void **object);
+
+ HRESULT (STDMETHODCALLTYPE *OpenSharedHandleByName)(
+ ID3D12Device1 *This,
+ const WCHAR *name,
+ DWORD access,
+ HANDLE *handle);
+
+ HRESULT (STDMETHODCALLTYPE *MakeResident)(
+ ID3D12Device1 *This,
+ UINT object_count,
+ ID3D12Pageable *const *objects);
+
+ HRESULT (STDMETHODCALLTYPE *Evict)(
+ ID3D12Device1 *This,
+ UINT object_count,
+ ID3D12Pageable *const *objects);
+
+ HRESULT (STDMETHODCALLTYPE *CreateFence)(
+ ID3D12Device1 *This,
+ UINT64 initial_value,
+ D3D12_FENCE_FLAGS flags,
+ REFIID riid,
+ void **fence);
+
+ HRESULT (STDMETHODCALLTYPE *GetDeviceRemovedReason)(
+ ID3D12Device1 *This);
+
+ void (STDMETHODCALLTYPE *GetCopyableFootprints)(
+ ID3D12Device1 *This,
+ const D3D12_RESOURCE_DESC *desc,
+ UINT first_sub_resource,
+ UINT sub_resource_count,
+ UINT64 base_offset,
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts,
+ UINT *row_count,
+ UINT64 *row_size,
+ UINT64 *total_bytes);
+
+ HRESULT (STDMETHODCALLTYPE *CreateQueryHeap)(
+ ID3D12Device1 *This,
+ const D3D12_QUERY_HEAP_DESC *desc,
+ REFIID riid,
+ void **heap);
+
+ HRESULT (STDMETHODCALLTYPE *SetStablePowerState)(
+ ID3D12Device1 *This,
+ BOOL enable);
+
+ HRESULT (STDMETHODCALLTYPE *CreateCommandSignature)(
+ ID3D12Device1 *This,
+ const D3D12_COMMAND_SIGNATURE_DESC *desc,
+ ID3D12RootSignature *root_signature,
+ REFIID riid,
+ void **command_signature);
+
+ void (STDMETHODCALLTYPE *GetResourceTiling)(
+ ID3D12Device1 *This,
+ ID3D12Resource *resource,
+ UINT *total_tile_count,
+ D3D12_PACKED_MIP_INFO *packed_mip_info,
+ D3D12_TILE_SHAPE *standard_tile_shape,
+ UINT *sub_resource_tiling_count,
+ UINT first_sub_resource_tiling,
+ D3D12_SUBRESOURCE_TILING *sub_resource_tilings);
+
+ LUID * (STDMETHODCALLTYPE *GetAdapterLuid)(
+ ID3D12Device1 *This,
+ LUID *__ret);
+
+ /*** ID3D12Device1 methods ***/
+ HRESULT (STDMETHODCALLTYPE *CreatePipelineLibrary)(
+ ID3D12Device1 *This,
+ const void *blob,
+ SIZE_T blob_size,
+ REFIID iid,
+ void **lib);
+
+ HRESULT (STDMETHODCALLTYPE *SetEventOnMultipleFenceCompletion)(
+ ID3D12Device1 *This,
+ ID3D12Fence *const *fences,
+ const UINT64 *values,
+ UINT fence_count,
+ D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags,
+ HANDLE event);
+
+ HRESULT (STDMETHODCALLTYPE *SetResidencyPriority)(
+ ID3D12Device1 *This,
+ UINT object_count,
+ ID3D12Pageable *const *objects,
+ const D3D12_RESIDENCY_PRIORITY *priorities);
+
+ END_INTERFACE
+} ID3D12Device1Vtbl;
+
+interface ID3D12Device1 {
+ CONST_VTBL ID3D12Device1Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Device1_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Device1_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Device1_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Object methods ***/
+#define ID3D12Device1_GetPrivateData(This,guid,data_size,data) (This)->lpVtbl->GetPrivateData(This,guid,data_size,data)
+#define ID3D12Device1_SetPrivateData(This,guid,data_size,data) (This)->lpVtbl->SetPrivateData(This,guid,data_size,data)
+#define ID3D12Device1_SetPrivateDataInterface(This,guid,data) (This)->lpVtbl->SetPrivateDataInterface(This,guid,data)
+#define ID3D12Device1_SetName(This,name) (This)->lpVtbl->SetName(This,name)
+/*** ID3D12Device methods ***/
+#define ID3D12Device1_GetNodeCount(This) (This)->lpVtbl->GetNodeCount(This)
+#define ID3D12Device1_CreateCommandQueue(This,desc,riid,command_queue) (This)->lpVtbl->CreateCommandQueue(This,desc,riid,command_queue)
+#define ID3D12Device1_CreateCommandAllocator(This,type,riid,command_allocator) (This)->lpVtbl->CreateCommandAllocator(This,type,riid,command_allocator)
+#define ID3D12Device1_CreateGraphicsPipelineState(This,desc,riid,pipeline_state) (This)->lpVtbl->CreateGraphicsPipelineState(This,desc,riid,pipeline_state)
+#define ID3D12Device1_CreateComputePipelineState(This,desc,riid,pipeline_state) (This)->lpVtbl->CreateComputePipelineState(This,desc,riid,pipeline_state)
+#define ID3D12Device1_CreateCommandList(This,node_mask,type,command_allocator,initial_pipeline_state,riid,command_list) (This)->lpVtbl->CreateCommandList(This,node_mask,type,command_allocator,initial_pipeline_state,riid,command_list)
+#define ID3D12Device1_CheckFeatureSupport(This,feature,feature_data,feature_data_size) (This)->lpVtbl->CheckFeatureSupport(This,feature,feature_data,feature_data_size)
+#define ID3D12Device1_CreateDescriptorHeap(This,desc,riid,descriptor_heap) (This)->lpVtbl->CreateDescriptorHeap(This,desc,riid,descriptor_heap)
+#define ID3D12Device1_GetDescriptorHandleIncrementSize(This,descriptor_heap_type) (This)->lpVtbl->GetDescriptorHandleIncrementSize(This,descriptor_heap_type)
+#define ID3D12Device1_CreateRootSignature(This,node_mask,bytecode,bytecode_length,riid,root_signature) (This)->lpVtbl->CreateRootSignature(This,node_mask,bytecode,bytecode_length,riid,root_signature)
+#define ID3D12Device1_CreateConstantBufferView(This,desc,descriptor) (This)->lpVtbl->CreateConstantBufferView(This,desc,descriptor)
+#define ID3D12Device1_CreateShaderResourceView(This,resource,desc,descriptor) (This)->lpVtbl->CreateShaderResourceView(This,resource,desc,descriptor)
+#define ID3D12Device1_CreateUnorderedAccessView(This,resource,counter_resource,desc,descriptor) (This)->lpVtbl->CreateUnorderedAccessView(This,resource,counter_resource,desc,descriptor)
+#define ID3D12Device1_CreateRenderTargetView(This,resource,desc,descriptor) (This)->lpVtbl->CreateRenderTargetView(This,resource,desc,descriptor)
+#define ID3D12Device1_CreateDepthStencilView(This,resource,desc,descriptor) (This)->lpVtbl->CreateDepthStencilView(This,resource,desc,descriptor)
+#define ID3D12Device1_CreateSampler(This,desc,descriptor) (This)->lpVtbl->CreateSampler(This,desc,descriptor)
+#define ID3D12Device1_CopyDescriptors(This,dst_descriptor_range_count,dst_descriptor_range_offsets,dst_descriptor_range_sizes,src_descriptor_range_count,src_descriptor_range_offsets,src_descriptor_range_sizes,descriptor_heap_type) (This)->lpVtbl->CopyDescriptors(This,dst_descriptor_range_count,dst_descriptor_range_offsets,dst_descriptor_range_sizes,src_descriptor_range_count,src_descriptor_range_offsets,src_descriptor_range_sizes,descriptor_heap_type)
+#define ID3D12Device1_CopyDescriptorsSimple(This,descriptor_count,dst_descriptor_range_offset,src_descriptor_range_offset,descriptor_heap_type) (This)->lpVtbl->CopyDescriptorsSimple(This,descriptor_count,dst_descriptor_range_offset,src_descriptor_range_offset,descriptor_heap_type)
+#define ID3D12Device1_GetResourceAllocationInfo(This,visible_mask,reource_desc_count,resource_descs) ID3D12Device1_GetResourceAllocationInfo_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#define ID3D12Device1_GetCustomHeapProperties(This,node_mask,heap_type) ID3D12Device1_GetCustomHeapProperties_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+#define ID3D12Device1_CreateCommittedResource(This,heap_properties,heap_flags,desc,initial_state,optimized_clear_value,riid,resource) (This)->lpVtbl->CreateCommittedResource(This,heap_properties,heap_flags,desc,initial_state,optimized_clear_value,riid,resource)
+#define ID3D12Device1_CreateHeap(This,desc,riid,heap) (This)->lpVtbl->CreateHeap(This,desc,riid,heap)
+#define ID3D12Device1_CreatePlacedResource(This,heap,heap_offset,desc,initial_state,optimized_clear_value,riid,resource) (This)->lpVtbl->CreatePlacedResource(This,heap,heap_offset,desc,initial_state,optimized_clear_value,riid,resource)
+#define ID3D12Device1_CreateReservedResource(This,desc,initial_state,optimized_clear_value,riid,resource) (This)->lpVtbl->CreateReservedResource(This,desc,initial_state,optimized_clear_value,riid,resource)
+#define ID3D12Device1_CreateSharedHandle(This,object,attributes,access,name,handle) (This)->lpVtbl->CreateSharedHandle(This,object,attributes,access,name,handle)
+#define ID3D12Device1_OpenSharedHandle(This,handle,riid,object) (This)->lpVtbl->OpenSharedHandle(This,handle,riid,object)
+#define ID3D12Device1_OpenSharedHandleByName(This,name,access,handle) (This)->lpVtbl->OpenSharedHandleByName(This,name,access,handle)
+#define ID3D12Device1_MakeResident(This,object_count,objects) (This)->lpVtbl->MakeResident(This,object_count,objects)
+#define ID3D12Device1_Evict(This,object_count,objects) (This)->lpVtbl->Evict(This,object_count,objects)
+#define ID3D12Device1_CreateFence(This,initial_value,flags,riid,fence) (This)->lpVtbl->CreateFence(This,initial_value,flags,riid,fence)
+#define ID3D12Device1_GetDeviceRemovedReason(This) (This)->lpVtbl->GetDeviceRemovedReason(This)
+#define ID3D12Device1_GetCopyableFootprints(This,desc,first_sub_resource,sub_resource_count,base_offset,layouts,row_count,row_size,total_bytes) (This)->lpVtbl->GetCopyableFootprints(This,desc,first_sub_resource,sub_resource_count,base_offset,layouts,row_count,row_size,total_bytes)
+#define ID3D12Device1_CreateQueryHeap(This,desc,riid,heap) (This)->lpVtbl->CreateQueryHeap(This,desc,riid,heap)
+#define ID3D12Device1_SetStablePowerState(This,enable) (This)->lpVtbl->SetStablePowerState(This,enable)
+#define ID3D12Device1_CreateCommandSignature(This,desc,root_signature,riid,command_signature) (This)->lpVtbl->CreateCommandSignature(This,desc,root_signature,riid,command_signature)
+#define ID3D12Device1_GetResourceTiling(This,resource,total_tile_count,packed_mip_info,standard_tile_shape,sub_resource_tiling_count,first_sub_resource_tiling,sub_resource_tilings) (This)->lpVtbl->GetResourceTiling(This,resource,total_tile_count,packed_mip_info,standard_tile_shape,sub_resource_tiling_count,first_sub_resource_tiling,sub_resource_tilings)
+#define ID3D12Device1_GetAdapterLuid(This) ID3D12Device1_GetAdapterLuid_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support
+/*** ID3D12Device1 methods ***/
+#define ID3D12Device1_CreatePipelineLibrary(This,blob,blob_size,iid,lib) (This)->lpVtbl->CreatePipelineLibrary(This,blob,blob_size,iid,lib)
+#define ID3D12Device1_SetEventOnMultipleFenceCompletion(This,fences,values,fence_count,flags,event) (This)->lpVtbl->SetEventOnMultipleFenceCompletion(This,fences,values,fence_count,flags,event)
+#define ID3D12Device1_SetResidencyPriority(This,object_count,objects,priorities) (This)->lpVtbl->SetResidencyPriority(This,object_count,objects,priorities)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Device1_QueryInterface(ID3D12Device1* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Device1_AddRef(ID3D12Device1* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Device1_Release(ID3D12Device1* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Object methods ***/
+static FORCEINLINE HRESULT ID3D12Device1_GetPrivateData(ID3D12Device1* This,REFGUID guid,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Device1_SetPrivateData(ID3D12Device1* This,REFGUID guid,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,guid,data_size,data);
+}
+static FORCEINLINE HRESULT ID3D12Device1_SetPrivateDataInterface(ID3D12Device1* This,REFGUID guid,const IUnknown *data) {
+ return This->lpVtbl->SetPrivateDataInterface(This,guid,data);
+}
+static FORCEINLINE HRESULT ID3D12Device1_SetName(ID3D12Device1* This,const WCHAR *name) {
+ return This->lpVtbl->SetName(This,name);
+}
+/*** ID3D12Device methods ***/
+static FORCEINLINE UINT ID3D12Device1_GetNodeCount(ID3D12Device1* This) {
+ return This->lpVtbl->GetNodeCount(This);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateCommandQueue(ID3D12Device1* This,const D3D12_COMMAND_QUEUE_DESC *desc,REFIID riid,void **command_queue) {
+ return This->lpVtbl->CreateCommandQueue(This,desc,riid,command_queue);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateCommandAllocator(ID3D12Device1* This,D3D12_COMMAND_LIST_TYPE type,REFIID riid,void **command_allocator) {
+ return This->lpVtbl->CreateCommandAllocator(This,type,riid,command_allocator);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateGraphicsPipelineState(ID3D12Device1* This,const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,REFIID riid,void **pipeline_state) {
+ return This->lpVtbl->CreateGraphicsPipelineState(This,desc,riid,pipeline_state);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateComputePipelineState(ID3D12Device1* This,const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc,REFIID riid,void **pipeline_state) {
+ return This->lpVtbl->CreateComputePipelineState(This,desc,riid,pipeline_state);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateCommandList(ID3D12Device1* This,UINT node_mask,D3D12_COMMAND_LIST_TYPE type,ID3D12CommandAllocator *command_allocator,ID3D12PipelineState *initial_pipeline_state,REFIID riid,void **command_list) {
+ return This->lpVtbl->CreateCommandList(This,node_mask,type,command_allocator,initial_pipeline_state,riid,command_list);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CheckFeatureSupport(ID3D12Device1* This,D3D12_FEATURE feature,void *feature_data,UINT feature_data_size) {
+ return This->lpVtbl->CheckFeatureSupport(This,feature,feature_data,feature_data_size);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateDescriptorHeap(ID3D12Device1* This,const D3D12_DESCRIPTOR_HEAP_DESC *desc,REFIID riid,void **descriptor_heap) {
+ return This->lpVtbl->CreateDescriptorHeap(This,desc,riid,descriptor_heap);
+}
+static FORCEINLINE UINT ID3D12Device1_GetDescriptorHandleIncrementSize(ID3D12Device1* This,D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) {
+ return This->lpVtbl->GetDescriptorHandleIncrementSize(This,descriptor_heap_type);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateRootSignature(ID3D12Device1* This,UINT node_mask,const void *bytecode,SIZE_T bytecode_length,REFIID riid,void **root_signature) {
+ return This->lpVtbl->CreateRootSignature(This,node_mask,bytecode,bytecode_length,riid,root_signature);
+}
+static FORCEINLINE void ID3D12Device1_CreateConstantBufferView(ID3D12Device1* This,const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateConstantBufferView(This,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device1_CreateShaderResourceView(ID3D12Device1* This,ID3D12Resource *resource,const D3D12_SHADER_RESOURCE_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateShaderResourceView(This,resource,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device1_CreateUnorderedAccessView(ID3D12Device1* This,ID3D12Resource *resource,ID3D12Resource *counter_resource,const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateUnorderedAccessView(This,resource,counter_resource,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device1_CreateRenderTargetView(ID3D12Device1* This,ID3D12Resource *resource,const D3D12_RENDER_TARGET_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateRenderTargetView(This,resource,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device1_CreateDepthStencilView(ID3D12Device1* This,ID3D12Resource *resource,const D3D12_DEPTH_STENCIL_VIEW_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateDepthStencilView(This,resource,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device1_CreateSampler(ID3D12Device1* This,const D3D12_SAMPLER_DESC *desc,D3D12_CPU_DESCRIPTOR_HANDLE descriptor) {
+ This->lpVtbl->CreateSampler(This,desc,descriptor);
+}
+static FORCEINLINE void ID3D12Device1_CopyDescriptors(ID3D12Device1* This,UINT dst_descriptor_range_count,const D3D12_CPU_DESCRIPTOR_HANDLE *dst_descriptor_range_offsets,const UINT *dst_descriptor_range_sizes,UINT src_descriptor_range_count,const D3D12_CPU_DESCRIPTOR_HANDLE *src_descriptor_range_offsets,const UINT *src_descriptor_range_sizes,D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) {
+ This->lpVtbl->CopyDescriptors(This,dst_descriptor_range_count,dst_descriptor_range_offsets,dst_descriptor_range_sizes,src_descriptor_range_count,src_descriptor_range_offsets,src_descriptor_range_sizes,descriptor_heap_type);
+}
+static FORCEINLINE void ID3D12Device1_CopyDescriptorsSimple(ID3D12Device1* This,UINT descriptor_count,const D3D12_CPU_DESCRIPTOR_HANDLE dst_descriptor_range_offset,const D3D12_CPU_DESCRIPTOR_HANDLE src_descriptor_range_offset,D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) {
+ This->lpVtbl->CopyDescriptorsSimple(This,descriptor_count,dst_descriptor_range_offset,src_descriptor_range_offset,descriptor_heap_type);
+}
+static FORCEINLINE D3D12_RESOURCE_ALLOCATION_INFO ID3D12Device1_GetResourceAllocationInfo(ID3D12Device1* This,UINT visible_mask,UINT reource_desc_count,const D3D12_RESOURCE_DESC *resource_descs) {
+ D3D12_RESOURCE_ALLOCATION_INFO __ret;
+ return *This->lpVtbl->GetResourceAllocationInfo(This,&__ret,visible_mask,reource_desc_count,resource_descs);
+}
+static FORCEINLINE D3D12_HEAP_PROPERTIES ID3D12Device1_GetCustomHeapProperties(ID3D12Device1* This,UINT node_mask,D3D12_HEAP_TYPE heap_type) {
+ D3D12_HEAP_PROPERTIES __ret;
+ return *This->lpVtbl->GetCustomHeapProperties(This,&__ret,node_mask,heap_type);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateCommittedResource(ID3D12Device1* This,const D3D12_HEAP_PROPERTIES *heap_properties,D3D12_HEAP_FLAGS heap_flags,const D3D12_RESOURCE_DESC *desc,D3D12_RESOURCE_STATES initial_state,const D3D12_CLEAR_VALUE *optimized_clear_value,REFIID riid,void **resource) {
+ return This->lpVtbl->CreateCommittedResource(This,heap_properties,heap_flags,desc,initial_state,optimized_clear_value,riid,resource);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateHeap(ID3D12Device1* This,const D3D12_HEAP_DESC *desc,REFIID riid,void **heap) {
+ return This->lpVtbl->CreateHeap(This,desc,riid,heap);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreatePlacedResource(ID3D12Device1* This,ID3D12Heap *heap,UINT64 heap_offset,const D3D12_RESOURCE_DESC *desc,D3D12_RESOURCE_STATES initial_state,const D3D12_CLEAR_VALUE *optimized_clear_value,REFIID riid,void **resource) {
+ return This->lpVtbl->CreatePlacedResource(This,heap,heap_offset,desc,initial_state,optimized_clear_value,riid,resource);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateReservedResource(ID3D12Device1* This,const D3D12_RESOURCE_DESC *desc,D3D12_RESOURCE_STATES initial_state,const D3D12_CLEAR_VALUE *optimized_clear_value,REFIID riid,void **resource) {
+ return This->lpVtbl->CreateReservedResource(This,desc,initial_state,optimized_clear_value,riid,resource);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateSharedHandle(ID3D12Device1* This,ID3D12DeviceChild *object,const SECURITY_ATTRIBUTES *attributes,DWORD access,const WCHAR *name,HANDLE *handle) {
+ return This->lpVtbl->CreateSharedHandle(This,object,attributes,access,name,handle);
+}
+static FORCEINLINE HRESULT ID3D12Device1_OpenSharedHandle(ID3D12Device1* This,HANDLE handle,REFIID riid,void **object) {
+ return This->lpVtbl->OpenSharedHandle(This,handle,riid,object);
+}
+static FORCEINLINE HRESULT ID3D12Device1_OpenSharedHandleByName(ID3D12Device1* This,const WCHAR *name,DWORD access,HANDLE *handle) {
+ return This->lpVtbl->OpenSharedHandleByName(This,name,access,handle);
+}
+static FORCEINLINE HRESULT ID3D12Device1_MakeResident(ID3D12Device1* This,UINT object_count,ID3D12Pageable *const *objects) {
+ return This->lpVtbl->MakeResident(This,object_count,objects);
+}
+static FORCEINLINE HRESULT ID3D12Device1_Evict(ID3D12Device1* This,UINT object_count,ID3D12Pageable *const *objects) {
+ return This->lpVtbl->Evict(This,object_count,objects);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateFence(ID3D12Device1* This,UINT64 initial_value,D3D12_FENCE_FLAGS flags,REFIID riid,void **fence) {
+ return This->lpVtbl->CreateFence(This,initial_value,flags,riid,fence);
+}
+static FORCEINLINE HRESULT ID3D12Device1_GetDeviceRemovedReason(ID3D12Device1* This) {
+ return This->lpVtbl->GetDeviceRemovedReason(This);
+}
+static FORCEINLINE void ID3D12Device1_GetCopyableFootprints(ID3D12Device1* This,const D3D12_RESOURCE_DESC *desc,UINT first_sub_resource,UINT sub_resource_count,UINT64 base_offset,D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts,UINT *row_count,UINT64 *row_size,UINT64 *total_bytes) {
+ This->lpVtbl->GetCopyableFootprints(This,desc,first_sub_resource,sub_resource_count,base_offset,layouts,row_count,row_size,total_bytes);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateQueryHeap(ID3D12Device1* This,const D3D12_QUERY_HEAP_DESC *desc,REFIID riid,void **heap) {
+ return This->lpVtbl->CreateQueryHeap(This,desc,riid,heap);
+}
+static FORCEINLINE HRESULT ID3D12Device1_SetStablePowerState(ID3D12Device1* This,BOOL enable) {
+ return This->lpVtbl->SetStablePowerState(This,enable);
+}
+static FORCEINLINE HRESULT ID3D12Device1_CreateCommandSignature(ID3D12Device1* This,const D3D12_COMMAND_SIGNATURE_DESC *desc,ID3D12RootSignature *root_signature,REFIID riid,void **command_signature) {
+ return This->lpVtbl->CreateCommandSignature(This,desc,root_signature,riid,command_signature);
+}
+static FORCEINLINE void ID3D12Device1_GetResourceTiling(ID3D12Device1* This,ID3D12Resource *resource,UINT *total_tile_count,D3D12_PACKED_MIP_INFO *packed_mip_info,D3D12_TILE_SHAPE *standard_tile_shape,UINT *sub_resource_tiling_count,UINT first_sub_resource_tiling,D3D12_SUBRESOURCE_TILING *sub_resource_tilings) {
+ This->lpVtbl->GetResourceTiling(This,resource,total_tile_count,packed_mip_info,standard_tile_shape,sub_resource_tiling_count,first_sub_resource_tiling,sub_resource_tilings);
+}
+static FORCEINLINE LUID ID3D12Device1_GetAdapterLuid(ID3D12Device1* This) {
+ LUID __ret;
+ return *This->lpVtbl->GetAdapterLuid(This,&__ret);
+}
+/*** ID3D12Device1 methods ***/
+static FORCEINLINE HRESULT ID3D12Device1_CreatePipelineLibrary(ID3D12Device1* This,const void *blob,SIZE_T blob_size,REFIID iid,void **lib) {
+ return This->lpVtbl->CreatePipelineLibrary(This,blob,blob_size,iid,lib);
+}
+static FORCEINLINE HRESULT ID3D12Device1_SetEventOnMultipleFenceCompletion(ID3D12Device1* This,ID3D12Fence *const *fences,const UINT64 *values,UINT fence_count,D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags,HANDLE event) {
+ return This->lpVtbl->SetEventOnMultipleFenceCompletion(This,fences,values,fence_count,flags,event);
+}
+static FORCEINLINE HRESULT ID3D12Device1_SetResidencyPriority(ID3D12Device1* This,UINT object_count,ID3D12Pageable *const *objects,const D3D12_RESIDENCY_PRIORITY *priorities) {
+ return This->lpVtbl->SetResidencyPriority(This,object_count,objects,priorities);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Device1_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12RootSignatureDeserializer interface
+ */
+#ifndef __ID3D12RootSignatureDeserializer_INTERFACE_DEFINED__
+#define __ID3D12RootSignatureDeserializer_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12RootSignatureDeserializer, 0x34ab647b, 0x3cc8, 0x46ac, 0x84,0x1b, 0xc0,0x96,0x56,0x45,0xc0,0x46);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("34ab647b-3cc8-46ac-841b-c0965645c046")
+ID3D12RootSignatureDeserializer : public IUnknown
+{
+ virtual const D3D12_ROOT_SIGNATURE_DESC * STDMETHODCALLTYPE GetRootSignatureDesc(
+ ) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12RootSignatureDeserializer, 0x34ab647b, 0x3cc8, 0x46ac, 0x84,0x1b, 0xc0,0x96,0x56,0x45,0xc0,0x46)
+#endif
+#else
+typedef struct ID3D12RootSignatureDeserializerVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12RootSignatureDeserializer *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12RootSignatureDeserializer *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12RootSignatureDeserializer *This);
+
+ /*** ID3D12RootSignatureDeserializer methods ***/
+ const D3D12_ROOT_SIGNATURE_DESC * (STDMETHODCALLTYPE *GetRootSignatureDesc)(
+ ID3D12RootSignatureDeserializer *This);
+
+ END_INTERFACE
+} ID3D12RootSignatureDeserializerVtbl;
+
+interface ID3D12RootSignatureDeserializer {
+ CONST_VTBL ID3D12RootSignatureDeserializerVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12RootSignatureDeserializer_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12RootSignatureDeserializer_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12RootSignatureDeserializer_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12RootSignatureDeserializer methods ***/
+#define ID3D12RootSignatureDeserializer_GetRootSignatureDesc(This) (This)->lpVtbl->GetRootSignatureDesc(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12RootSignatureDeserializer_QueryInterface(ID3D12RootSignatureDeserializer* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12RootSignatureDeserializer_AddRef(ID3D12RootSignatureDeserializer* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12RootSignatureDeserializer_Release(ID3D12RootSignatureDeserializer* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12RootSignatureDeserializer methods ***/
+static FORCEINLINE const D3D12_ROOT_SIGNATURE_DESC * ID3D12RootSignatureDeserializer_GetRootSignatureDesc(ID3D12RootSignatureDeserializer* This) {
+ return This->lpVtbl->GetRootSignatureDesc(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12RootSignatureDeserializer_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12VersionedRootSignatureDeserializer interface
+ */
+#ifndef __ID3D12VersionedRootSignatureDeserializer_INTERFACE_DEFINED__
+#define __ID3D12VersionedRootSignatureDeserializer_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12VersionedRootSignatureDeserializer, 0x7f91ce67, 0x090c, 0x4bb7, 0xb7,0x8e, 0xed,0x8f,0xf2,0xe3,0x1d,0xa0);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("7f91ce67-090c-4bb7-b78e-ed8ff2e31da0")
+ID3D12VersionedRootSignatureDeserializer : public IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE GetRootSignatureDescAtVersion(
+ D3D_ROOT_SIGNATURE_VERSION version,
+ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC **desc) = 0;
+
+ virtual const D3D12_VERSIONED_ROOT_SIGNATURE_DESC * STDMETHODCALLTYPE GetUnconvertedRootSignatureDesc(
+ ) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12VersionedRootSignatureDeserializer, 0x7f91ce67, 0x090c, 0x4bb7, 0xb7,0x8e, 0xed,0x8f,0xf2,0xe3,0x1d,0xa0)
+#endif
+#else
+typedef struct ID3D12VersionedRootSignatureDeserializerVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12VersionedRootSignatureDeserializer *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12VersionedRootSignatureDeserializer *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12VersionedRootSignatureDeserializer *This);
+
+ /*** ID3D12VersionedRootSignatureDeserializer methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetRootSignatureDescAtVersion)(
+ ID3D12VersionedRootSignatureDeserializer *This,
+ D3D_ROOT_SIGNATURE_VERSION version,
+ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC **desc);
+
+ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC * (STDMETHODCALLTYPE *GetUnconvertedRootSignatureDesc)(
+ ID3D12VersionedRootSignatureDeserializer *This);
+
+ END_INTERFACE
+} ID3D12VersionedRootSignatureDeserializerVtbl;
+
+interface ID3D12VersionedRootSignatureDeserializer {
+ CONST_VTBL ID3D12VersionedRootSignatureDeserializerVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12VersionedRootSignatureDeserializer_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12VersionedRootSignatureDeserializer_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12VersionedRootSignatureDeserializer_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12VersionedRootSignatureDeserializer methods ***/
+#define ID3D12VersionedRootSignatureDeserializer_GetRootSignatureDescAtVersion(This,version,desc) (This)->lpVtbl->GetRootSignatureDescAtVersion(This,version,desc)
+#define ID3D12VersionedRootSignatureDeserializer_GetUnconvertedRootSignatureDesc(This) (This)->lpVtbl->GetUnconvertedRootSignatureDesc(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12VersionedRootSignatureDeserializer_QueryInterface(ID3D12VersionedRootSignatureDeserializer* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12VersionedRootSignatureDeserializer_AddRef(ID3D12VersionedRootSignatureDeserializer* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12VersionedRootSignatureDeserializer_Release(ID3D12VersionedRootSignatureDeserializer* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12VersionedRootSignatureDeserializer methods ***/
+static FORCEINLINE HRESULT ID3D12VersionedRootSignatureDeserializer_GetRootSignatureDescAtVersion(ID3D12VersionedRootSignatureDeserializer* This,D3D_ROOT_SIGNATURE_VERSION version,const D3D12_VERSIONED_ROOT_SIGNATURE_DESC **desc) {
+ return This->lpVtbl->GetRootSignatureDescAtVersion(This,version,desc);
+}
+static FORCEINLINE const D3D12_VERSIONED_ROOT_SIGNATURE_DESC * ID3D12VersionedRootSignatureDeserializer_GetUnconvertedRootSignatureDesc(ID3D12VersionedRootSignatureDeserializer* This) {
+ return This->lpVtbl->GetUnconvertedRootSignatureDesc(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12VersionedRootSignatureDeserializer_INTERFACE_DEFINED__ */
+
+HRESULT __stdcall D3D12CreateRootSignatureDeserializer(const void *data,SIZE_T data_size,REFIID iid,void **deserializer);
+
+typedef HRESULT (__stdcall *PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER)(const void *data,SIZE_T data_size,REFIID iid,void **deserializer);
+HRESULT __stdcall D3D12CreateVersionedRootSignatureDeserializer(const void *data,SIZE_T data_size,REFIID iid,void **deserializer);
+
+HRESULT __stdcall D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *root_signature_desc,D3D_ROOT_SIGNATURE_VERSION version,ID3DBlob **blob,ID3DBlob **error_blob);
+
+typedef HRESULT (__stdcall *PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,ID3DBlob **blob,ID3DBlob **error_blob);
+HRESULT __stdcall D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *root_signature_desc,ID3DBlob **blob,ID3DBlob **error_blob);
+
+typedef HRESULT (__stdcall *PFN_D3D12_CREATE_DEVICE)(IUnknown *adapter,D3D_FEATURE_LEVEL minimum_feature_level,REFIID iid,void **device);
+HRESULT __stdcall D3D12CreateDevice(IUnknown *adapter,D3D_FEATURE_LEVEL minimum_feature_level,REFIID iid,void **device);
+
+typedef HRESULT (__stdcall *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID iid,void **debug);
+HRESULT __stdcall D3D12GetDebugInterface(REFIID iid,void **debug);
+
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_d3d12_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_d3d12.idl b/dlls/vkd3d/include/vkd3d_d3d12.idl
new file mode 100644
index 00000000000..48b87f09b12
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_d3d12.idl
@@ -0,0 +1,2547 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_windows.h";
+
+import "vkd3d_dxgibase.idl";
+
+import "vkd3d_d3dcommon.idl";
+
+cpp_quote("#ifndef _D3D12_CONSTANTS")
+cpp_quote("#define _D3D12_CONSTANTS")
+
+const UINT D3D12_CS_TGSM_REGISTER_COUNT = 8192;
+const UINT D3D12_MAX_ROOT_COST = 64;
+const UINT D3D12_VIEWPORT_BOUNDS_MAX = 32767;
+const UINT D3D12_VIEWPORT_BOUNDS_MIN = -32768;
+
+const UINT D3D12_COMMONSHADER_CONSTANT_BUFFER_REGISTER_COUNT = 15;
+
+const UINT D3D12_APPEND_ALIGNED_ELEMENT = 0xffffffff;
+cpp_quote("#define D3D12_DEFAULT_BLEND_FACTOR_ALPHA (1.0f)")
+cpp_quote("#define D3D12_DEFAULT_BLEND_FACTOR_BLUE (1.0f)")
+cpp_quote("#define D3D12_DEFAULT_BLEND_FACTOR_GREEN (1.0f)")
+cpp_quote("#define D3D12_DEFAULT_BLEND_FACTOR_RED (1.0f)")
+const UINT D3D12_DEFAULT_DEPTH_BIAS = 0;
+cpp_quote("#define D3D12_DEFAULT_DEPTH_BIAS_CLAMP (0.0f)")
+cpp_quote("#define D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS (0.0f)")
+const UINT D3D12_DEFAULT_STENCIL_READ_MASK = 0xff;
+const UINT D3D12_DEFAULT_STENCIL_WRITE_MASK = 0xff;
+const UINT D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND = 0xffffffff;
+cpp_quote("#define D3D12_FLOAT32_MAX (3.402823466e+38f)")
+const UINT D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32;
+const UINT D3D12_UAV_SLOT_COUNT = 64;
+const UINT D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT = 4096;
+const UINT D3D12_REQ_IMMEDIATE_CONSTANT_BUFFER_ELEMENT_COUNT = 4096;
+const UINT D3D12_REQ_MIP_LEVELS = 15;
+const UINT D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION = 2048;
+const UINT D3D12_REQ_TEXTURE1D_U_DIMENSION = 16384;
+const UINT D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION = 2048;
+const UINT D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION = 16384;
+const UINT D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION = 2048;
+const UINT D3D12_REQ_TEXTURECUBE_DIMENSION = 16384;
+const UINT D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES = 0xffffffff;
+const UINT D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT = 8;
+const UINT D3D12_SO_BUFFER_MAX_STRIDE_IN_BYTES = 2048;
+const UINT D3D12_SO_BUFFER_SLOT_COUNT = 4;
+const UINT D3D12_SO_DDI_REGISTER_INDEX_DENOTING_GAP = 0xffffffff;
+const UINT D3D12_SO_NO_RASTERIZED_STREAM = 0xffffffff;
+const UINT D3D12_SO_OUTPUT_COMPONENT_COUNT = 128;
+const UINT D3D12_SO_STREAM_COUNT = 4;
+const UINT D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT = 256;
+const UINT D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT = 4194304;
+const UINT D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT = 65536;
+const UINT D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT = 16;
+const UINT D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT = 65536;
+const UINT D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT = 4096;
+const UINT D3D12_STANDARD_MAXIMUM_ELEMENT_ALIGNMENT_BYTE_MULTIPLE = 4;
+const UINT D3D12_TEXTURE_DATA_PITCH_ALIGNMENT = 256;
+const UINT D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT = 512;
+const UINT D3D12_UAV_COUNTER_PLACEMENT_ALIGNMENT = 4096;
+const UINT D3D12_VS_INPUT_REGISTER_COUNT = 32;
+const UINT D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE = 16;
+
+cpp_quote("#endif")
+
+const UINT D3D12_SHADER_COMPONENT_MAPPING_MASK = 0x7;
+const UINT D3D12_SHADER_COMPONENT_MAPPING_SHIFT = 3;
+const UINT D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES
+ = 1 << (D3D12_SHADER_COMPONENT_MAPPING_SHIFT * 4);
+
+typedef enum D3D12_SHADER_MIN_PRECISION_SUPPORT
+{
+ D3D12_SHADER_MIN_PRECISION_SUPPORT_NONE = 0x0,
+ D3D12_SHADER_MIN_PRECISION_SUPPORT_10_BIT = 0x1,
+ D3D12_SHADER_MIN_PRECISION_SUPPORT_16_BIT = 0x2,
+} D3D12_SHADER_MIN_PRECISION_SUPPORT;
+
+typedef enum D3D12_TILED_RESOURCES_TIER
+{
+ D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED = 0,
+ D3D12_TILED_RESOURCES_TIER_1 = 1,
+ D3D12_TILED_RESOURCES_TIER_2 = 2,
+ D3D12_TILED_RESOURCES_TIER_3 = 3,
+} D3D12_TILED_RESOURCES_TIER;
+
+typedef enum D3D12_RESOURCE_BINDING_TIER
+{
+ D3D12_RESOURCE_BINDING_TIER_1 = 1,
+ D3D12_RESOURCE_BINDING_TIER_2 = 2,
+ D3D12_RESOURCE_BINDING_TIER_3 = 3,
+} D3D12_RESOURCE_BINDING_TIER;
+
+typedef enum D3D12_CONSERVATIVE_RASTERIZATION_TIER
+{
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED = 0,
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER_1 = 1,
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER_2 = 2,
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER_3 = 3,
+} D3D12_CONSERVATIVE_RASTERIZATION_TIER;
+
+typedef enum D3D12_CROSS_NODE_SHARING_TIER
+{
+ D3D12_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED = 0,
+ D3D12_CROSS_NODE_SHARING_TIER_1_EMULATED = 1,
+ D3D12_CROSS_NODE_SHARING_TIER_1 = 2,
+ D3D12_CROSS_NODE_SHARING_TIER_2 = 3,
+} D3D12_CROSS_NODE_SHARING_TIER;
+
+typedef enum D3D12_RESOURCE_HEAP_TIER
+{
+ D3D12_RESOURCE_HEAP_TIER_1 = 1,
+ D3D12_RESOURCE_HEAP_TIER_2 = 2,
+} D3D12_RESOURCE_HEAP_TIER;
+
+typedef enum D3D12_FORMAT_SUPPORT1
+{
+ D3D12_FORMAT_SUPPORT1_NONE = 0x00000000,
+ D3D12_FORMAT_SUPPORT1_BUFFER = 0x00000001,
+ D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER = 0x00000002,
+ D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER = 0x00000004,
+ D3D12_FORMAT_SUPPORT1_SO_BUFFER = 0x00000008,
+ D3D12_FORMAT_SUPPORT1_TEXTURE1D = 0x00000010,
+ D3D12_FORMAT_SUPPORT1_TEXTURE2D = 0x00000020,
+ D3D12_FORMAT_SUPPORT1_TEXTURE3D = 0x00000040,
+ D3D12_FORMAT_SUPPORT1_TEXTURECUBE = 0x00000080,
+ D3D12_FORMAT_SUPPORT1_SHADER_LOAD = 0x00000100,
+ D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE = 0x00000200,
+ D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_COMPARISON = 0x00000400,
+ D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_MONO_TEXT = 0x00000800,
+ D3D12_FORMAT_SUPPORT1_MIP = 0x00001000,
+ D3D12_FORMAT_SUPPORT1_RENDER_TARGET = 0x00004000,
+ D3D12_FORMAT_SUPPORT1_BLENDABLE = 0x00008000,
+ D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL = 0x00010000,
+ D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE = 0x00040000,
+ D3D12_FORMAT_SUPPORT1_DISPLAY = 0x00080000,
+ D3D12_FORMAT_SUPPORT1_CAST_WITHIN_BIT_LAYOUT = 0x00100000,
+ D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET = 0x00200000,
+ D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD = 0x00400000,
+ D3D12_FORMAT_SUPPORT1_SHADER_GATHER = 0x00800000,
+ D3D12_FORMAT_SUPPORT1_BACK_BUFFER_CAST = 0x01000000,
+ D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW = 0x02000000,
+ D3D12_FORMAT_SUPPORT1_SHADER_GATHER_COMPARISON = 0x04000000,
+ D3D12_FORMAT_SUPPORT1_DECODER_OUTPUT = 0x08000000,
+ D3D12_FORMAT_SUPPORT1_VIDEO_PROCESSOR_OUTPUT = 0x10000000,
+ D3D12_FORMAT_SUPPORT1_VIDEO_PROCESSOR_INPUT = 0x20000000,
+ D3D12_FORMAT_SUPPORT1_VIDEO_ENCODER = 0x40000000,
+} D3D12_FORMAT_SUPPORT1;
+
+typedef enum D3D12_FORMAT_SUPPORT2
+{
+ D3D12_FORMAT_SUPPORT2_NONE = 0x00000000,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_ADD = 0x00000001,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS = 0x00000002,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 0x00000004,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE = 0x00000008,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX = 0x00000010,
+ D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 0x00000020,
+ D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD = 0x00000040,
+ D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE = 0x00000080,
+ D3D12_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP = 0x00000100,
+ D3D12_FORMAT_SUPPORT2_TILED = 0x00000200,
+ D3D12_FORMAT_SUPPORT2_MULTIPLANE_OVERLAY = 0x00004000,
+} D3D12_FORMAT_SUPPORT2;
+
+typedef enum D3D12_WRITEBUFFERIMMEDIATE_MODE
+{
+ D3D12_WRITEBUFFERIMMEDIATE_MODE_DEFAULT = 0x0,
+ D3D12_WRITEBUFFERIMMEDIATE_MODE_MARKER_IN = 0x1,
+ D3D12_WRITEBUFFERIMMEDIATE_MODE_MARKER_OUT = 0x2,
+} D3D12_WRITEBUFFERIMMEDIATE_MODE;
+
+typedef enum D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER
+{
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED = 0x0,
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_1 = 0x1,
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_2 = 0x2,
+} D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER;
+
+typedef enum D3D12_SHADER_CACHE_SUPPORT_FLAGS
+{
+ D3D12_SHADER_CACHE_SUPPORT_NONE = 0x0,
+ D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO = 0x1,
+ D3D12_SHADER_CACHE_SUPPORT_LIBRARY = 0x2,
+ D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_INPROC_CACHE = 0x4,
+ D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_DISK_CACHE = 0x8,
+} D3D12_SHADER_CACHE_SUPPORT_FLAGS;
+
+typedef enum D3D12_COMMAND_LIST_SUPPORT_FLAGS
+{
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE = 0x0,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_DIRECT = 0x1,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_BUNDLE = 0x2,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_COMPUTE = 0x4,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_COPY = 0x8,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_DECODE = 0x10,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_PROCESS = 0x20,
+ D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_ENCODE = 0x40,
+} D3D12_COMMAND_LIST_SUPPORT_FLAGS;
+
+typedef enum D3D12_VIEW_INSTANCING_TIER
+{
+ D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED = 0x0,
+ D3D12_VIEW_INSTANCING_TIER_1 = 0x1,
+ D3D12_VIEW_INSTANCING_TIER_2 = 0x2,
+ D3D12_VIEW_INSTANCING_TIER_3 = 0x3,
+} D3D12_VIEW_INSTANCING_TIER;
+
+typedef enum D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER
+{
+ D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_0 = 0x0,
+ D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_1 = 0x1,
+} D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER;
+
+typedef enum D3D12_HEAP_SERIALIZATION_TIER
+{
+ D3D12_HEAP_SERIALIZATION_TIER_0 = 0x0,
+ D3D12_HEAP_SERIALIZATION_TIER_10 = 0xa,
+} D3D12_HEAP_SERIALIZATION_TIER;
+
+typedef enum D3D12_RENDER_PASS_TIER
+{
+ D3D12_RENDER_PASS_TIER_0 = 0x0,
+ D3D12_RENDER_PASS_TIER_1 = 0x1,
+ D3D12_RENDER_PASS_TIER_2 = 0x2,
+} D3D12_RENDER_PASS_TIER;
+
+typedef enum D3D12_RAYTRACING_TIER
+{
+ D3D12_RAYTRACING_TIER_NOT_SUPPORTED = 0x0,
+ D3D12_RAYTRACING_TIER_1_0 = 0xa,
+} D3D12_RAYTRACING_TIER;
+
+interface ID3D12Fence;
+interface ID3D12RootSignature;
+interface ID3D12Heap;
+interface ID3D12DescriptorHeap;
+interface ID3D12Resource;
+interface ID3D12CommandAllocator;
+interface ID3D12GraphicsCommandList;
+interface ID3D12CommandQueue;
+interface ID3D12PipelineState;
+interface ID3D12Device;
+
+typedef RECT D3D12_RECT;
+
+typedef struct D3D12_BOX
+{
+ UINT left;
+ UINT top;
+ UINT front;
+ UINT right;
+ UINT bottom;
+ UINT back;
+} D3D12_BOX;
+
+typedef struct D3D12_VIEWPORT
+{
+ FLOAT TopLeftX;
+ FLOAT TopLeftY;
+ FLOAT Width;
+ FLOAT Height;
+ FLOAT MinDepth;
+ FLOAT MaxDepth;
+} D3D12_VIEWPORT;
+
+typedef struct D3D12_RANGE
+{
+ SIZE_T Begin;
+ SIZE_T End;
+} D3D12_RANGE;
+
+typedef struct D3D12_RANGE_UINT64
+{
+ UINT64 Begin;
+ UINT64 End;
+} D3D12_RANGE_UINT64;
+
+typedef struct D3D12_SUBRESOURCE_RANGE_UINT64
+{
+ UINT Subresource;
+ D3D12_RANGE_UINT64 Range;
+} D3D12_SUBRESOURCE_RANGE_UINT64;
+
+typedef struct D3D12_RESOURCE_ALLOCATION_INFO
+{
+ UINT64 SizeInBytes;
+ UINT64 Alignment;
+} D3D12_RESOURCE_ALLOCATION_INFO;
+
+typedef struct D3D12_DRAW_ARGUMENTS
+{
+ UINT VertexCountPerInstance;
+ UINT InstanceCount;
+ UINT StartVertexLocation;
+ UINT StartInstanceLocation;
+} D3D12_DRAW_ARGUMENTS;
+
+typedef struct D3D12_DRAW_INDEXED_ARGUMENTS
+{
+ UINT IndexCountPerInstance;
+ UINT InstanceCount;
+ UINT StartIndexLocation;
+ INT BaseVertexLocation;
+ UINT StartInstanceLocation;
+} D3D12_DRAW_INDEXED_ARGUMENTS;
+
+typedef struct D3D12_DISPATCH_ARGUMENTS
+{
+ UINT ThreadGroupCountX;
+ UINT ThreadGroupCountY;
+ UINT ThreadGroupCountZ;
+} D3D12_DISPATCH_ARGUMENTS;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS
+{
+ BOOL DoublePrecisionFloatShaderOps;
+ BOOL OutputMergerLogicOp;
+ D3D12_SHADER_MIN_PRECISION_SUPPORT MinPrecisionSupport;
+ D3D12_TILED_RESOURCES_TIER TiledResourcesTier;
+ D3D12_RESOURCE_BINDING_TIER ResourceBindingTier;
+ BOOL PSSpecifiedStencilRefSupported;
+ BOOL TypedUAVLoadAdditionalFormats;
+ BOOL ROVsSupported;
+ D3D12_CONSERVATIVE_RASTERIZATION_TIER ConservativeRasterizationTier;
+ UINT MaxGPUVirtualAddressBitsPerResource;
+ BOOL StandardSwizzle64KBSupported;
+ D3D12_CROSS_NODE_SHARING_TIER CrossNodeSharingTier;
+ BOOL CrossAdapterRowMajorTextureSupported;
+ BOOL VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation;
+ D3D12_RESOURCE_HEAP_TIER ResourceHeapTier;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS;
+
+typedef struct D3D12_FEATURE_DATA_FORMAT_SUPPORT
+{
+ DXGI_FORMAT Format;
+ D3D12_FORMAT_SUPPORT1 Support1;
+ D3D12_FORMAT_SUPPORT2 Support2;
+} D3D12_FEATURE_DATA_FORMAT_SUPPORT;
+
+typedef enum D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS
+{
+ D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE = 0x00000000,
+ D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE = 0x00000001,
+} D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS;
+
+typedef struct D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS
+{
+ DXGI_FORMAT Format;
+ UINT SampleCount;
+ D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS Flags;
+ UINT NumQualityLevels;
+} D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS;
+
+typedef enum D3D12_HEAP_TYPE
+{
+ D3D12_HEAP_TYPE_DEFAULT = 1,
+ D3D12_HEAP_TYPE_UPLOAD = 2,
+ D3D12_HEAP_TYPE_READBACK = 3,
+ D3D12_HEAP_TYPE_CUSTOM = 4,
+} D3D12_HEAP_TYPE;
+
+typedef enum D3D12_CPU_PAGE_PROPERTY
+{
+ D3D12_CPU_PAGE_PROPERTY_UNKNOWN = 0,
+ D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE = 1,
+ D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE = 2,
+ D3D12_CPU_PAGE_PROPERTY_WRITE_BACK = 3,
+} D3D12_CPU_PAGE_PROPERTY;
+
+typedef enum D3D12_MEMORY_POOL
+{
+ D3D12_MEMORY_POOL_UNKNOWN = 0,
+ D3D12_MEMORY_POOL_L0 = 1,
+ D3D12_MEMORY_POOL_L1 = 2,
+} D3D12_MEMORY_POOL;
+
+typedef struct D3D12_HEAP_PROPERTIES
+{
+ D3D12_HEAP_TYPE Type;
+ D3D12_CPU_PAGE_PROPERTY CPUPageProperty;
+ D3D12_MEMORY_POOL MemoryPoolPreference;
+ UINT CreationNodeMask;
+ UINT VisibleNodeMask;
+} D3D12_HEAP_PROPERTIES;
+
+typedef enum D3D12_HEAP_FLAGS
+{
+ D3D12_HEAP_FLAG_NONE = 0x00,
+ D3D12_HEAP_FLAG_SHARED = 0x01,
+ D3D12_HEAP_FLAG_DENY_BUFFERS = 0x04,
+ D3D12_HEAP_FLAG_ALLOW_DISPLAY = 0x08,
+ D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER = 0x20,
+ D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES = 0x40,
+ D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES = 0x80,
+ D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0x00,
+ D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS = 0xc0,
+ D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES = 0x44,
+ D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES = 0x84,
+} D3D12_HEAP_FLAGS;
+
+typedef struct D3D12_HEAP_DESC
+{
+ UINT64 SizeInBytes;
+ D3D12_HEAP_PROPERTIES Properties;
+ UINT64 Alignment;
+ D3D12_HEAP_FLAGS Flags;
+} D3D12_HEAP_DESC;
+
+typedef struct D3D12_TILED_RESOURCE_COORDINATE
+{
+ UINT X;
+ UINT Y;
+ UINT Z;
+ UINT Subresource;
+} D3D12_TILED_RESOURCE_COORDINATE;
+
+typedef struct D3D12_TILE_REGION_SIZE
+{
+ UINT NumTiles;
+ BOOL UseBox;
+ UINT Width;
+ UINT16 Height;
+ UINT16 Depth;
+} D3D12_TILE_REGION_SIZE;
+
+typedef struct D3D12_SUBRESOURCE_TILING
+{
+ UINT WidthInTiles;
+ UINT16 HeightInTiles;
+ UINT16 DepthInTiles;
+ UINT StartTileIndexInOverallResource;
+} D3D12_SUBRESOURCE_TILING;
+
+typedef struct D3D12_TILE_SHAPE
+{
+ UINT WidthInTexels;
+ UINT HeightInTexels;
+ UINT DepthInTexels;
+} D3D12_TILE_SHAPE;
+
+typedef struct D3D12_SHADER_BYTECODE
+{
+ const void *pShaderBytecode;
+ SIZE_T BytecodeLength;
+} D3D12_SHADER_BYTECODE;
+
+typedef struct D3D12_DEPTH_STENCIL_VALUE
+{
+ FLOAT Depth;
+ UINT8 Stencil;
+} D3D12_DEPTH_STENCIL_VALUE;
+
+typedef struct D3D12_CLEAR_VALUE
+{
+ DXGI_FORMAT Format;
+ union
+ {
+ FLOAT Color[4];
+ D3D12_DEPTH_STENCIL_VALUE DepthStencil;
+ };
+} D3D12_CLEAR_VALUE;
+
+typedef struct D3D12_PACKED_MIP_INFO
+{
+ UINT8 NumStandardMips;
+ UINT8 NumPackedMips;
+ UINT NumTilesForPackedMips;
+ UINT StartTileIndexInOverallResource;
+} D3D12_PACKED_MIP_INFO;
+
+typedef enum D3D12_RESOURCE_STATES
+{
+ D3D12_RESOURCE_STATE_COMMON = 0,
+ D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER = 0x1,
+ D3D12_RESOURCE_STATE_INDEX_BUFFER = 0x2,
+ D3D12_RESOURCE_STATE_RENDER_TARGET = 0x4,
+ D3D12_RESOURCE_STATE_UNORDERED_ACCESS = 0x8,
+ D3D12_RESOURCE_STATE_DEPTH_WRITE = 0x10,
+ D3D12_RESOURCE_STATE_DEPTH_READ = 0x20,
+ D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE = 0x40,
+ D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE = 0x80,
+ D3D12_RESOURCE_STATE_STREAM_OUT = 0x100,
+ D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT = 0x200,
+ D3D12_RESOURCE_STATE_COPY_DEST = 0x400,
+ D3D12_RESOURCE_STATE_COPY_SOURCE = 0x800,
+ D3D12_RESOURCE_STATE_RESOLVE_DEST = 0x1000,
+ D3D12_RESOURCE_STATE_RESOLVE_SOURCE = 0x2000,
+ D3D12_RESOURCE_STATE_GENERIC_READ = 0x1 | 0x2 | 0x40 | 0x80 | 0x200 | 0x800,
+ D3D12_RESOURCE_STATE_PRESENT = 0x0,
+ D3D12_RESOURCE_STATE_PREDICATION = 0x200,
+} D3D12_RESOURCE_STATES;
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RESOURCE_STATES);")
+
+typedef enum D3D12_RESOURCE_BARRIER_TYPE
+{
+ D3D12_RESOURCE_BARRIER_TYPE_TRANSITION = 0,
+ D3D12_RESOURCE_BARRIER_TYPE_ALIASING = 1,
+ D3D12_RESOURCE_BARRIER_TYPE_UAV = 2,
+} D3D12_RESOURCE_BARRIER_TYPE;
+
+typedef enum D3D12_RESOURCE_BARRIER_FLAGS
+{
+ D3D12_RESOURCE_BARRIER_FLAG_NONE = 0x0,
+ D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY = 0x1,
+ D3D12_RESOURCE_BARRIER_FLAG_END_ONLY = 0x2,
+} D3D12_RESOURCE_BARRIER_FLAGS;
+
+typedef struct D3D12_RESOURCE_TRANSITION_BARRIER
+{
+ ID3D12Resource *pResource;
+ UINT Subresource;
+ D3D12_RESOURCE_STATES StateBefore;
+ D3D12_RESOURCE_STATES StateAfter;
+} D3D12_RESOURCE_TRANSITION_BARRIER;
+
+typedef struct D3D12_RESOURCE_ALIASING_BARRIER_ALIASING
+{
+ ID3D12Resource *pResourceBefore;
+ ID3D12Resource *pResourceAfter;
+} D3D12_RESOURCE_ALIASING_BARRIER;
+
+typedef struct D3D12_RESOURCE_UAV_BARRIER
+{
+ ID3D12Resource *pResource;
+} D3D12_RESOURCE_UAV_BARRIER;
+
+typedef struct D3D12_RESOURCE_BARRIER
+{
+ D3D12_RESOURCE_BARRIER_TYPE Type;
+ D3D12_RESOURCE_BARRIER_FLAGS Flags;
+ union
+ {
+ D3D12_RESOURCE_TRANSITION_BARRIER Transition;
+ D3D12_RESOURCE_ALIASING_BARRIER Aliasing;
+ D3D12_RESOURCE_UAV_BARRIER UAV;
+ };
+} D3D12_RESOURCE_BARRIER;
+
+typedef enum D3D12_RESOURCE_DIMENSION
+{
+ D3D12_RESOURCE_DIMENSION_UNKNOWN = 0,
+ D3D12_RESOURCE_DIMENSION_BUFFER = 1,
+ D3D12_RESOURCE_DIMENSION_TEXTURE1D = 2,
+ D3D12_RESOURCE_DIMENSION_TEXTURE2D = 3,
+ D3D12_RESOURCE_DIMENSION_TEXTURE3D = 4,
+} D3D12_RESOURCE_DIMENSION;
+
+typedef enum D3D12_TEXTURE_LAYOUT
+{
+ D3D12_TEXTURE_LAYOUT_UNKNOWN = 0,
+ D3D12_TEXTURE_LAYOUT_ROW_MAJOR = 1,
+ D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE = 2,
+ D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE = 3,
+} D3D12_TEXTURE_LAYOUT;
+
+typedef enum D3D12_RESOURCE_FLAGS
+{
+ D3D12_RESOURCE_FLAG_NONE = 0x0,
+ D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET = 0x1,
+ D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL = 0x2,
+ D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS = 0x4,
+ D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE = 0x8,
+ D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER = 0x10,
+ D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS = 0x20,
+} D3D12_RESOURCE_FLAGS;
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RESOURCE_FLAGS);")
+
+typedef struct D3D12_RESOURCE_DESC
+{
+ D3D12_RESOURCE_DIMENSION Dimension;
+ UINT64 Alignment;
+ UINT64 Width;
+ UINT Height;
+ UINT16 DepthOrArraySize;
+ UINT16 MipLevels;
+ DXGI_FORMAT Format;
+ DXGI_SAMPLE_DESC SampleDesc;
+ D3D12_TEXTURE_LAYOUT Layout;
+ D3D12_RESOURCE_FLAGS Flags;
+} D3D12_RESOURCE_DESC;
+
+typedef enum D3D12_RESOLVE_MODE
+{
+ D3D12_RESOLVE_MODE_DECOMPRESS = 0,
+ D3D12_RESOLVE_MODE_MIN = 1,
+ D3D12_RESOLVE_MODE_MAX = 2,
+ D3D12_RESOLVE_MODE_AVERAGE = 3,
+} D3D12_RESOLVE_MODE;
+
+typedef struct D3D12_SAMPLE_POSITION
+{
+ INT8 X;
+ INT8 Y;
+} D3D12_SAMPLE_POSITION;
+
+typedef enum D3D12_TEXTURE_COPY_TYPE
+{
+ D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX = 0,
+ D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT = 1,
+} D3D12_TEXTURE_COPY_TYPE;
+
+typedef struct D3D12_SUBRESOURCE_FOOTPRINT
+{
+ DXGI_FORMAT Format;
+ UINT Width;
+ UINT Height;
+ UINT Depth;
+ UINT RowPitch;
+} D3D12_SUBRESOURCE_FOOTPRINT;
+
+typedef struct D3D12_PLACED_SUBRESOURCE_FOOTPRINT
+{
+ UINT64 Offset;
+ D3D12_SUBRESOURCE_FOOTPRINT Footprint;
+} D3D12_PLACED_SUBRESOURCE_FOOTPRINT;
+
+typedef struct D3D12_TEXTURE_COPY_LOCATION
+{
+ ID3D12Resource *pResource;
+ D3D12_TEXTURE_COPY_TYPE Type;
+ union
+ {
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT PlacedFootprint;
+ UINT SubresourceIndex;
+ };
+} D3D12_TEXTURE_COPY_LOCATION;
+
+typedef enum D3D12_DESCRIPTOR_RANGE_TYPE
+{
+ D3D12_DESCRIPTOR_RANGE_TYPE_SRV = 0,
+ D3D12_DESCRIPTOR_RANGE_TYPE_UAV = 1,
+ D3D12_DESCRIPTOR_RANGE_TYPE_CBV = 2,
+ D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER = 3,
+} D3D12_DESCRIPTOR_RANGE_TYPE;
+
+typedef struct D3D12_DESCRIPTOR_RANGE
+{
+ D3D12_DESCRIPTOR_RANGE_TYPE RangeType;
+ UINT NumDescriptors;
+ UINT BaseShaderRegister;
+ UINT RegisterSpace;
+ UINT OffsetInDescriptorsFromTableStart;
+} D3D12_DESCRIPTOR_RANGE;
+
+typedef enum D3D12_DESCRIPTOR_RANGE_FLAGS
+{
+ D3D12_DESCRIPTOR_RANGE_FLAG_NONE = 0x0,
+ D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE = 0x1,
+ D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2,
+ D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
+ D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8,
+} D3D12_DESCRIPTOR_RANGE_FLAGS;
+
+typedef struct D3D12_DESCRIPTOR_RANGE1
+{
+ D3D12_DESCRIPTOR_RANGE_TYPE RangeType;
+ UINT NumDescriptors;
+ UINT BaseShaderRegister;
+ UINT RegisterSpace;
+ D3D12_DESCRIPTOR_RANGE_FLAGS Flags;
+ UINT OffsetInDescriptorsFromTableStart;
+} D3D12_DESCRIPTOR_RANGE1;
+
+typedef struct D3D12_ROOT_DESCRIPTOR_TABLE
+{
+ UINT NumDescriptorRanges;
+ const D3D12_DESCRIPTOR_RANGE *pDescriptorRanges;
+} D3D12_ROOT_DESCRIPTOR_TABLE;
+
+typedef struct D3D12_ROOT_DESCRIPTOR_TABLE1
+{
+ UINT NumDescriptorRanges;
+ const D3D12_DESCRIPTOR_RANGE1 *pDescriptorRanges;
+} D3D12_ROOT_DESCRIPTOR_TABLE1;
+
+typedef struct D3D12_ROOT_CONSTANTS
+{
+ UINT ShaderRegister;
+ UINT RegisterSpace;
+ UINT Num32BitValues;
+} D3D12_ROOT_CONSTANTS;
+
+typedef struct D3D12_ROOT_DESCRIPTOR
+{
+ UINT ShaderRegister;
+ UINT RegisterSpace;
+} D3D12_ROOT_DESCRIPTOR;
+
+typedef enum D3D12_ROOT_DESCRIPTOR_FLAGS
+{
+ D3D12_ROOT_DESCRIPTOR_FLAG_NONE = 0x0,
+ D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE = 0x2,
+ D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
+ D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC = 0x8,
+} D3D12_ROOT_DESCRIPTOR_FLAGS;
+
+typedef struct D3D12_ROOT_DESCRIPTOR1
+{
+ UINT ShaderRegister;
+ UINT RegisterSpace;
+ D3D12_ROOT_DESCRIPTOR_FLAGS Flags;
+} D3D12_ROOT_DESCRIPTOR1;
+
+typedef enum D3D12_ROOT_PARAMETER_TYPE
+{
+ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE = 0,
+ D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS = 1,
+ D3D12_ROOT_PARAMETER_TYPE_CBV = 2,
+ D3D12_ROOT_PARAMETER_TYPE_SRV = 3,
+ D3D12_ROOT_PARAMETER_TYPE_UAV = 4,
+} D3D12_ROOT_PARAMETER_TYPE;
+
+typedef enum D3D12_SHADER_VISIBILITY
+{
+ D3D12_SHADER_VISIBILITY_ALL = 0,
+ D3D12_SHADER_VISIBILITY_VERTEX = 1,
+ D3D12_SHADER_VISIBILITY_HULL = 2,
+ D3D12_SHADER_VISIBILITY_DOMAIN = 3,
+ D3D12_SHADER_VISIBILITY_GEOMETRY = 4,
+ D3D12_SHADER_VISIBILITY_PIXEL = 5,
+} D3D12_SHADER_VISIBILITY;
+
+typedef struct D3D12_ROOT_PARAMETER
+{
+ D3D12_ROOT_PARAMETER_TYPE ParameterType;
+ union
+ {
+ D3D12_ROOT_DESCRIPTOR_TABLE DescriptorTable;
+ D3D12_ROOT_CONSTANTS Constants;
+ D3D12_ROOT_DESCRIPTOR Descriptor;
+ };
+ D3D12_SHADER_VISIBILITY ShaderVisibility;
+} D3D12_ROOT_PARAMETER;
+
+typedef struct D3D12_ROOT_PARAMETER1
+{
+ D3D12_ROOT_PARAMETER_TYPE ParameterType;
+ union
+ {
+ D3D12_ROOT_DESCRIPTOR_TABLE1 DescriptorTable;
+ D3D12_ROOT_CONSTANTS Constants;
+ D3D12_ROOT_DESCRIPTOR1 Descriptor;
+ };
+ D3D12_SHADER_VISIBILITY ShaderVisibility;
+} D3D12_ROOT_PARAMETER1;
+
+typedef enum D3D12_STATIC_BORDER_COLOR
+{
+ D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK = 0,
+ D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK = 1,
+ D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE = 2,
+} D3D12_STATIC_BORDER_COLOR;
+
+typedef enum D3D12_FILTER
+{
+ D3D12_FILTER_MIN_MAG_MIP_POINT = 0x00,
+ D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR = 0x01,
+ D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x04,
+ D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x05,
+ D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT = 0x10,
+ D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11,
+ D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14,
+ D3D12_FILTER_MIN_MAG_MIP_LINEAR = 0x15,
+ D3D12_FILTER_ANISOTROPIC = 0x55,
+ D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT = 0x80,
+ D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x81,
+ D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x84,
+ D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR = 0x85,
+ D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT = 0x90,
+ D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x91,
+ D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x94,
+ D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR = 0x95,
+ D3D12_FILTER_COMPARISON_ANISOTROPIC = 0xd5,
+ D3D12_FILTER_MINIMUM_MIN_MAG_MIP_POINT = 0x100,
+ D3D12_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x101,
+ D3D12_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x104,
+ D3D12_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR = 0x105,
+ D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT = 0x110,
+ D3D12_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x111,
+ D3D12_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x114,
+ D3D12_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR = 0x115,
+ D3D12_FILTER_MINIMUM_ANISOTROPIC = 0x155,
+ D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_POINT = 0x180,
+ D3D12_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x181,
+ D3D12_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x184,
+ D3D12_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR = 0x185,
+ D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT = 0x190,
+ D3D12_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x191,
+ D3D12_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x194,
+ D3D12_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR = 0x195,
+ D3D12_FILTER_MAXIMUM_ANISOTROPIC = 0x1d5,
+} D3D12_FILTER;
+
+typedef enum D3D12_FILTER_TYPE
+{
+ D3D12_FILTER_TYPE_POINT = 0,
+ D3D12_FILTER_TYPE_LINEAR = 1,
+} D3D12_FILTER_TYPE;
+
+const UINT D3D12_MIP_FILTER_SHIFT = 0;
+const UINT D3D12_MAG_FILTER_SHIFT = 2;
+const UINT D3D12_MIN_FILTER_SHIFT = 4;
+const UINT D3D12_FILTER_TYPE_MASK = 0x3;
+
+const UINT D3D12_ANISOTROPIC_FILTERING_BIT = 0x40;
+
+typedef enum D3D12_FILTER_REDUCTION_TYPE
+{
+ D3D12_FILTER_REDUCTION_TYPE_STANDARD = 0,
+ D3D12_FILTER_REDUCTION_TYPE_COMPARISON = 1,
+ D3D12_FILTER_REDUCTION_TYPE_MINIMUM = 2,
+ D3D12_FILTER_REDUCTION_TYPE_MAXIMUM = 3,
+} D3D12_FILTER_REDUCTION_TYPE;
+
+const UINT D3D12_FILTER_REDUCTION_TYPE_MASK = 0x3;
+const UINT D3D12_FILTER_REDUCTION_TYPE_SHIFT = 7;
+
+cpp_quote("#define D3D12_DECODE_MAG_FILTER(filter) \\")
+cpp_quote(" ((D3D12_FILTER_TYPE)(((filter) >> D3D12_MAG_FILTER_SHIFT) & D3D12_FILTER_TYPE_MASK))")
+
+cpp_quote("#define D3D12_DECODE_MIN_FILTER(filter) \\")
+cpp_quote(" ((D3D12_FILTER_TYPE)(((filter) >> D3D12_MIN_FILTER_SHIFT) & D3D12_FILTER_TYPE_MASK))")
+
+cpp_quote("#define D3D12_DECODE_MIP_FILTER(filter) \\")
+cpp_quote(" ((D3D12_FILTER_TYPE)(((filter) >> D3D12_MIP_FILTER_SHIFT) & D3D12_FILTER_TYPE_MASK))")
+
+cpp_quote("#define D3D12_DECODE_IS_ANISOTROPIC_FILTER(filter) \\")
+cpp_quote(" (((filter) & D3D12_ANISOTROPIC_FILTERING_BIT) \\")
+cpp_quote(" && (D3D12_DECODE_MIN_FILTER(filter) == D3D12_FILTER_TYPE_LINEAR) \\")
+cpp_quote(" && (D3D12_DECODE_MAG_FILTER(filter) == D3D12_FILTER_TYPE_LINEAR) \\")
+cpp_quote(" && (D3D12_DECODE_MIP_FILTER(filter) == D3D12_FILTER_TYPE_LINEAR))")
+
+cpp_quote("#define D3D12_DECODE_FILTER_REDUCTION(filter) \\")
+cpp_quote(" ((D3D12_FILTER_REDUCTION_TYPE)(((filter) >> D3D12_FILTER_REDUCTION_TYPE_SHIFT) \\")
+cpp_quote(" & D3D12_FILTER_REDUCTION_TYPE_MASK))")
+
+cpp_quote("#define D3D12_DECODE_IS_COMPARISON_FILTER(filter) \\")
+cpp_quote(" (D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_COMPARISON)")
+
+typedef enum D3D12_TEXTURE_ADDRESS_MODE
+{
+ D3D12_TEXTURE_ADDRESS_MODE_WRAP = 1,
+ D3D12_TEXTURE_ADDRESS_MODE_MIRROR = 2,
+ D3D12_TEXTURE_ADDRESS_MODE_CLAMP = 3,
+ D3D12_TEXTURE_ADDRESS_MODE_BORDER = 4,
+ D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE = 5,
+} D3D12_TEXTURE_ADDRESS_MODE;
+
+typedef enum D3D12_COMPARISON_FUNC
+{
+ D3D12_COMPARISON_FUNC_NEVER = 1,
+ D3D12_COMPARISON_FUNC_LESS = 2,
+ D3D12_COMPARISON_FUNC_EQUAL = 3,
+ D3D12_COMPARISON_FUNC_LESS_EQUAL = 4,
+ D3D12_COMPARISON_FUNC_GREATER = 5,
+ D3D12_COMPARISON_FUNC_NOT_EQUAL = 6,
+ D3D12_COMPARISON_FUNC_GREATER_EQUAL = 7,
+ D3D12_COMPARISON_FUNC_ALWAYS = 8,
+} D3D12_COMPARISON_FUNC;
+
+typedef struct D3D12_STATIC_SAMPLER_DESC
+{
+ D3D12_FILTER Filter;
+ D3D12_TEXTURE_ADDRESS_MODE AddressU;
+ D3D12_TEXTURE_ADDRESS_MODE AddressV;
+ D3D12_TEXTURE_ADDRESS_MODE AddressW;
+ FLOAT MipLODBias;
+ UINT MaxAnisotropy;
+ D3D12_COMPARISON_FUNC ComparisonFunc;
+ D3D12_STATIC_BORDER_COLOR BorderColor;
+ FLOAT MinLOD;
+ FLOAT MaxLOD;
+ UINT ShaderRegister;
+ UINT RegisterSpace;
+ D3D12_SHADER_VISIBILITY ShaderVisibility;
+} D3D12_STATIC_SAMPLER_DESC;
+
+typedef enum D3D12_ROOT_SIGNATURE_FLAGS
+{
+ D3D12_ROOT_SIGNATURE_FLAG_NONE = 0x00,
+ D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0x01,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS = 0x02,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS = 0x04,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS = 0x08,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS = 0x10,
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20,
+ D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT = 0x40,
+} D3D12_ROOT_SIGNATURE_FLAGS;
+
+typedef struct D3D12_ROOT_SIGNATURE_DESC
+{
+ UINT NumParameters;
+ const D3D12_ROOT_PARAMETER *pParameters;
+ UINT NumStaticSamplers;
+ const D3D12_STATIC_SAMPLER_DESC *pStaticSamplers;
+ D3D12_ROOT_SIGNATURE_FLAGS Flags;
+} D3D12_ROOT_SIGNATURE_DESC;
+
+typedef struct D3D12_ROOT_SIGNATURE_DESC1
+{
+ UINT NumParameters;
+ const D3D12_ROOT_PARAMETER1 *pParameters;
+ UINT NumStaticSamplers;
+ const D3D12_STATIC_SAMPLER_DESC *pStaticSamplers;
+ D3D12_ROOT_SIGNATURE_FLAGS Flags;
+} D3D12_ROOT_SIGNATURE_DESC1;
+
+typedef enum D3D_ROOT_SIGNATURE_VERSION
+{
+ D3D_ROOT_SIGNATURE_VERSION_1 = 0x1,
+ D3D_ROOT_SIGNATURE_VERSION_1_0 = 0x1,
+ D3D_ROOT_SIGNATURE_VERSION_1_1 = 0x2,
+} D3D_ROOT_SIGNATURE_VERSION;
+
+typedef struct D3D12_VERSIONED_ROOT_SIGNATURE_DESC
+{
+ D3D_ROOT_SIGNATURE_VERSION Version;
+ union
+ {
+ D3D12_ROOT_SIGNATURE_DESC Desc_1_0;
+ D3D12_ROOT_SIGNATURE_DESC1 Desc_1_1;
+ };
+} D3D12_VERSIONED_ROOT_SIGNATURE_DESC;
+
+typedef enum D3D12_DESCRIPTOR_HEAP_TYPE
+{
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+ D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
+ D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
+ D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
+ D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES,
+} D3D12_DESCRIPTOR_HEAP_TYPE;
+
+typedef enum D3D12_DESCRIPTOR_HEAP_FLAGS
+{
+ D3D12_DESCRIPTOR_HEAP_FLAG_NONE = 0x0,
+ D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE = 0x1,
+} D3D12_DESCRIPTOR_HEAP_FLAGS;
+
+typedef struct D3D12_DESCRIPTOR_HEAP_DESC
+{
+ D3D12_DESCRIPTOR_HEAP_TYPE Type;
+ UINT NumDescriptors;
+ D3D12_DESCRIPTOR_HEAP_FLAGS Flags;
+ UINT NodeMask;
+} D3D12_DESCRIPTOR_HEAP_DESC;
+
+typedef UINT64 D3D12_GPU_VIRTUAL_ADDRESS;
+
+typedef struct D3D12_CONSTANT_BUFFER_VIEW_DESC
+{
+ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
+ UINT SizeInBytes;
+} D3D12_CONSTANT_BUFFER_VIEW_DESC;
+
+typedef enum D3D12_SRV_DIMENSION
+{
+ D3D12_SRV_DIMENSION_UNKNOWN = 0,
+ D3D12_SRV_DIMENSION_BUFFER = 1,
+ D3D12_SRV_DIMENSION_TEXTURE1D = 2,
+ D3D12_SRV_DIMENSION_TEXTURE1DARRAY = 3,
+ D3D12_SRV_DIMENSION_TEXTURE2D = 4,
+ D3D12_SRV_DIMENSION_TEXTURE2DARRAY = 5,
+ D3D12_SRV_DIMENSION_TEXTURE2DMS = 6,
+ D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY = 7,
+ D3D12_SRV_DIMENSION_TEXTURE3D = 8,
+ D3D12_SRV_DIMENSION_TEXTURECUBE = 9,
+ D3D12_SRV_DIMENSION_TEXTURECUBEARRAY = 10,
+} D3D12_SRV_DIMENSION;
+
+typedef enum D3D12_BUFFER_SRV_FLAGS
+{
+ D3D12_BUFFER_SRV_FLAG_NONE = 0x0,
+ D3D12_BUFFER_SRV_FLAG_RAW = 0x1,
+} D3D12_BUFFER_SRV_FLAGS;
+
+typedef enum D3D12_SHADER_COMPONENT_MAPPING
+{
+ D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0 = 0,
+ D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1 = 1,
+ D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2 = 2,
+ D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3 = 3,
+ D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0 = 4,
+ D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1 = 5,
+} D3D12_SHADER_COMPONENT_MAPPING;
+
+cpp_quote("#define D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(x, y, z, w) \\")
+cpp_quote(" (((x) & D3D12_SHADER_COMPONENT_MAPPING_MASK) \\")
+cpp_quote(" | (((y) & D3D12_SHADER_COMPONENT_MAPPING_MASK) << D3D12_SHADER_COMPONENT_MAPPING_SHIFT) \\")
+cpp_quote(" | (((z) & D3D12_SHADER_COMPONENT_MAPPING_MASK) << (D3D12_SHADER_COMPONENT_MAPPING_SHIFT * 2)) \\")
+cpp_quote(" | (((w) & D3D12_SHADER_COMPONENT_MAPPING_MASK) << (D3D12_SHADER_COMPONENT_MAPPING_SHIFT * 3)) \\")
+cpp_quote(" | D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES)")
+cpp_quote("#define D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(0, 1, 2, 3)")
+
+cpp_quote("#define D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(i, mapping) \\")
+cpp_quote(" ((D3D12_SHADER_COMPONENT_MAPPING)(mapping >> (i * D3D12_SHADER_COMPONENT_MAPPING_SHIFT) \\")
+cpp_quote(" & D3D12_SHADER_COMPONENT_MAPPING_MASK))")
+
+typedef struct D3D12_BUFFER_SRV
+{
+ UINT64 FirstElement;
+ UINT NumElements;
+ UINT StructureByteStride;
+ D3D12_BUFFER_SRV_FLAGS Flags;
+} D3D12_BUFFER_SRV;
+
+typedef struct D3D12_TEX1D_SRV
+{
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX1D_SRV;
+
+typedef struct D3D12_TEX1D_ARRAY_SRV
+{
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX1D_ARRAY_SRV;
+
+typedef struct D3D12_TEX2D_SRV
+{
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ UINT PlaneSlice;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX2D_SRV;
+
+typedef struct D3D12_TEX2D_ARRAY_SRV
+{
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+ UINT PlaneSlice;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX2D_ARRAY_SRV;
+
+typedef struct D3D12_TEX2DMS_SRV
+{
+ UINT UnusedField_NothingToDefine;
+} D3D12_TEX2DMS_SRV;
+
+typedef struct D3D12_TEX2DMS_ARRAY_SRV
+{
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX2DMS_ARRAY_SRV;
+
+typedef struct D3D12_TEX3D_SRV
+{
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEX3D_SRV;
+
+typedef struct D3D12_TEXCUBE_SRV
+{
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEXCUBE_SRV;
+
+typedef struct D3D12_TEXCUBE_ARRAY_SRV
+{
+ UINT MostDetailedMip;
+ UINT MipLevels;
+ UINT First2DArrayFace;
+ UINT NumCubes;
+ FLOAT ResourceMinLODClamp;
+} D3D12_TEXCUBE_ARRAY_SRV;
+
+typedef struct D3D12_SHADER_RESOURCE_VIEW_DESC
+{
+ DXGI_FORMAT Format;
+ D3D12_SRV_DIMENSION ViewDimension;
+ UINT Shader4ComponentMapping;
+ union
+ {
+ D3D12_BUFFER_SRV Buffer;
+ D3D12_TEX1D_SRV Texture1D;
+ D3D12_TEX1D_ARRAY_SRV Texture1DArray;
+ D3D12_TEX2D_SRV Texture2D;
+ D3D12_TEX2D_ARRAY_SRV Texture2DArray;
+ D3D12_TEX2DMS_SRV Texture2DMS;
+ D3D12_TEX2DMS_ARRAY_SRV Texture2DMSArray;
+ D3D12_TEX3D_SRV Texture3D;
+ D3D12_TEXCUBE_SRV TextureCube;
+ D3D12_TEXCUBE_ARRAY_SRV TextureCubeArray;
+ };
+} D3D12_SHADER_RESOURCE_VIEW_DESC;
+
+typedef enum D3D12_UAV_DIMENSION
+{
+ D3D12_UAV_DIMENSION_UNKNOWN = 0,
+ D3D12_UAV_DIMENSION_BUFFER = 1,
+ D3D12_UAV_DIMENSION_TEXTURE1D = 2,
+ D3D12_UAV_DIMENSION_TEXTURE1DARRAY = 3,
+ D3D12_UAV_DIMENSION_TEXTURE2D = 4,
+ D3D12_UAV_DIMENSION_TEXTURE2DARRAY = 5,
+ D3D12_UAV_DIMENSION_TEXTURE3D = 8,
+} D3D12_UAV_DIMENSION;
+
+typedef enum D3D12_BUFFER_UAV_FLAGS
+{
+ D3D12_BUFFER_UAV_FLAG_NONE = 0x0,
+ D3D12_BUFFER_UAV_FLAG_RAW = 0x1,
+} D3D12_BUFFER_UAV_FLAGS;
+
+typedef struct D3D12_BUFFER_UAV
+{
+ UINT64 FirstElement;
+ UINT NumElements;
+ UINT StructureByteStride;
+ UINT64 CounterOffsetInBytes;
+ D3D12_BUFFER_UAV_FLAGS Flags;
+} D3D12_BUFFER_UAV;
+
+typedef struct D3D12_TEX1D_UAV
+{
+ UINT MipSlice;
+} D3D12_TEX1D_UAV;
+
+typedef struct D3D12_TEX1D_ARRAY_UAV
+{
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX1D_ARRAY_UAV;
+
+typedef struct D3D12_TEX2D_UAV
+{
+ UINT MipSlice;
+ UINT PlaneSlice;
+} D3D12_TEX2D_UAV;
+
+typedef struct D3D12_TEX2D_ARRAY_UAV
+{
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+ UINT PlaneSlice;
+} D3D12_TEX2D_ARRAY_UAV;
+
+typedef struct D3D12_TEX3D_UAV
+{
+ UINT MipSlice;
+ UINT FirstWSlice;
+ UINT WSize;
+} D3D12_TEX3D_UAV;
+
+typedef struct D3D12_UNORDERED_ACCESS_VIEW_DESC
+{
+ DXGI_FORMAT Format;
+ D3D12_UAV_DIMENSION ViewDimension;
+ union
+ {
+ D3D12_BUFFER_UAV Buffer;
+ D3D12_TEX1D_UAV Texture1D;
+ D3D12_TEX1D_ARRAY_UAV Texture1DArray;
+ D3D12_TEX2D_UAV Texture2D;
+ D3D12_TEX2D_ARRAY_UAV Texture2DArray;
+ D3D12_TEX3D_UAV Texture3D;
+ };
+} D3D12_UNORDERED_ACCESS_VIEW_DESC;
+
+typedef enum D3D12_RTV_DIMENSION
+{
+ D3D12_RTV_DIMENSION_UNKNOWN = 0,
+ D3D12_RTV_DIMENSION_BUFFER = 1,
+ D3D12_RTV_DIMENSION_TEXTURE1D = 2,
+ D3D12_RTV_DIMENSION_TEXTURE1DARRAY = 3,
+ D3D12_RTV_DIMENSION_TEXTURE2D = 4,
+ D3D12_RTV_DIMENSION_TEXTURE2DARRAY = 5,
+ D3D12_RTV_DIMENSION_TEXTURE2DMS = 6,
+ D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY = 7,
+ D3D12_RTV_DIMENSION_TEXTURE3D = 8,
+} D3D12_RTV_DIMENSION;
+
+typedef struct D3D12_BUFFER_RTV
+{
+ UINT64 FirstElement;
+ UINT NumElements;
+} D3D12_BUFFER_RTV;
+
+typedef struct D3D12_TEX1D_RTV
+{
+ UINT MipSlice;
+} D3D12_TEX1D_RTV;
+
+typedef struct D3D12_TEX1D_ARRAY_RTV
+{
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX1D_ARRAY_RTV;
+
+typedef struct D3D12_TEX2D_RTV
+{
+ UINT MipSlice;
+ UINT PlaneSlice;
+} D3D12_TEX2D_RTV;
+
+typedef struct D3D12_TEX2D_ARRAY_RTV
+{
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+ UINT PlaneSlice;
+} D3D12_TEX2D_ARRAY_RTV;
+
+typedef struct D3D12_TEX2DMS_RTV
+{
+ UINT UnusedField_NothingToDefine;
+} D3D12_TEX2DMS_RTV;
+
+typedef struct D3D12_TEX2DMS_ARRAY_RTV
+{
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX2DMS_ARRAY_RTV;
+
+typedef struct D3D12_TEX3D_RTV
+{
+ UINT MipSlice;
+ UINT FirstWSlice;
+ UINT WSize;
+} D3D12_TEX3D_RTV;
+
+typedef struct D3D12_RENDER_TARGET_VIEW_DESC
+{
+ DXGI_FORMAT Format;
+ D3D12_RTV_DIMENSION ViewDimension;
+ union
+ {
+ D3D12_BUFFER_RTV Buffer;
+ D3D12_TEX1D_RTV Texture1D;
+ D3D12_TEX1D_ARRAY_RTV Texture1DArray;
+ D3D12_TEX2D_RTV Texture2D;
+ D3D12_TEX2D_ARRAY_RTV Texture2DArray;
+ D3D12_TEX2DMS_RTV Texture2DMS;
+ D3D12_TEX2DMS_ARRAY_RTV Texture2DMSArray;
+ D3D12_TEX3D_RTV Texture3D;
+ };
+} D3D12_RENDER_TARGET_VIEW_DESC;
+
+typedef enum D3D12_DSV_DIMENSION
+{
+ D3D12_DSV_DIMENSION_UNKNOWN = 0,
+ D3D12_DSV_DIMENSION_TEXTURE1D = 1,
+ D3D12_DSV_DIMENSION_TEXTURE1DARRAY = 2,
+ D3D12_DSV_DIMENSION_TEXTURE2D = 3,
+ D3D12_DSV_DIMENSION_TEXTURE2DARRAY = 4,
+ D3D12_DSV_DIMENSION_TEXTURE2DMS = 5,
+ D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY = 6,
+} D3D12_DSV_DIMENSION;
+
+typedef enum D3D12_DSV_FLAGS
+{
+ D3D12_DSV_FLAG_NONE = 0x0,
+ D3D12_DSV_FLAG_READ_ONLY_DEPTH = 0x1,
+ D3D12_DSV_FLAG_READ_ONLY_STENCIL = 0x2,
+} D3D12_DSV_FLAGS;
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_DSV_FLAGS);")
+
+typedef struct D3D12_TEX1D_DSV
+{
+ UINT MipSlice;
+} D3D12_TEX1D_DSV;
+
+typedef struct D3D12_TEX1D_ARRAY_DSV
+{
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX1D_ARRAY_DSV;
+
+typedef struct D3D12_TEX2D_DSV
+{
+ UINT MipSlice;
+} D3D12_TEX2D_DSV;
+
+typedef struct D3D12_TEX2D_ARRAY_DSV
+{
+ UINT MipSlice;
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX2D_ARRAY_DSV;
+
+typedef struct D3D12_TEX2DMS_DSV
+{
+ UINT UnusedField_NothingToDefine;
+} D3D12_TEX2DMS_DSV;
+
+typedef struct D3D12_TEX2DMS_ARRAY_DSV
+{
+ UINT FirstArraySlice;
+ UINT ArraySize;
+} D3D12_TEX2DMS_ARRAY_DSV;
+
+typedef struct D3D12_DEPTH_STENCIL_VIEW_DESC
+{
+ DXGI_FORMAT Format;
+ D3D12_DSV_DIMENSION ViewDimension;
+ D3D12_DSV_FLAGS Flags;
+ union
+ {
+ D3D12_TEX1D_DSV Texture1D;
+ D3D12_TEX1D_ARRAY_DSV Texture1DArray;
+ D3D12_TEX2D_DSV Texture2D;
+ D3D12_TEX2D_ARRAY_DSV Texture2DArray;
+ D3D12_TEX2DMS_DSV Texture2DMS;
+ D3D12_TEX2DMS_ARRAY_DSV Texture2DMSArray;
+ };
+} D3D12_DEPTH_STENCIL_VIEW_DESC;
+
+typedef struct D3D12_SAMPLER_DESC
+{
+ D3D12_FILTER Filter;
+ D3D12_TEXTURE_ADDRESS_MODE AddressU;
+ D3D12_TEXTURE_ADDRESS_MODE AddressV;
+ D3D12_TEXTURE_ADDRESS_MODE AddressW;
+ FLOAT MipLODBias;
+ UINT MaxAnisotropy;
+ D3D12_COMPARISON_FUNC ComparisonFunc;
+ FLOAT BorderColor[4];
+ FLOAT MinLOD;
+ FLOAT MaxLOD;
+} D3D12_SAMPLER_DESC;
+
+typedef struct D3D12_CPU_DESCRIPTOR_HANDLE
+{
+ SIZE_T ptr;
+} D3D12_CPU_DESCRIPTOR_HANDLE;
+
+typedef struct D3D12_GPU_DESCRIPTOR_HANDLE
+{
+ UINT64 ptr;
+} D3D12_GPU_DESCRIPTOR_HANDLE;
+
+typedef enum D3D12_STENCIL_OP
+{
+ D3D12_STENCIL_OP_KEEP = 1,
+ D3D12_STENCIL_OP_ZERO = 2,
+ D3D12_STENCIL_OP_REPLACE = 3,
+ D3D12_STENCIL_OP_INCR_SAT = 4,
+ D3D12_STENCIL_OP_DECR_SAT = 5,
+ D3D12_STENCIL_OP_INVERT = 6,
+ D3D12_STENCIL_OP_INCR = 7,
+ D3D12_STENCIL_OP_DECR = 8,
+} D3D12_STENCIL_OP;
+
+typedef struct D3D12_DEPTH_STENCILOP_DESC
+{
+ D3D12_STENCIL_OP StencilFailOp;
+ D3D12_STENCIL_OP StencilDepthFailOp;
+ D3D12_STENCIL_OP StencilPassOp;
+ D3D12_COMPARISON_FUNC StencilFunc;
+} D3D12_DEPTH_STENCILOP_DESC;
+
+typedef enum D3D12_DEPTH_WRITE_MASK
+{
+ D3D12_DEPTH_WRITE_MASK_ZERO = 0,
+ D3D12_DEPTH_WRITE_MASK_ALL = 1,
+} D3D12_DEPTH_WRITE_MASK;
+
+typedef struct D3D12_DEPTH_STENCIL_DESC
+{
+ BOOL DepthEnable;
+ D3D12_DEPTH_WRITE_MASK DepthWriteMask;
+ D3D12_COMPARISON_FUNC DepthFunc;
+ BOOL StencilEnable;
+ UINT8 StencilReadMask;
+ UINT8 StencilWriteMask;
+ D3D12_DEPTH_STENCILOP_DESC FrontFace;
+ D3D12_DEPTH_STENCILOP_DESC BackFace;
+} D3D12_DEPTH_STENCIL_DESC;
+
+typedef enum D3D12_BLEND
+{
+ D3D12_BLEND_ZERO = 1,
+ D3D12_BLEND_ONE = 2,
+ D3D12_BLEND_SRC_COLOR = 3,
+ D3D12_BLEND_INV_SRC_COLOR = 4,
+ D3D12_BLEND_SRC_ALPHA = 5,
+ D3D12_BLEND_INV_SRC_ALPHA = 6,
+ D3D12_BLEND_DEST_ALPHA = 7,
+ D3D12_BLEND_INV_DEST_ALPHA = 8,
+ D3D12_BLEND_DEST_COLOR = 9,
+ D3D12_BLEND_INV_DEST_COLOR = 10,
+ D3D12_BLEND_SRC_ALPHA_SAT = 11,
+ D3D12_BLEND_BLEND_FACTOR = 14,
+ D3D12_BLEND_INV_BLEND_FACTOR = 15,
+ D3D12_BLEND_SRC1_COLOR = 16,
+ D3D12_BLEND_INV_SRC1_COLOR = 17,
+ D3D12_BLEND_SRC1_ALPHA = 18,
+ D3D12_BLEND_INV_SRC1_ALPHA = 19,
+} D3D12_BLEND;
+
+typedef enum D3D12_BLEND_OP
+{
+ D3D12_BLEND_OP_ADD = 1,
+ D3D12_BLEND_OP_SUBTRACT = 2,
+ D3D12_BLEND_OP_REV_SUBTRACT = 3,
+ D3D12_BLEND_OP_MIN = 4,
+ D3D12_BLEND_OP_MAX = 5,
+} D3D12_BLEND_OP;
+
+typedef enum D3D12_LOGIC_OP
+{
+ D3D12_LOGIC_OP_CLEAR = 0,
+ D3D12_LOGIC_OP_SET = 1,
+ D3D12_LOGIC_OP_COPY = 2,
+ D3D12_LOGIC_OP_COPY_INVERTED = 3,
+ D3D12_LOGIC_OP_NOOP = 4,
+} D3D12_LOGIC_OP;
+
+typedef enum D3D12_COLOR_WRITE_ENABLE
+{
+ D3D12_COLOR_WRITE_ENABLE_RED = 0x1,
+ D3D12_COLOR_WRITE_ENABLE_GREEN = 0x2,
+ D3D12_COLOR_WRITE_ENABLE_BLUE = 0x4,
+ D3D12_COLOR_WRITE_ENABLE_ALPHA = 0x8,
+ D3D12_COLOR_WRITE_ENABLE_ALL = (D3D12_COLOR_WRITE_ENABLE_RED\
+ | D3D12_COLOR_WRITE_ENABLE_GREEN | D3D12_COLOR_WRITE_ENABLE_BLUE\
+ | D3D12_COLOR_WRITE_ENABLE_ALPHA),
+} D3D12_COLOR_WRITE_ENABLE;
+
+typedef struct D3D12_RENDER_TARGET_BLEND_DESC
+{
+ BOOL BlendEnable;
+ BOOL LogicOpEnable;
+ D3D12_BLEND SrcBlend;
+ D3D12_BLEND DestBlend;
+ D3D12_BLEND_OP BlendOp;
+ D3D12_BLEND SrcBlendAlpha;
+ D3D12_BLEND DestBlendAlpha;
+ D3D12_BLEND_OP BlendOpAlpha;
+ D3D12_LOGIC_OP LogicOp;
+ UINT8 RenderTargetWriteMask;
+} D3D12_RENDER_TARGET_BLEND_DESC;
+
+typedef struct D3D12_BLEND_DESC
+{
+ BOOL AlphaToCoverageEnable;
+ BOOL IndependentBlendEnable;
+ D3D12_RENDER_TARGET_BLEND_DESC RenderTarget[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
+} D3D12_BLEND_DESC;
+
+typedef enum D3D12_FILL_MODE
+{
+ D3D12_FILL_MODE_WIREFRAME = 2,
+ D3D12_FILL_MODE_SOLID = 3,
+} D3D12_FILL_MODE;
+
+typedef enum D3D12_CULL_MODE
+{
+ D3D12_CULL_MODE_NONE = 1,
+ D3D12_CULL_MODE_FRONT = 2,
+ D3D12_CULL_MODE_BACK = 3,
+} D3D12_CULL_MODE;
+
+typedef enum D3D12_CONSERVATIVE_RASTERIZATION_MODE
+{
+ D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF = 0,
+ D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON = 1,
+} D3D12_CONSERVATIVE_RASTERIZATION_MODE;
+
+typedef struct D3D12_RASTERIZER_DESC
+{
+ D3D12_FILL_MODE FillMode;
+ D3D12_CULL_MODE CullMode;
+ BOOL FrontCounterClockwise;
+ INT DepthBias;
+ FLOAT DepthBiasClamp;
+ FLOAT SlopeScaledDepthBias;
+ BOOL DepthClipEnable;
+ BOOL MultisampleEnable;
+ BOOL AntialiasedLineEnable;
+ UINT ForcedSampleCount;
+ D3D12_CONSERVATIVE_RASTERIZATION_MODE ConservativeRaster;
+} D3D12_RASTERIZER_DESC;
+
+typedef struct D3D12_SO_DECLARATION_ENTRY
+{
+ UINT Stream;
+ const char *SemanticName;
+ UINT SemanticIndex;
+ BYTE StartComponent;
+ BYTE ComponentCount;
+ BYTE OutputSlot;
+} D3D12_SO_DECLARATION_ENTRY;
+
+typedef struct D3D12_STREAM_OUTPUT_DESC
+{
+ const D3D12_SO_DECLARATION_ENTRY *pSODeclaration;
+ UINT NumEntries;
+ const UINT *pBufferStrides;
+ UINT NumStrides;
+ UINT RasterizedStream;
+} D3D12_STREAM_OUTPUT_DESC;
+
+typedef enum D3D12_INPUT_CLASSIFICATION
+{
+ D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA = 0,
+ D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA = 1,
+} D3D12_INPUT_CLASSIFICATION;
+
+typedef struct D3D12_INPUT_ELEMENT_DESC
+{
+ const char *SemanticName;
+ UINT SemanticIndex;
+ DXGI_FORMAT Format;
+ UINT InputSlot;
+ UINT AlignedByteOffset;
+ D3D12_INPUT_CLASSIFICATION InputSlotClass;
+ UINT InstanceDataStepRate;
+} D3D12_INPUT_ELEMENT_DESC;
+
+typedef struct D3D12_INPUT_LAYOUT_DESC
+{
+ const D3D12_INPUT_ELEMENT_DESC *pInputElementDescs;
+ UINT NumElements;
+} D3D12_INPUT_LAYOUT_DESC;
+
+typedef enum D3D12_INDEX_BUFFER_STRIP_CUT_VALUE
+{
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED = 0,
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF = 1,
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF = 2,
+} D3D12_INDEX_BUFFER_STRIP_CUT_VALUE;
+
+typedef D3D_PRIMITIVE_TOPOLOGY D3D12_PRIMITIVE_TOPOLOGY;
+
+typedef enum D3D12_PRIMITIVE_TOPOLOGY_TYPE
+{
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED = 0,
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT = 1,
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE = 2,
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE = 3,
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH = 4,
+} D3D12_PRIMITIVE_TOPOLOGY_TYPE;
+
+typedef struct D3D12_CACHED_PIPELINE_STATE
+{
+ const void *pCachedBlob;
+ SIZE_T CachedBlobSizeInBytes;
+} D3D12_CACHED_PIPELINE_STATE;
+
+typedef enum D3D12_PIPELINE_STATE_FLAGS
+{
+ D3D12_PIPELINE_STATE_FLAG_NONE = 0x0,
+ D3D12_PIPELINE_STATE_FLAG_DEBUG = 0x1,
+} D3D12_PIPELINE_STATE_FLAGS;
+
+typedef struct D3D12_GRAPHICS_PIPELINE_STATE_DESC
+{
+ ID3D12RootSignature *pRootSignature;
+ D3D12_SHADER_BYTECODE VS;
+ D3D12_SHADER_BYTECODE PS;
+ D3D12_SHADER_BYTECODE DS;
+ D3D12_SHADER_BYTECODE HS;
+ D3D12_SHADER_BYTECODE GS;
+ D3D12_STREAM_OUTPUT_DESC StreamOutput;
+ D3D12_BLEND_DESC BlendState;
+ UINT SampleMask;
+ D3D12_RASTERIZER_DESC RasterizerState;
+ D3D12_DEPTH_STENCIL_DESC DepthStencilState;
+ D3D12_INPUT_LAYOUT_DESC InputLayout;
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue;
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;
+ UINT NumRenderTargets;
+ DXGI_FORMAT RTVFormats[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
+ DXGI_FORMAT DSVFormat;
+ DXGI_SAMPLE_DESC SampleDesc;
+ UINT NodeMask;
+ D3D12_CACHED_PIPELINE_STATE CachedPSO;
+ D3D12_PIPELINE_STATE_FLAGS Flags;
+} D3D12_GRAPHICS_PIPELINE_STATE_DESC;
+
+typedef struct D3D12_COMPUTE_PIPELINE_STATE_DESC
+{
+ ID3D12RootSignature *pRootSignature;
+ D3D12_SHADER_BYTECODE CS;
+ UINT NodeMask;
+ D3D12_CACHED_PIPELINE_STATE CachedPSO;
+ D3D12_PIPELINE_STATE_FLAGS Flags;
+} D3D12_COMPUTE_PIPELINE_STATE_DESC;
+
+typedef enum D3D12_COMMAND_LIST_TYPE
+{
+ D3D12_COMMAND_LIST_TYPE_DIRECT = 0,
+ D3D12_COMMAND_LIST_TYPE_BUNDLE = 1,
+ D3D12_COMMAND_LIST_TYPE_COMPUTE = 2,
+ D3D12_COMMAND_LIST_TYPE_COPY = 3,
+} D3D12_COMMAND_LIST_TYPE;
+
+typedef enum D3D12_COMMAND_QUEUE_PRIORITY
+{
+ D3D12_COMMAND_QUEUE_PRIORITY_NORMAL = 0,
+ D3D12_COMMAND_QUEUE_PRIORITY_HIGH = 100,
+ D3D12_COMMAND_QUEUE_PRIORITY_GLOBAL_REALTIME = 10000,
+} D3D12_COMMAND_QUEUE_PRIORITY;
+
+typedef enum D3D12_COMMAND_QUEUE_FLAGS
+{
+ D3D12_COMMAND_QUEUE_FLAG_NONE = 0x0,
+ D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT = 0x1,
+} D3D12_COMMAND_QUEUE_FLAGS;
+
+typedef struct D3D12_COMMAND_QUEUE_DESC
+{
+ D3D12_COMMAND_LIST_TYPE Type;
+ INT Priority;
+ D3D12_COMMAND_QUEUE_FLAGS Flags;
+ UINT NodeMask;
+} D3D12_COMMAND_QUEUE_DESC;
+
+typedef struct D3D12_FEATURE_DATA_ARCHITECTURE
+{
+ UINT NodeIndex;
+ BOOL TileBasedRenderer;
+ BOOL UMA;
+ BOOL CacheCoherentUMA;
+} D3D12_FEATURE_DATA_ARCHITECTURE;
+
+typedef struct D3D12_FEATURE_DATA_FORMAT_INFO
+{
+ DXGI_FORMAT Format;
+ UINT8 PlaneCount;
+} D3D12_FEATURE_DATA_FORMAT_INFO;
+
+typedef struct D3D12_FEATURE_DATA_FEATURE_LEVELS
+{
+ UINT NumFeatureLevels;
+ const D3D_FEATURE_LEVEL *pFeatureLevelsRequested;
+ D3D_FEATURE_LEVEL MaxSupportedFeatureLevel;
+} D3D12_FEATURE_DATA_FEATURE_LEVELS;
+
+typedef struct D3D12_FEATURE_DATA_ROOT_SIGNATURE
+{
+ D3D_ROOT_SIGNATURE_VERSION HighestVersion;
+} D3D12_FEATURE_DATA_ROOT_SIGNATURE;
+
+typedef struct D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT
+{
+ UINT MaxGPUVirtualAddressBitsPerResource;
+ UINT MaxGPUVirtualAddressBitsPerProcess;
+} D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT;
+
+typedef enum D3D_SHADER_MODEL
+{
+ D3D_SHADER_MODEL_5_1 = 0x51,
+ D3D_SHADER_MODEL_6_0 = 0x60,
+} D3D_SHADER_MODEL;
+
+typedef struct D3D12_FEATURE_DATA_SHADER_MODEL
+{
+ D3D_SHADER_MODEL HighestShaderModel;
+} D3D12_FEATURE_DATA_SHADER_MODEL;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS1
+{
+ BOOL WaveOps;
+ UINT WaveLaneCountMin;
+ UINT WaveLaneCountMax;
+ UINT TotalLaneCount;
+ BOOL ExpandedComputeResourceStates;
+ BOOL Int64ShaderOps;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS1;
+
+typedef struct D3D12_FEATURE_DATA_ARCHITECTURE1
+{
+ UINT NodeIndex;
+ BOOL TileBasedRenderer;
+ BOOL UMA;
+ BOOL CacheCoherentUMA;
+ BOOL IsolatedMMU;
+} D3D12_FEATURE_DATA_ARCHITECTURE1;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS2
+{
+ BOOL DepthBoundsTestSupported;
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER ProgrammableSamplePositionsTier;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS2;
+
+typedef struct D3D12_FEATURE_DATA_SHADER_CACHE
+{
+ D3D12_SHADER_CACHE_SUPPORT_FLAGS SupportFlags;
+} D3D12_FEATURE_DATA_SHADER_CACHE;
+
+typedef struct D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY
+{
+ D3D12_COMMAND_LIST_TYPE CommandListType;
+ UINT Priority;
+ BOOL PriorityForTypeIsSupported;
+} D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS3
+{
+ BOOL CopyQueueTimestampQueriesSupported;
+ BOOL CastingFullyTypedFormatSupported;
+ D3D12_COMMAND_LIST_SUPPORT_FLAGS WriteBufferImmediateSupportFlags;
+ D3D12_VIEW_INSTANCING_TIER ViewInstancingTier;
+ BOOL BarycentricsSupported;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS3;
+
+typedef struct D3D12_FEATURE_DATA_EXISTING_HEAPS
+{
+ BOOL Supported;
+} D3D12_FEATURE_DATA_EXISTING_HEAPS;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS4
+{
+ BOOL MSAA64KBAlignedTextureSupported;
+ D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER SharedResourceCompatibilityTier;
+ BOOL Native16BitShaderOpsSupported;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS4;
+
+typedef struct D3D12_FEATURE_DATA_SERIALIZATION
+{
+ UINT NodeIndex;
+ D3D12_HEAP_SERIALIZATION_TIER HeapSerializationTier;
+} D3D12_FEATURE_DATA_SERIALIZATION;
+
+typedef struct D3D12_FEATURE_DATA_CROSS_NODE
+{
+ D3D12_CROSS_NODE_SHARING_TIER SharingTier;
+ BOOL AtomicShaderInstructions;
+} D3D12_FEATURE_DATA_CROSS_NODE;
+
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS5
+{
+ BOOL SRVOnlyTiledResourceTier3;
+ D3D12_RENDER_PASS_TIER RenderPassesTier;
+ D3D12_RAYTRACING_TIER RaytracingTier;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS5;
+
+typedef enum D3D12_FEATURE
+{
+ D3D12_FEATURE_D3D12_OPTIONS = 0,
+ D3D12_FEATURE_ARCHITECTURE = 1,
+ D3D12_FEATURE_FEATURE_LEVELS = 2,
+ D3D12_FEATURE_FORMAT_SUPPORT = 3,
+ D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS = 4,
+ D3D12_FEATURE_FORMAT_INFO = 5,
+ D3D12_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT = 6,
+ D3D12_FEATURE_SHADER_MODEL = 7,
+ D3D12_FEATURE_D3D12_OPTIONS1 = 8,
+ D3D12_FEATURE_ROOT_SIGNATURE = 12,
+ D3D12_FEATURE_ARCHITECTURE1 = 16,
+ D3D12_FEATURE_D3D12_OPTIONS2 = 18,
+ D3D12_FEATURE_SHADER_CACHE = 19,
+ D3D12_FEATURE_COMMAND_QUEUE_PRIORITY = 20,
+ D3D12_FEATURE_D3D12_OPTIONS3 = 21,
+ D3D12_FEATURE_EXISTING_HEAPS = 22,
+ D3D12_FEATURE_D3D12_OPTIONS4 = 23,
+ D3D12_FEATURE_SERIALIZATION = 24,
+ D3D12_FEATURE_CROSS_NODE = 25,
+ D3D12_FEATURE_D3D12_OPTIONS5 = 27,
+} D3D12_FEATURE;
+
+typedef struct D3D12_MEMCPY_DEST
+{
+ void *pData;
+ SIZE_T RowPitch;
+ SIZE_T SlicePitch;
+} D3D12_MEMCPY_DEST;
+
+typedef struct D3D12_SUBRESOURCE_DATA
+{
+ const void *pData;
+ LONG_PTR RowPitch;
+ LONG_PTR SlicePitch;
+} D3D12_SUBRESOURCE_DATA;
+
+typedef enum D3D12_MULTIPLE_FENCE_WAIT_FLAGS
+{
+ D3D12_MULTIPLE_FENCE_WAIT_FLAG_NONE = 0x0,
+ D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY = 0x1,
+ D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL = 0x0,
+} D3D12_MULTIPLE_FENCE_WAIT_FLAGS;
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_MULTIPLE_FENCE_WAIT_FLAGS);")
+
+typedef enum D3D12_RESIDENCY_PRIORITY
+{
+ D3D12_RESIDENCY_PRIORITY_MINIMUM = 0x28000000,
+ D3D12_RESIDENCY_PRIORITY_LOW = 0x50000000,
+ D3D12_RESIDENCY_PRIORITY_NORMAL = 0x78000000,
+ D3D12_RESIDENCY_PRIORITY_HIGH = 0xa0010000,
+ D3D12_RESIDENCY_PRIORITY_MAXIMUM = 0xc8000000,
+} D3D12_RESIDENCY_PRIORITY;
+
+typedef struct D3D12_WRITEBUFFERIMMEDIATE_PARAMETER
+{
+ D3D12_GPU_VIRTUAL_ADDRESS Dest;
+ UINT32 Value;
+} D3D12_WRITEBUFFERIMMEDIATE_PARAMETER;
+
+[
+ uuid(c4fec28f-7966-4e95-9f94-f431cb56c3b8),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Object : IUnknown
+{
+ HRESULT GetPrivateData(REFGUID guid, UINT *data_size, void *data);
+ HRESULT SetPrivateData(REFGUID guid, UINT data_size, const void *data);
+ HRESULT SetPrivateDataInterface(REFGUID guid, const IUnknown *data);
+ HRESULT SetName(const WCHAR *name);
+}
+
+[
+ uuid(905db94b-a00c-4140-9df5-2b64ca9ea357),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12DeviceChild : ID3D12Object
+{
+ HRESULT GetDevice(REFIID riid, void **device);
+}
+
+[
+ uuid(63ee58fb-1268-4835-86da-f008ce62f0d6),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Pageable : ID3D12DeviceChild
+{
+}
+
+[
+ uuid(6b3b2502-6e51-45b3-90ee-9884265e8df3),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Heap : ID3D12Pageable
+{
+ D3D12_HEAP_DESC GetDesc();
+}
+
+[
+ uuid(696442be-a72e-4059-bc79-5b5c98040fad),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Resource : ID3D12Pageable
+{
+ HRESULT Map(UINT sub_resource, const D3D12_RANGE *read_range, void **data);
+ void Unmap(UINT sub_resource, const D3D12_RANGE *written_range);
+
+ D3D12_RESOURCE_DESC GetDesc();
+
+ D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress();
+
+ HRESULT WriteToSubresource(UINT dst_sub_resource, const D3D12_BOX *dst_box,
+ const void *src_data, UINT src_row_pitch, UINT src_slice_pitch);
+ HRESULT ReadFromSubresource(void *dst_data, UINT dst_row_pitch, UINT dst_slice_pitch,
+ UINT src_sub_resource, const D3D12_BOX *src_box);
+
+ HRESULT GetHeapProperties(D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS *flags);
+}
+
+[
+ uuid(7116d91c-e7e4-47ce-b8c6-ec8168f437e5),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12CommandList : ID3D12DeviceChild
+{
+ D3D12_COMMAND_LIST_TYPE GetType();
+}
+
+typedef enum D3D12_TILE_COPY_FLAGS
+{
+ D3D12_TILE_COPY_FLAG_NONE = 0x0,
+ D3D12_TILE_COPY_FLAG_NO_HAZARD = 0x1,
+ D3D12_TILE_COPY_FLAG_LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE = 0x2,
+ D3D12_TILE_COPY_FLAG_SWIZZLED_TILED_RESOURCE_TO_LINEAR_BUFFER = 0x4,
+} D3D12_TILE_COPY_FLAGS;
+
+typedef struct D3D12_INDEX_BUFFER_VIEW
+{
+ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
+ UINT SizeInBytes;
+ DXGI_FORMAT Format;
+} D3D12_INDEX_BUFFER_VIEW;
+
+typedef struct D3D12_VERTEX_BUFFER_VIEW
+{
+ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
+ UINT SizeInBytes;
+ UINT StrideInBytes;
+} D3D12_VERTEX_BUFFER_VIEW;
+
+typedef struct D3D12_STREAM_OUTPUT_BUFFER_VIEW
+{
+ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
+ UINT64 SizeInBytes;
+ D3D12_GPU_VIRTUAL_ADDRESS BufferFilledSizeLocation;
+} D3D12_STREAM_OUTPUT_BUFFER_VIEW;
+
+typedef enum D3D12_CLEAR_FLAGS
+{
+ D3D12_CLEAR_FLAG_DEPTH = 0x1,
+ D3D12_CLEAR_FLAG_STENCIL = 0x2,
+} D3D12_CLEAR_FLAGS;
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_CLEAR_FLAGS);")
+
+typedef struct D3D12_DISCARD_REGION
+{
+ UINT NumRects;
+ const D3D12_RECT *pRects;
+ UINT FirstSubresource;
+ UINT NumSubresources;
+} D3D12_DISCARD_REGION;
+
+typedef enum D3D12_QUERY_TYPE
+{
+ D3D12_QUERY_TYPE_OCCLUSION = 0,
+ D3D12_QUERY_TYPE_BINARY_OCCLUSION = 1,
+ D3D12_QUERY_TYPE_TIMESTAMP = 2,
+ D3D12_QUERY_TYPE_PIPELINE_STATISTICS = 3,
+ D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 = 4,
+ D3D12_QUERY_TYPE_SO_STATISTICS_STREAM1 = 5,
+ D3D12_QUERY_TYPE_SO_STATISTICS_STREAM2 = 6,
+ D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3 = 7,
+} D3D12_QUERY_TYPE;
+
+typedef struct D3D12_QUERY_DATA_PIPELINE_STATISTICS
+{
+ UINT64 IAVertices;
+ UINT64 IAPrimitives;
+ UINT64 VSInvocations;
+ UINT64 GSInvocations;
+ UINT64 GSPrimitives;
+ UINT64 CInvocations;
+ UINT64 CPrimitives;
+ UINT64 PSInvocations;
+ UINT64 HSInvocations;
+ UINT64 DSInvocations;
+ UINT64 CSInvocations;
+} D3D12_QUERY_DATA_PIPELINE_STATISTICS;
+
+typedef struct D3D12_QUERY_DATA_SO_STATISTICS
+{
+ UINT64 NumPrimitivesWritten;
+ UINT64 PrimitivesStorageNeeded;
+} D3D12_QUERY_DATA_SO_STATISTICS;
+
+typedef enum D3D12_PREDICATION_OP
+{
+ D3D12_PREDICATION_OP_EQUAL_ZERO = 0,
+ D3D12_PREDICATION_OP_NOT_EQUAL_ZERO = 1,
+} D3D12_PREDICATION_OP;
+
+[
+ uuid(8efb471d-616c-4f49-90f7-127bb763fa51),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12DescriptorHeap : ID3D12Pageable
+{
+ D3D12_DESCRIPTOR_HEAP_DESC GetDesc();
+
+ D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandleForHeapStart();
+ D3D12_GPU_DESCRIPTOR_HANDLE GetGPUDescriptorHandleForHeapStart();
+}
+
+[
+ uuid(0d9658ae-ed45-469e-a61d-970ec583cab4),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12QueryHeap : ID3D12Pageable
+{
+}
+
+[
+ uuid(c36a797c-ec80-4f0a-8985-a7b2475082d1),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12CommandSignature : ID3D12Pageable
+{
+}
+
+[
+ uuid(5b160d0f-ac1b-4185-8ba8-b3ae42a5a455),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12GraphicsCommandList : ID3D12CommandList
+{
+ HRESULT Close();
+
+ HRESULT Reset(ID3D12CommandAllocator *allocator, ID3D12PipelineState *initial_state);
+
+ HRESULT ClearState(ID3D12PipelineState *pipeline_state);
+
+ void DrawInstanced(UINT vertex_count_per_instance, UINT instance_count,
+ UINT start_vertex_location, UINT start_instance_location);
+ void DrawIndexedInstanced(UINT index_count_per_instance, UINT instance_count,
+ UINT start_vertex_location, INT base_vertex_location, UINT start_instance_location);
+
+ void Dispatch(UINT x, UINT u, UINT z);
+
+ void CopyBufferRegion(ID3D12Resource *dst_buffer, UINT64 dst_offset,
+ ID3D12Resource *src_buffer, UINT64 src_offset, UINT64 byte_count);
+ void CopyTextureRegion(const D3D12_TEXTURE_COPY_LOCATION *dst,
+ UINT dst_x, UINT dst_y, UINT dst_z,
+ const D3D12_TEXTURE_COPY_LOCATION *src, const D3D12_BOX *src_box);
+ void CopyResource(ID3D12Resource *dst_resource, ID3D12Resource *src_resource);
+
+ void CopyTiles(ID3D12Resource *tiled_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *tile_region_size,
+ ID3D12Resource *buffer,
+ UINT64 buffer_offset,
+ D3D12_TILE_COPY_FLAGS flags);
+
+ void ResolveSubresource(ID3D12Resource *dst_resource, UINT dst_sub_resource,
+ ID3D12Resource *src_resource, UINT src_sub_resource,
+ DXGI_FORMAT format);
+
+ void IASetPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitive_topology);
+
+ void RSSetViewports(UINT viewport_count, const D3D12_VIEWPORT *viewports);
+ void RSSetScissorRects(UINT rect_count, const D3D12_RECT *rects);
+
+ void OMSetBlendFactor(const FLOAT blend_factor[4]);
+ void OMSetStencilRef(UINT stencil_ref);
+
+ void SetPipelineState(ID3D12PipelineState *pipeline_state);
+
+ void ResourceBarrier(UINT barrier_count, const D3D12_RESOURCE_BARRIER *barriers);
+
+ void ExecuteBundle(ID3D12GraphicsCommandList *command_list);
+
+ void SetDescriptorHeaps(UINT heap_count, ID3D12DescriptorHeap * const *heaps);
+
+ void SetComputeRootSignature(ID3D12RootSignature *root_signature);
+ void SetGraphicsRootSignature(ID3D12RootSignature *root_signature);
+
+ void SetComputeRootDescriptorTable(UINT root_parameter_index, D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor);
+ void SetGraphicsRootDescriptorTable(UINT root_parameter_index, D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor);
+
+ void SetComputeRoot32BitConstant(UINT root_parameter_index, UINT data, UINT dst_offset);
+ void SetGraphicsRoot32BitConstant(UINT root_parameter_index, UINT data, UINT dst_offset);
+
+ void SetComputeRoot32BitConstants(UINT root_parameter_index, UINT constant_count, const void *data,
+ UINT dst_offset);
+ void SetGraphicsRoot32BitConstants(UINT root_parameter_index, UINT constant_count, const void *data,
+ UINT dst_offset);
+
+ void SetComputeRootConstantBufferView(UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address);
+ void SetGraphicsRootConstantBufferView(UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void SetComputeRootShaderResourceView(UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address);
+ void SetGraphicsRootShaderResourceView(UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void SetComputeRootUnorderedAccessView(UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address);
+ void SetGraphicsRootUnorderedAccessView(UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address);
+
+ void IASetIndexBuffer(const D3D12_INDEX_BUFFER_VIEW *view);
+ void IASetVertexBuffers(UINT start_slot, UINT view_count, const D3D12_VERTEX_BUFFER_VIEW *views);
+
+ void SOSetTargets(UINT start_slot, UINT view_count, const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views);
+
+ void OMSetRenderTargets(UINT render_target_descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,
+ BOOL single_descriptor_handle,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor);
+
+ void ClearDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE dsv, D3D12_CLEAR_FLAGS flags,
+ FLOAT depth, UINT8 stencil, UINT rect_count, const D3D12_RECT *rects);
+ void ClearRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE rtv, const FLOAT color[4],
+ UINT rect_count, const D3D12_RECT *rects);
+ void ClearUnorderedAccessViewUint(D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource, const UINT values[4],
+ UINT rect_count, const D3D12_RECT *rects);
+ void ClearUnorderedAccessViewFloat(D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle,
+ D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource, const float values[4],
+ UINT rect_count, const D3D12_RECT *rects);
+
+ void DiscardResource(ID3D12Resource *resource, const D3D12_DISCARD_REGION *region);
+
+ void BeginQuery(ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT index);
+ void EndQuery(ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT index);
+ void ResolveQueryData(ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type,
+ UINT start_index, UINT query_count,
+ ID3D12Resource *dst_buffer, UINT64 aligned_dst_buffer_offset);
+
+ void SetPredication(ID3D12Resource *buffer, UINT64 aligned_buffer_offset,
+ D3D12_PREDICATION_OP operation);
+
+ void SetMarker(UINT metadata, const void *data, UINT size);
+ void BeginEvent(UINT metadata, const void *data, UINT size);
+ void EndEvent();
+
+ void ExecuteIndirect(ID3D12CommandSignature *command_signature,
+ UINT max_command_count, ID3D12Resource *arg_buffer, UINT64 arg_buffer_offset,
+ ID3D12Resource *count_buffer, UINT64 count_buffer_offset);
+}
+
+[
+ uuid(553103fb-1fe7-4557-bb38-946d7d0e7ca7),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12GraphicsCommandList1 : ID3D12GraphicsCommandList
+{
+ void AtomicCopyBufferUINT(ID3D12Resource *dst_buffer, UINT64 dst_offset,
+ ID3D12Resource *src_buffer, UINT64 src_offset,
+ UINT dependent_resource_count, ID3D12Resource * const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges);
+
+ void AtomicCopyBufferUINT64(ID3D12Resource *dst_buffer, UINT64 dst_offset,
+ ID3D12Resource *src_buffer, UINT64 src_offset,
+ UINT dependent_resource_count, ID3D12Resource * const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges);
+
+ void OMSetDepthBounds(FLOAT min, FLOAT max);
+
+ void SetSamplePositions(UINT sample_count, UINT pixel_count,
+ D3D12_SAMPLE_POSITION *sample_positions);
+
+ void ResolveSubresourceRegion(ID3D12Resource *dst_resource,
+ UINT dst_sub_resource_idx, UINT dst_x, UINT dst_y,
+ ID3D12Resource *src_resource, UINT src_sub_resource_idx,
+ D3D12_RECT *src_rect, DXGI_FORMAT format, D3D12_RESOLVE_MODE mode);
+
+ void SetViewInstanceMask(UINT mask);
+}
+
+[
+ uuid(38c3e585-ff17-412c-9150-4fc6f9d72a28),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12GraphicsCommandList2 : ID3D12GraphicsCommandList1
+{
+ void WriteBufferImmediate(UINT count,
+ const D3D12_WRITEBUFFERIMMEDIATE_PARAMETER *parameters,
+ const D3D12_WRITEBUFFERIMMEDIATE_MODE *modes);
+}
+
+typedef enum D3D12_TILE_RANGE_FLAGS
+{
+ D3D12_TILE_RANGE_FLAG_NONE = 0x0,
+ D3D12_TILE_RANGE_FLAG_NULL = 0x1,
+ D3D12_TILE_RANGE_FLAG_SKIP = 0x2,
+ D3D12_TILE_RANGE_FLAG_REUSE_SINGLE_TILE = 0x4
+} D3D12_TILE_RANGE_FLAGS;
+
+typedef enum D3D12_TILE_MAPPING_FLAGS
+{
+ D3D12_TILE_MAPPING_FLAG_NONE = 0x0,
+ D3D12_TILE_MAPPING_FLAG_NO_HAZARD = 0x1,
+} D3D12_TILE_MAPPING_FLAGS;
+
+[
+ uuid(0ec870a6-5d7e-4c22-8cfc-5baae07616ed),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12CommandQueue : ID3D12Pageable
+{
+ void UpdateTileMappings(ID3D12Resource *resource, UINT region_count,
+ const D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates,
+ const D3D12_TILE_REGION_SIZE *region_sizes,
+ UINT range_count,
+ const D3D12_TILE_RANGE_FLAGS *range_flags,
+ UINT *heap_range_offsets,
+ UINT *range_tile_counts,
+ D3D12_TILE_MAPPING_FLAGS flags);
+
+ void CopyTileMappings(ID3D12Resource *dst_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *dst_region_start_coordinate,
+ ID3D12Resource *src_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *src_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *region_size,
+ D3D12_TILE_MAPPING_FLAGS flags);
+
+ void ExecuteCommandLists(UINT command_list_count,
+ ID3D12CommandList * const * command_lists);
+
+ void SetMarker(UINT metadata, const void *data, UINT size);
+ void BeginEvent(UINT metadata, const void *data, UINT size);
+ void EndEvent();
+
+ HRESULT Signal(ID3D12Fence *fence, UINT64 value);
+ HRESULT Wait(ID3D12Fence *fence, UINT64 value);
+
+ HRESULT GetTimestampFrequency(UINT64 *frequency);
+ HRESULT GetClockCalibration(UINT64 *gpu_timestamp, UINT64 *cpu_timestamp);
+
+ D3D12_COMMAND_QUEUE_DESC GetDesc();
+}
+
+typedef enum D3D12_FENCE_FLAGS
+{
+ D3D12_FENCE_FLAG_NONE = 0x0,
+ D3D12_FENCE_FLAG_SHARED = 0x1,
+ D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER = 0x2,
+} D3D12_FENCE_FLAGS;
+
+typedef enum D3D12_QUERY_HEAP_TYPE
+{
+ D3D12_QUERY_HEAP_TYPE_OCCLUSION = 0,
+ D3D12_QUERY_HEAP_TYPE_TIMESTAMP = 1,
+ D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS = 2,
+ D3D12_QUERY_HEAP_TYPE_SO_STATISTICS = 3,
+} D3D12_QUERY_HEAP_TYPE;
+
+typedef struct D3D12_QUERY_HEAP_DESC
+{
+ D3D12_QUERY_HEAP_TYPE Type;
+ UINT Count;
+ UINT NodeMask;
+} D3D12_QUERY_HEAP_DESC;
+
+typedef enum D3D12_INDIRECT_ARGUMENT_TYPE
+{
+ D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,
+ D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED,
+ D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
+ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,
+ D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW,
+ D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
+ D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW,
+ D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW,
+ D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW,
+} D3D12_INDIRECT_ARGUMENT_TYPE;
+
+typedef struct D3D12_INDIRECT_ARGUMENT_DESC
+{
+ D3D12_INDIRECT_ARGUMENT_TYPE Type;
+ union
+ {
+ struct
+ {
+ UINT Slot;
+ } VertexBuffer;
+ struct
+ {
+ UINT RootParameterIndex;
+ UINT DestOffsetIn32BitValues;
+ UINT Num32BitValuesToSet;
+ } Constant;
+ struct
+ {
+ UINT RootParameterIndex;
+ } ConstantBufferView;
+ struct
+ {
+ UINT RootParameterIndex;
+ } ShaderResourceView;
+ struct
+ {
+ UINT RootParameterIndex;
+ } UnorderedAccessView;
+ };
+} D3D12_INDIRECT_ARGUMENT_DESC;
+
+typedef struct D3D12_COMMAND_SIGNATURE_DESC
+{
+ UINT ByteStride;
+ UINT NumArgumentDescs;
+ const D3D12_INDIRECT_ARGUMENT_DESC *pArgumentDescs;
+ UINT NodeMask;
+} D3D12_COMMAND_SIGNATURE_DESC;
+
+[
+ uuid(c54a6b66-72df-4ee8-8be5-a946a1429214),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12RootSignature : ID3D12DeviceChild
+{
+}
+
+[
+ uuid(765a30f3-f624-4c6f-a828-ace948622445),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12PipelineState : ID3D12Pageable
+{
+ HRESULT GetCachedBlob(ID3DBlob **blob);
+}
+
+[
+ uuid(0a753dcf-c4d8-4b91-adf6-be5a60d95a76),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Fence : ID3D12Pageable
+{
+ UINT64 GetCompletedValue();
+ HRESULT SetEventOnCompletion(UINT64 value, HANDLE event);
+ HRESULT Signal(UINT64 value);
+}
+
+[
+ uuid(6102dee4-af59-4b09-b999-b44d73f09b24),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12CommandAllocator : ID3D12Pageable
+{
+ HRESULT Reset();
+}
+
+[
+ uuid(189819f1-1db6-4b57-be54-1821339b85f7),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Device : ID3D12Object
+{
+ UINT GetNodeCount();
+
+ HRESULT CreateCommandQueue(const D3D12_COMMAND_QUEUE_DESC *desc,
+ REFIID riid, void **command_queue);
+ HRESULT CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE type,
+ REFIID riid, void **command_allocator);
+ HRESULT CreateGraphicsPipelineState(const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,
+ REFIID riid, void **pipeline_state);
+ HRESULT CreateComputePipelineState(const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc,
+ REFIID riid, void **pipeline_state);
+ HRESULT CreateCommandList(UINT node_mask,
+ D3D12_COMMAND_LIST_TYPE type,
+ ID3D12CommandAllocator *command_allocator,
+ ID3D12PipelineState *initial_pipeline_state,
+ REFIID riid, void **command_list);
+
+ HRESULT CheckFeatureSupport(D3D12_FEATURE feature,
+ void *feature_data, UINT feature_data_size);
+
+ HRESULT CreateDescriptorHeap(const D3D12_DESCRIPTOR_HEAP_DESC *desc,
+ REFIID riid, void **descriptor_heap);
+ UINT GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+
+ HRESULT CreateRootSignature(UINT node_mask,
+ const void *bytecode, SIZE_T bytecode_length,
+ REFIID riid, void **root_signature);
+
+ void CreateConstantBufferView(const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+ void CreateShaderResourceView(ID3D12Resource *resource,
+ const D3D12_SHADER_RESOURCE_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+ void CreateUnorderedAccessView(ID3D12Resource *resource, ID3D12Resource *counter_resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+ void CreateRenderTargetView(ID3D12Resource *resource,
+ const D3D12_RENDER_TARGET_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+ void CreateDepthStencilView(ID3D12Resource *resource,
+ const D3D12_DEPTH_STENCIL_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+ void CreateSampler(const D3D12_SAMPLER_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
+
+ void CopyDescriptors(UINT dst_descriptor_range_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *dst_descriptor_range_offsets,
+ const UINT *dst_descriptor_range_sizes,
+ UINT src_descriptor_range_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE *src_descriptor_range_offsets,
+ const UINT *src_descriptor_range_sizes,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+ void CopyDescriptorsSimple(UINT descriptor_count,
+ const D3D12_CPU_DESCRIPTOR_HANDLE dst_descriptor_range_offset,
+ const D3D12_CPU_DESCRIPTOR_HANDLE src_descriptor_range_offset,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type);
+
+ D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo(UINT visible_mask,
+ UINT reource_desc_count, const D3D12_RESOURCE_DESC *resource_descs);
+
+ D3D12_HEAP_PROPERTIES GetCustomHeapProperties(UINT node_mask,
+ D3D12_HEAP_TYPE heap_type);
+
+ HRESULT CreateCommittedResource(const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid, void **resource);
+
+ HRESULT CreateHeap(const D3D12_HEAP_DESC *desc, REFIID riid, void **heap);
+
+ HRESULT CreatePlacedResource(ID3D12Heap *heap, UINT64 heap_offset,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid, void **resource);
+ HRESULT CreateReservedResource(const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value,
+ REFIID riid, void **resource);
+
+ HRESULT CreateSharedHandle(ID3D12DeviceChild *object,
+ const SECURITY_ATTRIBUTES *attributes, DWORD access,
+ const WCHAR *name, HANDLE *handle);
+ HRESULT OpenSharedHandle(HANDLE handle,
+ REFIID riid, void **object);
+ HRESULT OpenSharedHandleByName(const WCHAR *name, DWORD access, HANDLE *handle);
+
+ HRESULT MakeResident(UINT object_count, ID3D12Pageable * const *objects);
+ HRESULT Evict(UINT object_count, ID3D12Pageable * const *objects);
+
+ HRESULT CreateFence(UINT64 initial_value, D3D12_FENCE_FLAGS flags, REFIID riid, void **fence);
+
+ HRESULT GetDeviceRemovedReason();
+
+ void GetCopyableFootprints(const D3D12_RESOURCE_DESC *desc,
+ UINT first_sub_resource,
+ UINT sub_resource_count,
+ UINT64 base_offset,
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts,
+ UINT *row_count,
+ UINT64 *row_size,
+ UINT64 *total_bytes);
+
+ HRESULT CreateQueryHeap(const D3D12_QUERY_HEAP_DESC *desc,
+ REFIID riid, void **heap);
+
+ HRESULT SetStablePowerState(BOOL enable);
+
+ HRESULT CreateCommandSignature(const D3D12_COMMAND_SIGNATURE_DESC *desc,
+ ID3D12RootSignature *root_signature,
+ REFIID riid, void **command_signature);
+
+ void GetResourceTiling(ID3D12Resource *resource,
+ UINT *total_tile_count,
+ D3D12_PACKED_MIP_INFO *packed_mip_info,
+ D3D12_TILE_SHAPE *standard_tile_shape,
+ UINT *sub_resource_tiling_count,
+ UINT first_sub_resource_tiling,
+ D3D12_SUBRESOURCE_TILING *sub_resource_tilings);
+
+ LUID GetAdapterLuid();
+}
+
+[
+ uuid(77acce80-638e-4e65-8895-c1f23386863e),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Device1 : ID3D12Device
+{
+ HRESULT CreatePipelineLibrary(const void *blob, SIZE_T blob_size, REFIID iid, void **lib);
+
+ HRESULT SetEventOnMultipleFenceCompletion(ID3D12Fence * const *fences,
+ const UINT64 *values, UINT fence_count, D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags, HANDLE event);
+
+ HRESULT SetResidencyPriority(UINT object_count, ID3D12Pageable * const *objects,
+ const D3D12_RESIDENCY_PRIORITY *priorities);
+}
+
+[
+ uuid(34ab647b-3cc8-46ac-841b-c0965645c046),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12RootSignatureDeserializer : IUnknown
+{
+ const D3D12_ROOT_SIGNATURE_DESC *GetRootSignatureDesc();
+}
+
+[
+ uuid(7f91ce67-090c-4bb7-b78e-ed8ff2e31da0),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12VersionedRootSignatureDeserializer : IUnknown
+{
+ HRESULT GetRootSignatureDescAtVersion(D3D_ROOT_SIGNATURE_VERSION version,
+ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC **desc);
+
+ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *GetUnconvertedRootSignatureDesc();
+};
+
+[local] HRESULT __stdcall D3D12CreateRootSignatureDeserializer(
+ const void *data, SIZE_T data_size, REFIID iid, void **deserializer);
+
+typedef HRESULT (__stdcall *PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER)(
+ const void *data, SIZE_T data_size, REFIID iid, void **deserializer);
+
+[local] HRESULT __stdcall D3D12CreateVersionedRootSignatureDeserializer(
+ const void *data, SIZE_T data_size, REFIID iid, void **deserializer);
+
+[local] HRESULT __stdcall D3D12SerializeRootSignature(
+ const D3D12_ROOT_SIGNATURE_DESC *root_signature_desc,
+ D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
+
+typedef HRESULT (__stdcall *PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)(
+ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc, ID3DBlob **blob, ID3DBlob **error_blob);
+
+[local] HRESULT __stdcall D3D12SerializeVersionedRootSignature(
+ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *root_signature_desc,
+ ID3DBlob **blob, ID3DBlob **error_blob);
+
+typedef HRESULT (__stdcall *PFN_D3D12_CREATE_DEVICE)(IUnknown *adapter,
+ D3D_FEATURE_LEVEL minimum_feature_level, REFIID iid, void **device);
+
+[local] HRESULT __stdcall D3D12CreateDevice(IUnknown *adapter,
+ D3D_FEATURE_LEVEL minimum_feature_level, REFIID iid, void **device);
+
+typedef HRESULT (__stdcall *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID iid, void **debug);
+
+[local] HRESULT __stdcall D3D12GetDebugInterface(REFIID iid, void **debug);
diff --git a/dlls/vkd3d/include/vkd3d_d3d12sdklayers.h b/dlls/vkd3d/include/vkd3d_d3d12sdklayers.h
new file mode 100644
index 00000000000..59bd50ff155
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_d3d12sdklayers.h
@@ -0,0 +1,228 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_d3d12sdklayers.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_d3d12sdklayers_h__
+#define __vkd3d_d3d12sdklayers_h__
+
+/* Forward declarations */
+
+#ifndef __ID3D12Debug_FWD_DEFINED__
+#define __ID3D12Debug_FWD_DEFINED__
+typedef interface ID3D12Debug ID3D12Debug;
+#ifdef __cplusplus
+interface ID3D12Debug;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D12Debug1_FWD_DEFINED__
+#define __ID3D12Debug1_FWD_DEFINED__
+typedef interface ID3D12Debug1 ID3D12Debug1;
+#ifdef __cplusplus
+interface ID3D12Debug1;
+#endif /* __cplusplus */
+#endif
+
+/* Headers for imported files */
+
+#include <vkd3d_d3d12.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************
+ * ID3D12Debug interface
+ */
+#ifndef __ID3D12Debug_INTERFACE_DEFINED__
+#define __ID3D12Debug_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Debug, 0x344488b7, 0x6846, 0x474b, 0xb9,0x89, 0xf0,0x27,0x44,0x82,0x45,0xe0);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("344488b7-6846-474b-b989-f027448245e0")
+ID3D12Debug : public IUnknown
+{
+ virtual void STDMETHODCALLTYPE EnableDebugLayer(
+ ) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Debug, 0x344488b7, 0x6846, 0x474b, 0xb9,0x89, 0xf0,0x27,0x44,0x82,0x45,0xe0)
+#endif
+#else
+typedef struct ID3D12DebugVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Debug *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Debug *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Debug *This);
+
+ /*** ID3D12Debug methods ***/
+ void (STDMETHODCALLTYPE *EnableDebugLayer)(
+ ID3D12Debug *This);
+
+ END_INTERFACE
+} ID3D12DebugVtbl;
+
+interface ID3D12Debug {
+ CONST_VTBL ID3D12DebugVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Debug_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Debug_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Debug_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Debug methods ***/
+#define ID3D12Debug_EnableDebugLayer(This) (This)->lpVtbl->EnableDebugLayer(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Debug_QueryInterface(ID3D12Debug* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Debug_AddRef(ID3D12Debug* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Debug_Release(ID3D12Debug* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Debug methods ***/
+static FORCEINLINE void ID3D12Debug_EnableDebugLayer(ID3D12Debug* This) {
+ This->lpVtbl->EnableDebugLayer(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Debug_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * ID3D12Debug1 interface
+ */
+#ifndef __ID3D12Debug1_INTERFACE_DEFINED__
+#define __ID3D12Debug1_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D12Debug1, 0xaffaa4ca, 0x63fe, 0x4d8e, 0xb8,0xad, 0x15,0x90,0x00,0xaf,0x43,0x04);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("affaa4ca-63fe-4d8e-b8ad-159000af4304")
+ID3D12Debug1 : public IUnknown
+{
+ virtual void STDMETHODCALLTYPE EnableDebugLayer(
+ ) = 0;
+
+ virtual void STDMETHODCALLTYPE SetEnableGPUBasedValidation(
+ BOOL enable) = 0;
+
+ virtual void STDMETHODCALLTYPE SetEnableSynchronizedCommandQueueValidation(
+ BOOL enable) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D12Debug1, 0xaffaa4ca, 0x63fe, 0x4d8e, 0xb8,0xad, 0x15,0x90,0x00,0xaf,0x43,0x04)
+#endif
+#else
+typedef struct ID3D12Debug1Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D12Debug1 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D12Debug1 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D12Debug1 *This);
+
+ /*** ID3D12Debug1 methods ***/
+ void (STDMETHODCALLTYPE *EnableDebugLayer)(
+ ID3D12Debug1 *This);
+
+ void (STDMETHODCALLTYPE *SetEnableGPUBasedValidation)(
+ ID3D12Debug1 *This,
+ BOOL enable);
+
+ void (STDMETHODCALLTYPE *SetEnableSynchronizedCommandQueueValidation)(
+ ID3D12Debug1 *This,
+ BOOL enable);
+
+ END_INTERFACE
+} ID3D12Debug1Vtbl;
+
+interface ID3D12Debug1 {
+ CONST_VTBL ID3D12Debug1Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D12Debug1_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D12Debug1_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D12Debug1_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D12Debug1 methods ***/
+#define ID3D12Debug1_EnableDebugLayer(This) (This)->lpVtbl->EnableDebugLayer(This)
+#define ID3D12Debug1_SetEnableGPUBasedValidation(This,enable) (This)->lpVtbl->SetEnableGPUBasedValidation(This,enable)
+#define ID3D12Debug1_SetEnableSynchronizedCommandQueueValidation(This,enable) (This)->lpVtbl->SetEnableSynchronizedCommandQueueValidation(This,enable)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D12Debug1_QueryInterface(ID3D12Debug1* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D12Debug1_AddRef(ID3D12Debug1* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D12Debug1_Release(ID3D12Debug1* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D12Debug1 methods ***/
+static FORCEINLINE void ID3D12Debug1_EnableDebugLayer(ID3D12Debug1* This) {
+ This->lpVtbl->EnableDebugLayer(This);
+}
+static FORCEINLINE void ID3D12Debug1_SetEnableGPUBasedValidation(ID3D12Debug1* This,BOOL enable) {
+ This->lpVtbl->SetEnableGPUBasedValidation(This,enable);
+}
+static FORCEINLINE void ID3D12Debug1_SetEnableSynchronizedCommandQueueValidation(ID3D12Debug1* This,BOOL enable) {
+ This->lpVtbl->SetEnableSynchronizedCommandQueueValidation(This,enable);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D12Debug1_INTERFACE_DEFINED__ */
+
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_d3d12sdklayers_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_d3d12sdklayers.idl b/dlls/vkd3d/include/vkd3d_d3d12sdklayers.idl
new file mode 100644
index 00000000000..76634628a67
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_d3d12sdklayers.idl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016-2019 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_d3d12.idl";
+
+[
+ uuid(344488b7-6846-474b-b989-f027448245e0),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Debug : IUnknown
+{
+ void EnableDebugLayer();
+}
+
+[
+ uuid(affaa4ca-63fe-4d8e-b8ad-159000af4304),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D12Debug1 : IUnknown
+{
+ void EnableDebugLayer();
+ void SetEnableGPUBasedValidation(BOOL enable);
+ void SetEnableSynchronizedCommandQueueValidation(BOOL enable);
+}
diff --git a/dlls/vkd3d/include/vkd3d_d3dcommon.h b/dlls/vkd3d/include/vkd3d_d3dcommon.h
new file mode 100644
index 00000000000..7c9e7206794
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_d3dcommon.h
@@ -0,0 +1,296 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_d3dcommon.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_d3dcommon_h__
+#define __vkd3d_d3dcommon_h__
+
+/* Forward declarations */
+
+#ifndef __IUnknown_FWD_DEFINED__
+#define __IUnknown_FWD_DEFINED__
+typedef interface IUnknown IUnknown;
+#ifdef __cplusplus
+interface IUnknown;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __ID3D10Blob_FWD_DEFINED__
+#define __ID3D10Blob_FWD_DEFINED__
+typedef interface ID3D10Blob ID3D10Blob;
+#ifdef __cplusplus
+interface ID3D10Blob;
+#endif /* __cplusplus */
+#endif
+
+/* Headers for imported files */
+
+#include <vkd3d_windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __VKD3D_UNKNOWN_H
+#define __VKD3D_UNKNOWN_H
+#if 0
+typedef IID *REFIID;
+typedef IID *REFGUID;
+#endif
+#if !defined(_WIN32)
+typedef void *HWND;
+typedef void *HMODULE;
+typedef struct LUID {
+ DWORD LowPart;
+ LONG HighPart;
+} LUID;
+typedef struct _RECT {
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+} RECT;
+#endif
+/*****************************************************************************
+ * IUnknown interface
+ */
+#ifndef __IUnknown_INTERFACE_DEFINED__
+#define __IUnknown_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("00000000-0000-0000-c000-000000000046")
+IUnknown
+{
+
+ BEGIN_INTERFACE
+
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void **object) = 0;
+
+ virtual ULONG STDMETHODCALLTYPE AddRef(
+ ) = 0;
+
+ virtual ULONG STDMETHODCALLTYPE Release(
+ ) = 0;
+
+ END_INTERFACE
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IUnknown, 0x00000000, 0x0000, 0x0000, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46)
+#endif
+#else
+typedef struct IUnknownVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IUnknown *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IUnknown *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IUnknown *This);
+
+ END_INTERFACE
+} IUnknownVtbl;
+
+interface IUnknown {
+ CONST_VTBL IUnknownVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IUnknown_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IUnknown_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IUnknown_Release(This) (This)->lpVtbl->Release(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IUnknown_QueryInterface(IUnknown* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IUnknown_AddRef(IUnknown* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IUnknown_Release(IUnknown* This) {
+ return This->lpVtbl->Release(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IUnknown_INTERFACE_DEFINED__ */
+
+#endif /* __VKD3D_UNKNOWN_H */
+typedef enum D3D_PRIMITIVE_TOPOLOGY {
+ D3D_PRIMITIVE_TOPOLOGY_UNDEFINED = 0,
+ D3D_PRIMITIVE_TOPOLOGY_POINTLIST = 1,
+ D3D_PRIMITIVE_TOPOLOGY_LINELIST = 2,
+ D3D_PRIMITIVE_TOPOLOGY_LINESTRIP = 3,
+ D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4,
+ D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5,
+ D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10,
+ D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11,
+ D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12,
+ D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13,
+ D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST = 33,
+ D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST = 34,
+ D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST = 35,
+ D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST = 36,
+ D3D_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST = 37,
+ D3D_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST = 38,
+ D3D_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST = 39,
+ D3D_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST = 40,
+ D3D_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST = 41,
+ D3D_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST = 42,
+ D3D_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST = 43,
+ D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST = 44,
+ D3D_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST = 45,
+ D3D_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST = 46,
+ D3D_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST = 47,
+ D3D_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST = 48,
+ D3D_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST = 49,
+ D3D_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST = 50,
+ D3D_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST = 51,
+ D3D_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST = 52,
+ D3D_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST = 53,
+ D3D_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST = 54,
+ D3D_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST = 55,
+ D3D_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST = 56,
+ D3D_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST = 57,
+ D3D_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST = 58,
+ D3D_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST = 59,
+ D3D_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST = 60,
+ D3D_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST = 61,
+ D3D_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST = 62,
+ D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST = 63,
+ D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST = 64
+} D3D_PRIMITIVE_TOPOLOGY;
+typedef enum D3D_FEATURE_LEVEL {
+ D3D_FEATURE_LEVEL_9_1 = 0x9100,
+ D3D_FEATURE_LEVEL_9_2 = 0x9200,
+ D3D_FEATURE_LEVEL_9_3 = 0x9300,
+ D3D_FEATURE_LEVEL_10_0 = 0xa000,
+ D3D_FEATURE_LEVEL_10_1 = 0xa100,
+ D3D_FEATURE_LEVEL_11_0 = 0xb000,
+ D3D_FEATURE_LEVEL_11_1 = 0xb100,
+ D3D_FEATURE_LEVEL_12_0 = 0xc000,
+ D3D_FEATURE_LEVEL_12_1 = 0xc100
+} D3D_FEATURE_LEVEL;
+/*****************************************************************************
+ * ID3D10Blob interface
+ */
+#ifndef __ID3D10Blob_INTERFACE_DEFINED__
+#define __ID3D10Blob_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_ID3D10Blob, 0x8ba5fb08, 0x5195, 0x40e2, 0xac,0x58, 0x0d,0x98,0x9c,0x3a,0x01,0x02);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("8ba5fb08-5195-40e2-ac58-0d989c3a0102")
+ID3D10Blob : public IUnknown
+{
+ virtual void * STDMETHODCALLTYPE GetBufferPointer(
+ ) = 0;
+
+ virtual SIZE_T STDMETHODCALLTYPE GetBufferSize(
+ ) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID3D10Blob, 0x8ba5fb08, 0x5195, 0x40e2, 0xac,0x58, 0x0d,0x98,0x9c,0x3a,0x01,0x02)
+#endif
+#else
+typedef struct ID3D10BlobVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ ID3D10Blob *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ ID3D10Blob *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ ID3D10Blob *This);
+
+ /*** ID3D10Blob methods ***/
+ void * (STDMETHODCALLTYPE *GetBufferPointer)(
+ ID3D10Blob *This);
+
+ SIZE_T (STDMETHODCALLTYPE *GetBufferSize)(
+ ID3D10Blob *This);
+
+ END_INTERFACE
+} ID3D10BlobVtbl;
+
+interface ID3D10Blob {
+ CONST_VTBL ID3D10BlobVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define ID3D10Blob_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define ID3D10Blob_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define ID3D10Blob_Release(This) (This)->lpVtbl->Release(This)
+/*** ID3D10Blob methods ***/
+#define ID3D10Blob_GetBufferPointer(This) (This)->lpVtbl->GetBufferPointer(This)
+#define ID3D10Blob_GetBufferSize(This) (This)->lpVtbl->GetBufferSize(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT ID3D10Blob_QueryInterface(ID3D10Blob* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG ID3D10Blob_AddRef(ID3D10Blob* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG ID3D10Blob_Release(ID3D10Blob* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** ID3D10Blob methods ***/
+static FORCEINLINE void * ID3D10Blob_GetBufferPointer(ID3D10Blob* This) {
+ return This->lpVtbl->GetBufferPointer(This);
+}
+static FORCEINLINE SIZE_T ID3D10Blob_GetBufferSize(ID3D10Blob* This) {
+ return This->lpVtbl->GetBufferSize(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __ID3D10Blob_INTERFACE_DEFINED__ */
+
+typedef ID3D10Blob ID3DBlob;
+#define IID_ID3DBlob IID_ID3D10Blob
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_d3dcommon_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_d3dcommon.idl b/dlls/vkd3d/include/vkd3d_d3dcommon.idl
new file mode 100644
index 00000000000..8bfa567c538
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_d3dcommon.idl
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_windows.h";
+
+#include "vkd3d_unknown.idl"
+
+typedef enum D3D_PRIMITIVE_TOPOLOGY
+{
+ D3D_PRIMITIVE_TOPOLOGY_UNDEFINED = 0,
+ D3D_PRIMITIVE_TOPOLOGY_POINTLIST = 1,
+ D3D_PRIMITIVE_TOPOLOGY_LINELIST = 2,
+ D3D_PRIMITIVE_TOPOLOGY_LINESTRIP = 3,
+ D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4,
+ D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5,
+ D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10,
+ D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11,
+ D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12,
+ D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13,
+ D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST = 33,
+ D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST,
+ D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST,
+} D3D_PRIMITIVE_TOPOLOGY;
+
+typedef enum D3D_FEATURE_LEVEL
+{
+ D3D_FEATURE_LEVEL_9_1 = 0x9100,
+ D3D_FEATURE_LEVEL_9_2 = 0x9200,
+ D3D_FEATURE_LEVEL_9_3 = 0x9300,
+ D3D_FEATURE_LEVEL_10_0 = 0xa000,
+ D3D_FEATURE_LEVEL_10_1 = 0xa100,
+ D3D_FEATURE_LEVEL_11_0 = 0xb000,
+ D3D_FEATURE_LEVEL_11_1 = 0xb100,
+ D3D_FEATURE_LEVEL_12_0 = 0xc000,
+ D3D_FEATURE_LEVEL_12_1 = 0xc100,
+} D3D_FEATURE_LEVEL;
+
+[
+ uuid(8ba5fb08-5195-40e2-ac58-0d989c3a0102),
+ object,
+ local,
+ pointer_default(unique)
+]
+interface ID3D10Blob : IUnknown
+{
+ void *GetBufferPointer();
+ SIZE_T GetBufferSize();
+}
+
+typedef ID3D10Blob ID3DBlob;
+cpp_quote("#define IID_ID3DBlob IID_ID3D10Blob")
diff --git a/dlls/vkd3d/include/vkd3d_dxgi.h b/dlls/vkd3d/include/vkd3d_dxgi.h
new file mode 100644
index 00000000000..89926cb524a
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgi.h
@@ -0,0 +1,1237 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_dxgi.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_dxgi_h__
+#define __vkd3d_dxgi_h__
+
+/* Forward declarations */
+
+#ifndef __IUnknown_FWD_DEFINED__
+#define __IUnknown_FWD_DEFINED__
+typedef interface IUnknown IUnknown;
+#ifdef __cplusplus
+interface IUnknown;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIObject_FWD_DEFINED__
+#define __IDXGIObject_FWD_DEFINED__
+typedef interface IDXGIObject IDXGIObject;
+#ifdef __cplusplus
+interface IDXGIObject;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIDeviceSubObject_FWD_DEFINED__
+#define __IDXGIDeviceSubObject_FWD_DEFINED__
+typedef interface IDXGIDeviceSubObject IDXGIDeviceSubObject;
+#ifdef __cplusplus
+interface IDXGIDeviceSubObject;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIAdapter_FWD_DEFINED__
+#define __IDXGIAdapter_FWD_DEFINED__
+typedef interface IDXGIAdapter IDXGIAdapter;
+#ifdef __cplusplus
+interface IDXGIAdapter;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGISwapChain_FWD_DEFINED__
+#define __IDXGISwapChain_FWD_DEFINED__
+typedef interface IDXGISwapChain IDXGISwapChain;
+#ifdef __cplusplus
+interface IDXGISwapChain;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIFactory_FWD_DEFINED__
+#define __IDXGIFactory_FWD_DEFINED__
+typedef interface IDXGIFactory IDXGIFactory;
+#ifdef __cplusplus
+interface IDXGIFactory;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIFactory1_FWD_DEFINED__
+#define __IDXGIFactory1_FWD_DEFINED__
+typedef interface IDXGIFactory1 IDXGIFactory1;
+#ifdef __cplusplus
+interface IDXGIFactory1;
+#endif /* __cplusplus */
+#endif
+
+/* Headers for imported files */
+
+#include <vkd3d_dxgitype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __VKD3D_UNKNOWN_H
+#define __VKD3D_UNKNOWN_H
+#if 0
+typedef IID *REFIID;
+typedef IID *REFGUID;
+#endif
+#if !defined(_WIN32)
+typedef void *HWND;
+typedef void *HMODULE;
+typedef struct LUID {
+ DWORD LowPart;
+ LONG HighPart;
+} LUID;
+typedef struct _RECT {
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+} RECT;
+#endif
+/*****************************************************************************
+ * IUnknown interface
+ */
+#ifndef __IUnknown_INTERFACE_DEFINED__
+#define __IUnknown_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("00000000-0000-0000-c000-000000000046")
+IUnknown
+{
+
+ BEGIN_INTERFACE
+
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void **object) = 0;
+
+ virtual ULONG STDMETHODCALLTYPE AddRef(
+ ) = 0;
+
+ virtual ULONG STDMETHODCALLTYPE Release(
+ ) = 0;
+
+ END_INTERFACE
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IUnknown, 0x00000000, 0x0000, 0x0000, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46)
+#endif
+#else
+typedef struct IUnknownVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IUnknown *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IUnknown *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IUnknown *This);
+
+ END_INTERFACE
+} IUnknownVtbl;
+
+interface IUnknown {
+ CONST_VTBL IUnknownVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IUnknown_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IUnknown_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IUnknown_Release(This) (This)->lpVtbl->Release(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IUnknown_QueryInterface(IUnknown* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IUnknown_AddRef(IUnknown* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IUnknown_Release(IUnknown* This) {
+ return This->lpVtbl->Release(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IUnknown_INTERFACE_DEFINED__ */
+
+#endif /* __VKD3D_UNKNOWN_H */
+typedef enum DXGI_SWAP_EFFECT {
+ DXGI_SWAP_EFFECT_DISCARD = 0x0,
+ DXGI_SWAP_EFFECT_SEQUENTIAL = 0x1,
+ DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL = 0x3,
+ DXGI_SWAP_EFFECT_FLIP_DISCARD = 0x4
+} DXGI_SWAP_EFFECT;
+typedef enum DXGI_MODE_ROTATION {
+ DXGI_MODE_ROTATION_UNSPECIFIED = 0x0,
+ DXGI_MODE_ROTATION_IDENTITY = 0x1,
+ DXGI_MODE_ROTATION_ROTATE90 = 0x2,
+ DXGI_MODE_ROTATION_ROTATE180 = 0x3,
+ DXGI_MODE_ROTATION_ROTATE270 = 0x4
+} DXGI_MODE_ROTATION;
+#ifndef __IDXGIAdapter1_FWD_DEFINED__
+#define __IDXGIAdapter1_FWD_DEFINED__
+typedef interface IDXGIAdapter1 IDXGIAdapter1;
+#ifdef __cplusplus
+interface IDXGIAdapter1;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIOutput_FWD_DEFINED__
+#define __IDXGIOutput_FWD_DEFINED__
+typedef interface IDXGIOutput IDXGIOutput;
+#ifdef __cplusplus
+interface IDXGIOutput;
+#endif /* __cplusplus */
+#endif
+
+typedef struct DXGI_SWAP_CHAIN_DESC DXGI_SWAP_CHAIN_DESC;
+typedef struct DXGI_FRAME_STATISTICS DXGI_FRAME_STATISTICS;
+typedef UINT DXGI_USAGE;
+#define DXGI_USAGE_SHADER_INPUT (0x10)
+
+#define DXGI_USAGE_RENDER_TARGET_OUTPUT (0x20)
+
+#define DXGI_USAGE_BACK_BUFFER (0x40)
+
+#define DXGI_USAGE_SHARED (0x80)
+
+#define DXGI_USAGE_READ_ONLY (0x100)
+
+#define DXGI_USAGE_DISCARD_ON_PRESENT (0x200)
+
+#define DXGI_USAGE_UNORDERED_ACCESS (0x400)
+
+typedef struct DXGI_ADAPTER_DESC {
+ WCHAR Description[128];
+ UINT VendorId;
+ UINT DeviceId;
+ UINT SubSysId;
+ UINT Revision;
+ SIZE_T DedicatedVideoMemory;
+ SIZE_T DedicatedSystemMemory;
+ SIZE_T SharedSystemMemory;
+ LUID AdapterLuid;
+} DXGI_ADAPTER_DESC;
+/*****************************************************************************
+ * IDXGIObject interface
+ */
+#ifndef __IDXGIObject_INTERFACE_DEFINED__
+#define __IDXGIObject_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIObject, 0xaec22fb8, 0x76f3, 0x4639, 0x9b,0xe0, 0x28,0xeb,0x43,0xa6,0x7a,0x2e);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("aec22fb8-76f3-4639-9be0-28eb43a67a2e")
+IDXGIObject : public IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE SetPrivateData(
+ REFGUID name,
+ UINT data_size,
+ const void *data) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPrivateDataInterface(
+ REFGUID name,
+ const IUnknown *unknown) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPrivateData(
+ REFGUID name,
+ UINT *data_size,
+ void *data) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetParent(
+ REFIID riid,
+ void **parent) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIObject, 0xaec22fb8, 0x76f3, 0x4639, 0x9b,0xe0, 0x28,0xeb,0x43,0xa6,0x7a,0x2e)
+#endif
+#else
+typedef struct IDXGIObjectVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIObject *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIObject *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIObject *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGIObject *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGIObject *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGIObject *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGIObject *This,
+ REFIID riid,
+ void **parent);
+
+ END_INTERFACE
+} IDXGIObjectVtbl;
+
+interface IDXGIObject {
+ CONST_VTBL IDXGIObjectVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIObject_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGIObject_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIObject_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGIObject_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGIObject_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGIObject_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGIObject_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIObject_QueryInterface(IDXGIObject* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGIObject_AddRef(IDXGIObject* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIObject_Release(IDXGIObject* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGIObject_SetPrivateData(IDXGIObject* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIObject_GetPrivateDataInterface(IDXGIObject* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGIObject_GetPrivateData(IDXGIObject* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIObject_GetParent(IDXGIObject* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIObject_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGIDeviceSubObject interface
+ */
+#ifndef __IDXGIDeviceSubObject_INTERFACE_DEFINED__
+#define __IDXGIDeviceSubObject_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIDeviceSubObject, 0x3d3e0379, 0xf9de, 0x4d58, 0xbb,0x6c, 0x18,0xd6,0x29,0x92,0xf1,0xa6);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("3d3e0379-f9de-4d58-bb6c-18d62992f1a6")
+IDXGIDeviceSubObject : public IDXGIObject
+{
+ virtual HRESULT STDMETHODCALLTYPE GetDevice(
+ REFIID riid,
+ void **device) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIDeviceSubObject, 0x3d3e0379, 0xf9de, 0x4d58, 0xbb,0x6c, 0x18,0xd6,0x29,0x92,0xf1,0xa6)
+#endif
+#else
+typedef struct IDXGIDeviceSubObjectVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIDeviceSubObject *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIDeviceSubObject *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIDeviceSubObject *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGIDeviceSubObject *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGIDeviceSubObject *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGIDeviceSubObject *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGIDeviceSubObject *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIDeviceSubObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ IDXGIDeviceSubObject *This,
+ REFIID riid,
+ void **device);
+
+ END_INTERFACE
+} IDXGIDeviceSubObjectVtbl;
+
+interface IDXGIDeviceSubObject {
+ CONST_VTBL IDXGIDeviceSubObjectVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIDeviceSubObject_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGIDeviceSubObject_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIDeviceSubObject_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGIDeviceSubObject_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGIDeviceSubObject_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGIDeviceSubObject_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGIDeviceSubObject_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIDeviceSubObject methods ***/
+#define IDXGIDeviceSubObject_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIDeviceSubObject_QueryInterface(IDXGIDeviceSubObject* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGIDeviceSubObject_AddRef(IDXGIDeviceSubObject* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIDeviceSubObject_Release(IDXGIDeviceSubObject* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGIDeviceSubObject_SetPrivateData(IDXGIDeviceSubObject* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIDeviceSubObject_GetPrivateDataInterface(IDXGIDeviceSubObject* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGIDeviceSubObject_GetPrivateData(IDXGIDeviceSubObject* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIDeviceSubObject_GetParent(IDXGIDeviceSubObject* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIDeviceSubObject methods ***/
+static FORCEINLINE HRESULT IDXGIDeviceSubObject_GetDevice(IDXGIDeviceSubObject* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIDeviceSubObject_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGIAdapter interface
+ */
+#ifndef __IDXGIAdapter_INTERFACE_DEFINED__
+#define __IDXGIAdapter_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIAdapter, 0x2411e7e1, 0x12ac, 0x4ccf, 0xbd,0x14, 0x97,0x98,0xe8,0x53,0x4d,0xc0);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("2411e7e1-12ac-4ccf-bd14-9798e8534dc0")
+IDXGIAdapter : public IDXGIObject
+{
+ virtual HRESULT STDMETHODCALLTYPE EnumOutputs(
+ UINT output_idx,
+ IDXGIOutput **output) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDesc(
+ DXGI_ADAPTER_DESC *desc) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CheckInterfaceSupport(
+ REFGUID guid,
+ void *umd_version) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIAdapter, 0x2411e7e1, 0x12ac, 0x4ccf, 0xbd,0x14, 0x97,0x98,0xe8,0x53,0x4d,0xc0)
+#endif
+#else
+typedef struct IDXGIAdapterVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIAdapter *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIAdapter *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIAdapter *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGIAdapter *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGIAdapter *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGIAdapter *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGIAdapter *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIAdapter methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumOutputs)(
+ IDXGIAdapter *This,
+ UINT output_idx,
+ IDXGIOutput **output);
+
+ HRESULT (STDMETHODCALLTYPE *GetDesc)(
+ IDXGIAdapter *This,
+ DXGI_ADAPTER_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *CheckInterfaceSupport)(
+ IDXGIAdapter *This,
+ REFGUID guid,
+ void *umd_version);
+
+ END_INTERFACE
+} IDXGIAdapterVtbl;
+
+interface IDXGIAdapter {
+ CONST_VTBL IDXGIAdapterVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIAdapter_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGIAdapter_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIAdapter_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGIAdapter_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGIAdapter_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGIAdapter_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGIAdapter_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIAdapter methods ***/
+#define IDXGIAdapter_EnumOutputs(This,output_idx,output) (This)->lpVtbl->EnumOutputs(This,output_idx,output)
+#define IDXGIAdapter_GetDesc(This,desc) (This)->lpVtbl->GetDesc(This,desc)
+#define IDXGIAdapter_CheckInterfaceSupport(This,guid,umd_version) (This)->lpVtbl->CheckInterfaceSupport(This,guid,umd_version)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIAdapter_QueryInterface(IDXGIAdapter* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGIAdapter_AddRef(IDXGIAdapter* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIAdapter_Release(IDXGIAdapter* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGIAdapter_SetPrivateData(IDXGIAdapter* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIAdapter_GetPrivateDataInterface(IDXGIAdapter* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGIAdapter_GetPrivateData(IDXGIAdapter* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIAdapter_GetParent(IDXGIAdapter* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIAdapter methods ***/
+static FORCEINLINE HRESULT IDXGIAdapter_EnumOutputs(IDXGIAdapter* This,UINT output_idx,IDXGIOutput **output) {
+ return This->lpVtbl->EnumOutputs(This,output_idx,output);
+}
+static FORCEINLINE HRESULT IDXGIAdapter_GetDesc(IDXGIAdapter* This,DXGI_ADAPTER_DESC *desc) {
+ return This->lpVtbl->GetDesc(This,desc);
+}
+static FORCEINLINE HRESULT IDXGIAdapter_CheckInterfaceSupport(IDXGIAdapter* This,REFGUID guid,void *umd_version) {
+ return This->lpVtbl->CheckInterfaceSupport(This,guid,umd_version);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIAdapter_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGISwapChain interface
+ */
+#ifndef __IDXGISwapChain_INTERFACE_DEFINED__
+#define __IDXGISwapChain_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGISwapChain, 0x310d36a0, 0xd2e7, 0x4c0a, 0xaa,0x04, 0x6a,0x9d,0x23,0xb8,0x88,0x6a);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("310d36a0-d2e7-4c0a-aa04-6a9d23b8886a")
+IDXGISwapChain : public IDXGIDeviceSubObject
+{
+ virtual HRESULT STDMETHODCALLTYPE Present(
+ UINT sync_interval,
+ UINT flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBuffer(
+ UINT buffer_idx,
+ REFIID riid,
+ void **surface) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetFullscreenState(
+ BOOL fullscreen,
+ IDXGIOutput *target) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFullscreenState(
+ BOOL *fullscreen,
+ IDXGIOutput **target) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDesc(
+ DXGI_SWAP_CHAIN_DESC *desc) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ResizeBuffers(
+ UINT buffer_count,
+ UINT width,
+ UINT height,
+ DXGI_FORMAT format,
+ UINT flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ResizeTarget(
+ const DXGI_MODE_DESC *desc) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetContainingOutput(
+ IDXGIOutput **output) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics(
+ DXGI_FRAME_STATISTICS *stats) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(
+ UINT *last_present_count) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGISwapChain, 0x310d36a0, 0xd2e7, 0x4c0a, 0xaa,0x04, 0x6a,0x9d,0x23,0xb8,0x88,0x6a)
+#endif
+#else
+typedef struct IDXGISwapChainVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGISwapChain *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGISwapChain *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGISwapChain *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGISwapChain *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGISwapChain *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGISwapChain *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGISwapChain *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIDeviceSubObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ IDXGISwapChain *This,
+ REFIID riid,
+ void **device);
+
+ /*** IDXGISwapChain methods ***/
+ HRESULT (STDMETHODCALLTYPE *Present)(
+ IDXGISwapChain *This,
+ UINT sync_interval,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetBuffer)(
+ IDXGISwapChain *This,
+ UINT buffer_idx,
+ REFIID riid,
+ void **surface);
+
+ HRESULT (STDMETHODCALLTYPE *SetFullscreenState)(
+ IDXGISwapChain *This,
+ BOOL fullscreen,
+ IDXGIOutput *target);
+
+ HRESULT (STDMETHODCALLTYPE *GetFullscreenState)(
+ IDXGISwapChain *This,
+ BOOL *fullscreen,
+ IDXGIOutput **target);
+
+ HRESULT (STDMETHODCALLTYPE *GetDesc)(
+ IDXGISwapChain *This,
+ DXGI_SWAP_CHAIN_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeBuffers)(
+ IDXGISwapChain *This,
+ UINT buffer_count,
+ UINT width,
+ UINT height,
+ DXGI_FORMAT format,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeTarget)(
+ IDXGISwapChain *This,
+ const DXGI_MODE_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetContainingOutput)(
+ IDXGISwapChain *This,
+ IDXGIOutput **output);
+
+ HRESULT (STDMETHODCALLTYPE *GetFrameStatistics)(
+ IDXGISwapChain *This,
+ DXGI_FRAME_STATISTICS *stats);
+
+ HRESULT (STDMETHODCALLTYPE *GetLastPresentCount)(
+ IDXGISwapChain *This,
+ UINT *last_present_count);
+
+ END_INTERFACE
+} IDXGISwapChainVtbl;
+
+interface IDXGISwapChain {
+ CONST_VTBL IDXGISwapChainVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGISwapChain_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGISwapChain_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGISwapChain_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGISwapChain_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGISwapChain_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGISwapChain_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGISwapChain_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIDeviceSubObject methods ***/
+#define IDXGISwapChain_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** IDXGISwapChain methods ***/
+#define IDXGISwapChain_Present(This,sync_interval,flags) (This)->lpVtbl->Present(This,sync_interval,flags)
+#define IDXGISwapChain_GetBuffer(This,buffer_idx,riid,surface) (This)->lpVtbl->GetBuffer(This,buffer_idx,riid,surface)
+#define IDXGISwapChain_SetFullscreenState(This,fullscreen,target) (This)->lpVtbl->SetFullscreenState(This,fullscreen,target)
+#define IDXGISwapChain_GetFullscreenState(This,fullscreen,target) (This)->lpVtbl->GetFullscreenState(This,fullscreen,target)
+#define IDXGISwapChain_GetDesc(This,desc) (This)->lpVtbl->GetDesc(This,desc)
+#define IDXGISwapChain_ResizeBuffers(This,buffer_count,width,height,format,flags) (This)->lpVtbl->ResizeBuffers(This,buffer_count,width,height,format,flags)
+#define IDXGISwapChain_ResizeTarget(This,desc) (This)->lpVtbl->ResizeTarget(This,desc)
+#define IDXGISwapChain_GetContainingOutput(This,output) (This)->lpVtbl->GetContainingOutput(This,output)
+#define IDXGISwapChain_GetFrameStatistics(This,stats) (This)->lpVtbl->GetFrameStatistics(This,stats)
+#define IDXGISwapChain_GetLastPresentCount(This,last_present_count) (This)->lpVtbl->GetLastPresentCount(This,last_present_count)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain_QueryInterface(IDXGISwapChain* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGISwapChain_AddRef(IDXGISwapChain* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGISwapChain_Release(IDXGISwapChain* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain_SetPrivateData(IDXGISwapChain* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetPrivateDataInterface(IDXGISwapChain* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetPrivateData(IDXGISwapChain* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetParent(IDXGISwapChain* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIDeviceSubObject methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain_GetDevice(IDXGISwapChain* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** IDXGISwapChain methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain_Present(IDXGISwapChain* This,UINT sync_interval,UINT flags) {
+ return This->lpVtbl->Present(This,sync_interval,flags);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetBuffer(IDXGISwapChain* This,UINT buffer_idx,REFIID riid,void **surface) {
+ return This->lpVtbl->GetBuffer(This,buffer_idx,riid,surface);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_SetFullscreenState(IDXGISwapChain* This,BOOL fullscreen,IDXGIOutput *target) {
+ return This->lpVtbl->SetFullscreenState(This,fullscreen,target);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetFullscreenState(IDXGISwapChain* This,BOOL *fullscreen,IDXGIOutput **target) {
+ return This->lpVtbl->GetFullscreenState(This,fullscreen,target);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetDesc(IDXGISwapChain* This,DXGI_SWAP_CHAIN_DESC *desc) {
+ return This->lpVtbl->GetDesc(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_ResizeBuffers(IDXGISwapChain* This,UINT buffer_count,UINT width,UINT height,DXGI_FORMAT format,UINT flags) {
+ return This->lpVtbl->ResizeBuffers(This,buffer_count,width,height,format,flags);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_ResizeTarget(IDXGISwapChain* This,const DXGI_MODE_DESC *desc) {
+ return This->lpVtbl->ResizeTarget(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetContainingOutput(IDXGISwapChain* This,IDXGIOutput **output) {
+ return This->lpVtbl->GetContainingOutput(This,output);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetFrameStatistics(IDXGISwapChain* This,DXGI_FRAME_STATISTICS *stats) {
+ return This->lpVtbl->GetFrameStatistics(This,stats);
+}
+static FORCEINLINE HRESULT IDXGISwapChain_GetLastPresentCount(IDXGISwapChain* This,UINT *last_present_count) {
+ return This->lpVtbl->GetLastPresentCount(This,last_present_count);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGISwapChain_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGIFactory interface
+ */
+#ifndef __IDXGIFactory_INTERFACE_DEFINED__
+#define __IDXGIFactory_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIFactory, 0x7b7166ec, 0x21c7, 0x44ae, 0xb2,0x1a, 0xc9,0xae,0x32,0x1a,0xe3,0x69);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("7b7166ec-21c7-44ae-b21a-c9ae321ae369")
+IDXGIFactory : public IDXGIObject
+{
+ virtual HRESULT STDMETHODCALLTYPE EnumAdapters(
+ UINT adapter_idx,
+ IDXGIAdapter **adapter) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MakeWindowAssociation(
+ HWND hwnd,
+ UINT flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetWindowAssociation(
+ HWND *hwnd) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateSwapChain(
+ IUnknown *device,
+ DXGI_SWAP_CHAIN_DESC *desc,
+ IDXGISwapChain **swapchain) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateSoftwareAdapter(
+ HMODULE hmodule,
+ IDXGIAdapter **adapter) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIFactory, 0x7b7166ec, 0x21c7, 0x44ae, 0xb2,0x1a, 0xc9,0xae,0x32,0x1a,0xe3,0x69)
+#endif
+#else
+typedef struct IDXGIFactoryVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIFactory *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIFactory *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIFactory *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGIFactory *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGIFactory *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGIFactory *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGIFactory *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIFactory methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters)(
+ IDXGIFactory *This,
+ UINT adapter_idx,
+ IDXGIAdapter **adapter);
+
+ HRESULT (STDMETHODCALLTYPE *MakeWindowAssociation)(
+ IDXGIFactory *This,
+ HWND hwnd,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetWindowAssociation)(
+ IDXGIFactory *This,
+ HWND *hwnd);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChain)(
+ IDXGIFactory *This,
+ IUnknown *device,
+ DXGI_SWAP_CHAIN_DESC *desc,
+ IDXGISwapChain **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSoftwareAdapter)(
+ IDXGIFactory *This,
+ HMODULE hmodule,
+ IDXGIAdapter **adapter);
+
+ END_INTERFACE
+} IDXGIFactoryVtbl;
+
+interface IDXGIFactory {
+ CONST_VTBL IDXGIFactoryVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIFactory_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGIFactory_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIFactory_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGIFactory_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGIFactory_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGIFactory_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGIFactory_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIFactory methods ***/
+#define IDXGIFactory_EnumAdapters(This,adapter_idx,adapter) (This)->lpVtbl->EnumAdapters(This,adapter_idx,adapter)
+#define IDXGIFactory_MakeWindowAssociation(This,hwnd,flags) (This)->lpVtbl->MakeWindowAssociation(This,hwnd,flags)
+#define IDXGIFactory_GetWindowAssociation(This,hwnd) (This)->lpVtbl->GetWindowAssociation(This,hwnd)
+#define IDXGIFactory_CreateSwapChain(This,device,desc,swapchain) (This)->lpVtbl->CreateSwapChain(This,device,desc,swapchain)
+#define IDXGIFactory_CreateSoftwareAdapter(This,hmodule,adapter) (This)->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIFactory_QueryInterface(IDXGIFactory* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGIFactory_AddRef(IDXGIFactory* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIFactory_Release(IDXGIFactory* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGIFactory_SetPrivateData(IDXGIFactory* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory_GetPrivateDataInterface(IDXGIFactory* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGIFactory_GetPrivateData(IDXGIFactory* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory_GetParent(IDXGIFactory* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIFactory methods ***/
+static FORCEINLINE HRESULT IDXGIFactory_EnumAdapters(IDXGIFactory* This,UINT adapter_idx,IDXGIAdapter **adapter) {
+ return This->lpVtbl->EnumAdapters(This,adapter_idx,adapter);
+}
+static FORCEINLINE HRESULT IDXGIFactory_MakeWindowAssociation(IDXGIFactory* This,HWND hwnd,UINT flags) {
+ return This->lpVtbl->MakeWindowAssociation(This,hwnd,flags);
+}
+static FORCEINLINE HRESULT IDXGIFactory_GetWindowAssociation(IDXGIFactory* This,HWND *hwnd) {
+ return This->lpVtbl->GetWindowAssociation(This,hwnd);
+}
+static FORCEINLINE HRESULT IDXGIFactory_CreateSwapChain(IDXGIFactory* This,IUnknown *device,DXGI_SWAP_CHAIN_DESC *desc,IDXGISwapChain **swapchain) {
+ return This->lpVtbl->CreateSwapChain(This,device,desc,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory_CreateSoftwareAdapter(IDXGIFactory* This,HMODULE hmodule,IDXGIAdapter **adapter) {
+ return This->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIFactory_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGIFactory1 interface
+ */
+#ifndef __IDXGIFactory1_INTERFACE_DEFINED__
+#define __IDXGIFactory1_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIFactory1, 0x770aae78, 0xf26f, 0x4dba, 0xa8,0x29, 0x25,0x3c,0x83,0xd1,0xb3,0x87);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("770aae78-f26f-4dba-a829-253c83d1b387")
+IDXGIFactory1 : public IDXGIFactory
+{
+ virtual HRESULT STDMETHODCALLTYPE EnumAdapters1(
+ UINT adapter_idx,
+ IDXGIAdapter1 **adpter) = 0;
+
+ virtual BOOL STDMETHODCALLTYPE IsCurrent(
+ ) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIFactory1, 0x770aae78, 0xf26f, 0x4dba, 0xa8,0x29, 0x25,0x3c,0x83,0xd1,0xb3,0x87)
+#endif
+#else
+typedef struct IDXGIFactory1Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIFactory1 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIFactory1 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIFactory1 *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGIFactory1 *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGIFactory1 *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGIFactory1 *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGIFactory1 *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIFactory methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters)(
+ IDXGIFactory1 *This,
+ UINT adapter_idx,
+ IDXGIAdapter **adapter);
+
+ HRESULT (STDMETHODCALLTYPE *MakeWindowAssociation)(
+ IDXGIFactory1 *This,
+ HWND hwnd,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetWindowAssociation)(
+ IDXGIFactory1 *This,
+ HWND *hwnd);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChain)(
+ IDXGIFactory1 *This,
+ IUnknown *device,
+ DXGI_SWAP_CHAIN_DESC *desc,
+ IDXGISwapChain **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSoftwareAdapter)(
+ IDXGIFactory1 *This,
+ HMODULE hmodule,
+ IDXGIAdapter **adapter);
+
+ /*** IDXGIFactory1 methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters1)(
+ IDXGIFactory1 *This,
+ UINT adapter_idx,
+ IDXGIAdapter1 **adpter);
+
+ BOOL (STDMETHODCALLTYPE *IsCurrent)(
+ IDXGIFactory1 *This);
+
+ END_INTERFACE
+} IDXGIFactory1Vtbl;
+
+interface IDXGIFactory1 {
+ CONST_VTBL IDXGIFactory1Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIFactory1_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGIFactory1_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIFactory1_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGIFactory1_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGIFactory1_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGIFactory1_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGIFactory1_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIFactory methods ***/
+#define IDXGIFactory1_EnumAdapters(This,adapter_idx,adapter) (This)->lpVtbl->EnumAdapters(This,adapter_idx,adapter)
+#define IDXGIFactory1_MakeWindowAssociation(This,hwnd,flags) (This)->lpVtbl->MakeWindowAssociation(This,hwnd,flags)
+#define IDXGIFactory1_GetWindowAssociation(This,hwnd) (This)->lpVtbl->GetWindowAssociation(This,hwnd)
+#define IDXGIFactory1_CreateSwapChain(This,device,desc,swapchain) (This)->lpVtbl->CreateSwapChain(This,device,desc,swapchain)
+#define IDXGIFactory1_CreateSoftwareAdapter(This,hmodule,adapter) (This)->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter)
+/*** IDXGIFactory1 methods ***/
+#define IDXGIFactory1_EnumAdapters1(This,adapter_idx,adpter) (This)->lpVtbl->EnumAdapters1(This,adapter_idx,adpter)
+#define IDXGIFactory1_IsCurrent(This) (This)->lpVtbl->IsCurrent(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIFactory1_QueryInterface(IDXGIFactory1* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGIFactory1_AddRef(IDXGIFactory1* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIFactory1_Release(IDXGIFactory1* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGIFactory1_SetPrivateData(IDXGIFactory1* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory1_GetPrivateDataInterface(IDXGIFactory1* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGIFactory1_GetPrivateData(IDXGIFactory1* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory1_GetParent(IDXGIFactory1* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIFactory methods ***/
+static FORCEINLINE HRESULT IDXGIFactory1_EnumAdapters(IDXGIFactory1* This,UINT adapter_idx,IDXGIAdapter **adapter) {
+ return This->lpVtbl->EnumAdapters(This,adapter_idx,adapter);
+}
+static FORCEINLINE HRESULT IDXGIFactory1_MakeWindowAssociation(IDXGIFactory1* This,HWND hwnd,UINT flags) {
+ return This->lpVtbl->MakeWindowAssociation(This,hwnd,flags);
+}
+static FORCEINLINE HRESULT IDXGIFactory1_GetWindowAssociation(IDXGIFactory1* This,HWND *hwnd) {
+ return This->lpVtbl->GetWindowAssociation(This,hwnd);
+}
+static FORCEINLINE HRESULT IDXGIFactory1_CreateSwapChain(IDXGIFactory1* This,IUnknown *device,DXGI_SWAP_CHAIN_DESC *desc,IDXGISwapChain **swapchain) {
+ return This->lpVtbl->CreateSwapChain(This,device,desc,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory1_CreateSoftwareAdapter(IDXGIFactory1* This,HMODULE hmodule,IDXGIAdapter **adapter) {
+ return This->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter);
+}
+/*** IDXGIFactory1 methods ***/
+static FORCEINLINE HRESULT IDXGIFactory1_EnumAdapters1(IDXGIFactory1* This,UINT adapter_idx,IDXGIAdapter1 **adpter) {
+ return This->lpVtbl->EnumAdapters1(This,adapter_idx,adpter);
+}
+static FORCEINLINE BOOL IDXGIFactory1_IsCurrent(IDXGIFactory1* This) {
+ return This->lpVtbl->IsCurrent(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIFactory1_INTERFACE_DEFINED__ */
+
+HRESULT __stdcall CreateDXGIFactory(REFIID riid,void **factory);
+
+HRESULT __stdcall CreateDXGIFactory1(REFIID riid,void **factory);
+
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_dxgi_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_dxgi.idl b/dlls/vkd3d/include/vkd3d_dxgi.idl
new file mode 100644
index 00000000000..7e07a78dd36
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgi.idl
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ * Copyright 2016 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_dxgitype.idl";
+
+#include "vkd3d_unknown.idl"
+
+typedef enum DXGI_SWAP_EFFECT
+{
+ DXGI_SWAP_EFFECT_DISCARD = 0x0,
+ DXGI_SWAP_EFFECT_SEQUENTIAL = 0x1,
+ DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL = 0x3,
+ DXGI_SWAP_EFFECT_FLIP_DISCARD = 0x4,
+} DXGI_SWAP_EFFECT;
+
+typedef enum DXGI_MODE_ROTATION
+{
+ DXGI_MODE_ROTATION_UNSPECIFIED = 0x0,
+ DXGI_MODE_ROTATION_IDENTITY = 0x1,
+ DXGI_MODE_ROTATION_ROTATE90 = 0x2,
+ DXGI_MODE_ROTATION_ROTATE180 = 0x3,
+ DXGI_MODE_ROTATION_ROTATE270 = 0x4,
+} DXGI_MODE_ROTATION;
+
+interface IDXGIAdapter1;
+interface IDXGIOutput;
+typedef struct DXGI_SWAP_CHAIN_DESC DXGI_SWAP_CHAIN_DESC;
+typedef struct DXGI_FRAME_STATISTICS DXGI_FRAME_STATISTICS;
+
+typedef UINT DXGI_USAGE;
+
+const DXGI_USAGE DXGI_USAGE_SHADER_INPUT = 0x00000010ul;
+const DXGI_USAGE DXGI_USAGE_RENDER_TARGET_OUTPUT = 0x00000020ul;
+const DXGI_USAGE DXGI_USAGE_BACK_BUFFER = 0x00000040ul;
+const DXGI_USAGE DXGI_USAGE_SHARED = 0x00000080ul;
+const DXGI_USAGE DXGI_USAGE_READ_ONLY = 0x00000100ul;
+const DXGI_USAGE DXGI_USAGE_DISCARD_ON_PRESENT = 0x00000200ul;
+const DXGI_USAGE DXGI_USAGE_UNORDERED_ACCESS = 0x00000400ul;
+
+typedef struct DXGI_ADAPTER_DESC
+{
+ WCHAR Description[128];
+ UINT VendorId;
+ UINT DeviceId;
+ UINT SubSysId;
+ UINT Revision;
+ SIZE_T DedicatedVideoMemory;
+ SIZE_T DedicatedSystemMemory;
+ SIZE_T SharedSystemMemory;
+ LUID AdapterLuid;
+} DXGI_ADAPTER_DESC;
+
+[
+ local,
+ object,
+ uuid(aec22fb8-76f3-4639-9be0-28eb43a67a2e),
+ pointer_default(unique)
+]
+interface IDXGIObject : IUnknown
+{
+ HRESULT SetPrivateData(REFGUID name, UINT data_size, const void *data);
+ HRESULT GetPrivateDataInterface(REFGUID name, const IUnknown *unknown);
+ HRESULT GetPrivateData(REFGUID name, UINT *data_size, void *data);
+ HRESULT GetParent(REFIID riid, void **parent);
+}
+
+[
+ local,
+ object,
+ uuid(3d3e0379-f9de-4d58-bb6c-18d62992f1a6),
+ pointer_default(unique)
+]
+interface IDXGIDeviceSubObject : IDXGIObject
+{
+ HRESULT GetDevice(REFIID riid, void **device);
+}
+
+[
+ object,
+ local,
+ uuid(2411e7e1-12ac-4ccf-bd14-9798e8534dc0)
+]
+interface IDXGIAdapter : IDXGIObject
+{
+ HRESULT EnumOutputs(UINT output_idx, IDXGIOutput **output);
+ HRESULT GetDesc(DXGI_ADAPTER_DESC *desc);
+ HRESULT CheckInterfaceSupport(REFGUID guid, void *umd_version);
+}
+
+[
+ local,
+ object,
+ uuid(310d36a0-d2e7-4c0a-aa04-6a9d23b8886a),
+ pointer_default(unique)
+]
+interface IDXGISwapChain : IDXGIDeviceSubObject
+{
+ HRESULT Present(UINT sync_interval, UINT flags);
+ HRESULT GetBuffer(UINT buffer_idx, REFIID riid, void **surface);
+ HRESULT SetFullscreenState(BOOL fullscreen, IDXGIOutput *target);
+ HRESULT GetFullscreenState(BOOL *fullscreen, IDXGIOutput **target);
+ HRESULT GetDesc(DXGI_SWAP_CHAIN_DESC *desc);
+ HRESULT ResizeBuffers(UINT buffer_count, UINT width, UINT height, DXGI_FORMAT format, UINT flags);
+ HRESULT ResizeTarget(const DXGI_MODE_DESC *desc);
+ HRESULT GetContainingOutput(IDXGIOutput **output);
+ HRESULT GetFrameStatistics(DXGI_FRAME_STATISTICS *stats);
+ HRESULT GetLastPresentCount(UINT *last_present_count);
+}
+
+[
+ local,
+ object,
+ uuid(7b7166ec-21c7-44ae-b21a-c9ae321ae369),
+ pointer_default(unique)
+]
+interface IDXGIFactory : IDXGIObject
+{
+ HRESULT EnumAdapters(UINT adapter_idx, IDXGIAdapter **adapter);
+ HRESULT MakeWindowAssociation(HWND hwnd, UINT flags);
+ HRESULT GetWindowAssociation(HWND *hwnd);
+ HRESULT CreateSwapChain(IUnknown *device, DXGI_SWAP_CHAIN_DESC *desc, IDXGISwapChain **swapchain);
+ HRESULT CreateSoftwareAdapter(HMODULE hmodule, IDXGIAdapter **adapter);
+}
+
+[
+ local,
+ object,
+ uuid(770aae78-f26f-4dba-a829-253c83d1b387),
+ pointer_default(unique)
+]
+interface IDXGIFactory1 : IDXGIFactory
+{
+ HRESULT EnumAdapters1(UINT adapter_idx, IDXGIAdapter1 **adpter);
+ BOOL IsCurrent();
+}
+
+[local] HRESULT __stdcall CreateDXGIFactory(REFIID riid, void **factory);
+[local] HRESULT __stdcall CreateDXGIFactory1(REFIID riid, void **factory);
diff --git a/dlls/vkd3d/include/vkd3d_dxgi1_2.h b/dlls/vkd3d/include/vkd3d_dxgi1_2.h
new file mode 100644
index 00000000000..cc37ef815b2
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgi1_2.h
@@ -0,0 +1,751 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_dxgi1_2.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_dxgi1_2_h__
+#define __vkd3d_dxgi1_2_h__
+
+/* Forward declarations */
+
+#ifndef __IDXGISwapChain1_FWD_DEFINED__
+#define __IDXGISwapChain1_FWD_DEFINED__
+typedef interface IDXGISwapChain1 IDXGISwapChain1;
+#ifdef __cplusplus
+interface IDXGISwapChain1;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIFactory2_FWD_DEFINED__
+#define __IDXGIFactory2_FWD_DEFINED__
+typedef interface IDXGIFactory2 IDXGIFactory2;
+#ifdef __cplusplus
+interface IDXGIFactory2;
+#endif /* __cplusplus */
+#endif
+
+/* Headers for imported files */
+
+#include <vkd3d_dxgi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum DXGI_SCALING {
+ DXGI_SCALING_STRETCH = 0x0,
+ DXGI_SCALING_NONE = 0x1,
+ DXGI_SCALING_ASPECT_RATIO_STRETCH = 0x2,
+ DXGI_SCALING_FORCE_DWORD = 0xffffffff
+} DXGI_SCALING;
+typedef enum DXGI_ALPHA_MODE {
+ DXGI_ALPHA_MODE_UNSPECIFIED = 0x0,
+ DXGI_ALPHA_MODE_PREMULTIPLIED = 0x1,
+ DXGI_ALPHA_MODE_STRAIGHT = 0x2,
+ DXGI_ALPHA_MODE_IGNORE = 0x3,
+ DXGI_ALPHA_MODE_FORCE_DWORD = 0xffffffff
+} DXGI_ALPHA_MODE;
+typedef struct DXGI_SWAP_CHAIN_DESC1 {
+ UINT Width;
+ UINT Height;
+ DXGI_FORMAT Format;
+ BOOL Stereo;
+ DXGI_SAMPLE_DESC SampleDesc;
+ DXGI_USAGE BufferUsage;
+ UINT BufferCount;
+ DXGI_SCALING Scaling;
+ DXGI_SWAP_EFFECT SwapEffect;
+ DXGI_ALPHA_MODE AlphaMode;
+ UINT Flags;
+} DXGI_SWAP_CHAIN_DESC1;
+typedef struct DXGI_SWAP_CHAIN_FULLSCREEN_DESC DXGI_SWAP_CHAIN_FULLSCREEN_DESC;
+typedef struct DXGI_PRESENT_PARAMETERS DXGI_PRESENT_PARAMETERS;
+/*****************************************************************************
+ * IDXGISwapChain1 interface
+ */
+#ifndef __IDXGISwapChain1_INTERFACE_DEFINED__
+#define __IDXGISwapChain1_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGISwapChain1, 0x790a45f7, 0x0d42, 0x4876, 0x98,0x3a, 0x0a,0x55,0xcf,0xe6,0xf4,0xaa);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("790a45f7-0d42-4876-983a-0a55cfe6f4aa")
+IDXGISwapChain1 : public IDXGISwapChain
+{
+ virtual HRESULT STDMETHODCALLTYPE GetDesc1(
+ DXGI_SWAP_CHAIN_DESC1 *desc) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFullscreenDesc(
+ DXGI_SWAP_CHAIN_FULLSCREEN_DESC *desc) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHwnd(
+ HWND *hwnd) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCoreWindow(
+ REFIID riid,
+ void **object) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Present1(
+ UINT sync_interval,
+ UINT flags,
+ const DXGI_PRESENT_PARAMETERS *parameters) = 0;
+
+ virtual BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetRestrictToOutput(
+ IDXGIOutput **output) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetBackgroundColor(
+ const DXGI_RGBA *color) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBackgroundColor(
+ DXGI_RGBA *color) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetRotation(
+ DXGI_MODE_ROTATION rotation) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetRotation(
+ DXGI_MODE_ROTATION *rotation) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGISwapChain1, 0x790a45f7, 0x0d42, 0x4876, 0x98,0x3a, 0x0a,0x55,0xcf,0xe6,0xf4,0xaa)
+#endif
+#else
+typedef struct IDXGISwapChain1Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGISwapChain1 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGISwapChain1 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGISwapChain1 *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGISwapChain1 *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGISwapChain1 *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGISwapChain1 *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGISwapChain1 *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIDeviceSubObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ IDXGISwapChain1 *This,
+ REFIID riid,
+ void **device);
+
+ /*** IDXGISwapChain methods ***/
+ HRESULT (STDMETHODCALLTYPE *Present)(
+ IDXGISwapChain1 *This,
+ UINT sync_interval,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetBuffer)(
+ IDXGISwapChain1 *This,
+ UINT buffer_idx,
+ REFIID riid,
+ void **surface);
+
+ HRESULT (STDMETHODCALLTYPE *SetFullscreenState)(
+ IDXGISwapChain1 *This,
+ BOOL fullscreen,
+ IDXGIOutput *target);
+
+ HRESULT (STDMETHODCALLTYPE *GetFullscreenState)(
+ IDXGISwapChain1 *This,
+ BOOL *fullscreen,
+ IDXGIOutput **target);
+
+ HRESULT (STDMETHODCALLTYPE *GetDesc)(
+ IDXGISwapChain1 *This,
+ DXGI_SWAP_CHAIN_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeBuffers)(
+ IDXGISwapChain1 *This,
+ UINT buffer_count,
+ UINT width,
+ UINT height,
+ DXGI_FORMAT format,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeTarget)(
+ IDXGISwapChain1 *This,
+ const DXGI_MODE_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetContainingOutput)(
+ IDXGISwapChain1 *This,
+ IDXGIOutput **output);
+
+ HRESULT (STDMETHODCALLTYPE *GetFrameStatistics)(
+ IDXGISwapChain1 *This,
+ DXGI_FRAME_STATISTICS *stats);
+
+ HRESULT (STDMETHODCALLTYPE *GetLastPresentCount)(
+ IDXGISwapChain1 *This,
+ UINT *last_present_count);
+
+ /*** IDXGISwapChain1 methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDesc1)(
+ IDXGISwapChain1 *This,
+ DXGI_SWAP_CHAIN_DESC1 *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetFullscreenDesc)(
+ IDXGISwapChain1 *This,
+ DXGI_SWAP_CHAIN_FULLSCREEN_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetHwnd)(
+ IDXGISwapChain1 *This,
+ HWND *hwnd);
+
+ HRESULT (STDMETHODCALLTYPE *GetCoreWindow)(
+ IDXGISwapChain1 *This,
+ REFIID riid,
+ void **object);
+
+ HRESULT (STDMETHODCALLTYPE *Present1)(
+ IDXGISwapChain1 *This,
+ UINT sync_interval,
+ UINT flags,
+ const DXGI_PRESENT_PARAMETERS *parameters);
+
+ BOOL (STDMETHODCALLTYPE *IsTemporaryMonoSupported)(
+ IDXGISwapChain1 *This);
+
+ HRESULT (STDMETHODCALLTYPE *GetRestrictToOutput)(
+ IDXGISwapChain1 *This,
+ IDXGIOutput **output);
+
+ HRESULT (STDMETHODCALLTYPE *SetBackgroundColor)(
+ IDXGISwapChain1 *This,
+ const DXGI_RGBA *color);
+
+ HRESULT (STDMETHODCALLTYPE *GetBackgroundColor)(
+ IDXGISwapChain1 *This,
+ DXGI_RGBA *color);
+
+ HRESULT (STDMETHODCALLTYPE *SetRotation)(
+ IDXGISwapChain1 *This,
+ DXGI_MODE_ROTATION rotation);
+
+ HRESULT (STDMETHODCALLTYPE *GetRotation)(
+ IDXGISwapChain1 *This,
+ DXGI_MODE_ROTATION *rotation);
+
+ END_INTERFACE
+} IDXGISwapChain1Vtbl;
+
+interface IDXGISwapChain1 {
+ CONST_VTBL IDXGISwapChain1Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGISwapChain1_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGISwapChain1_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGISwapChain1_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGISwapChain1_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGISwapChain1_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGISwapChain1_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGISwapChain1_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIDeviceSubObject methods ***/
+#define IDXGISwapChain1_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** IDXGISwapChain methods ***/
+#define IDXGISwapChain1_Present(This,sync_interval,flags) (This)->lpVtbl->Present(This,sync_interval,flags)
+#define IDXGISwapChain1_GetBuffer(This,buffer_idx,riid,surface) (This)->lpVtbl->GetBuffer(This,buffer_idx,riid,surface)
+#define IDXGISwapChain1_SetFullscreenState(This,fullscreen,target) (This)->lpVtbl->SetFullscreenState(This,fullscreen,target)
+#define IDXGISwapChain1_GetFullscreenState(This,fullscreen,target) (This)->lpVtbl->GetFullscreenState(This,fullscreen,target)
+#define IDXGISwapChain1_GetDesc(This,desc) (This)->lpVtbl->GetDesc(This,desc)
+#define IDXGISwapChain1_ResizeBuffers(This,buffer_count,width,height,format,flags) (This)->lpVtbl->ResizeBuffers(This,buffer_count,width,height,format,flags)
+#define IDXGISwapChain1_ResizeTarget(This,desc) (This)->lpVtbl->ResizeTarget(This,desc)
+#define IDXGISwapChain1_GetContainingOutput(This,output) (This)->lpVtbl->GetContainingOutput(This,output)
+#define IDXGISwapChain1_GetFrameStatistics(This,stats) (This)->lpVtbl->GetFrameStatistics(This,stats)
+#define IDXGISwapChain1_GetLastPresentCount(This,last_present_count) (This)->lpVtbl->GetLastPresentCount(This,last_present_count)
+/*** IDXGISwapChain1 methods ***/
+#define IDXGISwapChain1_GetDesc1(This,desc) (This)->lpVtbl->GetDesc1(This,desc)
+#define IDXGISwapChain1_GetFullscreenDesc(This,desc) (This)->lpVtbl->GetFullscreenDesc(This,desc)
+#define IDXGISwapChain1_GetHwnd(This,hwnd) (This)->lpVtbl->GetHwnd(This,hwnd)
+#define IDXGISwapChain1_GetCoreWindow(This,riid,object) (This)->lpVtbl->GetCoreWindow(This,riid,object)
+#define IDXGISwapChain1_Present1(This,sync_interval,flags,parameters) (This)->lpVtbl->Present1(This,sync_interval,flags,parameters)
+#define IDXGISwapChain1_IsTemporaryMonoSupported(This) (This)->lpVtbl->IsTemporaryMonoSupported(This)
+#define IDXGISwapChain1_GetRestrictToOutput(This,output) (This)->lpVtbl->GetRestrictToOutput(This,output)
+#define IDXGISwapChain1_SetBackgroundColor(This,color) (This)->lpVtbl->SetBackgroundColor(This,color)
+#define IDXGISwapChain1_GetBackgroundColor(This,color) (This)->lpVtbl->GetBackgroundColor(This,color)
+#define IDXGISwapChain1_SetRotation(This,rotation) (This)->lpVtbl->SetRotation(This,rotation)
+#define IDXGISwapChain1_GetRotation(This,rotation) (This)->lpVtbl->GetRotation(This,rotation)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain1_QueryInterface(IDXGISwapChain1* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGISwapChain1_AddRef(IDXGISwapChain1* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGISwapChain1_Release(IDXGISwapChain1* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain1_SetPrivateData(IDXGISwapChain1* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetPrivateDataInterface(IDXGISwapChain1* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetPrivateData(IDXGISwapChain1* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetParent(IDXGISwapChain1* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIDeviceSubObject methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain1_GetDevice(IDXGISwapChain1* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** IDXGISwapChain methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain1_Present(IDXGISwapChain1* This,UINT sync_interval,UINT flags) {
+ return This->lpVtbl->Present(This,sync_interval,flags);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetBuffer(IDXGISwapChain1* This,UINT buffer_idx,REFIID riid,void **surface) {
+ return This->lpVtbl->GetBuffer(This,buffer_idx,riid,surface);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_SetFullscreenState(IDXGISwapChain1* This,BOOL fullscreen,IDXGIOutput *target) {
+ return This->lpVtbl->SetFullscreenState(This,fullscreen,target);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetFullscreenState(IDXGISwapChain1* This,BOOL *fullscreen,IDXGIOutput **target) {
+ return This->lpVtbl->GetFullscreenState(This,fullscreen,target);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetDesc(IDXGISwapChain1* This,DXGI_SWAP_CHAIN_DESC *desc) {
+ return This->lpVtbl->GetDesc(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_ResizeBuffers(IDXGISwapChain1* This,UINT buffer_count,UINT width,UINT height,DXGI_FORMAT format,UINT flags) {
+ return This->lpVtbl->ResizeBuffers(This,buffer_count,width,height,format,flags);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_ResizeTarget(IDXGISwapChain1* This,const DXGI_MODE_DESC *desc) {
+ return This->lpVtbl->ResizeTarget(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetContainingOutput(IDXGISwapChain1* This,IDXGIOutput **output) {
+ return This->lpVtbl->GetContainingOutput(This,output);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetFrameStatistics(IDXGISwapChain1* This,DXGI_FRAME_STATISTICS *stats) {
+ return This->lpVtbl->GetFrameStatistics(This,stats);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetLastPresentCount(IDXGISwapChain1* This,UINT *last_present_count) {
+ return This->lpVtbl->GetLastPresentCount(This,last_present_count);
+}
+/*** IDXGISwapChain1 methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain1_GetDesc1(IDXGISwapChain1* This,DXGI_SWAP_CHAIN_DESC1 *desc) {
+ return This->lpVtbl->GetDesc1(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetFullscreenDesc(IDXGISwapChain1* This,DXGI_SWAP_CHAIN_FULLSCREEN_DESC *desc) {
+ return This->lpVtbl->GetFullscreenDesc(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetHwnd(IDXGISwapChain1* This,HWND *hwnd) {
+ return This->lpVtbl->GetHwnd(This,hwnd);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetCoreWindow(IDXGISwapChain1* This,REFIID riid,void **object) {
+ return This->lpVtbl->GetCoreWindow(This,riid,object);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_Present1(IDXGISwapChain1* This,UINT sync_interval,UINT flags,const DXGI_PRESENT_PARAMETERS *parameters) {
+ return This->lpVtbl->Present1(This,sync_interval,flags,parameters);
+}
+static FORCEINLINE BOOL IDXGISwapChain1_IsTemporaryMonoSupported(IDXGISwapChain1* This) {
+ return This->lpVtbl->IsTemporaryMonoSupported(This);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetRestrictToOutput(IDXGISwapChain1* This,IDXGIOutput **output) {
+ return This->lpVtbl->GetRestrictToOutput(This,output);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_SetBackgroundColor(IDXGISwapChain1* This,const DXGI_RGBA *color) {
+ return This->lpVtbl->SetBackgroundColor(This,color);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetBackgroundColor(IDXGISwapChain1* This,DXGI_RGBA *color) {
+ return This->lpVtbl->GetBackgroundColor(This,color);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_SetRotation(IDXGISwapChain1* This,DXGI_MODE_ROTATION rotation) {
+ return This->lpVtbl->SetRotation(This,rotation);
+}
+static FORCEINLINE HRESULT IDXGISwapChain1_GetRotation(IDXGISwapChain1* This,DXGI_MODE_ROTATION *rotation) {
+ return This->lpVtbl->GetRotation(This,rotation);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGISwapChain1_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGIFactory2 interface
+ */
+#ifndef __IDXGIFactory2_INTERFACE_DEFINED__
+#define __IDXGIFactory2_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIFactory2, 0x50c83a1c, 0xe072, 0x4c48, 0x87,0xb0, 0x36,0x30,0xfa,0x36,0xa6,0xd0);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("50c83a1c-e072-4c48-87b0-3630fa36a6d0")
+IDXGIFactory2 : public IDXGIFactory1
+{
+ virtual BOOL STDMETHODCALLTYPE IsWindowedStereoEnabled(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd(
+ IUnknown *device,
+ HWND window,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForCoreWindow(
+ IUnknown *device,
+ IUnknown *window,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetSharedResourceAdapterLuid(
+ HANDLE resource,
+ LUID *luid) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RegisterStereoStatusWindow(
+ HWND window,
+ UINT msg,
+ DWORD *cookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RegisterStereoStatusEvent(
+ HANDLE event,
+ DWORD *cookie) = 0;
+
+ virtual void STDMETHODCALLTYPE UnregisterStereoStatus(
+ DWORD cookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusWindow(
+ HWND window,
+ UINT msg,
+ DWORD *cookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusEvent(
+ HANDLE event,
+ DWORD *cookie) = 0;
+
+ virtual void STDMETHODCALLTYPE UnregisterOcclusionStatus(
+ DWORD cookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForComposition(
+ IUnknown *device,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIFactory2, 0x50c83a1c, 0xe072, 0x4c48, 0x87,0xb0, 0x36,0x30,0xfa,0x36,0xa6,0xd0)
+#endif
+#else
+typedef struct IDXGIFactory2Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIFactory2 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIFactory2 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIFactory2 *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGIFactory2 *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGIFactory2 *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGIFactory2 *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGIFactory2 *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIFactory methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters)(
+ IDXGIFactory2 *This,
+ UINT adapter_idx,
+ IDXGIAdapter **adapter);
+
+ HRESULT (STDMETHODCALLTYPE *MakeWindowAssociation)(
+ IDXGIFactory2 *This,
+ HWND hwnd,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetWindowAssociation)(
+ IDXGIFactory2 *This,
+ HWND *hwnd);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChain)(
+ IDXGIFactory2 *This,
+ IUnknown *device,
+ DXGI_SWAP_CHAIN_DESC *desc,
+ IDXGISwapChain **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSoftwareAdapter)(
+ IDXGIFactory2 *This,
+ HMODULE hmodule,
+ IDXGIAdapter **adapter);
+
+ /*** IDXGIFactory1 methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters1)(
+ IDXGIFactory2 *This,
+ UINT adapter_idx,
+ IDXGIAdapter1 **adpter);
+
+ BOOL (STDMETHODCALLTYPE *IsCurrent)(
+ IDXGIFactory2 *This);
+
+ /*** IDXGIFactory2 methods ***/
+ BOOL (STDMETHODCALLTYPE *IsWindowedStereoEnabled)(
+ IDXGIFactory2 *This);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForHwnd)(
+ IDXGIFactory2 *This,
+ IUnknown *device,
+ HWND window,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForCoreWindow)(
+ IDXGIFactory2 *This,
+ IUnknown *device,
+ IUnknown *window,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *GetSharedResourceAdapterLuid)(
+ IDXGIFactory2 *This,
+ HANDLE resource,
+ LUID *luid);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterStereoStatusWindow)(
+ IDXGIFactory2 *This,
+ HWND window,
+ UINT msg,
+ DWORD *cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterStereoStatusEvent)(
+ IDXGIFactory2 *This,
+ HANDLE event,
+ DWORD *cookie);
+
+ void (STDMETHODCALLTYPE *UnregisterStereoStatus)(
+ IDXGIFactory2 *This,
+ DWORD cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterOcclusionStatusWindow)(
+ IDXGIFactory2 *This,
+ HWND window,
+ UINT msg,
+ DWORD *cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterOcclusionStatusEvent)(
+ IDXGIFactory2 *This,
+ HANDLE event,
+ DWORD *cookie);
+
+ void (STDMETHODCALLTYPE *UnregisterOcclusionStatus)(
+ IDXGIFactory2 *This,
+ DWORD cookie);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForComposition)(
+ IDXGIFactory2 *This,
+ IUnknown *device,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ END_INTERFACE
+} IDXGIFactory2Vtbl;
+
+interface IDXGIFactory2 {
+ CONST_VTBL IDXGIFactory2Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIFactory2_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGIFactory2_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIFactory2_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGIFactory2_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGIFactory2_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGIFactory2_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGIFactory2_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIFactory methods ***/
+#define IDXGIFactory2_EnumAdapters(This,adapter_idx,adapter) (This)->lpVtbl->EnumAdapters(This,adapter_idx,adapter)
+#define IDXGIFactory2_MakeWindowAssociation(This,hwnd,flags) (This)->lpVtbl->MakeWindowAssociation(This,hwnd,flags)
+#define IDXGIFactory2_GetWindowAssociation(This,hwnd) (This)->lpVtbl->GetWindowAssociation(This,hwnd)
+#define IDXGIFactory2_CreateSwapChain(This,device,desc,swapchain) (This)->lpVtbl->CreateSwapChain(This,device,desc,swapchain)
+#define IDXGIFactory2_CreateSoftwareAdapter(This,hmodule,adapter) (This)->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter)
+/*** IDXGIFactory1 methods ***/
+#define IDXGIFactory2_EnumAdapters1(This,adapter_idx,adpter) (This)->lpVtbl->EnumAdapters1(This,adapter_idx,adpter)
+#define IDXGIFactory2_IsCurrent(This) (This)->lpVtbl->IsCurrent(This)
+/*** IDXGIFactory2 methods ***/
+#define IDXGIFactory2_IsWindowedStereoEnabled(This) (This)->lpVtbl->IsWindowedStereoEnabled(This)
+#define IDXGIFactory2_CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain)
+#define IDXGIFactory2_CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain)
+#define IDXGIFactory2_GetSharedResourceAdapterLuid(This,resource,luid) (This)->lpVtbl->GetSharedResourceAdapterLuid(This,resource,luid)
+#define IDXGIFactory2_RegisterStereoStatusWindow(This,window,msg,cookie) (This)->lpVtbl->RegisterStereoStatusWindow(This,window,msg,cookie)
+#define IDXGIFactory2_RegisterStereoStatusEvent(This,event,cookie) (This)->lpVtbl->RegisterStereoStatusEvent(This,event,cookie)
+#define IDXGIFactory2_UnregisterStereoStatus(This,cookie) (This)->lpVtbl->UnregisterStereoStatus(This,cookie)
+#define IDXGIFactory2_RegisterOcclusionStatusWindow(This,window,msg,cookie) (This)->lpVtbl->RegisterOcclusionStatusWindow(This,window,msg,cookie)
+#define IDXGIFactory2_RegisterOcclusionStatusEvent(This,event,cookie) (This)->lpVtbl->RegisterOcclusionStatusEvent(This,event,cookie)
+#define IDXGIFactory2_UnregisterOcclusionStatus(This,cookie) (This)->lpVtbl->UnregisterOcclusionStatus(This,cookie)
+#define IDXGIFactory2_CreateSwapChainForComposition(This,device,desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForComposition(This,device,desc,output,swapchain)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIFactory2_QueryInterface(IDXGIFactory2* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGIFactory2_AddRef(IDXGIFactory2* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIFactory2_Release(IDXGIFactory2* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGIFactory2_SetPrivateData(IDXGIFactory2* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_GetPrivateDataInterface(IDXGIFactory2* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_GetPrivateData(IDXGIFactory2* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_GetParent(IDXGIFactory2* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIFactory methods ***/
+static FORCEINLINE HRESULT IDXGIFactory2_EnumAdapters(IDXGIFactory2* This,UINT adapter_idx,IDXGIAdapter **adapter) {
+ return This->lpVtbl->EnumAdapters(This,adapter_idx,adapter);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_MakeWindowAssociation(IDXGIFactory2* This,HWND hwnd,UINT flags) {
+ return This->lpVtbl->MakeWindowAssociation(This,hwnd,flags);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_GetWindowAssociation(IDXGIFactory2* This,HWND *hwnd) {
+ return This->lpVtbl->GetWindowAssociation(This,hwnd);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_CreateSwapChain(IDXGIFactory2* This,IUnknown *device,DXGI_SWAP_CHAIN_DESC *desc,IDXGISwapChain **swapchain) {
+ return This->lpVtbl->CreateSwapChain(This,device,desc,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_CreateSoftwareAdapter(IDXGIFactory2* This,HMODULE hmodule,IDXGIAdapter **adapter) {
+ return This->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter);
+}
+/*** IDXGIFactory1 methods ***/
+static FORCEINLINE HRESULT IDXGIFactory2_EnumAdapters1(IDXGIFactory2* This,UINT adapter_idx,IDXGIAdapter1 **adpter) {
+ return This->lpVtbl->EnumAdapters1(This,adapter_idx,adpter);
+}
+static FORCEINLINE BOOL IDXGIFactory2_IsCurrent(IDXGIFactory2* This) {
+ return This->lpVtbl->IsCurrent(This);
+}
+/*** IDXGIFactory2 methods ***/
+static FORCEINLINE BOOL IDXGIFactory2_IsWindowedStereoEnabled(IDXGIFactory2* This) {
+ return This->lpVtbl->IsWindowedStereoEnabled(This);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_CreateSwapChainForHwnd(IDXGIFactory2* This,IUnknown *device,HWND window,const DXGI_SWAP_CHAIN_DESC1 *desc,const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_CreateSwapChainForCoreWindow(IDXGIFactory2* This,IUnknown *device,IUnknown *window,const DXGI_SWAP_CHAIN_DESC1 *desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_GetSharedResourceAdapterLuid(IDXGIFactory2* This,HANDLE resource,LUID *luid) {
+ return This->lpVtbl->GetSharedResourceAdapterLuid(This,resource,luid);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_RegisterStereoStatusWindow(IDXGIFactory2* This,HWND window,UINT msg,DWORD *cookie) {
+ return This->lpVtbl->RegisterStereoStatusWindow(This,window,msg,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_RegisterStereoStatusEvent(IDXGIFactory2* This,HANDLE event,DWORD *cookie) {
+ return This->lpVtbl->RegisterStereoStatusEvent(This,event,cookie);
+}
+static FORCEINLINE void IDXGIFactory2_UnregisterStereoStatus(IDXGIFactory2* This,DWORD cookie) {
+ This->lpVtbl->UnregisterStereoStatus(This,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_RegisterOcclusionStatusWindow(IDXGIFactory2* This,HWND window,UINT msg,DWORD *cookie) {
+ return This->lpVtbl->RegisterOcclusionStatusWindow(This,window,msg,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_RegisterOcclusionStatusEvent(IDXGIFactory2* This,HANDLE event,DWORD *cookie) {
+ return This->lpVtbl->RegisterOcclusionStatusEvent(This,event,cookie);
+}
+static FORCEINLINE void IDXGIFactory2_UnregisterOcclusionStatus(IDXGIFactory2* This,DWORD cookie) {
+ This->lpVtbl->UnregisterOcclusionStatus(This,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory2_CreateSwapChainForComposition(IDXGIFactory2* This,IUnknown *device,const DXGI_SWAP_CHAIN_DESC1 *desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForComposition(This,device,desc,output,swapchain);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIFactory2_INTERFACE_DEFINED__ */
+
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_dxgi1_2_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_dxgi1_2.idl b/dlls/vkd3d/include/vkd3d_dxgi1_2.idl
new file mode 100644
index 00000000000..e7f951ac917
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgi1_2.idl
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ * Copyright 2016 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_dxgi.idl";
+
+typedef enum DXGI_SCALING
+{
+ DXGI_SCALING_STRETCH = 0x0,
+ DXGI_SCALING_NONE = 0x1,
+ DXGI_SCALING_ASPECT_RATIO_STRETCH = 0x2,
+ DXGI_SCALING_FORCE_DWORD = 0xffffffff,
+} DXGI_SCALING;
+
+typedef enum DXGI_ALPHA_MODE
+{
+ DXGI_ALPHA_MODE_UNSPECIFIED = 0x0,
+ DXGI_ALPHA_MODE_PREMULTIPLIED = 0x1,
+ DXGI_ALPHA_MODE_STRAIGHT = 0x2,
+ DXGI_ALPHA_MODE_IGNORE = 0x3,
+ DXGI_ALPHA_MODE_FORCE_DWORD = 0xffffffff,
+} DXGI_ALPHA_MODE;
+
+typedef struct DXGI_SWAP_CHAIN_DESC1
+{
+ UINT Width;
+ UINT Height;
+ DXGI_FORMAT Format;
+ BOOL Stereo;
+ DXGI_SAMPLE_DESC SampleDesc;
+ DXGI_USAGE BufferUsage;
+ UINT BufferCount;
+ DXGI_SCALING Scaling;
+ DXGI_SWAP_EFFECT SwapEffect;
+ DXGI_ALPHA_MODE AlphaMode;
+ UINT Flags;
+} DXGI_SWAP_CHAIN_DESC1;
+
+typedef struct DXGI_SWAP_CHAIN_FULLSCREEN_DESC DXGI_SWAP_CHAIN_FULLSCREEN_DESC;
+typedef struct DXGI_PRESENT_PARAMETERS DXGI_PRESENT_PARAMETERS;
+
+[
+ local,
+ object,
+ uuid(790a45f7-0d42-4876-983a-0a55cfe6f4aa),
+ pointer_default(unique)
+]
+interface IDXGISwapChain1 : IDXGISwapChain
+{
+ HRESULT GetDesc1(DXGI_SWAP_CHAIN_DESC1 *desc);
+ HRESULT GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC *desc);
+ HRESULT GetHwnd(HWND *hwnd);
+ HRESULT GetCoreWindow(REFIID riid, void **object);
+ HRESULT Present1(UINT sync_interval, UINT flags, const DXGI_PRESENT_PARAMETERS *parameters);
+ BOOL IsTemporaryMonoSupported();
+ HRESULT GetRestrictToOutput(IDXGIOutput **output);
+ HRESULT SetBackgroundColor(const DXGI_RGBA *color);
+ HRESULT GetBackgroundColor(DXGI_RGBA *color);
+ HRESULT SetRotation(DXGI_MODE_ROTATION rotation);
+ HRESULT GetRotation(DXGI_MODE_ROTATION *rotation);
+}
+
+[
+ local,
+ object,
+ uuid(50c83a1c-e072-4c48-87b0-3630fa36a6d0),
+ pointer_default(unique)
+]
+interface IDXGIFactory2 : IDXGIFactory1
+{
+ BOOL IsWindowedStereoEnabled();
+ HRESULT CreateSwapChainForHwnd(IUnknown *device, HWND window, const DXGI_SWAP_CHAIN_DESC1 *desc,
+ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc, IDXGIOutput *output, IDXGISwapChain1 **swapchain);
+ HRESULT CreateSwapChainForCoreWindow(IUnknown *device, IUnknown *window, const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output, IDXGISwapChain1 **swapchain);
+ HRESULT GetSharedResourceAdapterLuid(HANDLE resource, LUID *luid);
+ HRESULT RegisterStereoStatusWindow(HWND window, UINT msg, DWORD *cookie);
+ HRESULT RegisterStereoStatusEvent(HANDLE event, DWORD *cookie);
+ void UnregisterStereoStatus(DWORD cookie);
+ HRESULT RegisterOcclusionStatusWindow(HWND window, UINT msg, DWORD *cookie);
+ HRESULT RegisterOcclusionStatusEvent(HANDLE event, DWORD *cookie);
+ void UnregisterOcclusionStatus(DWORD cookie);
+ HRESULT CreateSwapChainForComposition(IUnknown *device, const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output, IDXGISwapChain1 **swapchain);
+}
diff --git a/dlls/vkd3d/include/vkd3d_dxgi1_3.h b/dlls/vkd3d/include/vkd3d_dxgi1_3.h
new file mode 100644
index 00000000000..4dfc91df35d
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgi1_3.h
@@ -0,0 +1,732 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_dxgi1_3.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_dxgi1_3_h__
+#define __vkd3d_dxgi1_3_h__
+
+/* Forward declarations */
+
+#ifndef __IDXGISwapChain2_FWD_DEFINED__
+#define __IDXGISwapChain2_FWD_DEFINED__
+typedef interface IDXGISwapChain2 IDXGISwapChain2;
+#ifdef __cplusplus
+interface IDXGISwapChain2;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIFactory3_FWD_DEFINED__
+#define __IDXGIFactory3_FWD_DEFINED__
+typedef interface IDXGIFactory3 IDXGIFactory3;
+#ifdef __cplusplus
+interface IDXGIFactory3;
+#endif /* __cplusplus */
+#endif
+
+/* Headers for imported files */
+
+#include <vkd3d_dxgi1_2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DXGI_MATRIX_3X2_F DXGI_MATRIX_3X2_F;
+/*****************************************************************************
+ * IDXGISwapChain2 interface
+ */
+#ifndef __IDXGISwapChain2_INTERFACE_DEFINED__
+#define __IDXGISwapChain2_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGISwapChain2, 0xa8be2ac4, 0x199f, 0x4946, 0xb3,0x31, 0x79,0x59,0x9f,0xb9,0x8d,0xe7);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("a8be2ac4-199f-4946-b331-79599fb98de7")
+IDXGISwapChain2 : public IDXGISwapChain1
+{
+ virtual HRESULT STDMETHODCALLTYPE SetSourceSize(
+ UINT width,
+ UINT height) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetSourceSize(
+ UINT *width,
+ UINT *height) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(
+ UINT latency) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(
+ UINT *latency) = 0;
+
+ virtual HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetMatrixTransform(
+ const DXGI_MATRIX_3X2_F *matrix) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetMatrixTransform(
+ DXGI_MATRIX_3X2_F *matrix) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGISwapChain2, 0xa8be2ac4, 0x199f, 0x4946, 0xb3,0x31, 0x79,0x59,0x9f,0xb9,0x8d,0xe7)
+#endif
+#else
+typedef struct IDXGISwapChain2Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGISwapChain2 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGISwapChain2 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGISwapChain2 *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGISwapChain2 *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGISwapChain2 *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGISwapChain2 *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGISwapChain2 *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIDeviceSubObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ IDXGISwapChain2 *This,
+ REFIID riid,
+ void **device);
+
+ /*** IDXGISwapChain methods ***/
+ HRESULT (STDMETHODCALLTYPE *Present)(
+ IDXGISwapChain2 *This,
+ UINT sync_interval,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetBuffer)(
+ IDXGISwapChain2 *This,
+ UINT buffer_idx,
+ REFIID riid,
+ void **surface);
+
+ HRESULT (STDMETHODCALLTYPE *SetFullscreenState)(
+ IDXGISwapChain2 *This,
+ BOOL fullscreen,
+ IDXGIOutput *target);
+
+ HRESULT (STDMETHODCALLTYPE *GetFullscreenState)(
+ IDXGISwapChain2 *This,
+ BOOL *fullscreen,
+ IDXGIOutput **target);
+
+ HRESULT (STDMETHODCALLTYPE *GetDesc)(
+ IDXGISwapChain2 *This,
+ DXGI_SWAP_CHAIN_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeBuffers)(
+ IDXGISwapChain2 *This,
+ UINT buffer_count,
+ UINT width,
+ UINT height,
+ DXGI_FORMAT format,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeTarget)(
+ IDXGISwapChain2 *This,
+ const DXGI_MODE_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetContainingOutput)(
+ IDXGISwapChain2 *This,
+ IDXGIOutput **output);
+
+ HRESULT (STDMETHODCALLTYPE *GetFrameStatistics)(
+ IDXGISwapChain2 *This,
+ DXGI_FRAME_STATISTICS *stats);
+
+ HRESULT (STDMETHODCALLTYPE *GetLastPresentCount)(
+ IDXGISwapChain2 *This,
+ UINT *last_present_count);
+
+ /*** IDXGISwapChain1 methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDesc1)(
+ IDXGISwapChain2 *This,
+ DXGI_SWAP_CHAIN_DESC1 *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetFullscreenDesc)(
+ IDXGISwapChain2 *This,
+ DXGI_SWAP_CHAIN_FULLSCREEN_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetHwnd)(
+ IDXGISwapChain2 *This,
+ HWND *hwnd);
+
+ HRESULT (STDMETHODCALLTYPE *GetCoreWindow)(
+ IDXGISwapChain2 *This,
+ REFIID riid,
+ void **object);
+
+ HRESULT (STDMETHODCALLTYPE *Present1)(
+ IDXGISwapChain2 *This,
+ UINT sync_interval,
+ UINT flags,
+ const DXGI_PRESENT_PARAMETERS *parameters);
+
+ BOOL (STDMETHODCALLTYPE *IsTemporaryMonoSupported)(
+ IDXGISwapChain2 *This);
+
+ HRESULT (STDMETHODCALLTYPE *GetRestrictToOutput)(
+ IDXGISwapChain2 *This,
+ IDXGIOutput **output);
+
+ HRESULT (STDMETHODCALLTYPE *SetBackgroundColor)(
+ IDXGISwapChain2 *This,
+ const DXGI_RGBA *color);
+
+ HRESULT (STDMETHODCALLTYPE *GetBackgroundColor)(
+ IDXGISwapChain2 *This,
+ DXGI_RGBA *color);
+
+ HRESULT (STDMETHODCALLTYPE *SetRotation)(
+ IDXGISwapChain2 *This,
+ DXGI_MODE_ROTATION rotation);
+
+ HRESULT (STDMETHODCALLTYPE *GetRotation)(
+ IDXGISwapChain2 *This,
+ DXGI_MODE_ROTATION *rotation);
+
+ /*** IDXGISwapChain2 methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetSourceSize)(
+ IDXGISwapChain2 *This,
+ UINT width,
+ UINT height);
+
+ HRESULT (STDMETHODCALLTYPE *GetSourceSize)(
+ IDXGISwapChain2 *This,
+ UINT *width,
+ UINT *height);
+
+ HRESULT (STDMETHODCALLTYPE *SetMaximumFrameLatency)(
+ IDXGISwapChain2 *This,
+ UINT latency);
+
+ HRESULT (STDMETHODCALLTYPE *GetMaximumFrameLatency)(
+ IDXGISwapChain2 *This,
+ UINT *latency);
+
+ HANDLE (STDMETHODCALLTYPE *GetFrameLatencyWaitableObject)(
+ IDXGISwapChain2 *This);
+
+ HRESULT (STDMETHODCALLTYPE *SetMatrixTransform)(
+ IDXGISwapChain2 *This,
+ const DXGI_MATRIX_3X2_F *matrix);
+
+ HRESULT (STDMETHODCALLTYPE *GetMatrixTransform)(
+ IDXGISwapChain2 *This,
+ DXGI_MATRIX_3X2_F *matrix);
+
+ END_INTERFACE
+} IDXGISwapChain2Vtbl;
+
+interface IDXGISwapChain2 {
+ CONST_VTBL IDXGISwapChain2Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGISwapChain2_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGISwapChain2_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGISwapChain2_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGISwapChain2_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGISwapChain2_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGISwapChain2_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGISwapChain2_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIDeviceSubObject methods ***/
+#define IDXGISwapChain2_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** IDXGISwapChain methods ***/
+#define IDXGISwapChain2_Present(This,sync_interval,flags) (This)->lpVtbl->Present(This,sync_interval,flags)
+#define IDXGISwapChain2_GetBuffer(This,buffer_idx,riid,surface) (This)->lpVtbl->GetBuffer(This,buffer_idx,riid,surface)
+#define IDXGISwapChain2_SetFullscreenState(This,fullscreen,target) (This)->lpVtbl->SetFullscreenState(This,fullscreen,target)
+#define IDXGISwapChain2_GetFullscreenState(This,fullscreen,target) (This)->lpVtbl->GetFullscreenState(This,fullscreen,target)
+#define IDXGISwapChain2_GetDesc(This,desc) (This)->lpVtbl->GetDesc(This,desc)
+#define IDXGISwapChain2_ResizeBuffers(This,buffer_count,width,height,format,flags) (This)->lpVtbl->ResizeBuffers(This,buffer_count,width,height,format,flags)
+#define IDXGISwapChain2_ResizeTarget(This,desc) (This)->lpVtbl->ResizeTarget(This,desc)
+#define IDXGISwapChain2_GetContainingOutput(This,output) (This)->lpVtbl->GetContainingOutput(This,output)
+#define IDXGISwapChain2_GetFrameStatistics(This,stats) (This)->lpVtbl->GetFrameStatistics(This,stats)
+#define IDXGISwapChain2_GetLastPresentCount(This,last_present_count) (This)->lpVtbl->GetLastPresentCount(This,last_present_count)
+/*** IDXGISwapChain1 methods ***/
+#define IDXGISwapChain2_GetDesc1(This,desc) (This)->lpVtbl->GetDesc1(This,desc)
+#define IDXGISwapChain2_GetFullscreenDesc(This,desc) (This)->lpVtbl->GetFullscreenDesc(This,desc)
+#define IDXGISwapChain2_GetHwnd(This,hwnd) (This)->lpVtbl->GetHwnd(This,hwnd)
+#define IDXGISwapChain2_GetCoreWindow(This,riid,object) (This)->lpVtbl->GetCoreWindow(This,riid,object)
+#define IDXGISwapChain2_Present1(This,sync_interval,flags,parameters) (This)->lpVtbl->Present1(This,sync_interval,flags,parameters)
+#define IDXGISwapChain2_IsTemporaryMonoSupported(This) (This)->lpVtbl->IsTemporaryMonoSupported(This)
+#define IDXGISwapChain2_GetRestrictToOutput(This,output) (This)->lpVtbl->GetRestrictToOutput(This,output)
+#define IDXGISwapChain2_SetBackgroundColor(This,color) (This)->lpVtbl->SetBackgroundColor(This,color)
+#define IDXGISwapChain2_GetBackgroundColor(This,color) (This)->lpVtbl->GetBackgroundColor(This,color)
+#define IDXGISwapChain2_SetRotation(This,rotation) (This)->lpVtbl->SetRotation(This,rotation)
+#define IDXGISwapChain2_GetRotation(This,rotation) (This)->lpVtbl->GetRotation(This,rotation)
+/*** IDXGISwapChain2 methods ***/
+#define IDXGISwapChain2_SetSourceSize(This,width,height) (This)->lpVtbl->SetSourceSize(This,width,height)
+#define IDXGISwapChain2_GetSourceSize(This,width,height) (This)->lpVtbl->GetSourceSize(This,width,height)
+#define IDXGISwapChain2_SetMaximumFrameLatency(This,latency) (This)->lpVtbl->SetMaximumFrameLatency(This,latency)
+#define IDXGISwapChain2_GetMaximumFrameLatency(This,latency) (This)->lpVtbl->GetMaximumFrameLatency(This,latency)
+#define IDXGISwapChain2_GetFrameLatencyWaitableObject(This) (This)->lpVtbl->GetFrameLatencyWaitableObject(This)
+#define IDXGISwapChain2_SetMatrixTransform(This,matrix) (This)->lpVtbl->SetMatrixTransform(This,matrix)
+#define IDXGISwapChain2_GetMatrixTransform(This,matrix) (This)->lpVtbl->GetMatrixTransform(This,matrix)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain2_QueryInterface(IDXGISwapChain2* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGISwapChain2_AddRef(IDXGISwapChain2* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGISwapChain2_Release(IDXGISwapChain2* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain2_SetPrivateData(IDXGISwapChain2* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetPrivateDataInterface(IDXGISwapChain2* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetPrivateData(IDXGISwapChain2* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetParent(IDXGISwapChain2* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIDeviceSubObject methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain2_GetDevice(IDXGISwapChain2* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** IDXGISwapChain methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain2_Present(IDXGISwapChain2* This,UINT sync_interval,UINT flags) {
+ return This->lpVtbl->Present(This,sync_interval,flags);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetBuffer(IDXGISwapChain2* This,UINT buffer_idx,REFIID riid,void **surface) {
+ return This->lpVtbl->GetBuffer(This,buffer_idx,riid,surface);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_SetFullscreenState(IDXGISwapChain2* This,BOOL fullscreen,IDXGIOutput *target) {
+ return This->lpVtbl->SetFullscreenState(This,fullscreen,target);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetFullscreenState(IDXGISwapChain2* This,BOOL *fullscreen,IDXGIOutput **target) {
+ return This->lpVtbl->GetFullscreenState(This,fullscreen,target);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetDesc(IDXGISwapChain2* This,DXGI_SWAP_CHAIN_DESC *desc) {
+ return This->lpVtbl->GetDesc(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_ResizeBuffers(IDXGISwapChain2* This,UINT buffer_count,UINT width,UINT height,DXGI_FORMAT format,UINT flags) {
+ return This->lpVtbl->ResizeBuffers(This,buffer_count,width,height,format,flags);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_ResizeTarget(IDXGISwapChain2* This,const DXGI_MODE_DESC *desc) {
+ return This->lpVtbl->ResizeTarget(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetContainingOutput(IDXGISwapChain2* This,IDXGIOutput **output) {
+ return This->lpVtbl->GetContainingOutput(This,output);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetFrameStatistics(IDXGISwapChain2* This,DXGI_FRAME_STATISTICS *stats) {
+ return This->lpVtbl->GetFrameStatistics(This,stats);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetLastPresentCount(IDXGISwapChain2* This,UINT *last_present_count) {
+ return This->lpVtbl->GetLastPresentCount(This,last_present_count);
+}
+/*** IDXGISwapChain1 methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain2_GetDesc1(IDXGISwapChain2* This,DXGI_SWAP_CHAIN_DESC1 *desc) {
+ return This->lpVtbl->GetDesc1(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetFullscreenDesc(IDXGISwapChain2* This,DXGI_SWAP_CHAIN_FULLSCREEN_DESC *desc) {
+ return This->lpVtbl->GetFullscreenDesc(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetHwnd(IDXGISwapChain2* This,HWND *hwnd) {
+ return This->lpVtbl->GetHwnd(This,hwnd);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetCoreWindow(IDXGISwapChain2* This,REFIID riid,void **object) {
+ return This->lpVtbl->GetCoreWindow(This,riid,object);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_Present1(IDXGISwapChain2* This,UINT sync_interval,UINT flags,const DXGI_PRESENT_PARAMETERS *parameters) {
+ return This->lpVtbl->Present1(This,sync_interval,flags,parameters);
+}
+static FORCEINLINE BOOL IDXGISwapChain2_IsTemporaryMonoSupported(IDXGISwapChain2* This) {
+ return This->lpVtbl->IsTemporaryMonoSupported(This);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetRestrictToOutput(IDXGISwapChain2* This,IDXGIOutput **output) {
+ return This->lpVtbl->GetRestrictToOutput(This,output);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_SetBackgroundColor(IDXGISwapChain2* This,const DXGI_RGBA *color) {
+ return This->lpVtbl->SetBackgroundColor(This,color);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetBackgroundColor(IDXGISwapChain2* This,DXGI_RGBA *color) {
+ return This->lpVtbl->GetBackgroundColor(This,color);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_SetRotation(IDXGISwapChain2* This,DXGI_MODE_ROTATION rotation) {
+ return This->lpVtbl->SetRotation(This,rotation);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetRotation(IDXGISwapChain2* This,DXGI_MODE_ROTATION *rotation) {
+ return This->lpVtbl->GetRotation(This,rotation);
+}
+/*** IDXGISwapChain2 methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain2_SetSourceSize(IDXGISwapChain2* This,UINT width,UINT height) {
+ return This->lpVtbl->SetSourceSize(This,width,height);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetSourceSize(IDXGISwapChain2* This,UINT *width,UINT *height) {
+ return This->lpVtbl->GetSourceSize(This,width,height);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_SetMaximumFrameLatency(IDXGISwapChain2* This,UINT latency) {
+ return This->lpVtbl->SetMaximumFrameLatency(This,latency);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetMaximumFrameLatency(IDXGISwapChain2* This,UINT *latency) {
+ return This->lpVtbl->GetMaximumFrameLatency(This,latency);
+}
+static FORCEINLINE HANDLE IDXGISwapChain2_GetFrameLatencyWaitableObject(IDXGISwapChain2* This) {
+ return This->lpVtbl->GetFrameLatencyWaitableObject(This);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_SetMatrixTransform(IDXGISwapChain2* This,const DXGI_MATRIX_3X2_F *matrix) {
+ return This->lpVtbl->SetMatrixTransform(This,matrix);
+}
+static FORCEINLINE HRESULT IDXGISwapChain2_GetMatrixTransform(IDXGISwapChain2* This,DXGI_MATRIX_3X2_F *matrix) {
+ return This->lpVtbl->GetMatrixTransform(This,matrix);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGISwapChain2_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGIFactory3 interface
+ */
+#ifndef __IDXGIFactory3_INTERFACE_DEFINED__
+#define __IDXGIFactory3_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIFactory3, 0x25483823, 0xcd46, 0x4c7d, 0x86,0xca, 0x47,0xaa,0x95,0xb8,0x37,0xbd);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("25483823-cd46-4c7d-86ca-47aa95b837bd")
+IDXGIFactory3 : public IDXGIFactory2
+{
+ virtual UINT STDMETHODCALLTYPE GetCreationFlags(
+ ) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIFactory3, 0x25483823, 0xcd46, 0x4c7d, 0x86,0xca, 0x47,0xaa,0x95,0xb8,0x37,0xbd)
+#endif
+#else
+typedef struct IDXGIFactory3Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIFactory3 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIFactory3 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIFactory3 *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGIFactory3 *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGIFactory3 *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGIFactory3 *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGIFactory3 *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIFactory methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters)(
+ IDXGIFactory3 *This,
+ UINT adapter_idx,
+ IDXGIAdapter **adapter);
+
+ HRESULT (STDMETHODCALLTYPE *MakeWindowAssociation)(
+ IDXGIFactory3 *This,
+ HWND hwnd,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetWindowAssociation)(
+ IDXGIFactory3 *This,
+ HWND *hwnd);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChain)(
+ IDXGIFactory3 *This,
+ IUnknown *device,
+ DXGI_SWAP_CHAIN_DESC *desc,
+ IDXGISwapChain **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSoftwareAdapter)(
+ IDXGIFactory3 *This,
+ HMODULE hmodule,
+ IDXGIAdapter **adapter);
+
+ /*** IDXGIFactory1 methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters1)(
+ IDXGIFactory3 *This,
+ UINT adapter_idx,
+ IDXGIAdapter1 **adpter);
+
+ BOOL (STDMETHODCALLTYPE *IsCurrent)(
+ IDXGIFactory3 *This);
+
+ /*** IDXGIFactory2 methods ***/
+ BOOL (STDMETHODCALLTYPE *IsWindowedStereoEnabled)(
+ IDXGIFactory3 *This);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForHwnd)(
+ IDXGIFactory3 *This,
+ IUnknown *device,
+ HWND window,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForCoreWindow)(
+ IDXGIFactory3 *This,
+ IUnknown *device,
+ IUnknown *window,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *GetSharedResourceAdapterLuid)(
+ IDXGIFactory3 *This,
+ HANDLE resource,
+ LUID *luid);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterStereoStatusWindow)(
+ IDXGIFactory3 *This,
+ HWND window,
+ UINT msg,
+ DWORD *cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterStereoStatusEvent)(
+ IDXGIFactory3 *This,
+ HANDLE event,
+ DWORD *cookie);
+
+ void (STDMETHODCALLTYPE *UnregisterStereoStatus)(
+ IDXGIFactory3 *This,
+ DWORD cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterOcclusionStatusWindow)(
+ IDXGIFactory3 *This,
+ HWND window,
+ UINT msg,
+ DWORD *cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterOcclusionStatusEvent)(
+ IDXGIFactory3 *This,
+ HANDLE event,
+ DWORD *cookie);
+
+ void (STDMETHODCALLTYPE *UnregisterOcclusionStatus)(
+ IDXGIFactory3 *This,
+ DWORD cookie);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForComposition)(
+ IDXGIFactory3 *This,
+ IUnknown *device,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ /*** IDXGIFactory3 methods ***/
+ UINT (STDMETHODCALLTYPE *GetCreationFlags)(
+ IDXGIFactory3 *This);
+
+ END_INTERFACE
+} IDXGIFactory3Vtbl;
+
+interface IDXGIFactory3 {
+ CONST_VTBL IDXGIFactory3Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIFactory3_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGIFactory3_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIFactory3_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGIFactory3_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGIFactory3_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGIFactory3_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGIFactory3_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIFactory methods ***/
+#define IDXGIFactory3_EnumAdapters(This,adapter_idx,adapter) (This)->lpVtbl->EnumAdapters(This,adapter_idx,adapter)
+#define IDXGIFactory3_MakeWindowAssociation(This,hwnd,flags) (This)->lpVtbl->MakeWindowAssociation(This,hwnd,flags)
+#define IDXGIFactory3_GetWindowAssociation(This,hwnd) (This)->lpVtbl->GetWindowAssociation(This,hwnd)
+#define IDXGIFactory3_CreateSwapChain(This,device,desc,swapchain) (This)->lpVtbl->CreateSwapChain(This,device,desc,swapchain)
+#define IDXGIFactory3_CreateSoftwareAdapter(This,hmodule,adapter) (This)->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter)
+/*** IDXGIFactory1 methods ***/
+#define IDXGIFactory3_EnumAdapters1(This,adapter_idx,adpter) (This)->lpVtbl->EnumAdapters1(This,adapter_idx,adpter)
+#define IDXGIFactory3_IsCurrent(This) (This)->lpVtbl->IsCurrent(This)
+/*** IDXGIFactory2 methods ***/
+#define IDXGIFactory3_IsWindowedStereoEnabled(This) (This)->lpVtbl->IsWindowedStereoEnabled(This)
+#define IDXGIFactory3_CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain)
+#define IDXGIFactory3_CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain)
+#define IDXGIFactory3_GetSharedResourceAdapterLuid(This,resource,luid) (This)->lpVtbl->GetSharedResourceAdapterLuid(This,resource,luid)
+#define IDXGIFactory3_RegisterStereoStatusWindow(This,window,msg,cookie) (This)->lpVtbl->RegisterStereoStatusWindow(This,window,msg,cookie)
+#define IDXGIFactory3_RegisterStereoStatusEvent(This,event,cookie) (This)->lpVtbl->RegisterStereoStatusEvent(This,event,cookie)
+#define IDXGIFactory3_UnregisterStereoStatus(This,cookie) (This)->lpVtbl->UnregisterStereoStatus(This,cookie)
+#define IDXGIFactory3_RegisterOcclusionStatusWindow(This,window,msg,cookie) (This)->lpVtbl->RegisterOcclusionStatusWindow(This,window,msg,cookie)
+#define IDXGIFactory3_RegisterOcclusionStatusEvent(This,event,cookie) (This)->lpVtbl->RegisterOcclusionStatusEvent(This,event,cookie)
+#define IDXGIFactory3_UnregisterOcclusionStatus(This,cookie) (This)->lpVtbl->UnregisterOcclusionStatus(This,cookie)
+#define IDXGIFactory3_CreateSwapChainForComposition(This,device,desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForComposition(This,device,desc,output,swapchain)
+/*** IDXGIFactory3 methods ***/
+#define IDXGIFactory3_GetCreationFlags(This) (This)->lpVtbl->GetCreationFlags(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIFactory3_QueryInterface(IDXGIFactory3* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGIFactory3_AddRef(IDXGIFactory3* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIFactory3_Release(IDXGIFactory3* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGIFactory3_SetPrivateData(IDXGIFactory3* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_GetPrivateDataInterface(IDXGIFactory3* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_GetPrivateData(IDXGIFactory3* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_GetParent(IDXGIFactory3* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIFactory methods ***/
+static FORCEINLINE HRESULT IDXGIFactory3_EnumAdapters(IDXGIFactory3* This,UINT adapter_idx,IDXGIAdapter **adapter) {
+ return This->lpVtbl->EnumAdapters(This,adapter_idx,adapter);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_MakeWindowAssociation(IDXGIFactory3* This,HWND hwnd,UINT flags) {
+ return This->lpVtbl->MakeWindowAssociation(This,hwnd,flags);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_GetWindowAssociation(IDXGIFactory3* This,HWND *hwnd) {
+ return This->lpVtbl->GetWindowAssociation(This,hwnd);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_CreateSwapChain(IDXGIFactory3* This,IUnknown *device,DXGI_SWAP_CHAIN_DESC *desc,IDXGISwapChain **swapchain) {
+ return This->lpVtbl->CreateSwapChain(This,device,desc,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_CreateSoftwareAdapter(IDXGIFactory3* This,HMODULE hmodule,IDXGIAdapter **adapter) {
+ return This->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter);
+}
+/*** IDXGIFactory1 methods ***/
+static FORCEINLINE HRESULT IDXGIFactory3_EnumAdapters1(IDXGIFactory3* This,UINT adapter_idx,IDXGIAdapter1 **adpter) {
+ return This->lpVtbl->EnumAdapters1(This,adapter_idx,adpter);
+}
+static FORCEINLINE BOOL IDXGIFactory3_IsCurrent(IDXGIFactory3* This) {
+ return This->lpVtbl->IsCurrent(This);
+}
+/*** IDXGIFactory2 methods ***/
+static FORCEINLINE BOOL IDXGIFactory3_IsWindowedStereoEnabled(IDXGIFactory3* This) {
+ return This->lpVtbl->IsWindowedStereoEnabled(This);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_CreateSwapChainForHwnd(IDXGIFactory3* This,IUnknown *device,HWND window,const DXGI_SWAP_CHAIN_DESC1 *desc,const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_CreateSwapChainForCoreWindow(IDXGIFactory3* This,IUnknown *device,IUnknown *window,const DXGI_SWAP_CHAIN_DESC1 *desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_GetSharedResourceAdapterLuid(IDXGIFactory3* This,HANDLE resource,LUID *luid) {
+ return This->lpVtbl->GetSharedResourceAdapterLuid(This,resource,luid);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_RegisterStereoStatusWindow(IDXGIFactory3* This,HWND window,UINT msg,DWORD *cookie) {
+ return This->lpVtbl->RegisterStereoStatusWindow(This,window,msg,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_RegisterStereoStatusEvent(IDXGIFactory3* This,HANDLE event,DWORD *cookie) {
+ return This->lpVtbl->RegisterStereoStatusEvent(This,event,cookie);
+}
+static FORCEINLINE void IDXGIFactory3_UnregisterStereoStatus(IDXGIFactory3* This,DWORD cookie) {
+ This->lpVtbl->UnregisterStereoStatus(This,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_RegisterOcclusionStatusWindow(IDXGIFactory3* This,HWND window,UINT msg,DWORD *cookie) {
+ return This->lpVtbl->RegisterOcclusionStatusWindow(This,window,msg,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_RegisterOcclusionStatusEvent(IDXGIFactory3* This,HANDLE event,DWORD *cookie) {
+ return This->lpVtbl->RegisterOcclusionStatusEvent(This,event,cookie);
+}
+static FORCEINLINE void IDXGIFactory3_UnregisterOcclusionStatus(IDXGIFactory3* This,DWORD cookie) {
+ This->lpVtbl->UnregisterOcclusionStatus(This,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory3_CreateSwapChainForComposition(IDXGIFactory3* This,IUnknown *device,const DXGI_SWAP_CHAIN_DESC1 *desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForComposition(This,device,desc,output,swapchain);
+}
+/*** IDXGIFactory3 methods ***/
+static FORCEINLINE UINT IDXGIFactory3_GetCreationFlags(IDXGIFactory3* This) {
+ return This->lpVtbl->GetCreationFlags(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIFactory3_INTERFACE_DEFINED__ */
+
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_dxgi1_3_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_dxgi1_3.idl b/dlls/vkd3d/include/vkd3d_dxgi1_3.idl
new file mode 100644
index 00000000000..88ac0a34f70
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgi1_3.idl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ * Copyright 2016 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_dxgi1_2.idl";
+
+typedef struct DXGI_MATRIX_3X2_F DXGI_MATRIX_3X2_F;
+
+[
+ local,
+ object,
+ uuid(a8be2ac4-199f-4946-b331-79599fb98de7),
+ pointer_default(unique)
+]
+interface IDXGISwapChain2 : IDXGISwapChain1
+{
+ HRESULT SetSourceSize(UINT width, UINT height);
+ HRESULT GetSourceSize(UINT *width, UINT *height);
+ HRESULT SetMaximumFrameLatency(UINT latency);
+ HRESULT GetMaximumFrameLatency(UINT *latency);
+ HANDLE GetFrameLatencyWaitableObject();
+ HRESULT SetMatrixTransform(const DXGI_MATRIX_3X2_F *matrix);
+ HRESULT GetMatrixTransform(DXGI_MATRIX_3X2_F *matrix);
+}
+
+[
+ local,
+ object,
+ uuid(25483823-cd46-4c7d-86ca-47aa95b837bd),
+ pointer_default(unique)
+]
+interface IDXGIFactory3 : IDXGIFactory2
+{
+ UINT GetCreationFlags();
+}
diff --git a/dlls/vkd3d/include/vkd3d_dxgi1_4.h b/dlls/vkd3d/include/vkd3d_dxgi1_4.h
new file mode 100644
index 00000000000..eaa2b94b12f
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgi1_4.h
@@ -0,0 +1,796 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_dxgi1_4.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_dxgi1_4_h__
+#define __vkd3d_dxgi1_4_h__
+
+/* Forward declarations */
+
+#ifndef __IDXGISwapChain3_FWD_DEFINED__
+#define __IDXGISwapChain3_FWD_DEFINED__
+typedef interface IDXGISwapChain3 IDXGISwapChain3;
+#ifdef __cplusplus
+interface IDXGISwapChain3;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIFactory4_FWD_DEFINED__
+#define __IDXGIFactory4_FWD_DEFINED__
+typedef interface IDXGIFactory4 IDXGIFactory4;
+#ifdef __cplusplus
+interface IDXGIFactory4;
+#endif /* __cplusplus */
+#endif
+
+/* Headers for imported files */
+
+#include <vkd3d_dxgi1_3.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************
+ * IDXGISwapChain3 interface
+ */
+#ifndef __IDXGISwapChain3_INTERFACE_DEFINED__
+#define __IDXGISwapChain3_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGISwapChain3, 0x94d99bdb, 0xf1f8, 0x4ab0, 0xb2,0x36, 0x7d,0xa0,0x17,0x0e,0xda,0xb1);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("94d99bdb-f1f8-4ab0-b236-7da0170edab1")
+IDXGISwapChain3 : public IDXGISwapChain2
+{
+ virtual UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex(
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport(
+ DXGI_COLOR_SPACE_TYPE type,
+ UINT *support) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetColorSpace1(
+ DXGI_COLOR_SPACE_TYPE type) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ResizeBuffers1(
+ UINT buffer_count,
+ UINT width,
+ UINT height,
+ DXGI_FORMAT format,
+ UINT flags,
+ const UINT *node_mask,
+ IUnknown *const *present_queue) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGISwapChain3, 0x94d99bdb, 0xf1f8, 0x4ab0, 0xb2,0x36, 0x7d,0xa0,0x17,0x0e,0xda,0xb1)
+#endif
+#else
+typedef struct IDXGISwapChain3Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGISwapChain3 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGISwapChain3 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGISwapChain3 *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGISwapChain3 *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGISwapChain3 *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGISwapChain3 *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGISwapChain3 *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIDeviceSubObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ IDXGISwapChain3 *This,
+ REFIID riid,
+ void **device);
+
+ /*** IDXGISwapChain methods ***/
+ HRESULT (STDMETHODCALLTYPE *Present)(
+ IDXGISwapChain3 *This,
+ UINT sync_interval,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetBuffer)(
+ IDXGISwapChain3 *This,
+ UINT buffer_idx,
+ REFIID riid,
+ void **surface);
+
+ HRESULT (STDMETHODCALLTYPE *SetFullscreenState)(
+ IDXGISwapChain3 *This,
+ BOOL fullscreen,
+ IDXGIOutput *target);
+
+ HRESULT (STDMETHODCALLTYPE *GetFullscreenState)(
+ IDXGISwapChain3 *This,
+ BOOL *fullscreen,
+ IDXGIOutput **target);
+
+ HRESULT (STDMETHODCALLTYPE *GetDesc)(
+ IDXGISwapChain3 *This,
+ DXGI_SWAP_CHAIN_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeBuffers)(
+ IDXGISwapChain3 *This,
+ UINT buffer_count,
+ UINT width,
+ UINT height,
+ DXGI_FORMAT format,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeTarget)(
+ IDXGISwapChain3 *This,
+ const DXGI_MODE_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetContainingOutput)(
+ IDXGISwapChain3 *This,
+ IDXGIOutput **output);
+
+ HRESULT (STDMETHODCALLTYPE *GetFrameStatistics)(
+ IDXGISwapChain3 *This,
+ DXGI_FRAME_STATISTICS *stats);
+
+ HRESULT (STDMETHODCALLTYPE *GetLastPresentCount)(
+ IDXGISwapChain3 *This,
+ UINT *last_present_count);
+
+ /*** IDXGISwapChain1 methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDesc1)(
+ IDXGISwapChain3 *This,
+ DXGI_SWAP_CHAIN_DESC1 *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetFullscreenDesc)(
+ IDXGISwapChain3 *This,
+ DXGI_SWAP_CHAIN_FULLSCREEN_DESC *desc);
+
+ HRESULT (STDMETHODCALLTYPE *GetHwnd)(
+ IDXGISwapChain3 *This,
+ HWND *hwnd);
+
+ HRESULT (STDMETHODCALLTYPE *GetCoreWindow)(
+ IDXGISwapChain3 *This,
+ REFIID riid,
+ void **object);
+
+ HRESULT (STDMETHODCALLTYPE *Present1)(
+ IDXGISwapChain3 *This,
+ UINT sync_interval,
+ UINT flags,
+ const DXGI_PRESENT_PARAMETERS *parameters);
+
+ BOOL (STDMETHODCALLTYPE *IsTemporaryMonoSupported)(
+ IDXGISwapChain3 *This);
+
+ HRESULT (STDMETHODCALLTYPE *GetRestrictToOutput)(
+ IDXGISwapChain3 *This,
+ IDXGIOutput **output);
+
+ HRESULT (STDMETHODCALLTYPE *SetBackgroundColor)(
+ IDXGISwapChain3 *This,
+ const DXGI_RGBA *color);
+
+ HRESULT (STDMETHODCALLTYPE *GetBackgroundColor)(
+ IDXGISwapChain3 *This,
+ DXGI_RGBA *color);
+
+ HRESULT (STDMETHODCALLTYPE *SetRotation)(
+ IDXGISwapChain3 *This,
+ DXGI_MODE_ROTATION rotation);
+
+ HRESULT (STDMETHODCALLTYPE *GetRotation)(
+ IDXGISwapChain3 *This,
+ DXGI_MODE_ROTATION *rotation);
+
+ /*** IDXGISwapChain2 methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetSourceSize)(
+ IDXGISwapChain3 *This,
+ UINT width,
+ UINT height);
+
+ HRESULT (STDMETHODCALLTYPE *GetSourceSize)(
+ IDXGISwapChain3 *This,
+ UINT *width,
+ UINT *height);
+
+ HRESULT (STDMETHODCALLTYPE *SetMaximumFrameLatency)(
+ IDXGISwapChain3 *This,
+ UINT latency);
+
+ HRESULT (STDMETHODCALLTYPE *GetMaximumFrameLatency)(
+ IDXGISwapChain3 *This,
+ UINT *latency);
+
+ HANDLE (STDMETHODCALLTYPE *GetFrameLatencyWaitableObject)(
+ IDXGISwapChain3 *This);
+
+ HRESULT (STDMETHODCALLTYPE *SetMatrixTransform)(
+ IDXGISwapChain3 *This,
+ const DXGI_MATRIX_3X2_F *matrix);
+
+ HRESULT (STDMETHODCALLTYPE *GetMatrixTransform)(
+ IDXGISwapChain3 *This,
+ DXGI_MATRIX_3X2_F *matrix);
+
+ /*** IDXGISwapChain3 methods ***/
+ UINT (STDMETHODCALLTYPE *GetCurrentBackBufferIndex)(
+ IDXGISwapChain3 *This);
+
+ HRESULT (STDMETHODCALLTYPE *CheckColorSpaceSupport)(
+ IDXGISwapChain3 *This,
+ DXGI_COLOR_SPACE_TYPE type,
+ UINT *support);
+
+ HRESULT (STDMETHODCALLTYPE *SetColorSpace1)(
+ IDXGISwapChain3 *This,
+ DXGI_COLOR_SPACE_TYPE type);
+
+ HRESULT (STDMETHODCALLTYPE *ResizeBuffers1)(
+ IDXGISwapChain3 *This,
+ UINT buffer_count,
+ UINT width,
+ UINT height,
+ DXGI_FORMAT format,
+ UINT flags,
+ const UINT *node_mask,
+ IUnknown *const *present_queue);
+
+ END_INTERFACE
+} IDXGISwapChain3Vtbl;
+
+interface IDXGISwapChain3 {
+ CONST_VTBL IDXGISwapChain3Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGISwapChain3_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGISwapChain3_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGISwapChain3_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGISwapChain3_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGISwapChain3_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGISwapChain3_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGISwapChain3_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIDeviceSubObject methods ***/
+#define IDXGISwapChain3_GetDevice(This,riid,device) (This)->lpVtbl->GetDevice(This,riid,device)
+/*** IDXGISwapChain methods ***/
+#define IDXGISwapChain3_Present(This,sync_interval,flags) (This)->lpVtbl->Present(This,sync_interval,flags)
+#define IDXGISwapChain3_GetBuffer(This,buffer_idx,riid,surface) (This)->lpVtbl->GetBuffer(This,buffer_idx,riid,surface)
+#define IDXGISwapChain3_SetFullscreenState(This,fullscreen,target) (This)->lpVtbl->SetFullscreenState(This,fullscreen,target)
+#define IDXGISwapChain3_GetFullscreenState(This,fullscreen,target) (This)->lpVtbl->GetFullscreenState(This,fullscreen,target)
+#define IDXGISwapChain3_GetDesc(This,desc) (This)->lpVtbl->GetDesc(This,desc)
+#define IDXGISwapChain3_ResizeBuffers(This,buffer_count,width,height,format,flags) (This)->lpVtbl->ResizeBuffers(This,buffer_count,width,height,format,flags)
+#define IDXGISwapChain3_ResizeTarget(This,desc) (This)->lpVtbl->ResizeTarget(This,desc)
+#define IDXGISwapChain3_GetContainingOutput(This,output) (This)->lpVtbl->GetContainingOutput(This,output)
+#define IDXGISwapChain3_GetFrameStatistics(This,stats) (This)->lpVtbl->GetFrameStatistics(This,stats)
+#define IDXGISwapChain3_GetLastPresentCount(This,last_present_count) (This)->lpVtbl->GetLastPresentCount(This,last_present_count)
+/*** IDXGISwapChain1 methods ***/
+#define IDXGISwapChain3_GetDesc1(This,desc) (This)->lpVtbl->GetDesc1(This,desc)
+#define IDXGISwapChain3_GetFullscreenDesc(This,desc) (This)->lpVtbl->GetFullscreenDesc(This,desc)
+#define IDXGISwapChain3_GetHwnd(This,hwnd) (This)->lpVtbl->GetHwnd(This,hwnd)
+#define IDXGISwapChain3_GetCoreWindow(This,riid,object) (This)->lpVtbl->GetCoreWindow(This,riid,object)
+#define IDXGISwapChain3_Present1(This,sync_interval,flags,parameters) (This)->lpVtbl->Present1(This,sync_interval,flags,parameters)
+#define IDXGISwapChain3_IsTemporaryMonoSupported(This) (This)->lpVtbl->IsTemporaryMonoSupported(This)
+#define IDXGISwapChain3_GetRestrictToOutput(This,output) (This)->lpVtbl->GetRestrictToOutput(This,output)
+#define IDXGISwapChain3_SetBackgroundColor(This,color) (This)->lpVtbl->SetBackgroundColor(This,color)
+#define IDXGISwapChain3_GetBackgroundColor(This,color) (This)->lpVtbl->GetBackgroundColor(This,color)
+#define IDXGISwapChain3_SetRotation(This,rotation) (This)->lpVtbl->SetRotation(This,rotation)
+#define IDXGISwapChain3_GetRotation(This,rotation) (This)->lpVtbl->GetRotation(This,rotation)
+/*** IDXGISwapChain2 methods ***/
+#define IDXGISwapChain3_SetSourceSize(This,width,height) (This)->lpVtbl->SetSourceSize(This,width,height)
+#define IDXGISwapChain3_GetSourceSize(This,width,height) (This)->lpVtbl->GetSourceSize(This,width,height)
+#define IDXGISwapChain3_SetMaximumFrameLatency(This,latency) (This)->lpVtbl->SetMaximumFrameLatency(This,latency)
+#define IDXGISwapChain3_GetMaximumFrameLatency(This,latency) (This)->lpVtbl->GetMaximumFrameLatency(This,latency)
+#define IDXGISwapChain3_GetFrameLatencyWaitableObject(This) (This)->lpVtbl->GetFrameLatencyWaitableObject(This)
+#define IDXGISwapChain3_SetMatrixTransform(This,matrix) (This)->lpVtbl->SetMatrixTransform(This,matrix)
+#define IDXGISwapChain3_GetMatrixTransform(This,matrix) (This)->lpVtbl->GetMatrixTransform(This,matrix)
+/*** IDXGISwapChain3 methods ***/
+#define IDXGISwapChain3_GetCurrentBackBufferIndex(This) (This)->lpVtbl->GetCurrentBackBufferIndex(This)
+#define IDXGISwapChain3_CheckColorSpaceSupport(This,type,support) (This)->lpVtbl->CheckColorSpaceSupport(This,type,support)
+#define IDXGISwapChain3_SetColorSpace1(This,type) (This)->lpVtbl->SetColorSpace1(This,type)
+#define IDXGISwapChain3_ResizeBuffers1(This,buffer_count,width,height,format,flags,node_mask,present_queue) (This)->lpVtbl->ResizeBuffers1(This,buffer_count,width,height,format,flags,node_mask,present_queue)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain3_QueryInterface(IDXGISwapChain3* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGISwapChain3_AddRef(IDXGISwapChain3* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGISwapChain3_Release(IDXGISwapChain3* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain3_SetPrivateData(IDXGISwapChain3* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetPrivateDataInterface(IDXGISwapChain3* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetPrivateData(IDXGISwapChain3* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetParent(IDXGISwapChain3* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIDeviceSubObject methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain3_GetDevice(IDXGISwapChain3* This,REFIID riid,void **device) {
+ return This->lpVtbl->GetDevice(This,riid,device);
+}
+/*** IDXGISwapChain methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain3_Present(IDXGISwapChain3* This,UINT sync_interval,UINT flags) {
+ return This->lpVtbl->Present(This,sync_interval,flags);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetBuffer(IDXGISwapChain3* This,UINT buffer_idx,REFIID riid,void **surface) {
+ return This->lpVtbl->GetBuffer(This,buffer_idx,riid,surface);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_SetFullscreenState(IDXGISwapChain3* This,BOOL fullscreen,IDXGIOutput *target) {
+ return This->lpVtbl->SetFullscreenState(This,fullscreen,target);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetFullscreenState(IDXGISwapChain3* This,BOOL *fullscreen,IDXGIOutput **target) {
+ return This->lpVtbl->GetFullscreenState(This,fullscreen,target);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetDesc(IDXGISwapChain3* This,DXGI_SWAP_CHAIN_DESC *desc) {
+ return This->lpVtbl->GetDesc(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_ResizeBuffers(IDXGISwapChain3* This,UINT buffer_count,UINT width,UINT height,DXGI_FORMAT format,UINT flags) {
+ return This->lpVtbl->ResizeBuffers(This,buffer_count,width,height,format,flags);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_ResizeTarget(IDXGISwapChain3* This,const DXGI_MODE_DESC *desc) {
+ return This->lpVtbl->ResizeTarget(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetContainingOutput(IDXGISwapChain3* This,IDXGIOutput **output) {
+ return This->lpVtbl->GetContainingOutput(This,output);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetFrameStatistics(IDXGISwapChain3* This,DXGI_FRAME_STATISTICS *stats) {
+ return This->lpVtbl->GetFrameStatistics(This,stats);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetLastPresentCount(IDXGISwapChain3* This,UINT *last_present_count) {
+ return This->lpVtbl->GetLastPresentCount(This,last_present_count);
+}
+/*** IDXGISwapChain1 methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain3_GetDesc1(IDXGISwapChain3* This,DXGI_SWAP_CHAIN_DESC1 *desc) {
+ return This->lpVtbl->GetDesc1(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetFullscreenDesc(IDXGISwapChain3* This,DXGI_SWAP_CHAIN_FULLSCREEN_DESC *desc) {
+ return This->lpVtbl->GetFullscreenDesc(This,desc);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetHwnd(IDXGISwapChain3* This,HWND *hwnd) {
+ return This->lpVtbl->GetHwnd(This,hwnd);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetCoreWindow(IDXGISwapChain3* This,REFIID riid,void **object) {
+ return This->lpVtbl->GetCoreWindow(This,riid,object);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_Present1(IDXGISwapChain3* This,UINT sync_interval,UINT flags,const DXGI_PRESENT_PARAMETERS *parameters) {
+ return This->lpVtbl->Present1(This,sync_interval,flags,parameters);
+}
+static FORCEINLINE BOOL IDXGISwapChain3_IsTemporaryMonoSupported(IDXGISwapChain3* This) {
+ return This->lpVtbl->IsTemporaryMonoSupported(This);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetRestrictToOutput(IDXGISwapChain3* This,IDXGIOutput **output) {
+ return This->lpVtbl->GetRestrictToOutput(This,output);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_SetBackgroundColor(IDXGISwapChain3* This,const DXGI_RGBA *color) {
+ return This->lpVtbl->SetBackgroundColor(This,color);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetBackgroundColor(IDXGISwapChain3* This,DXGI_RGBA *color) {
+ return This->lpVtbl->GetBackgroundColor(This,color);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_SetRotation(IDXGISwapChain3* This,DXGI_MODE_ROTATION rotation) {
+ return This->lpVtbl->SetRotation(This,rotation);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetRotation(IDXGISwapChain3* This,DXGI_MODE_ROTATION *rotation) {
+ return This->lpVtbl->GetRotation(This,rotation);
+}
+/*** IDXGISwapChain2 methods ***/
+static FORCEINLINE HRESULT IDXGISwapChain3_SetSourceSize(IDXGISwapChain3* This,UINT width,UINT height) {
+ return This->lpVtbl->SetSourceSize(This,width,height);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetSourceSize(IDXGISwapChain3* This,UINT *width,UINT *height) {
+ return This->lpVtbl->GetSourceSize(This,width,height);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_SetMaximumFrameLatency(IDXGISwapChain3* This,UINT latency) {
+ return This->lpVtbl->SetMaximumFrameLatency(This,latency);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetMaximumFrameLatency(IDXGISwapChain3* This,UINT *latency) {
+ return This->lpVtbl->GetMaximumFrameLatency(This,latency);
+}
+static FORCEINLINE HANDLE IDXGISwapChain3_GetFrameLatencyWaitableObject(IDXGISwapChain3* This) {
+ return This->lpVtbl->GetFrameLatencyWaitableObject(This);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_SetMatrixTransform(IDXGISwapChain3* This,const DXGI_MATRIX_3X2_F *matrix) {
+ return This->lpVtbl->SetMatrixTransform(This,matrix);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_GetMatrixTransform(IDXGISwapChain3* This,DXGI_MATRIX_3X2_F *matrix) {
+ return This->lpVtbl->GetMatrixTransform(This,matrix);
+}
+/*** IDXGISwapChain3 methods ***/
+static FORCEINLINE UINT IDXGISwapChain3_GetCurrentBackBufferIndex(IDXGISwapChain3* This) {
+ return This->lpVtbl->GetCurrentBackBufferIndex(This);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_CheckColorSpaceSupport(IDXGISwapChain3* This,DXGI_COLOR_SPACE_TYPE type,UINT *support) {
+ return This->lpVtbl->CheckColorSpaceSupport(This,type,support);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_SetColorSpace1(IDXGISwapChain3* This,DXGI_COLOR_SPACE_TYPE type) {
+ return This->lpVtbl->SetColorSpace1(This,type);
+}
+static FORCEINLINE HRESULT IDXGISwapChain3_ResizeBuffers1(IDXGISwapChain3* This,UINT buffer_count,UINT width,UINT height,DXGI_FORMAT format,UINT flags,const UINT *node_mask,IUnknown *const *present_queue) {
+ return This->lpVtbl->ResizeBuffers1(This,buffer_count,width,height,format,flags,node_mask,present_queue);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGISwapChain3_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGIFactory4 interface
+ */
+#ifndef __IDXGIFactory4_INTERFACE_DEFINED__
+#define __IDXGIFactory4_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIFactory4, 0x1bc6ea02, 0xef36, 0x464f, 0xbf,0x0c, 0x21,0xca,0x39,0xe5,0x16,0x8a);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("1bc6ea02-ef36-464f-bf0c-21ca39e5168a")
+IDXGIFactory4 : public IDXGIFactory3
+{
+ virtual HRESULT STDMETHODCALLTYPE EnumAdapterByLuid(
+ LUID luid,
+ REFIID iid,
+ void **adapter) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnumWarpAdapter(
+ REFIID iid,
+ void **adapter) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIFactory4, 0x1bc6ea02, 0xef36, 0x464f, 0xbf,0x0c, 0x21,0xca,0x39,0xe5,0x16,0x8a)
+#endif
+#else
+typedef struct IDXGIFactory4Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIFactory4 *This,
+ REFIID riid,
+ void **object);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIFactory4 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIFactory4 *This);
+
+ /*** IDXGIObject methods ***/
+ HRESULT (STDMETHODCALLTYPE *SetPrivateData)(
+ IDXGIFactory4 *This,
+ REFGUID name,
+ UINT data_size,
+ const void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateDataInterface)(
+ IDXGIFactory4 *This,
+ REFGUID name,
+ const IUnknown *unknown);
+
+ HRESULT (STDMETHODCALLTYPE *GetPrivateData)(
+ IDXGIFactory4 *This,
+ REFGUID name,
+ UINT *data_size,
+ void *data);
+
+ HRESULT (STDMETHODCALLTYPE *GetParent)(
+ IDXGIFactory4 *This,
+ REFIID riid,
+ void **parent);
+
+ /*** IDXGIFactory methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters)(
+ IDXGIFactory4 *This,
+ UINT adapter_idx,
+ IDXGIAdapter **adapter);
+
+ HRESULT (STDMETHODCALLTYPE *MakeWindowAssociation)(
+ IDXGIFactory4 *This,
+ HWND hwnd,
+ UINT flags);
+
+ HRESULT (STDMETHODCALLTYPE *GetWindowAssociation)(
+ IDXGIFactory4 *This,
+ HWND *hwnd);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChain)(
+ IDXGIFactory4 *This,
+ IUnknown *device,
+ DXGI_SWAP_CHAIN_DESC *desc,
+ IDXGISwapChain **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSoftwareAdapter)(
+ IDXGIFactory4 *This,
+ HMODULE hmodule,
+ IDXGIAdapter **adapter);
+
+ /*** IDXGIFactory1 methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapters1)(
+ IDXGIFactory4 *This,
+ UINT adapter_idx,
+ IDXGIAdapter1 **adpter);
+
+ BOOL (STDMETHODCALLTYPE *IsCurrent)(
+ IDXGIFactory4 *This);
+
+ /*** IDXGIFactory2 methods ***/
+ BOOL (STDMETHODCALLTYPE *IsWindowedStereoEnabled)(
+ IDXGIFactory4 *This);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForHwnd)(
+ IDXGIFactory4 *This,
+ IUnknown *device,
+ HWND window,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForCoreWindow)(
+ IDXGIFactory4 *This,
+ IUnknown *device,
+ IUnknown *window,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ HRESULT (STDMETHODCALLTYPE *GetSharedResourceAdapterLuid)(
+ IDXGIFactory4 *This,
+ HANDLE resource,
+ LUID *luid);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterStereoStatusWindow)(
+ IDXGIFactory4 *This,
+ HWND window,
+ UINT msg,
+ DWORD *cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterStereoStatusEvent)(
+ IDXGIFactory4 *This,
+ HANDLE event,
+ DWORD *cookie);
+
+ void (STDMETHODCALLTYPE *UnregisterStereoStatus)(
+ IDXGIFactory4 *This,
+ DWORD cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterOcclusionStatusWindow)(
+ IDXGIFactory4 *This,
+ HWND window,
+ UINT msg,
+ DWORD *cookie);
+
+ HRESULT (STDMETHODCALLTYPE *RegisterOcclusionStatusEvent)(
+ IDXGIFactory4 *This,
+ HANDLE event,
+ DWORD *cookie);
+
+ void (STDMETHODCALLTYPE *UnregisterOcclusionStatus)(
+ IDXGIFactory4 *This,
+ DWORD cookie);
+
+ HRESULT (STDMETHODCALLTYPE *CreateSwapChainForComposition)(
+ IDXGIFactory4 *This,
+ IUnknown *device,
+ const DXGI_SWAP_CHAIN_DESC1 *desc,
+ IDXGIOutput *output,
+ IDXGISwapChain1 **swapchain);
+
+ /*** IDXGIFactory3 methods ***/
+ UINT (STDMETHODCALLTYPE *GetCreationFlags)(
+ IDXGIFactory4 *This);
+
+ /*** IDXGIFactory4 methods ***/
+ HRESULT (STDMETHODCALLTYPE *EnumAdapterByLuid)(
+ IDXGIFactory4 *This,
+ LUID luid,
+ REFIID iid,
+ void **adapter);
+
+ HRESULT (STDMETHODCALLTYPE *EnumWarpAdapter)(
+ IDXGIFactory4 *This,
+ REFIID iid,
+ void **adapter);
+
+ END_INTERFACE
+} IDXGIFactory4Vtbl;
+
+interface IDXGIFactory4 {
+ CONST_VTBL IDXGIFactory4Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIFactory4_QueryInterface(This,riid,object) (This)->lpVtbl->QueryInterface(This,riid,object)
+#define IDXGIFactory4_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIFactory4_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIObject methods ***/
+#define IDXGIFactory4_SetPrivateData(This,name,data_size,data) (This)->lpVtbl->SetPrivateData(This,name,data_size,data)
+#define IDXGIFactory4_GetPrivateDataInterface(This,name,unknown) (This)->lpVtbl->GetPrivateDataInterface(This,name,unknown)
+#define IDXGIFactory4_GetPrivateData(This,name,data_size,data) (This)->lpVtbl->GetPrivateData(This,name,data_size,data)
+#define IDXGIFactory4_GetParent(This,riid,parent) (This)->lpVtbl->GetParent(This,riid,parent)
+/*** IDXGIFactory methods ***/
+#define IDXGIFactory4_EnumAdapters(This,adapter_idx,adapter) (This)->lpVtbl->EnumAdapters(This,adapter_idx,adapter)
+#define IDXGIFactory4_MakeWindowAssociation(This,hwnd,flags) (This)->lpVtbl->MakeWindowAssociation(This,hwnd,flags)
+#define IDXGIFactory4_GetWindowAssociation(This,hwnd) (This)->lpVtbl->GetWindowAssociation(This,hwnd)
+#define IDXGIFactory4_CreateSwapChain(This,device,desc,swapchain) (This)->lpVtbl->CreateSwapChain(This,device,desc,swapchain)
+#define IDXGIFactory4_CreateSoftwareAdapter(This,hmodule,adapter) (This)->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter)
+/*** IDXGIFactory1 methods ***/
+#define IDXGIFactory4_EnumAdapters1(This,adapter_idx,adpter) (This)->lpVtbl->EnumAdapters1(This,adapter_idx,adpter)
+#define IDXGIFactory4_IsCurrent(This) (This)->lpVtbl->IsCurrent(This)
+/*** IDXGIFactory2 methods ***/
+#define IDXGIFactory4_IsWindowedStereoEnabled(This) (This)->lpVtbl->IsWindowedStereoEnabled(This)
+#define IDXGIFactory4_CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain)
+#define IDXGIFactory4_CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain)
+#define IDXGIFactory4_GetSharedResourceAdapterLuid(This,resource,luid) (This)->lpVtbl->GetSharedResourceAdapterLuid(This,resource,luid)
+#define IDXGIFactory4_RegisterStereoStatusWindow(This,window,msg,cookie) (This)->lpVtbl->RegisterStereoStatusWindow(This,window,msg,cookie)
+#define IDXGIFactory4_RegisterStereoStatusEvent(This,event,cookie) (This)->lpVtbl->RegisterStereoStatusEvent(This,event,cookie)
+#define IDXGIFactory4_UnregisterStereoStatus(This,cookie) (This)->lpVtbl->UnregisterStereoStatus(This,cookie)
+#define IDXGIFactory4_RegisterOcclusionStatusWindow(This,window,msg,cookie) (This)->lpVtbl->RegisterOcclusionStatusWindow(This,window,msg,cookie)
+#define IDXGIFactory4_RegisterOcclusionStatusEvent(This,event,cookie) (This)->lpVtbl->RegisterOcclusionStatusEvent(This,event,cookie)
+#define IDXGIFactory4_UnregisterOcclusionStatus(This,cookie) (This)->lpVtbl->UnregisterOcclusionStatus(This,cookie)
+#define IDXGIFactory4_CreateSwapChainForComposition(This,device,desc,output,swapchain) (This)->lpVtbl->CreateSwapChainForComposition(This,device,desc,output,swapchain)
+/*** IDXGIFactory3 methods ***/
+#define IDXGIFactory4_GetCreationFlags(This) (This)->lpVtbl->GetCreationFlags(This)
+/*** IDXGIFactory4 methods ***/
+#define IDXGIFactory4_EnumAdapterByLuid(This,luid,iid,adapter) (This)->lpVtbl->EnumAdapterByLuid(This,luid,iid,adapter)
+#define IDXGIFactory4_EnumWarpAdapter(This,iid,adapter) (This)->lpVtbl->EnumWarpAdapter(This,iid,adapter)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIFactory4_QueryInterface(IDXGIFactory4* This,REFIID riid,void **object) {
+ return This->lpVtbl->QueryInterface(This,riid,object);
+}
+static FORCEINLINE ULONG IDXGIFactory4_AddRef(IDXGIFactory4* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIFactory4_Release(IDXGIFactory4* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIObject methods ***/
+static FORCEINLINE HRESULT IDXGIFactory4_SetPrivateData(IDXGIFactory4* This,REFGUID name,UINT data_size,const void *data) {
+ return This->lpVtbl->SetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_GetPrivateDataInterface(IDXGIFactory4* This,REFGUID name,const IUnknown *unknown) {
+ return This->lpVtbl->GetPrivateDataInterface(This,name,unknown);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_GetPrivateData(IDXGIFactory4* This,REFGUID name,UINT *data_size,void *data) {
+ return This->lpVtbl->GetPrivateData(This,name,data_size,data);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_GetParent(IDXGIFactory4* This,REFIID riid,void **parent) {
+ return This->lpVtbl->GetParent(This,riid,parent);
+}
+/*** IDXGIFactory methods ***/
+static FORCEINLINE HRESULT IDXGIFactory4_EnumAdapters(IDXGIFactory4* This,UINT adapter_idx,IDXGIAdapter **adapter) {
+ return This->lpVtbl->EnumAdapters(This,adapter_idx,adapter);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_MakeWindowAssociation(IDXGIFactory4* This,HWND hwnd,UINT flags) {
+ return This->lpVtbl->MakeWindowAssociation(This,hwnd,flags);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_GetWindowAssociation(IDXGIFactory4* This,HWND *hwnd) {
+ return This->lpVtbl->GetWindowAssociation(This,hwnd);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_CreateSwapChain(IDXGIFactory4* This,IUnknown *device,DXGI_SWAP_CHAIN_DESC *desc,IDXGISwapChain **swapchain) {
+ return This->lpVtbl->CreateSwapChain(This,device,desc,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_CreateSoftwareAdapter(IDXGIFactory4* This,HMODULE hmodule,IDXGIAdapter **adapter) {
+ return This->lpVtbl->CreateSoftwareAdapter(This,hmodule,adapter);
+}
+/*** IDXGIFactory1 methods ***/
+static FORCEINLINE HRESULT IDXGIFactory4_EnumAdapters1(IDXGIFactory4* This,UINT adapter_idx,IDXGIAdapter1 **adpter) {
+ return This->lpVtbl->EnumAdapters1(This,adapter_idx,adpter);
+}
+static FORCEINLINE BOOL IDXGIFactory4_IsCurrent(IDXGIFactory4* This) {
+ return This->lpVtbl->IsCurrent(This);
+}
+/*** IDXGIFactory2 methods ***/
+static FORCEINLINE BOOL IDXGIFactory4_IsWindowedStereoEnabled(IDXGIFactory4* This) {
+ return This->lpVtbl->IsWindowedStereoEnabled(This);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_CreateSwapChainForHwnd(IDXGIFactory4* This,IUnknown *device,HWND window,const DXGI_SWAP_CHAIN_DESC1 *desc,const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForHwnd(This,device,window,desc,fullscreen_desc,output,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_CreateSwapChainForCoreWindow(IDXGIFactory4* This,IUnknown *device,IUnknown *window,const DXGI_SWAP_CHAIN_DESC1 *desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForCoreWindow(This,device,window,desc,output,swapchain);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_GetSharedResourceAdapterLuid(IDXGIFactory4* This,HANDLE resource,LUID *luid) {
+ return This->lpVtbl->GetSharedResourceAdapterLuid(This,resource,luid);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_RegisterStereoStatusWindow(IDXGIFactory4* This,HWND window,UINT msg,DWORD *cookie) {
+ return This->lpVtbl->RegisterStereoStatusWindow(This,window,msg,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_RegisterStereoStatusEvent(IDXGIFactory4* This,HANDLE event,DWORD *cookie) {
+ return This->lpVtbl->RegisterStereoStatusEvent(This,event,cookie);
+}
+static FORCEINLINE void IDXGIFactory4_UnregisterStereoStatus(IDXGIFactory4* This,DWORD cookie) {
+ This->lpVtbl->UnregisterStereoStatus(This,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_RegisterOcclusionStatusWindow(IDXGIFactory4* This,HWND window,UINT msg,DWORD *cookie) {
+ return This->lpVtbl->RegisterOcclusionStatusWindow(This,window,msg,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_RegisterOcclusionStatusEvent(IDXGIFactory4* This,HANDLE event,DWORD *cookie) {
+ return This->lpVtbl->RegisterOcclusionStatusEvent(This,event,cookie);
+}
+static FORCEINLINE void IDXGIFactory4_UnregisterOcclusionStatus(IDXGIFactory4* This,DWORD cookie) {
+ This->lpVtbl->UnregisterOcclusionStatus(This,cookie);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_CreateSwapChainForComposition(IDXGIFactory4* This,IUnknown *device,const DXGI_SWAP_CHAIN_DESC1 *desc,IDXGIOutput *output,IDXGISwapChain1 **swapchain) {
+ return This->lpVtbl->CreateSwapChainForComposition(This,device,desc,output,swapchain);
+}
+/*** IDXGIFactory3 methods ***/
+static FORCEINLINE UINT IDXGIFactory4_GetCreationFlags(IDXGIFactory4* This) {
+ return This->lpVtbl->GetCreationFlags(This);
+}
+/*** IDXGIFactory4 methods ***/
+static FORCEINLINE HRESULT IDXGIFactory4_EnumAdapterByLuid(IDXGIFactory4* This,LUID luid,REFIID iid,void **adapter) {
+ return This->lpVtbl->EnumAdapterByLuid(This,luid,iid,adapter);
+}
+static FORCEINLINE HRESULT IDXGIFactory4_EnumWarpAdapter(IDXGIFactory4* This,REFIID iid,void **adapter) {
+ return This->lpVtbl->EnumWarpAdapter(This,iid,adapter);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIFactory4_INTERFACE_DEFINED__ */
+
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_dxgi1_4_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_dxgi1_4.idl b/dlls/vkd3d/include/vkd3d_dxgi1_4.idl
new file mode 100644
index 00000000000..ccd2224c82d
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgi1_4.idl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ * Copyright 2016 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_dxgi1_3.idl";
+
+[
+ local,
+ object,
+ uuid(94d99bdb-f1f8-4ab0-b236-7da0170edab1),
+ pointer_default(unique)
+]
+interface IDXGISwapChain3 : IDXGISwapChain2
+{
+ UINT GetCurrentBackBufferIndex();
+ HRESULT CheckColorSpaceSupport(DXGI_COLOR_SPACE_TYPE type, UINT *support);
+ HRESULT SetColorSpace1(DXGI_COLOR_SPACE_TYPE type);
+ HRESULT ResizeBuffers1(UINT buffer_count, UINT width, UINT height, DXGI_FORMAT format,
+ UINT flags, const UINT *node_mask, IUnknown *const *present_queue);
+}
+
+[
+ local,
+ object,
+ uuid(1bc6ea02-ef36-464f-bf0c-21ca39e5168a),
+ pointer_default(unique),
+]
+interface IDXGIFactory4 : IDXGIFactory3
+{
+ HRESULT EnumAdapterByLuid(LUID luid, REFIID iid, void **adapter);
+ HRESULT EnumWarpAdapter(REFIID iid, void **adapter);
+}
diff --git a/dlls/vkd3d/include/vkd3d_dxgibase.h b/dlls/vkd3d/include/vkd3d_dxgibase.h
new file mode 100644
index 00000000000..31e686a2640
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgibase.h
@@ -0,0 +1,49 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_dxgibase.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_dxgibase_h__
+#define __vkd3d_dxgibase_h__
+
+/* Forward declarations */
+
+/* Headers for imported files */
+
+#include <vkd3d_windows.h>
+#include <vkd3d_dxgiformat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef DXGI_ERROR_INVALID_CALL
+#define DXGI_ERROR_INVALID_CALL _HRESULT_TYPEDEF_(0x887a0001)
+#endif
+#ifndef DXGI_ERROR_DEVICE_REMOVED
+#define DXGI_ERROR_DEVICE_REMOVED _HRESULT_TYPEDEF_(0x887a0005)
+#endif
+typedef struct DXGI_SAMPLE_DESC {
+ UINT Count;
+ UINT Quality;
+} DXGI_SAMPLE_DESC;
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_dxgibase_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_dxgibase.idl b/dlls/vkd3d/include/vkd3d_dxgibase.idl
new file mode 100644
index 00000000000..93f931e0944
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgibase.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_windows.h";
+
+import "vkd3d_dxgiformat.idl";
+
+cpp_quote("#ifndef DXGI_ERROR_INVALID_CALL")
+cpp_quote("#define DXGI_ERROR_INVALID_CALL _HRESULT_TYPEDEF_(0x887a0001)")
+cpp_quote("#endif")
+cpp_quote("#ifndef DXGI_ERROR_DEVICE_REMOVED")
+cpp_quote("#define DXGI_ERROR_DEVICE_REMOVED _HRESULT_TYPEDEF_(0x887a0005)")
+cpp_quote("#endif")
+
+typedef struct DXGI_SAMPLE_DESC
+{
+ UINT Count;
+ UINT Quality;
+} DXGI_SAMPLE_DESC;
diff --git a/dlls/vkd3d/include/vkd3d_dxgiformat.h b/dlls/vkd3d/include/vkd3d_dxgiformat.h
new file mode 100644
index 00000000000..f0bf0774969
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgiformat.h
@@ -0,0 +1,156 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_dxgiformat.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_dxgiformat_h__
+#define __vkd3d_dxgiformat_h__
+
+/* Forward declarations */
+
+/* Headers for imported files */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum DXGI_FORMAT {
+ DXGI_FORMAT_UNKNOWN = 0x0,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS = 0x1,
+ DXGI_FORMAT_R32G32B32A32_FLOAT = 0x2,
+ DXGI_FORMAT_R32G32B32A32_UINT = 0x3,
+ DXGI_FORMAT_R32G32B32A32_SINT = 0x4,
+ DXGI_FORMAT_R32G32B32_TYPELESS = 0x5,
+ DXGI_FORMAT_R32G32B32_FLOAT = 0x6,
+ DXGI_FORMAT_R32G32B32_UINT = 0x7,
+ DXGI_FORMAT_R32G32B32_SINT = 0x8,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS = 0x9,
+ DXGI_FORMAT_R16G16B16A16_FLOAT = 0xa,
+ DXGI_FORMAT_R16G16B16A16_UNORM = 0xb,
+ DXGI_FORMAT_R16G16B16A16_UINT = 0xc,
+ DXGI_FORMAT_R16G16B16A16_SNORM = 0xd,
+ DXGI_FORMAT_R16G16B16A16_SINT = 0xe,
+ DXGI_FORMAT_R32G32_TYPELESS = 0xf,
+ DXGI_FORMAT_R32G32_FLOAT = 0x10,
+ DXGI_FORMAT_R32G32_UINT = 0x11,
+ DXGI_FORMAT_R32G32_SINT = 0x12,
+ DXGI_FORMAT_R32G8X24_TYPELESS = 0x13,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 0x14,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 0x15,
+ DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 0x16,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS = 0x17,
+ DXGI_FORMAT_R10G10B10A2_UNORM = 0x18,
+ DXGI_FORMAT_R10G10B10A2_UINT = 0x19,
+ DXGI_FORMAT_R11G11B10_FLOAT = 0x1a,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS = 0x1b,
+ DXGI_FORMAT_R8G8B8A8_UNORM = 0x1c,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 0x1d,
+ DXGI_FORMAT_R8G8B8A8_UINT = 0x1e,
+ DXGI_FORMAT_R8G8B8A8_SNORM = 0x1f,
+ DXGI_FORMAT_R8G8B8A8_SINT = 0x20,
+ DXGI_FORMAT_R16G16_TYPELESS = 0x21,
+ DXGI_FORMAT_R16G16_FLOAT = 0x22,
+ DXGI_FORMAT_R16G16_UNORM = 0x23,
+ DXGI_FORMAT_R16G16_UINT = 0x24,
+ DXGI_FORMAT_R16G16_SNORM = 0x25,
+ DXGI_FORMAT_R16G16_SINT = 0x26,
+ DXGI_FORMAT_R32_TYPELESS = 0x27,
+ DXGI_FORMAT_D32_FLOAT = 0x28,
+ DXGI_FORMAT_R32_FLOAT = 0x29,
+ DXGI_FORMAT_R32_UINT = 0x2a,
+ DXGI_FORMAT_R32_SINT = 0x2b,
+ DXGI_FORMAT_R24G8_TYPELESS = 0x2c,
+ DXGI_FORMAT_D24_UNORM_S8_UINT = 0x2d,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 0x2e,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT = 0x2f,
+ DXGI_FORMAT_R8G8_TYPELESS = 0x30,
+ DXGI_FORMAT_R8G8_UNORM = 0x31,
+ DXGI_FORMAT_R8G8_UINT = 0x32,
+ DXGI_FORMAT_R8G8_SNORM = 0x33,
+ DXGI_FORMAT_R8G8_SINT = 0x34,
+ DXGI_FORMAT_R16_TYPELESS = 0x35,
+ DXGI_FORMAT_R16_FLOAT = 0x36,
+ DXGI_FORMAT_D16_UNORM = 0x37,
+ DXGI_FORMAT_R16_UNORM = 0x38,
+ DXGI_FORMAT_R16_UINT = 0x39,
+ DXGI_FORMAT_R16_SNORM = 0x3a,
+ DXGI_FORMAT_R16_SINT = 0x3b,
+ DXGI_FORMAT_R8_TYPELESS = 0x3c,
+ DXGI_FORMAT_R8_UNORM = 0x3d,
+ DXGI_FORMAT_R8_UINT = 0x3e,
+ DXGI_FORMAT_R8_SNORM = 0x3f,
+ DXGI_FORMAT_R8_SINT = 0x40,
+ DXGI_FORMAT_A8_UNORM = 0x41,
+ DXGI_FORMAT_R1_UNORM = 0x42,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 0x43,
+ DXGI_FORMAT_R8G8_B8G8_UNORM = 0x44,
+ DXGI_FORMAT_G8R8_G8B8_UNORM = 0x45,
+ DXGI_FORMAT_BC1_TYPELESS = 0x46,
+ DXGI_FORMAT_BC1_UNORM = 0x47,
+ DXGI_FORMAT_BC1_UNORM_SRGB = 0x48,
+ DXGI_FORMAT_BC2_TYPELESS = 0x49,
+ DXGI_FORMAT_BC2_UNORM = 0x4a,
+ DXGI_FORMAT_BC2_UNORM_SRGB = 0x4b,
+ DXGI_FORMAT_BC3_TYPELESS = 0x4c,
+ DXGI_FORMAT_BC3_UNORM = 0x4d,
+ DXGI_FORMAT_BC3_UNORM_SRGB = 0x4e,
+ DXGI_FORMAT_BC4_TYPELESS = 0x4f,
+ DXGI_FORMAT_BC4_UNORM = 0x50,
+ DXGI_FORMAT_BC4_SNORM = 0x51,
+ DXGI_FORMAT_BC5_TYPELESS = 0x52,
+ DXGI_FORMAT_BC5_UNORM = 0x53,
+ DXGI_FORMAT_BC5_SNORM = 0x54,
+ DXGI_FORMAT_B5G6R5_UNORM = 0x55,
+ DXGI_FORMAT_B5G5R5A1_UNORM = 0x56,
+ DXGI_FORMAT_B8G8R8A8_UNORM = 0x57,
+ DXGI_FORMAT_B8G8R8X8_UNORM = 0x58,
+ DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 0x59,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS = 0x5a,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 0x5b,
+ DXGI_FORMAT_B8G8R8X8_TYPELESS = 0x5c,
+ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 0x5d,
+ DXGI_FORMAT_BC6H_TYPELESS = 0x5e,
+ DXGI_FORMAT_BC6H_UF16 = 0x5f,
+ DXGI_FORMAT_BC6H_SF16 = 0x60,
+ DXGI_FORMAT_BC7_TYPELESS = 0x61,
+ DXGI_FORMAT_BC7_UNORM = 0x62,
+ DXGI_FORMAT_BC7_UNORM_SRGB = 0x63,
+ DXGI_FORMAT_AYUV = 0x64,
+ DXGI_FORMAT_Y410 = 0x65,
+ DXGI_FORMAT_Y416 = 0x66,
+ DXGI_FORMAT_NV12 = 0x67,
+ DXGI_FORMAT_P010 = 0x68,
+ DXGI_FORMAT_P016 = 0x69,
+ DXGI_FORMAT_420_OPAQUE = 0x6a,
+ DXGI_FORMAT_YUY2 = 0x6b,
+ DXGI_FORMAT_Y210 = 0x6c,
+ DXGI_FORMAT_Y216 = 0x6d,
+ DXGI_FORMAT_NV11 = 0x6e,
+ DXGI_FORMAT_AI44 = 0x6f,
+ DXGI_FORMAT_IA44 = 0x70,
+ DXGI_FORMAT_P8 = 0x71,
+ DXGI_FORMAT_A8P8 = 0x72,
+ DXGI_FORMAT_B4G4R4A4_UNORM = 0x73,
+ DXGI_FORMAT_FORCE_UINT = 0xffffffff
+} DXGI_FORMAT;
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_dxgiformat_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_dxgiformat.idl b/dlls/vkd3d/include/vkd3d_dxgiformat.idl
new file mode 100644
index 00000000000..63129bbefa1
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgiformat.idl
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+typedef enum DXGI_FORMAT
+{
+ DXGI_FORMAT_UNKNOWN = 0x00,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS = 0x01,
+ DXGI_FORMAT_R32G32B32A32_FLOAT = 0x02,
+ DXGI_FORMAT_R32G32B32A32_UINT = 0x03,
+ DXGI_FORMAT_R32G32B32A32_SINT = 0x04,
+ DXGI_FORMAT_R32G32B32_TYPELESS = 0x05,
+ DXGI_FORMAT_R32G32B32_FLOAT = 0x06,
+ DXGI_FORMAT_R32G32B32_UINT = 0x07,
+ DXGI_FORMAT_R32G32B32_SINT = 0x08,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS = 0x09,
+ DXGI_FORMAT_R16G16B16A16_FLOAT = 0x0a,
+ DXGI_FORMAT_R16G16B16A16_UNORM = 0x0b,
+ DXGI_FORMAT_R16G16B16A16_UINT = 0x0c,
+ DXGI_FORMAT_R16G16B16A16_SNORM = 0x0d,
+ DXGI_FORMAT_R16G16B16A16_SINT = 0x0e,
+ DXGI_FORMAT_R32G32_TYPELESS = 0x0f,
+ DXGI_FORMAT_R32G32_FLOAT = 0x10,
+ DXGI_FORMAT_R32G32_UINT = 0x11,
+ DXGI_FORMAT_R32G32_SINT = 0x12,
+ DXGI_FORMAT_R32G8X24_TYPELESS = 0x13,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 0x14,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 0x15,
+ DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 0x16,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS = 0x17,
+ DXGI_FORMAT_R10G10B10A2_UNORM = 0x18,
+ DXGI_FORMAT_R10G10B10A2_UINT = 0x19,
+ DXGI_FORMAT_R11G11B10_FLOAT = 0x1a,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS = 0x1b,
+ DXGI_FORMAT_R8G8B8A8_UNORM = 0x1c,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 0x1d,
+ DXGI_FORMAT_R8G8B8A8_UINT = 0x1e,
+ DXGI_FORMAT_R8G8B8A8_SNORM = 0x1f,
+ DXGI_FORMAT_R8G8B8A8_SINT = 0x20,
+ DXGI_FORMAT_R16G16_TYPELESS = 0x21,
+ DXGI_FORMAT_R16G16_FLOAT = 0x22,
+ DXGI_FORMAT_R16G16_UNORM = 0x23,
+ DXGI_FORMAT_R16G16_UINT = 0x24,
+ DXGI_FORMAT_R16G16_SNORM = 0x25,
+ DXGI_FORMAT_R16G16_SINT = 0x26,
+ DXGI_FORMAT_R32_TYPELESS = 0x27,
+ DXGI_FORMAT_D32_FLOAT = 0x28,
+ DXGI_FORMAT_R32_FLOAT = 0x29,
+ DXGI_FORMAT_R32_UINT = 0x2a,
+ DXGI_FORMAT_R32_SINT = 0x2b,
+ DXGI_FORMAT_R24G8_TYPELESS = 0x2c,
+ DXGI_FORMAT_D24_UNORM_S8_UINT = 0x2d,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 0x2e,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT = 0x2f,
+ DXGI_FORMAT_R8G8_TYPELESS = 0x30,
+ DXGI_FORMAT_R8G8_UNORM = 0x31,
+ DXGI_FORMAT_R8G8_UINT = 0x32,
+ DXGI_FORMAT_R8G8_SNORM = 0x33,
+ DXGI_FORMAT_R8G8_SINT = 0x34,
+ DXGI_FORMAT_R16_TYPELESS = 0x35,
+ DXGI_FORMAT_R16_FLOAT = 0x36,
+ DXGI_FORMAT_D16_UNORM = 0x37,
+ DXGI_FORMAT_R16_UNORM = 0x38,
+ DXGI_FORMAT_R16_UINT = 0x39,
+ DXGI_FORMAT_R16_SNORM = 0x3a,
+ DXGI_FORMAT_R16_SINT = 0x3b,
+ DXGI_FORMAT_R8_TYPELESS = 0x3c,
+ DXGI_FORMAT_R8_UNORM = 0x3d,
+ DXGI_FORMAT_R8_UINT = 0x3e,
+ DXGI_FORMAT_R8_SNORM = 0x3f,
+ DXGI_FORMAT_R8_SINT = 0x40,
+ DXGI_FORMAT_A8_UNORM = 0x41,
+ DXGI_FORMAT_R1_UNORM = 0x42,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 0x43,
+ DXGI_FORMAT_R8G8_B8G8_UNORM = 0x44,
+ DXGI_FORMAT_G8R8_G8B8_UNORM = 0x45,
+ DXGI_FORMAT_BC1_TYPELESS = 0x46,
+ DXGI_FORMAT_BC1_UNORM = 0x47,
+ DXGI_FORMAT_BC1_UNORM_SRGB = 0x48,
+ DXGI_FORMAT_BC2_TYPELESS = 0x49,
+ DXGI_FORMAT_BC2_UNORM = 0x4a,
+ DXGI_FORMAT_BC2_UNORM_SRGB = 0x4b,
+ DXGI_FORMAT_BC3_TYPELESS = 0x4c,
+ DXGI_FORMAT_BC3_UNORM = 0x4d,
+ DXGI_FORMAT_BC3_UNORM_SRGB = 0x4e,
+ DXGI_FORMAT_BC4_TYPELESS = 0x4f,
+ DXGI_FORMAT_BC4_UNORM = 0x50,
+ DXGI_FORMAT_BC4_SNORM = 0x51,
+ DXGI_FORMAT_BC5_TYPELESS = 0x52,
+ DXGI_FORMAT_BC5_UNORM = 0x53,
+ DXGI_FORMAT_BC5_SNORM = 0x54,
+ DXGI_FORMAT_B5G6R5_UNORM = 0x55,
+ DXGI_FORMAT_B5G5R5A1_UNORM = 0x56,
+ DXGI_FORMAT_B8G8R8A8_UNORM = 0x57,
+ DXGI_FORMAT_B8G8R8X8_UNORM = 0x58,
+ DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 0x59,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS = 0x5a,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 0x5b,
+ DXGI_FORMAT_B8G8R8X8_TYPELESS = 0x5c,
+ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 0x5d,
+ DXGI_FORMAT_BC6H_TYPELESS = 0x5e,
+ DXGI_FORMAT_BC6H_UF16 = 0x5f,
+ DXGI_FORMAT_BC6H_SF16 = 0x60,
+ DXGI_FORMAT_BC7_TYPELESS = 0x61,
+ DXGI_FORMAT_BC7_UNORM = 0x62,
+ DXGI_FORMAT_BC7_UNORM_SRGB = 0x63,
+ DXGI_FORMAT_AYUV = 0x64,
+ DXGI_FORMAT_Y410 = 0x65,
+ DXGI_FORMAT_Y416 = 0x66,
+ DXGI_FORMAT_NV12 = 0x67,
+ DXGI_FORMAT_P010 = 0x68,
+ DXGI_FORMAT_P016 = 0x69,
+ DXGI_FORMAT_420_OPAQUE = 0x6a,
+ DXGI_FORMAT_YUY2 = 0x6b,
+ DXGI_FORMAT_Y210 = 0x6c,
+ DXGI_FORMAT_Y216 = 0x6d,
+ DXGI_FORMAT_NV11 = 0x6e,
+ DXGI_FORMAT_AI44 = 0x6f,
+ DXGI_FORMAT_IA44 = 0x70,
+ DXGI_FORMAT_P8 = 0x71,
+ DXGI_FORMAT_A8P8 = 0x72,
+ DXGI_FORMAT_B4G4R4A4_UNORM = 0x73,
+
+ DXGI_FORMAT_FORCE_UINT = 0xffffffff,
+} DXGI_FORMAT;
diff --git a/dlls/vkd3d/include/vkd3d_dxgitype.h b/dlls/vkd3d/include/vkd3d_dxgitype.h
new file mode 100644
index 00000000000..b1761b52770
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgitype.h
@@ -0,0 +1,57 @@
+/*** Autogenerated by WIDL 5.17 from include/vkd3d_dxgitype.idl - Do not edit ***/
+
+#ifdef _WIN32
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+#include <rpc.h>
+#include <rpcndr.h>
+#endif
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __vkd3d_dxgitype_h__
+#define __vkd3d_dxgitype_h__
+
+/* Forward declarations */
+
+/* Headers for imported files */
+
+#include <vkd3d_windows.h>
+#include <vkd3d_dxgibase.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum DXGI_COLOR_SPACE_TYPE {
+ DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0x0,
+ DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 = 0x1,
+ DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709 = 0x2,
+ DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 = 0x3,
+ DXGI_COLOR_SPACE_RESERVED = 0x4,
+ DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 = 0x5,
+ DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 = 0x6,
+ DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601 = 0x7,
+ DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 = 0x8,
+ DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 = 0x9,
+ DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 = 0xa,
+ DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 = 0xb,
+ DXGI_COLOR_SPACE_CUSTOM = 0xffffffff
+} DXGI_COLOR_SPACE_TYPE;
+typedef struct _D3DCOLORVALUE D3DCOLORVALUE;
+typedef struct _D3DCOLORVALUE DXGI_RGBA;
+typedef struct DXGI_MODE_DESC DXGI_MODE_DESC;
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __vkd3d_dxgitype_h__ */
diff --git a/dlls/vkd3d/include/vkd3d_dxgitype.idl b/dlls/vkd3d/include/vkd3d_dxgitype.idl
new file mode 100644
index 00000000000..74806c0ce41
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_dxgitype.idl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ * Copyright 2016 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "vkd3d_windows.h";
+import "vkd3d_dxgibase.idl";
+
+typedef enum DXGI_COLOR_SPACE_TYPE
+{
+ DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0x0,
+ DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 = 0x1,
+ DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709 = 0x2,
+ DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 = 0x3,
+ DXGI_COLOR_SPACE_RESERVED = 0x4,
+ DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 = 0x5,
+ DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 = 0x6,
+ DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601 = 0x7,
+ DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 = 0x8,
+ DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 = 0x9,
+ DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 = 0xa,
+ DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 = 0xb,
+ DXGI_COLOR_SPACE_CUSTOM = 0xffffffff,
+} DXGI_COLOR_SPACE_TYPE;
+
+typedef struct _D3DCOLORVALUE D3DCOLORVALUE, DXGI_RGBA;
+typedef struct DXGI_MODE_DESC DXGI_MODE_DESC;
diff --git a/dlls/vkd3d/include/vkd3d_shader.h b/dlls/vkd3d/include/vkd3d_shader.h
new file mode 100644
index 00000000000..3efd355fda3
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_shader.h
@@ -0,0 +1,1502 @@
+/*
+ * Copyright 2017-2019 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_SHADER_H
+#define __VKD3D_SHADER_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <vkd3d_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * \file vkd3d_shader.h
+ *
+ * \since 1.2
+ *
+ * This file contains definitions for the vkd3d-shader library.
+ *
+ * The vkd3d-shader library provides multiple utilities related to the
+ * compilation, transformation, and reflection of GPU shaders.
+ */
+
+/** The type of a chained structure. */
+enum vkd3d_shader_structure_type
+{
+ /** The structure is a vkd3d_shader_compile_info structure. */
+ VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO,
+ /** The structure is a vkd3d_shader_interface_info structure. */
+ VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO,
+ /** The structure is a vkd3d_shader_scan_descriptor_info structure. */
+ VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO,
+ /** The structure is a vkd3d_shader_spirv_domain_shader_target_info structure. */
+ VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_DOMAIN_SHADER_TARGET_INFO,
+ /** The structure is a vkd3d_shader_spirv_target_info structure. */
+ VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO,
+ /** The structure is a vkd3d_shader_transform_feedback_info structure. */
+ VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
+};
+
+/**
+ * Determines how buffer UAVs are stored.
+ *
+ * This also affects UAV counters in Vulkan environments. In OpenGL
+ * environments, atomic counter buffers are always used for UAV counters.
+ */
+enum vkd3d_shader_compile_option_buffer_uav
+{
+ /** Use buffer textures for buffer UAVs. This is the default value. */
+ VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_TEXEL_BUFFER = 0x00000000,
+ /** Use storage buffers for buffer UAVs. */
+ VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_BUFFER = 0x00000001,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV),
+};
+
+enum vkd3d_shader_compile_option_formatting_flags
+{
+ VKD3D_SHADER_COMPILE_OPTION_FORMATTING_NONE = 0x00000000,
+ VKD3D_SHADER_COMPILE_OPTION_FORMATTING_COLOUR = 0x00000001,
+ VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT = 0x00000002,
+ VKD3D_SHADER_COMPILE_OPTION_FORMATTING_OFFSETS = 0x00000004,
+ VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER = 0x00000008,
+ VKD3D_SHADER_COMPILE_OPTION_FORMATTING_RAW_IDS = 0x00000010,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FORMATTING_FLAGS),
+};
+
+enum vkd3d_shader_compile_option_name
+{
+ /**
+ * If \a value is nonzero, do not include debug information in the
+ * compiled shader. The default value is zero.
+ *
+ * This option is supported by vkd3d_shader_compile(). However, not all
+ * compilers support generating debug information.
+ */
+ VKD3D_SHADER_COMPILE_OPTION_STRIP_DEBUG = 0x00000001,
+ /** \a value is a member of enum vkd3d_shader_compile_option_buffer_uav. */
+ VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV = 0x00000002,
+ /** \a value is a member of enum vkd3d_shader_compile_option_formatting_flags. */
+ VKD3D_SHADER_COMPILE_OPTION_FORMATTING = 0x00000003,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME),
+};
+
+/**
+ * Various settings which may affect shader compilation or scanning, passed as
+ * part of struct vkd3d_shader_compile_info. For more details, see the
+ * documentation for individual options.
+ */
+struct vkd3d_shader_compile_option
+{
+ /** Name of the option. */
+ enum vkd3d_shader_compile_option_name name;
+ /**
+ * A value associated with the option. The type and interpretation of the
+ * value depends on the option in question.
+ */
+ unsigned int value;
+};
+
+/** Describes which shader stages a resource is visible to. */
+enum vkd3d_shader_visibility
+{
+ /** The resource is visible to all shader stages. */
+ VKD3D_SHADER_VISIBILITY_ALL = 0,
+ /** The resource is visible only to the vertex shader. */
+ VKD3D_SHADER_VISIBILITY_VERTEX = 1,
+ /** The resource is visible only to the hull shader. */
+ VKD3D_SHADER_VISIBILITY_HULL = 2,
+ /** The resource is visible only to the domain shader. */
+ VKD3D_SHADER_VISIBILITY_DOMAIN = 3,
+ /** The resource is visible only to the geometry shader. */
+ VKD3D_SHADER_VISIBILITY_GEOMETRY = 4,
+ /** The resource is visible only to the pixel shader. */
+ VKD3D_SHADER_VISIBILITY_PIXEL = 5,
+
+ /** The resource is visible only to the compute shader. */
+ VKD3D_SHADER_VISIBILITY_COMPUTE = 1000000000,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_VISIBILITY),
+};
+
+/** A generic structure containing a GPU shader, in text or byte-code format. */
+struct vkd3d_shader_code
+{
+ /** Pointer to the code. */
+ const void *code;
+ /** Size of \a code, in bytes. */
+ size_t size;
+};
+
+/** The type of a shader resource descriptor. */
+enum vkd3d_shader_descriptor_type
+{
+ /**
+ * The descriptor is a shader resource view. In Direct3D assembly, this is
+ * bound to a t# register.
+ */
+ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV = 0x0,
+ /**
+ * The descriptor is an unordered access view. In Direct3D assembly, this is
+ * bound to a u# register.
+ */
+ VKD3D_SHADER_DESCRIPTOR_TYPE_UAV = 0x1,
+ /**
+ * The descriptor is a constant buffer view. In Direct3D assembly, this is
+ * bound to a cb# register.
+ */
+ VKD3D_SHADER_DESCRIPTOR_TYPE_CBV = 0x2,
+ /**
+ * The descriptor is a sampler. In Direct3D assembly, this is bound to an s#
+ * register.
+ */
+ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER = 0x3,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_TYPE),
+};
+
+/**
+ * A common structure describing the bind point of a descriptor or descriptor
+ * array in the target environment.
+ */
+struct vkd3d_shader_descriptor_binding
+{
+ /**
+ * The set of the descriptor. If the target environment does not support
+ * descriptor sets, this value must be set to 0.
+ */
+ unsigned int set;
+ /** The binding index of the descriptor. */
+ unsigned int binding;
+ /**
+ * The size of this descriptor array. Descriptor arrays are not supported in
+ * this version of vkd3d-shader, and therefore this value must be 1.
+ */
+ unsigned int count;
+};
+
+enum vkd3d_shader_binding_flag
+{
+ VKD3D_SHADER_BINDING_FLAG_BUFFER = 0x00000001,
+ VKD3D_SHADER_BINDING_FLAG_IMAGE = 0x00000002,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_BINDING_FLAG),
+};
+
+enum vkd3d_shader_parameter_type
+{
+ VKD3D_SHADER_PARAMETER_TYPE_UNKNOWN,
+ VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT,
+ VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_TYPE),
+};
+
+enum vkd3d_shader_parameter_data_type
+{
+ VKD3D_SHADER_PARAMETER_DATA_TYPE_UNKNOWN,
+ VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_DATA_TYPE),
+};
+
+enum vkd3d_shader_parameter_name
+{
+ VKD3D_SHADER_PARAMETER_NAME_UNKNOWN,
+ VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME),
+};
+
+struct vkd3d_shader_parameter_immediate_constant
+{
+ union
+ {
+ uint32_t u32;
+ } u;
+};
+
+struct vkd3d_shader_parameter_specialization_constant
+{
+ uint32_t id;
+};
+
+struct vkd3d_shader_parameter
+{
+ enum vkd3d_shader_parameter_name name;
+ enum vkd3d_shader_parameter_type type;
+ enum vkd3d_shader_parameter_data_type data_type;
+ union
+ {
+ struct vkd3d_shader_parameter_immediate_constant immediate_constant;
+ struct vkd3d_shader_parameter_specialization_constant specialization_constant;
+ } u;
+};
+
+/**
+ * Describes the mapping of a single resource or resource array to its binding
+ * point in the target environment.
+ *
+ * For example, to map a Direct3D SRV with register space 2, register "t3" to
+ * a Vulkan descriptor in set 4 and with binding 5, set the following members:
+ * - \a type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV
+ * - \a register_space = 2
+ * - \a register_index = 3
+ * - \a binding.set = 4
+ * - \a binding.binding = 5
+ * - \a binding.count = 1
+ *
+ * This structure is used in struct vkd3d_shader_interface_info.
+ */
+struct vkd3d_shader_resource_binding
+{
+ /** The type of this descriptor. */
+ enum vkd3d_shader_descriptor_type type;
+ /**
+ * Register space of the Direct3D resource. If the source format does not
+ * support multiple register spaces, this parameter must be set to 0.
+ */
+ unsigned int register_space;
+ /** Register index of the DXBC resource. */
+ unsigned int register_index;
+ /** Shader stage(s) to which the resource is visible. */
+ enum vkd3d_shader_visibility shader_visibility;
+ /** A combination of zero or more elements of vkd3d_shader_binding_flag. */
+ unsigned int flags;
+
+ /** The binding in the target environment. */
+ struct vkd3d_shader_descriptor_binding binding;
+};
+
+#define VKD3D_SHADER_DUMMY_SAMPLER_INDEX ~0u
+
+/**
+ * Describes the mapping of a Direct3D resource-sampler pair to a combined
+ * sampler (i.e. sampled image).
+ *
+ * This structure is used in struct vkd3d_shader_interface_info.
+ */
+struct vkd3d_shader_combined_resource_sampler
+{
+ /**
+ * Register space of the Direct3D resource. If the source format does not
+ * support multiple register spaces, this parameter must be set to 0.
+ */
+ unsigned int resource_space;
+ /** Register index of the Direct3D resource. */
+ unsigned int resource_index;
+ /**
+ * Register space of the Direct3D sampler. If the source format does not
+ * support multiple register spaces, this parameter must be set to 0.
+ */
+ unsigned int sampler_space;
+ /** Register index of the Direct3D sampler. */
+ unsigned int sampler_index;
+ /** Shader stage(s) to which the resource is visible. */
+ enum vkd3d_shader_visibility shader_visibility;
+ /** A combination of zero or more elements of vkd3d_shader_binding_flag. */
+ unsigned int flags;
+
+ /** The binding in the target environment. */
+ struct vkd3d_shader_descriptor_binding binding;
+};
+
+/**
+ * Describes the mapping of a single Direct3D UAV counter.
+ *
+ * This structure is used in struct vkd3d_shader_interface_info.
+ */
+struct vkd3d_shader_uav_counter_binding
+{
+ /**
+ * Register space of the Direct3D UAV descriptor. If the source format does
+ * not support multiple register spaces, this parameter must be set to 0.
+ */
+ unsigned int register_space;
+ /** Register index of the Direct3D UAV descriptor. */
+ unsigned int register_index;
+ /** Shader stage(s) to which the UAV counter is visible. */
+ enum vkd3d_shader_visibility shader_visibility;
+
+ /** The binding in the target environment. */
+ struct vkd3d_shader_descriptor_binding binding;
+ unsigned int offset;
+};
+
+/**
+ * Describes the mapping of a Direct3D constant buffer to a range of push
+ * constants in the target environment.
+ *
+ * This structure is used in struct vkd3d_shader_interface_info.
+ */
+struct vkd3d_shader_push_constant_buffer
+{
+ /**
+ * Register space of the Direct3D resource. If the source format does not
+ * support multiple register spaces, this parameter must be set to 0.
+ */
+ unsigned int register_space;
+ /** Register index of the Direct3D resource. */
+ unsigned int register_index;
+ /** Shader stage(s) to which the resource is visible. */
+ enum vkd3d_shader_visibility shader_visibility;
+
+ /** Offset, in bytes, of the target push constants. */
+ unsigned int offset;
+ /** Size, in bytes, of the target push constants. */
+ unsigned int size;
+};
+
+/**
+ * A chained structure describing the interface between a compiled shader and
+ * the target environment.
+ *
+ * For example, when compiling Direct3D shader byte code to SPIR-V, this
+ * structure contains mappings from Direct3D descriptor registers to SPIR-V
+ * descriptor bindings.
+ *
+ * This structure is optional. If omitted, vkd3d_shader_compile() will use a
+ * default mapping, in which resources are mapped to sequential bindings in
+ * register set 0.
+ *
+ * This structure extends vkd3d_shader_compile_info.
+ *
+ * This structure contains only input parameters.
+ */
+struct vkd3d_shader_interface_info
+{
+ /** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO. */
+ enum vkd3d_shader_structure_type type;
+ /** Optional pointer to a structure containing further parameters. */
+ const void *next;
+
+ /** Pointer to an array of bindings for shader resource descriptors. */
+ const struct vkd3d_shader_resource_binding *bindings;
+ /** Size, in elements, of \ref bindings. */
+ unsigned int binding_count;
+
+ /** Pointer to an array of bindings for push constant buffers. */
+ const struct vkd3d_shader_push_constant_buffer *push_constant_buffers;
+ /** Size, in elements, of \ref push_constant_buffers. */
+ unsigned int push_constant_buffer_count;
+
+ /** Pointer to an array of bindings for combined samplers. */
+ const struct vkd3d_shader_combined_resource_sampler *combined_samplers;
+ /** Size, in elements, of \ref combined_samplers. */
+ unsigned int combined_sampler_count;
+
+ /** Pointer to an array of bindings for UAV counters. */
+ const struct vkd3d_shader_uav_counter_binding *uav_counters;
+ /** Size, in elements, of \ref uav_counters. */
+ unsigned int uav_counter_count;
+};
+
+struct vkd3d_shader_transform_feedback_element
+{
+ unsigned int stream_index;
+ const char *semantic_name;
+ unsigned int semantic_index;
+ uint8_t component_index;
+ uint8_t component_count;
+ uint8_t output_slot;
+};
+
+/* Extends vkd3d_shader_interface_info. */
+struct vkd3d_shader_transform_feedback_info
+{
+ enum vkd3d_shader_structure_type type;
+ const void *next;
+
+ const struct vkd3d_shader_transform_feedback_element *elements;
+ unsigned int element_count;
+ const unsigned int *buffer_strides;
+ unsigned int buffer_stride_count;
+};
+
+/** The format of a shader to be compiled or scanned. */
+enum vkd3d_shader_source_type
+{
+ /**
+ * The shader has no type or is to be ignored. This is not a valid value
+ * for vkd3d_shader_compile() or vkd3d_shader_scan().
+ */
+ VKD3D_SHADER_SOURCE_NONE,
+ /**
+ * A 'Tokenized Program Format' shader embedded in a DXBC container. This is
+ * the format used for Direct3D shader model 4 and 5 shaders.
+ */
+ VKD3D_SHADER_SOURCE_DXBC_TPF,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SOURCE_TYPE),
+};
+
+/** The output format of a compiled shader. */
+enum vkd3d_shader_target_type
+{
+ /**
+ * The shader has no type or is to be ignored. This is not a valid value
+ * for vkd3d_shader_compile() or vkd3d_shader_scan().
+ */
+ VKD3D_SHADER_TARGET_NONE,
+ /**
+ * A SPIR-V shader in binary form. This is the format used for Vulkan
+ * shaders.
+ */
+ VKD3D_SHADER_TARGET_SPIRV_BINARY,
+ VKD3D_SHADER_TARGET_SPIRV_TEXT,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET_TYPE),
+};
+
+/**
+ * Describes the minimum severity of compilation messages returned by
+ * vkd3d_shader_compile() and similar functions.
+ */
+enum vkd3d_shader_log_level
+{
+ /** No messages will be returned. */
+ VKD3D_SHADER_LOG_NONE,
+ /** Only fatal errors which prevent successful compilation will be returned. */
+ VKD3D_SHADER_LOG_ERROR,
+ /** Non-fatal warnings and fatal errors will be returned. */
+ VKD3D_SHADER_LOG_WARNING,
+ /**
+ * All messages, including general informational messages, will be returned.
+ */
+ VKD3D_SHADER_LOG_INFO,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_LOG_LEVEL),
+};
+
+/**
+ * A chained structure containing compilation parameters.
+ */
+struct vkd3d_shader_compile_info
+{
+ /** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO. */
+ enum vkd3d_shader_structure_type type;
+ /**
+ * Optional pointer to a structure containing further parameters. For a list
+ * of valid structures, refer to the respective function documentation. If
+ * no further parameters are needed, this field should be set to NULL.
+ */
+ const void *next;
+
+ /** Input source code or byte code. */
+ struct vkd3d_shader_code source;
+
+ /** Format of the input code passed in \ref source. */
+ enum vkd3d_shader_source_type source_type;
+ /** Desired output format. */
+ enum vkd3d_shader_target_type target_type;
+
+ /**
+ * Pointer to an array of compilation options. This field is ignored if
+ * \ref option_count is zero, but must be valid otherwise.
+ *
+ * If the same option is specified multiple times, only the last value is
+ * used.
+ *
+ * Options not relevant to or not supported by a particular shader compiler
+ * or scanner will be ignored.
+ */
+ const struct vkd3d_shader_compile_option *options;
+ /** Size, in elements, of \ref options. */
+ unsigned int option_count;
+
+ /** Minimum severity of messages returned from the shader function. */
+ enum vkd3d_shader_log_level log_level;
+ /**
+ * Name of the initial source file, which may be used in error messages or
+ * debug information. This parameter is optional and may be NULL.
+ */
+ const char *source_name;
+};
+
+enum vkd3d_shader_spirv_environment
+{
+ VKD3D_SHADER_SPIRV_ENVIRONMENT_NONE,
+ VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5,
+ VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0, /* default target */
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SPIRV_ENVIRONMENT),
+};
+
+enum vkd3d_shader_spirv_extension
+{
+ VKD3D_SHADER_SPIRV_EXTENSION_NONE,
+ VKD3D_SHADER_SPIRV_EXTENSION_EXT_DEMOTE_TO_HELPER_INVOCATION,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SPIRV_EXTENSION),
+};
+
+/* Extends vkd3d_shader_compile_info. */
+struct vkd3d_shader_spirv_target_info
+{
+ enum vkd3d_shader_structure_type type;
+ const void *next;
+
+ const char *entry_point; /* "main" if NULL. */
+
+ enum vkd3d_shader_spirv_environment environment;
+
+ const enum vkd3d_shader_spirv_extension *extensions;
+ unsigned int extension_count;
+
+ const struct vkd3d_shader_parameter *parameters;
+ unsigned int parameter_count;
+
+ bool dual_source_blending;
+ const unsigned int *output_swizzles;
+ unsigned int output_swizzle_count;
+};
+
+enum vkd3d_shader_tessellator_output_primitive
+{
+ VKD3D_SHADER_TESSELLATOR_OUTPUT_POINT = 0x1,
+ VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE = 0x2,
+ VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CW = 0x3,
+ VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW = 0x4,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TESSELLATOR_OUTPUT_PRIMITIVE),
+};
+
+enum vkd3d_shader_tessellator_partitioning
+{
+ VKD3D_SHADER_TESSELLATOR_PARTITIONING_INTEGER = 0x1,
+ VKD3D_SHADER_TESSELLATOR_PARTITIONING_POW2 = 0x2,
+ VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 0x3,
+ VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 0x4,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TESSELLATOR_PARTITIONING),
+};
+
+/* Extends vkd3d_shader_spirv_target_info. */
+struct vkd3d_shader_spirv_domain_shader_target_info
+{
+ enum vkd3d_shader_structure_type type;
+ const void *next;
+
+ enum vkd3d_shader_tessellator_output_primitive output_primitive;
+ enum vkd3d_shader_tessellator_partitioning partitioning;
+};
+
+/* root signature 1.0 */
+enum vkd3d_shader_filter
+{
+ VKD3D_SHADER_FILTER_MIN_MAG_MIP_POINT = 0x000,
+ VKD3D_SHADER_FILTER_MIN_MAG_POINT_MIP_LINEAR = 0x001,
+ VKD3D_SHADER_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x004,
+ VKD3D_SHADER_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x005,
+ VKD3D_SHADER_FILTER_MIN_LINEAR_MAG_MIP_POINT = 0x010,
+ VKD3D_SHADER_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x011,
+ VKD3D_SHADER_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x014,
+ VKD3D_SHADER_FILTER_MIN_MAG_MIP_LINEAR = 0x015,
+ VKD3D_SHADER_FILTER_ANISOTROPIC = 0x055,
+ VKD3D_SHADER_FILTER_COMPARISON_MIN_MAG_MIP_POINT = 0x080,
+ VKD3D_SHADER_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x081,
+ VKD3D_SHADER_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x084,
+ VKD3D_SHADER_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR = 0x085,
+ VKD3D_SHADER_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT = 0x090,
+ VKD3D_SHADER_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x091,
+ VKD3D_SHADER_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x094,
+ VKD3D_SHADER_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR = 0x095,
+ VKD3D_SHADER_FILTER_COMPARISON_ANISOTROPIC = 0x0d5,
+ VKD3D_SHADER_FILTER_MINIMUM_MIN_MAG_MIP_POINT = 0x100,
+ VKD3D_SHADER_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x101,
+ VKD3D_SHADER_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x104,
+ VKD3D_SHADER_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR = 0x105,
+ VKD3D_SHADER_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT = 0x110,
+ VKD3D_SHADER_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x111,
+ VKD3D_SHADER_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x114,
+ VKD3D_SHADER_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR = 0x115,
+ VKD3D_SHADER_FILTER_MINIMUM_ANISOTROPIC = 0x155,
+ VKD3D_SHADER_FILTER_MAXIMUM_MIN_MAG_MIP_POINT = 0x180,
+ VKD3D_SHADER_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x181,
+ VKD3D_SHADER_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x184,
+ VKD3D_SHADER_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR = 0x185,
+ VKD3D_SHADER_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT = 0x190,
+ VKD3D_SHADER_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x191,
+ VKD3D_SHADER_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x194,
+ VKD3D_SHADER_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR = 0x195,
+ VKD3D_SHADER_FILTER_MAXIMUM_ANISOTROPIC = 0x1d5,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_FILTER),
+};
+
+enum vkd3d_shader_texture_address_mode
+{
+ VKD3D_SHADER_TEXTURE_ADDRESS_MODE_WRAP = 0x1,
+ VKD3D_SHADER_TEXTURE_ADDRESS_MODE_MIRROR = 0x2,
+ VKD3D_SHADER_TEXTURE_ADDRESS_MODE_CLAMP = 0x3,
+ VKD3D_SHADER_TEXTURE_ADDRESS_MODE_BORDER = 0x4,
+ VKD3D_SHADER_TEXTURE_ADDRESS_MODE_MIRROR_ONCE = 0x5,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TEXTURE_ADDRESS_MODE),
+};
+
+enum vkd3d_shader_comparison_func
+{
+ VKD3D_SHADER_COMPARISON_FUNC_NEVER = 0x1,
+ VKD3D_SHADER_COMPARISON_FUNC_LESS = 0x2,
+ VKD3D_SHADER_COMPARISON_FUNC_EQUAL = 0x3,
+ VKD3D_SHADER_COMPARISON_FUNC_LESS_EQUAL = 0x4,
+ VKD3D_SHADER_COMPARISON_FUNC_GREATER = 0x5,
+ VKD3D_SHADER_COMPARISON_FUNC_NOT_EQUAL = 0x6,
+ VKD3D_SHADER_COMPARISON_FUNC_GREATER_EQUAL = 0x7,
+ VKD3D_SHADER_COMPARISON_FUNC_ALWAYS = 0x8,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPARISON_FUNC),
+};
+
+enum vkd3d_shader_static_border_colour
+{
+ VKD3D_SHADER_STATIC_BORDER_COLOUR_TRANSPARENT_BLACK = 0x0,
+ VKD3D_SHADER_STATIC_BORDER_COLOUR_OPAQUE_BLACK = 0x1,
+ VKD3D_SHADER_STATIC_BORDER_COLOUR_OPAQUE_WHITE = 0x2,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STATIC_BORDER_COLOUR),
+};
+
+struct vkd3d_shader_static_sampler_desc
+{
+ enum vkd3d_shader_filter filter;
+ enum vkd3d_shader_texture_address_mode address_u;
+ enum vkd3d_shader_texture_address_mode address_v;
+ enum vkd3d_shader_texture_address_mode address_w;
+ float mip_lod_bias;
+ unsigned int max_anisotropy;
+ enum vkd3d_shader_comparison_func comparison_func;
+ enum vkd3d_shader_static_border_colour border_colour;
+ float min_lod;
+ float max_lod;
+ unsigned int shader_register;
+ unsigned int register_space;
+ enum vkd3d_shader_visibility shader_visibility;
+};
+
+struct vkd3d_shader_descriptor_range
+{
+ enum vkd3d_shader_descriptor_type range_type;
+ unsigned int descriptor_count;
+ unsigned int base_shader_register;
+ unsigned int register_space;
+ unsigned int descriptor_table_offset;
+};
+
+struct vkd3d_shader_root_descriptor_table
+{
+ unsigned int descriptor_range_count;
+ const struct vkd3d_shader_descriptor_range *descriptor_ranges;
+};
+
+struct vkd3d_shader_root_constants
+{
+ unsigned int shader_register;
+ unsigned int register_space;
+ unsigned int value_count;
+};
+
+struct vkd3d_shader_root_descriptor
+{
+ unsigned int shader_register;
+ unsigned int register_space;
+};
+
+enum vkd3d_shader_root_parameter_type
+{
+ VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE = 0x0,
+ VKD3D_SHADER_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS = 0x1,
+ VKD3D_SHADER_ROOT_PARAMETER_TYPE_CBV = 0x2,
+ VKD3D_SHADER_ROOT_PARAMETER_TYPE_SRV = 0x3,
+ VKD3D_SHADER_ROOT_PARAMETER_TYPE_UAV = 0x4,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_ROOT_PARAMETER_TYPE),
+};
+
+struct vkd3d_shader_root_parameter
+{
+ enum vkd3d_shader_root_parameter_type parameter_type;
+ union
+ {
+ struct vkd3d_shader_root_descriptor_table descriptor_table;
+ struct vkd3d_shader_root_constants constants;
+ struct vkd3d_shader_root_descriptor descriptor;
+ } u;
+ enum vkd3d_shader_visibility shader_visibility;
+};
+
+enum vkd3d_shader_root_signature_flags
+{
+ VKD3D_SHADER_ROOT_SIGNATURE_FLAG_NONE = 0x00,
+ VKD3D_SHADER_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0x01,
+ VKD3D_SHADER_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS = 0x02,
+ VKD3D_SHADER_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS = 0x04,
+ VKD3D_SHADER_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS = 0x08,
+ VKD3D_SHADER_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS = 0x10,
+ VKD3D_SHADER_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20,
+ VKD3D_SHADER_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT = 0x40,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_ROOT_SIGNATURE_FLAGS),
+};
+
+struct vkd3d_shader_root_signature_desc
+{
+ unsigned int parameter_count;
+ const struct vkd3d_shader_root_parameter *parameters;
+ unsigned int static_sampler_count;
+ const struct vkd3d_shader_static_sampler_desc *static_samplers;
+ enum vkd3d_shader_root_signature_flags flags;
+};
+
+/* root signature 1.1 */
+enum vkd3d_shader_root_descriptor_flags
+{
+ VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_NONE = 0x0,
+ VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE = 0x2,
+ VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
+ VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_DATA_STATIC = 0x8,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_ROOT_DESCRIPTOR_FLAGS),
+};
+
+enum vkd3d_shader_descriptor_range_flags
+{
+ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_NONE = 0x0,
+ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE = 0x1,
+ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2,
+ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
+ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_RANGE_FLAGS),
+};
+
+struct vkd3d_shader_descriptor_range1
+{
+ enum vkd3d_shader_descriptor_type range_type;
+ unsigned int descriptor_count;
+ unsigned int base_shader_register;
+ unsigned int register_space;
+ enum vkd3d_shader_descriptor_range_flags flags;
+ unsigned int descriptor_table_offset;
+};
+
+struct vkd3d_shader_root_descriptor_table1
+{
+ unsigned int descriptor_range_count;
+ const struct vkd3d_shader_descriptor_range1 *descriptor_ranges;
+};
+
+struct vkd3d_shader_root_descriptor1
+{
+ unsigned int shader_register;
+ unsigned int register_space;
+ enum vkd3d_shader_root_descriptor_flags flags;
+};
+
+struct vkd3d_shader_root_parameter1
+{
+ enum vkd3d_shader_root_parameter_type parameter_type;
+ union
+ {
+ struct vkd3d_shader_root_descriptor_table1 descriptor_table;
+ struct vkd3d_shader_root_constants constants;
+ struct vkd3d_shader_root_descriptor1 descriptor;
+ } u;
+ enum vkd3d_shader_visibility shader_visibility;
+};
+
+struct vkd3d_shader_root_signature_desc1
+{
+ unsigned int parameter_count;
+ const struct vkd3d_shader_root_parameter1 *parameters;
+ unsigned int static_sampler_count;
+ const struct vkd3d_shader_static_sampler_desc *static_samplers;
+ enum vkd3d_shader_root_signature_flags flags;
+};
+
+enum vkd3d_shader_root_signature_version
+{
+ VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0 = 0x1,
+ VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1 = 0x2,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_ROOT_SIGNATURE_VERSION),
+};
+
+struct vkd3d_shader_versioned_root_signature_desc
+{
+ enum vkd3d_shader_root_signature_version version;
+ union
+ {
+ struct vkd3d_shader_root_signature_desc v_1_0;
+ struct vkd3d_shader_root_signature_desc1 v_1_1;
+ } u;
+};
+
+/**
+ * The type of a shader resource, returned as part of struct
+ * vkd3d_shader_descriptor_info.
+ */
+enum vkd3d_shader_resource_type
+{
+ /**
+ * The type is invalid or not applicable for this descriptor. This value is
+ * returned for samplers.
+ */
+ VKD3D_SHADER_RESOURCE_NONE = 0x0,
+ /** Dimensionless buffer. */
+ VKD3D_SHADER_RESOURCE_BUFFER = 0x1,
+ /** 1-dimensional texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_1D = 0x2,
+ /** 2-dimensional texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_2D = 0x3,
+ /** Multisampled 2-dimensional texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_2DMS = 0x4,
+ /** 3-dimensional texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_3D = 0x5,
+ /** Cubemap texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_CUBE = 0x6,
+ /** 1-dimensional array texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY = 0x7,
+ /** 2-dimensional array texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY = 0x8,
+ /** Multisampled 2-dimensional array texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY = 0x9,
+ /** Cubemap array texture. */
+ VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY = 0xa,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_RESOURCE_TYPE),
+};
+
+/**
+ * The type of the data contained in a shader resource, returned as part of
+ * struct vkd3d_shader_descriptor_info. All formats are 32-bit.
+ */
+enum vkd3d_shader_resource_data_type
+{
+ /** Unsigned normalized integer. */
+ VKD3D_SHADER_RESOURCE_DATA_UNORM = 0x1,
+ /** Signed normalized integer. */
+ VKD3D_SHADER_RESOURCE_DATA_SNORM = 0x2,
+ /** Signed integer. */
+ VKD3D_SHADER_RESOURCE_DATA_INT = 0x3,
+ /** Unsigned integer. */
+ VKD3D_SHADER_RESOURCE_DATA_UINT = 0x4,
+ /** IEEE floating-point. */
+ VKD3D_SHADER_RESOURCE_DATA_FLOAT = 0x5,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_RESOURCE_DATA_TYPE),
+};
+
+/**
+ * Additional flags describing a shader descriptor, returned as part of struct
+ * vkd3d_shader_descriptor_info.
+ */
+enum vkd3d_shader_descriptor_info_flag
+{
+ /**
+ * The descriptor is a UAV resource, whose counter is read from or written
+ * to by the shader.
+ */
+ VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER = 0x00000001,
+ /** The descriptor is a UAV resource, which is read from by the shader. */
+ VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ = 0x00000002,
+ /** The descriptor is a comparison sampler. */
+ VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE = 0x00000004,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_INFO_FLAG),
+};
+
+/**
+ * Describes a single shader descriptor; returned as part of
+ * struct vkd3d_shader_scan_descriptor_info.
+ */
+struct vkd3d_shader_descriptor_info
+{
+ /** Type of the descriptor (for example, SRV, CBV, UAV, or sampler). */
+ enum vkd3d_shader_descriptor_type type;
+ /**
+ * Register space of the resource, or 0 if the shader does not
+ * support multiple register spaces.
+ */
+ unsigned int register_space;
+ /** Register index of the descriptor. */
+ unsigned int register_index;
+ /** Resource type, if applicable, including its dimension. */
+ enum vkd3d_shader_resource_type resource_type;
+ /** Data type contained in the resource (for example, float or integer). */
+ enum vkd3d_shader_resource_data_type resource_data_type;
+ /**
+ * Bitwise combination of zero or more members of
+ * \ref vkd3d_shader_descriptor_info_flag.
+ */
+ unsigned int flags;
+ /** Size of this descriptor array, or 1 if a single descriptor. */
+ unsigned int count;
+};
+
+/**
+ * A chained structure enumerating the descriptors declared by a shader.
+ *
+ * This structure extends vkd3d_shader_compile_info.
+ */
+struct vkd3d_shader_scan_descriptor_info
+{
+ /**
+ * Input; must be set to VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO.
+ */
+ enum vkd3d_shader_structure_type type;
+ /** Input; optional pointer to a structure containing further parameters. */
+ const void *next;
+
+ /** Output; returns a pointer to an array of descriptors. */
+ struct vkd3d_shader_descriptor_info *descriptors;
+ /** Output; size, in elements, of \ref descriptors. */
+ unsigned int descriptor_count;
+};
+
+/**
+ * Data type of a shader varying, returned as part of struct
+ * vkd3d_shader_signature_element.
+ */
+enum vkd3d_shader_component_type
+{
+ /** The varying has no type. */
+ VKD3D_SHADER_COMPONENT_VOID = 0x0,
+ /** 32-bit unsigned integer. */
+ VKD3D_SHADER_COMPONENT_UINT = 0x1,
+ /** 32-bit signed integer. */
+ VKD3D_SHADER_COMPONENT_INT = 0x2,
+ /** 32-bit IEEE floating-point. */
+ VKD3D_SHADER_COMPONENT_FLOAT = 0x3,
+ /** Boolean. */
+ VKD3D_SHADER_COMPONENT_BOOL = 0x4,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPONENT_TYPE),
+};
+
+/** System value semantic, returned as part of struct vkd3d_shader_signature. */
+enum vkd3d_shader_sysval_semantic
+{
+ /** No system value. */
+ VKD3D_SHADER_SV_NONE = 0x00,
+ /** Vertex position; SV_Position in Direct3D. */
+ VKD3D_SHADER_SV_POSITION = 0x01,
+ /** Clip distance; SV_ClipDistance in Direct3D. */
+ VKD3D_SHADER_SV_CLIP_DISTANCE = 0x02,
+ /** Cull distance; SV_CullDistance in Direct3D. */
+ VKD3D_SHADER_SV_CULL_DISTANCE = 0x03,
+ /** Render target layer; SV_RenderTargetArrayIndex in Direct3D. */
+ VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX = 0x04,
+ /** Viewport index; SV_ViewportArrayIndex in Direct3D. */
+ VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX = 0x05,
+ /** Vertex ID; SV_VertexID in Direct3D. */
+ VKD3D_SHADER_SV_VERTEX_ID = 0x06,
+ /** Primtive ID; SV_PrimitiveID in Direct3D. */
+ VKD3D_SHADER_SV_PRIMITIVE_ID = 0x07,
+ /** Instance ID; SV_InstanceID in Direct3D. */
+ VKD3D_SHADER_SV_INSTANCE_ID = 0x08,
+ /** Whether the triangle is front-facing; SV_IsFrontFace in Direct3D. */
+ VKD3D_SHADER_SV_IS_FRONT_FACE = 0x09,
+ /** Sample index; SV_SampleIndex in Direct3D. */
+ VKD3D_SHADER_SV_SAMPLE_INDEX = 0x0a,
+ VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE = 0x0b,
+ VKD3D_SHADER_SV_TESS_FACTOR_QUADINT = 0x0c,
+ VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE = 0x0d,
+ VKD3D_SHADER_SV_TESS_FACTOR_TRIINT = 0x0e,
+ VKD3D_SHADER_SV_TESS_FACTOR_LINEDET = 0x0f,
+ VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN = 0x10,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SYSVAL_SEMANTIC),
+};
+
+/**
+ * Minimum interpolation precision of a shader varying, returned as part of
+ * struct vkd3d_shader_signature_element.
+ */
+enum vkd3d_shader_minimum_precision
+{
+ VKD3D_SHADER_MINIMUM_PRECISION_NONE = 0,
+ /** 16-bit floating-point. */
+ VKD3D_SHADER_MINIMUM_PRECISION_FLOAT_16 = 1,
+ /** 10-bit fixed point (2 integer and 8 fractional bits). */
+ VKD3D_SHADER_MINIMUM_PRECISION_FIXED_8_2 = 2,
+ /** 16-bit signed integer. */
+ VKD3D_SHADER_MINIMUM_PRECISION_INT_16 = 4,
+ /** 16-bit unsigned integer. */
+ VKD3D_SHADER_MINIMUM_PRECISION_UINT_16 = 5,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_MINIMUM_PRECISION),
+};
+
+/**
+ * A single shader varying, returned as part of struct vkd3d_shader_signature.
+ */
+struct vkd3d_shader_signature_element
+{
+ /** Semantic name. */
+ const char *semantic_name;
+ /** Semantic index, or 0 if the semantic is not indexed. */
+ unsigned int semantic_index;
+ /**
+ * Stream index of a geometry shader output semantic. If the signature is
+ * not a geometry shader output signature, this field will be set to 0.
+ */
+ unsigned int stream_index;
+ /**
+ * System value semantic. If the varying is not a system value, this field
+ * will be set to VKD3D_SHADER_SV_NONE.
+ */
+ enum vkd3d_shader_sysval_semantic sysval_semantic;
+ /** Data type. */
+ enum vkd3d_shader_component_type component_type;
+ /** Register index. */
+ unsigned int register_index;
+ /** Mask of the register components allocated to this varying. */
+ unsigned int mask;
+ /**
+ * Subset of \ref mask which the shader reads from or writes to. Unlike
+ * Direct3D shader bytecode, the mask for output and tessellation signatures
+ * is not inverted, i.e. bits set in this field denote components which are
+ * written to.
+ */
+ unsigned int used_mask;
+ /** Minimum interpolation precision. */
+ enum vkd3d_shader_minimum_precision min_precision;
+};
+
+/**
+ * Description of a shader input or output signature. This structure is
+ * populated by vkd3d_shader_parse_input_signature().
+ *
+ * The helper function vkd3d_shader_find_signature_element() will look up a
+ * varying element by its semantic name, semantic index, and stream index.
+ */
+struct vkd3d_shader_signature
+{
+ /** Pointer to an array of varyings. */
+ struct vkd3d_shader_signature_element *elements;
+ /** Size, in elements, of \ref elements. */
+ unsigned int element_count;
+};
+
+/** Possible values for a single component of a vkd3d-shader swizzle. */
+enum vkd3d_shader_swizzle_component
+{
+ VKD3D_SHADER_SWIZZLE_X = 0x0,
+ VKD3D_SHADER_SWIZZLE_Y = 0x1,
+ VKD3D_SHADER_SWIZZLE_Z = 0x2,
+ VKD3D_SHADER_SWIZZLE_W = 0x3,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SWIZZLE_COMPONENT),
+};
+
+/**
+ * A mask selecting one component from a vkd3d-shader swizzle. The component has
+ * type \ref vkd3d_shader_swizzle_component.
+ */
+#define VKD3D_SHADER_SWIZZLE_MASK (0xffu)
+/** The offset, in bits, of the nth parameter of a vkd3d-shader swizzle. */
+#define VKD3D_SHADER_SWIZZLE_SHIFT(idx) (8u * (idx))
+
+/**
+ * A helper macro which returns a vkd3d-shader swizzle with the given
+ * components. The components are specified as the suffixes to members of
+ * \ref vkd3d_shader_swizzle_component. For example, the swizzle ".xwyy" can be
+ * represented as:
+ * \code
+ * VKD3D_SHADER_SWIZZLE(X, W, Y, Y)
+ * \endcode
+ */
+#define VKD3D_SHADER_SWIZZLE(x, y, z, w) \
+ vkd3d_shader_create_swizzle(VKD3D_SHADER_SWIZZLE_ ## x, \
+ VKD3D_SHADER_SWIZZLE_ ## y, \
+ VKD3D_SHADER_SWIZZLE_ ## z, \
+ VKD3D_SHADER_SWIZZLE_ ## w)
+
+/** The identity swizzle ".xyzw". */
+#define VKD3D_SHADER_NO_SWIZZLE VKD3D_SHADER_SWIZZLE(X, Y, Z, W)
+
+/** Build a vkd3d-shader swizzle with the given components. */
+static inline uint32_t vkd3d_shader_create_swizzle(enum vkd3d_shader_swizzle_component x,
+ enum vkd3d_shader_swizzle_component y, enum vkd3d_shader_swizzle_component z,
+ enum vkd3d_shader_swizzle_component w)
+{
+ return ((x & VKD3D_SHADER_SWIZZLE_MASK) << VKD3D_SHADER_SWIZZLE_SHIFT(0))
+ | ((y & VKD3D_SHADER_SWIZZLE_MASK) << VKD3D_SHADER_SWIZZLE_SHIFT(1))
+ | ((z & VKD3D_SHADER_SWIZZLE_MASK) << VKD3D_SHADER_SWIZZLE_SHIFT(2))
+ | ((w & VKD3D_SHADER_SWIZZLE_MASK) << VKD3D_SHADER_SWIZZLE_SHIFT(3));
+}
+
+#ifndef VKD3D_SHADER_NO_PROTOTYPES
+
+/**
+ * Returns the current version of this library.
+ *
+ * \param major Output location for the major version of this library.
+ *
+ * \param minor Output location for the minor version of this library.
+ *
+ * \return A human-readable string describing the library name and version. This
+ * string is null-terminated and UTF-8 encoded. This may be a pointer to static
+ * data in libvkd3d-shader; it should not be freed.
+ */
+const char *vkd3d_shader_get_version(unsigned int *major, unsigned int *minor);
+/**
+ * Returns the source types supported, with any target type, by
+ * vkd3d_shader_compile().
+ *
+ * Use vkd3d_shader_get_supported_target_types() to determine which target types
+ * are supported for each source type.
+ *
+ * \param count Output location for the size, in elements, of the returned
+ * array.
+ *
+ * \return Pointer to an array of source types supported by this version of
+ * vkd3d-shader. This array may be a pointer to static data in libvkd3d-shader;
+ * it should not be freed.
+ */
+const enum vkd3d_shader_source_type *vkd3d_shader_get_supported_source_types(unsigned int *count);
+/**
+ * Returns the target types supported, with the given source type, by
+ * vkd3d_shader_compile().
+ *
+ * \param source_type Source type for which to enumerate supported target types.
+ *
+ * \param count Output location for the size, in elements, of the returned
+ * array.
+ *
+ * \return Pointer to an array of target types supported by this version of
+ * vkd3d-shader. This array may be a pointer to static data in libvkd3d-shader;
+ * it should not be freed.
+ */
+const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
+ enum vkd3d_shader_source_type source_type, unsigned int *count);
+
+/**
+ * Transform a form of GPU shader source code or byte code into another form of
+ * source code or byte code.
+ *
+ * This version of vkd3d-shader supports the following transformations:
+ * - VKD3D_SHADER_SOURCE_DXBC_TPF to VKD3D_SHADER_TARGET_SPIRV_BINARY
+ *
+ * Supported transformations can also be detected at runtime with the functions
+ * vkd3d_shader_get_supported_source_types() and
+ * vkd3d_shader_get_supported_target_types().
+ *
+ * Depending on the source and target types, this function may support the
+ * following chained structures:
+ * - vkd3d_shader_interface_info
+ * - vkd3d_shader_spirv_domain_shader_target_info
+ * - vkd3d_shader_spirv_target_info
+ * - vkd3d_shader_transform_feedback_info
+ *
+ * \param compile_info A chained structure containing compilation parameters.
+ *
+ * \param out A pointer to a vkd3d_shader_code structure in which the compiled
+ * code will be stored.
+ * \n
+ * The compiled shader is allocated by vkd3d-shader and should be freed with
+ * vkd3d_shader_free_shader_code() when no longer needed.
+ *
+ * \param messages Optional output location for error or informational messages
+ * produced by the compiler.
+ * \n
+ * This string is null-terminated and UTF-8 encoded.
+ * \n
+ * The messages are allocated by vkd3d-shader and should be freed with
+ * vkd3d_shader_free_messages() when no longer needed.
+ * \n
+ * The messages returned can be regulated with the \a log_level member of struct
+ * vkd3d_shader_compile_info. Regardless of the requested level, if this
+ * parameter is NULL, no compilation messages will be returned.
+ * \n
+ * If no compilation messages are produced by the compiler, this parameter may
+ * receive NULL instead of a valid string pointer.
+ *
+ * \return A member of \ref vkd3d_result.
+ */
+int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
+ struct vkd3d_shader_code *out, char **messages);
+/**
+ * Free shader messages allocated by another vkd3d-shader function, such as
+ * vkd3d_shader_compile().
+ *
+ * \param messages Messages to free. This pointer is optional and may be NULL,
+ * in which case no action will be taken.
+ */
+void vkd3d_shader_free_messages(char *messages);
+/**
+ * Free shader code allocated by another vkd3d-shader function, such as
+ * vkd3d_shader_compile().
+ *
+ * This function frees the \ref vkd3d_shader_code.code member, but does not free
+ * the structure itself.
+ *
+ * \param code Code to free.
+ */
+void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code);
+
+/**
+ * Convert a byte code description of a shader root signature to a structural
+ * description which can be easily parsed by C code.
+ *
+ * This function corresponds to
+ * ID3D12VersionedRootSignatureDeserializer::GetUnconvertedRootSignatureDesc().
+ *
+ * This function performs the reverse transformation of
+ * vkd3d_shader_serialize_root_signature().
+ *
+ * This function parses a standalone root signature, and should not be confused
+ * with vkd3d_shader_parse_input_signature().
+ *
+ * \param dxbc Compiled byte code, in DXBC format.
+ *
+ * \param root_signature Output location in which the decompiled root signature
+ * will be stored.
+ * \n
+ * Members of \a root_signature may be allocated by vkd3d-shader. The signature
+ * should be freed with vkd3d_shader_free_root_signature() when no longer
+ * needed.
+ *
+ * \param messages Optional output location for error or informational messages
+ * produced by the compiler.
+ * \n
+ * This parameter behaves identically to the \a messages parameter of
+ * vkd3d_shader_compile().
+ *
+ * \return A member of \ref vkd3d_result.
+ */
+int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
+ struct vkd3d_shader_versioned_root_signature_desc *root_signature, char **messages);
+/**
+ * Free a structural representation of a shader root signature allocated by
+ * vkd3d_shader_convert_root_signature() or vkd3d_shader_parse_root_signature().
+ *
+ * This function may free members of struct
+ * vkd3d_shader_versioned_root_signature_desc, but does not free the structure
+ * itself.
+ *
+ * \param root_signature Signature description to free.
+ */
+void vkd3d_shader_free_root_signature(struct vkd3d_shader_versioned_root_signature_desc *root_signature);
+
+/**
+ * Convert a structural description of a shader root signature to a byte code
+ * format capable of being read by ID3D12Device::CreateRootSignature. The
+ * compiled signature is compatible with Microsoft D3D 12.
+ *
+ * This function corresponds to D3D12SerializeVersionedRootSignature().
+ *
+ * \param root_signature Description of the root signature.
+ *
+ * \param dxbc A pointer to a vkd3d_shader_code structure in which the compiled
+ * code will be stored.
+ * \n
+ * The compiled signature is allocated by vkd3d-shader and should be freed with
+ * vkd3d_shader_free_shader_code() when no longer needed.
+ *
+ * \param messages Optional output location for error or informational messages
+ * produced by the compiler.
+ * \n
+ * This parameter behaves identically to the \a messages parameter of
+ * vkd3d_shader_compile().
+ *
+ * \return A member of \ref vkd3d_result.
+ */
+int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_root_signature_desc *root_signature,
+ struct vkd3d_shader_code *dxbc, char **messages);
+/**
+ * Convert a structural representation of a root signature to a different
+ * version of structural representation.
+ *
+ * This function corresponds to
+ * ID3D12VersionedRootSignatureDeserializer::GetRootSignatureDescAtVersion().
+ *
+ * \param dst A pointer to a vkd3d_shader_versioned_root_signature_desc
+ * structure in which the converted signature will be stored.
+ * \n
+ * Members of \a dst may be allocated by vkd3d-shader. The signature should be
+ * freed with vkd3d_shader_free_root_signature() when no longer needed.
+ *
+ * \param version The desired version to convert \a src to. This version must
+ * not be equal to \a src->version.
+ *
+ * \param src Input root signature description.
+ *
+ * \return A member of \ref vkd3d_result.
+ */
+int vkd3d_shader_convert_root_signature(struct vkd3d_shader_versioned_root_signature_desc *dst,
+ enum vkd3d_shader_root_signature_version version, const struct vkd3d_shader_versioned_root_signature_desc *src);
+
+/**
+ * Parse shader source code or byte code, returning various types of requested
+ * information.
+ *
+ * Currently this function supports the following code types:
+ * - VKD3D_SHADER_SOURCE_DXBC_TPF
+ *
+ * \param compile_info A chained structure containing scan parameters.
+ * \n
+ * The DXBC_TPF scanner supports the following chained structures:
+ * - vkd3d_shader_scan_descriptor_info
+ * \n
+ * Although the \a compile_info parameter is read-only, chained structures
+ * passed to this function need not be, and may serve as output parameters,
+ * depending on their structure type.
+ *
+ * \param messages Optional output location for error or informational messages
+ * produced by the compiler.
+ * \n
+ * This parameter behaves identically to the \a messages parameter of
+ * vkd3d_shader_compile().
+ *
+ * \return A member of \ref vkd3d_result.
+ */
+int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char **messages);
+/**
+ * Free members of struct vkd3d_shader_scan_descriptor_info() allocated by
+ * vkd3d_shader_scan().
+ *
+ * This function may free members of vkd3d_shader_scan_descriptor_info, but
+ * does not free the structure itself.
+ *
+ * \param scan_descriptor_info Descriptor information to free.
+ */
+void vkd3d_shader_free_scan_descriptor_info(struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info);
+
+/**
+ * Read the input signature of a compiled shader, returning a structural
+ * description which can be easily parsed by C code.
+ *
+ * This function parses a compiled shader. To parse a standalone root signature,
+ * use vkd3d_shader_parse_root_signature().
+ *
+ * \param dxbc Compiled byte code, in DXBC format.
+ *
+ * \param signature Output location in which the parsed root signature will be
+ * stored.
+ * \n
+ * Members of \a signature may be allocated by vkd3d-shader. The signature
+ * should be freed with vkd3d_shader_free_shader_signature() when no longer
+ * needed.
+ *
+ * \param messages Optional output location for error or informational messages
+ * produced by the compiler.
+ * \n
+ * This parameter behaves identically to the \a messages parameter of
+ * vkd3d_shader_compile().
+ *
+ * \return A member of \ref vkd3d_result.
+ */
+int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
+ struct vkd3d_shader_signature *signature, char **messages);
+/**
+ * Find a single element of a parsed input signature.
+ *
+ * \param signature The parsed input signature. This structure is normally
+ * populated by vkd3d_shader_parse_input_signature().
+ *
+ * \param semantic_name Semantic name of the desired element. This function
+ * performs a case-insensitive comparison with respect to the ASCII plane.
+ *
+ * \param semantic_index Semantic index of the desired element.
+ *
+ * \param stream_index Geometry shader stream index of the desired element. If
+ * the signature is not a geometry shader output signature, this parameter must
+ * be set to 0.
+ *
+ * \return A description of the element matching the requested parameters, or
+ * NULL if no such element was found. If not NULL, the return value points into
+ * the \a signature parameter and should not be explicitly freed.
+ */
+struct vkd3d_shader_signature_element *vkd3d_shader_find_signature_element(
+ const struct vkd3d_shader_signature *signature, const char *semantic_name,
+ unsigned int semantic_index, unsigned int stream_index);
+/**
+ * Free a structural representation of a shader input signature allocated by
+ * vkd3d_shader_parse_input_signature().
+ *
+ * This function may free members of struct vkd3d_shader_signature, but does not
+ * free the structure itself.
+ *
+ * \param signature Signature description to free.
+ */
+void vkd3d_shader_free_shader_signature(struct vkd3d_shader_signature *signature);
+
+#endif /* VKD3D_SHADER_NO_PROTOTYPES */
+
+/** Type of vkd3d_shader_get_version(). */
+typedef const char *(*PFN_vkd3d_shader_get_version)(unsigned int *major, unsigned int *minor);
+/** Type of vkd3d_shader_get_supported_source_types(). */
+typedef const enum vkd3d_shader_source_type *(*PFN_vkd3d_shader_get_supported_source_types)(unsigned int *count);
+/** Type of vkd3d_shader_get_supported_target_types(). */
+typedef const enum vkd3d_shader_target_type *(*PFN_vkd3d_shader_get_supported_target_types)(
+ enum vkd3d_shader_source_type source_type, unsigned int *count);
+
+/** Type of vkd3d_shader_compile(). */
+typedef int (*PFN_vkd3d_shader_compile)(const struct vkd3d_shader_compile_info *compile_info,
+ struct vkd3d_shader_code *out, char **messages);
+/** Type of vkd3d_shader_free_messages(). */
+typedef void (*PFN_vkd3d_shader_free_messages)(char *messages);
+/** Type of vkd3d_shader_free_shader_code(). */
+typedef void (*PFN_vkd3d_shader_free_shader_code)(struct vkd3d_shader_code *code);
+
+/** Type of vkd3d_shader_parse_root_signature(). */
+typedef int (*PFN_vkd3d_shader_parse_root_signature)(const struct vkd3d_shader_code *dxbc,
+ struct vkd3d_shader_versioned_root_signature_desc *root_signature, char **messages);
+/** Type of vkd3d_shader_free_root_signature(). */
+typedef void (*PFN_vkd3d_shader_free_root_signature)(struct vkd3d_shader_versioned_root_signature_desc *root_signature);
+
+/** Type of vkd3d_shader_serialize_root_signature(). */
+typedef int (*PFN_vkd3d_shader_serialize_root_signature)(
+ const struct vkd3d_shader_versioned_root_signature_desc *root_signature,
+ struct vkd3d_shader_code *dxbc, char **messages);
+
+/** Type of vkd3d_shader_convert_root_signature(). */
+typedef int (*PFN_vkd3d_shader_convert_root_signature)(struct vkd3d_shader_versioned_root_signature_desc *dst,
+ enum vkd3d_shader_root_signature_version version, const struct vkd3d_shader_versioned_root_signature_desc *src);
+
+/** Type of vkd3d_shader_scan(). */
+typedef int (*PFN_vkd3d_shader_scan)(const struct vkd3d_shader_compile_info *compile_info, char **messages);
+/** Type of vkd3d_shader_free_scan_descriptor_info(). */
+typedef void (*PFN_vkd3d_shader_free_scan_descriptor_info)(
+ struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info);
+
+/** Type of vkd3d_shader_parse_input_signature(). */
+typedef int (*PFN_vkd3d_shader_parse_input_signature)(const struct vkd3d_shader_code *dxbc,
+ struct vkd3d_shader_signature *signature, char **messages);
+/** Type of vkd3d_shader_find_signature_element(). */
+typedef struct vkd3d_shader_signature_element * (*PFN_vkd3d_shader_find_signature_element)(
+ const struct vkd3d_shader_signature *signature, const char *semantic_name,
+ unsigned int semantic_index, unsigned int stream_index);
+/** Type of vkd3d_shader_free_shader_signature(). */
+typedef void (*PFN_vkd3d_shader_free_shader_signature)(struct vkd3d_shader_signature *signature);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __VKD3D_SHADER_H */
diff --git a/dlls/vkd3d/include/vkd3d_types.h b/dlls/vkd3d/include/vkd3d_types.h
new file mode 100644
index 00000000000..020eb2400fb
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_types.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016-2018 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_TYPES_H
+#define __VKD3D_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * \file vkd3d_types.h
+ *
+ * This file contains definitions for basic types used by vkd3d libraries.
+ */
+
+#define VKD3D_FORCE_32_BIT_ENUM(name) name##_FORCE_32BIT = 0x7fffffff
+
+/**
+ * Result codes returned by some vkd3d functions. Error codes always have
+ * negative values; non-error codes never do.
+ */
+enum vkd3d_result
+{
+ /** Success. */
+ VKD3D_OK = 0,
+ /** An unspecified failure occurred. */
+ VKD3D_ERROR = -1,
+ /** There are not enough resources available to complete the operation. */
+ VKD3D_ERROR_OUT_OF_MEMORY = -2,
+ /** One or more parameters passed to a vkd3d function were invalid. */
+ VKD3D_ERROR_INVALID_ARGUMENT = -3,
+ /** A shader passed to a vkd3d function was invalid. */
+ VKD3D_ERROR_INVALID_SHADER = -4,
+ /** The operation is not implemented in this version of vkd3d. */
+ VKD3D_ERROR_NOT_IMPLEMENTED = -5,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_RESULT),
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __VKD3D_TYPES_H */
diff --git a/dlls/vkd3d/include/vkd3d_unknown.idl b/dlls/vkd3d/include/vkd3d_unknown.idl
new file mode 100644
index 00000000000..9a7198c82d1
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_unknown.idl
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+cpp_quote("#ifndef __VKD3D_UNKNOWN_H")
+cpp_quote("#define __VKD3D_UNKNOWN_H")
+
+/* For IDL only. */
+cpp_quote("#if 0")
+typedef IID *REFIID;
+typedef IID *REFGUID;
+cpp_quote("#endif")
+
+cpp_quote("#if !defined(_WIN32)")
+typedef void *HWND;
+typedef void *HMODULE;
+
+typedef struct LUID
+{
+ DWORD LowPart;
+ LONG HighPart;
+} LUID;
+
+typedef struct _RECT
+{
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+} RECT;
+cpp_quote("#endif")
+
+[uuid(00000000-0000-0000-C000-000000000046), object, local, pointer_default(unique)]
+interface IUnknown
+{
+ HRESULT QueryInterface(REFIID riid, void **object);
+ ULONG AddRef();
+ ULONG Release();
+}
+
+cpp_quote("#endif /* __VKD3D_UNKNOWN_H */")
diff --git a/dlls/vkd3d/include/vkd3d_utils.h b/dlls/vkd3d/include/vkd3d_utils.h
new file mode 100644
index 00000000000..02687ed613f
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_utils.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_UTILS_H
+#define __VKD3D_UTILS_H
+
+#include <vkd3d.h>
+
+#ifndef VKD3D_UTILS_API_VERSION
+#define VKD3D_UTILS_API_VERSION VKD3D_API_VERSION_1_0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define VKD3D_WAIT_OBJECT_0 (0)
+#define VKD3D_WAIT_TIMEOUT (1)
+#define VKD3D_WAIT_FAILED (~0u)
+#define VKD3D_INFINITE (~0u)
+
+/* 1.0 */
+HANDLE vkd3d_create_event(void);
+HRESULT vkd3d_signal_event(HANDLE event);
+unsigned int vkd3d_wait_event(HANDLE event, unsigned int milliseconds);
+void vkd3d_destroy_event(HANDLE event);
+
+#define D3D12CreateDevice(a, b, c, d) D3D12CreateDeviceVKD3D(a, b, c, d, VKD3D_UTILS_API_VERSION)
+HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size, REFIID iid, void **deserializer);
+HRESULT WINAPI D3D12GetDebugInterface(REFIID iid, void **debug);
+HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *desc,
+ D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
+
+/* 1.2 */
+HRESULT WINAPI D3D12CreateDeviceVKD3D(IUnknown *adapter, D3D_FEATURE_LEVEL feature_level,
+ REFIID iid, void **device, enum vkd3d_api_version api_version);
+HRESULT WINAPI D3D12CreateVersionedRootSignatureDeserializer(const void *data,
+ SIZE_T data_size, REFIID iid, void **deserializer);
+HRESULT WINAPI D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
+ ID3DBlob **blob, ID3DBlob **error_blob);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __VKD3D_UTILS_H */
diff --git a/dlls/vkd3d/include/vkd3d_windows.h b/dlls/vkd3d/include/vkd3d_windows.h
new file mode 100644
index 00000000000..ad2f08a613a
--- /dev/null
+++ b/dlls/vkd3d/include/vkd3d_windows.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_WINDOWS_H
+#define __VKD3D_WINDOWS_H
+#ifndef _INC_WINDOWS
+
+/* Nameless unions */
+#ifndef __C89_NAMELESS
+# ifdef NONAMELESSUNION
+# define __C89_NAMELESS
+# define __C89_NAMELESSUNIONNAME u
+# else
+# define __C89_NAMELESS
+# define __C89_NAMELESSUNIONNAME
+# endif /* NONAMELESSUNION */
+#endif /* __C89_NAMELESS */
+
+#if !defined(_WIN32) || defined(__WIDL__)
+
+# if !defined(__WIDL__)
+# if !defined(VKD3D_WIN32_WCHAR)
+# include <wchar.h>
+# endif
+# include <stdint.h>
+# endif
+
+# ifdef __GNUC__
+# define DECLSPEC_ALIGN(x) __attribute__((aligned(x)))
+# endif
+
+/* HRESULT */
+typedef int HRESULT;
+# define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
+# define FAILED(hr) ((HRESULT)(hr) < 0)
+
+# define _HRESULT_TYPEDEF_(x) ((HRESULT)x)
+
+# define S_OK _HRESULT_TYPEDEF_(0)
+# define S_FALSE _HRESULT_TYPEDEF_(1)
+
+# define E_NOTIMPL _HRESULT_TYPEDEF_(0x80004001)
+# define E_NOINTERFACE _HRESULT_TYPEDEF_(0x80004002)
+# define E_POINTER _HRESULT_TYPEDEF_(0x80004003)
+# define E_ABORT _HRESULT_TYPEDEF_(0x80004004)
+# define E_FAIL _HRESULT_TYPEDEF_(0x80004005)
+# define E_OUTOFMEMORY _HRESULT_TYPEDEF_(0x8007000E)
+# define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057)
+
+# define DXGI_ERROR_NOT_FOUND _HRESULT_TYPEDEF_(0x887a0002)
+# define DXGI_ERROR_MORE_DATA _HRESULT_TYPEDEF_(0x887a0003)
+
+/* Basic types */
+typedef unsigned char BYTE;
+typedef unsigned int DWORD;
+typedef int INT;
+typedef unsigned int UINT;
+typedef int LONG;
+typedef unsigned int ULONG;
+typedef float FLOAT;
+typedef LONG BOOL;
+
+/* Assuming LP64 model */
+typedef char INT8;
+typedef unsigned char UINT8;
+typedef short INT16;
+typedef unsigned short UINT16;
+typedef int INT32;
+typedef unsigned int UINT32;
+# if defined(__WIDL__)
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+# else
+typedef int64_t DECLSPEC_ALIGN(8) INT64;
+typedef uint64_t DECLSPEC_ALIGN(8) UINT64;
+# endif
+typedef long LONG_PTR;
+typedef unsigned long ULONG_PTR;
+
+typedef ULONG_PTR SIZE_T;
+
+# ifdef VKD3D_WIN32_WCHAR
+typedef unsigned short WCHAR;
+# else
+typedef wchar_t WCHAR;
+# endif /* VKD3D_WIN32_WCHAR */
+typedef void *HANDLE;
+
+/* GUID */
+# ifdef __WIDL__
+typedef struct
+{
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+} GUID;
+# else
+typedef struct _GUID
+{
+ unsigned int Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+} GUID;
+# endif
+
+typedef GUID IID;
+
+# ifdef INITGUID
+# ifndef __cplusplus
+# define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ const GUID name DECLSPEC_HIDDEN; \
+ const GUID name = \
+ { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 }}
+# else
+# define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID name DECLSPEC_HIDDEN; \
+ EXTERN_C const GUID name = \
+ { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 }}
+# endif
+# else
+# define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID name DECLSPEC_HIDDEN;
+# endif /* INITGUID */
+
+/* __uuidof emulation */
+#if defined(__cplusplus) && !defined(_MSC_VER)
+
+extern "C++"
+{
+ template<typename T> const GUID &__vkd3d_uuidof();
+}
+
+# define __CRT_UUID_DECL(type, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ extern "C++" \
+ { \
+ template<> inline const GUID &__vkd3d_uuidof<type>() \
+ { \
+ static const IID __uuid_inst = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}; \
+ return __uuid_inst; \
+ } \
+ template<> inline const GUID &__vkd3d_uuidof<type *>() \
+ { \
+ return __vkd3d_uuidof<type>(); \
+ } \
+ }
+
+# define __uuidof(type) __vkd3d_uuidof<typeof(type)>()
+#else
+# define __CRT_UUID_DECL(type, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
+#endif /* defined(__cplusplus) && !defined(_MSC_VER) */
+
+typedef struct SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES;
+#endif /* !defined(_WIN32) || defined(__WIDL__) */
+
+
+#ifndef _WIN32
+# include <stddef.h>
+# include <stdlib.h>
+# include <string.h>
+
+# define COM_NO_WINDOWS_H
+
+# define FORCEINLINE inline
+
+# define CONTAINING_RECORD(address, type, field) \
+ ((type *)((char *)(address) - offsetof(type, field)))
+
+# ifdef __x86_64__
+# define __stdcall __attribute__((ms_abi))
+# else
+# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || defined(__APPLE__)
+# define __stdcall __attribute__((__stdcall__)) __attribute__((__force_align_arg_pointer__))
+# else
+# define __stdcall __attribute__((__stdcall__))
+# endif
+# endif
+
+# define WINAPI __stdcall
+# define STDMETHODCALLTYPE __stdcall
+
+# ifdef __GNUC__
+# define DECLSPEC_SELECTANY __attribute__((weak))
+# endif
+
+/* Macros for COM interfaces */
+# define interface struct
+# define BEGIN_INTERFACE
+# define END_INTERFACE
+# define MIDL_INTERFACE(x) struct
+
+# ifdef __cplusplus
+# define EXTERN_C extern "C"
+# else
+# define EXTERN_C extern
+# endif
+
+# define CONST_VTBL const
+
+# define TRUE 1
+# define FALSE 0
+
+# if defined(__cplusplus) && !defined(CINTERFACE)
+# define REFIID const IID &
+# define REFGUID const GUID &
+# else
+# define REFIID const IID * const
+# define REFGUID const GUID * const
+# endif
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+# define IsEqualGUID(guid1, guid2) (!memcmp(&(guid1), &(guid2), sizeof(GUID)))
+#else
+# define IsEqualGUID(guid1, guid2) (!memcmp(guid1, guid2, sizeof(GUID)))
+#endif
+
+#elif !defined(__WIDL__)
+
+# include <windows.h>
+
+#endif /* _WIN32 */
+
+
+/* Define DECLSPEC_HIDDEN */
+#ifndef DECLSPEC_HIDDEN
+# if defined(__MINGW32__)
+# define DECLSPEC_HIDDEN
+# elif defined(__GNUC__)
+# define DECLSPEC_HIDDEN __attribute__((visibility("hidden")))
+# else
+# define DECLSPEC_HIDDEN
+# endif
+#endif /* DECLSPEC_HIDDEN */
+
+/* Define min() & max() macros */
+#ifndef NOMINMAX
+# ifndef min
+# define min(a, b) (((a) <= (b)) ? (a) : (b))
+# endif
+
+# ifndef max
+# define max(a, b) (((a) >= (b)) ? (a) : (b))
+# endif
+#endif /* NOMINMAX */
+
+#ifndef DEFINE_ENUM_FLAG_OPERATORS
+#ifdef __cplusplus
+# define DEFINE_ENUM_FLAG_OPERATORS(type) \
+extern "C++" \
+{ \
+ inline type operator &(type x, type y) { return (type)((int)x & (int)y); } \
+ inline type operator &=(type &x, type y) { return (type &)((int &)x &= (int)y); } \
+ inline type operator ~(type x) { return (type)~(int)x; } \
+ inline type operator |(type x, type y) { return (type)((int)x | (int)y); } \
+ inline type operator |=(type &x, type y) { return (type &)((int &)x |= (int)y); } \
+ inline type operator ^(type x, type y) { return (type)((int)x ^ (int)y); } \
+ inline type operator ^=(type &x, type y) { return (type &)((int &)x ^= (int)y); } \
+}
+#else
+# define DEFINE_ENUM_FLAG_OPERATORS(type)
+#endif
+#endif /* DEFINE_ENUM_FLAG_OPERATORS */
+
+#endif /* _INC_WINDOWS */
+#endif /* __VKD3D_WINDOWS_H */
diff --git a/dlls/vkd3d/libs/vkd3d-common/debug.c b/dlls/vkd3d/libs/vkd3d-common/debug.c
new file mode 100644
index 00000000000..33deed6592a
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-common/debug.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_debug.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#define VKD3D_DEBUG_BUFFER_COUNT 64
+#define VKD3D_DEBUG_BUFFER_SIZE 512
+
+extern const char *vkd3d_dbg_env_name DECLSPEC_HIDDEN;
+
+static const char *debug_level_names[] =
+{
+ /* VKD3D_DBG_LEVEL_NONE */ "none",
+ /* VKD3D_DBG_LEVEL_ERR */ "err",
+ /* VKD3D_DBG_LEVEL_FIXME */ "fixme",
+ /* VKD3D_DBG_LEVEL_WARN */ "warn",
+ /* VKD3D_DBG_LEVEL_TRACE */ "trace",
+};
+
+enum vkd3d_dbg_level vkd3d_dbg_get_level(void)
+{
+ static unsigned int level = ~0u;
+ const char *vkd3d_debug;
+ unsigned int i;
+
+ if (level != ~0u)
+ return level;
+
+ if (!(vkd3d_debug = getenv(vkd3d_dbg_env_name)))
+ vkd3d_debug = "";
+
+ for (i = 0; i < ARRAY_SIZE(debug_level_names); ++i)
+ {
+ if (!strcmp(debug_level_names[i], vkd3d_debug))
+ {
+ level = i;
+ return level;
+ }
+ }
+
+ /* Default debug level. */
+ level = VKD3D_DBG_LEVEL_FIXME;
+ return level;
+}
+
+void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function, const char *fmt, ...)
+{
+ va_list args;
+
+ if (vkd3d_dbg_get_level() < level)
+ return;
+
+ assert(level < ARRAY_SIZE(debug_level_names));
+
+ fprintf(stderr, "%s:%s: ", debug_level_names[level], function);
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
+
+static char *get_buffer(void)
+{
+ static char buffers[VKD3D_DEBUG_BUFFER_COUNT][VKD3D_DEBUG_BUFFER_SIZE];
+ static LONG buffer_index;
+ LONG current_index;
+
+ current_index = InterlockedIncrement(&buffer_index) % ARRAY_SIZE(buffers);
+ return buffers[current_index];
+}
+
+const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args)
+{
+ char *buffer;
+
+ buffer = get_buffer();
+ vsnprintf(buffer, VKD3D_DEBUG_BUFFER_SIZE, fmt, args);
+ buffer[VKD3D_DEBUG_BUFFER_SIZE - 1] = '\0';
+ return buffer;
+}
+
+const char *vkd3d_dbg_sprintf(const char *fmt, ...)
+{
+ const char *buffer;
+ va_list args;
+
+ va_start(args, fmt);
+ buffer = vkd3d_dbg_vsprintf(fmt, args);
+ va_end(args);
+ return buffer;
+}
+
+const char *debugstr_a(const char *str)
+{
+ char *buffer, *ptr;
+ char c;
+
+ if (!str)
+ return "(null)";
+
+ ptr = buffer = get_buffer();
+
+ *ptr++ = '"';
+ while ((c = *str++) && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 8)
+ {
+ int escape_char;
+
+ switch (c)
+ {
+ case '"':
+ case '\\':
+ case '\n':
+ case '\r':
+ case '\t':
+ escape_char = c;
+ break;
+ default:
+ escape_char = 0;
+ break;
+ }
+
+ if (escape_char)
+ {
+ *ptr++ = '\\';
+ *ptr++ = escape_char;
+ continue;
+ }
+
+ if (isprint(c))
+ {
+ *ptr++ = c;
+ }
+ else
+ {
+ *ptr++ = '\\';
+ sprintf(ptr, "%02x", c);
+ ptr += 2;
+ }
+ }
+ *ptr++ = '"';
+
+ if (c)
+ {
+ *ptr++ = '.';
+ *ptr++ = '.';
+ *ptr++ = '.';
+ }
+ *ptr = '\0';
+
+ return buffer;
+}
+
+static const char *debugstr_w16(const uint16_t *wstr)
+{
+ char *buffer, *ptr;
+ uint16_t c;
+
+ if (!wstr)
+ return "(null)";
+
+ ptr = buffer = get_buffer();
+
+ *ptr++ = '"';
+ while ((c = *wstr++) && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 10)
+ {
+ int escape_char;
+
+ switch (c)
+ {
+ case '"':
+ case '\\':
+ case '\n':
+ case '\r':
+ case '\t':
+ escape_char = c;
+ break;
+ default:
+ escape_char = 0;
+ break;
+ }
+
+ if (escape_char)
+ {
+ *ptr++ = '\\';
+ *ptr++ = escape_char;
+ continue;
+ }
+
+ if (isprint(c))
+ {
+ *ptr++ = c;
+ }
+ else
+ {
+ *ptr++ = '\\';
+ sprintf(ptr, "%04x", c);
+ ptr += 4;
+ }
+ }
+ *ptr++ = '"';
+
+ if (c)
+ {
+ *ptr++ = '.';
+ *ptr++ = '.';
+ *ptr++ = '.';
+ }
+ *ptr = '\0';
+
+ return buffer;
+}
+
+static const char *debugstr_w32(const uint32_t *wstr)
+{
+ char *buffer, *ptr;
+ uint32_t c;
+
+ if (!wstr)
+ return "(null)";
+
+ ptr = buffer = get_buffer();
+
+ *ptr++ = '"';
+ while ((c = *wstr++) && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 10)
+ {
+ int escape_char;
+
+ switch (c)
+ {
+ case '"':
+ case '\\':
+ case '\n':
+ case '\r':
+ case '\t':
+ escape_char = c;
+ break;
+ default:
+ escape_char = 0;
+ break;
+ }
+
+ if (escape_char)
+ {
+ *ptr++ = '\\';
+ *ptr++ = escape_char;
+ continue;
+ }
+
+ if (isprint(c))
+ {
+ *ptr++ = c;
+ }
+ else
+ {
+ *ptr++ = '\\';
+ sprintf(ptr, "%04x", c);
+ ptr += 4;
+ }
+ }
+ *ptr++ = '"';
+
+ if (c)
+ {
+ *ptr++ = '.';
+ *ptr++ = '.';
+ *ptr++ = '.';
+ }
+ *ptr = '\0';
+
+ return buffer;
+}
+
+const char *debugstr_w(const WCHAR *wstr, size_t wchar_size)
+{
+ if (wchar_size == 2)
+ return debugstr_w16((const uint16_t *)wstr);
+ return debugstr_w32((const uint32_t *)wstr);
+}
+
+unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value)
+{
+ const char *value = getenv(name);
+ unsigned long r;
+ char *end_ptr;
+
+ if (value)
+ {
+ errno = 0;
+ r = strtoul(value, &end_ptr, 0);
+ if (!errno && end_ptr != value)
+ return min(r, UINT_MAX);
+ }
+
+ return default_value;
+}
+
+static bool is_option_separator(char c)
+{
+ return c == ',' || c == ';' || c == '\0';
+}
+
+bool vkd3d_debug_list_has_member(const char *string, const char *member)
+{
+ char prev_char, next_char;
+ const char *p;
+
+ p = string;
+ while (p)
+ {
+ if ((p = strstr(p, member)))
+ {
+ prev_char = p > string ? p[-1] : 0;
+ p += strlen(member);
+ next_char = *p;
+
+ if (is_option_separator(prev_char) && is_option_separator(next_char))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+uint64_t vkd3d_parse_debug_options(const char *string,
+ const struct vkd3d_debug_option *options, unsigned int option_count)
+{
+ uint64_t flags = 0;
+ unsigned int i;
+
+ for (i = 0; i < option_count; ++i)
+ {
+ const struct vkd3d_debug_option *opt = &options[i];
+
+ if (vkd3d_debug_list_has_member(string, opt->name))
+ flags |= opt->flag;
+ }
+
+ return flags;
+}
diff --git a/dlls/vkd3d/libs/vkd3d-common/memory.c b/dlls/vkd3d/libs/vkd3d-common/memory.c
new file mode 100644
index 00000000000..2bf8947e090
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-common/memory.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 Henri Verbeet for CodeWeavers
+ * Copyright 2017 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_memory.h"
+
+bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
+{
+ size_t new_capacity, max_capacity;
+ void *new_elements;
+
+ if (element_count <= *capacity)
+ return true;
+
+ max_capacity = ~(size_t)0 / element_size;
+ if (max_capacity < element_count)
+ return false;
+
+ new_capacity = max(*capacity, 4);
+ while (new_capacity < element_count && new_capacity <= max_capacity / 2)
+ new_capacity *= 2;
+
+ if (new_capacity < element_count)
+ new_capacity = element_count;
+
+ if (!(new_elements = vkd3d_realloc(*elements, new_capacity * element_size)))
+ return false;
+
+ *elements = new_elements;
+ *capacity = new_capacity;
+
+ return true;
+}
diff --git a/dlls/vkd3d/libs/vkd3d-common/utf8.c b/dlls/vkd3d/libs/vkd3d-common/utf8.c
new file mode 100644
index 00000000000..8bf4eb05e4f
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-common/utf8.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2000 Alexandre Julliard
+ * Copyright 2019 Zhiyi Zhang for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_memory.h"
+#include "vkd3d_utf8.h"
+
+#include <inttypes.h>
+
+static size_t vkd3d_utf8_len(uint32_t c)
+{
+ /* 0x00-0x7f: 1 byte */
+ if (c < 0x80)
+ return 1;
+ /* 0x80-0x7ff: 2 bytes */
+ if (c < 0x800)
+ return 2;
+ /* 0x800-0xffff: 3 bytes */
+ if (c < 0x10000)
+ return 3;
+ /* 0x10000-0x10ffff: 4 bytes */
+ return 4;
+}
+
+static void vkd3d_utf8_append(char **dst, uint32_t c)
+{
+ char *d = *dst;
+
+ /* 0x00-0x7f: 1 byte */
+ if (c < 0x80)
+ {
+ d[0] = c;
+ *dst += 1;
+ return;
+ }
+
+ /* 0x80-0x7ff: 2 bytes */
+ if (c < 0x800)
+ {
+ d[1] = 0x80 | (c & 0x3f);
+ c >>= 6;
+ d[0] = 0xc0 | c;
+ *dst += 2;
+ return;
+ }
+
+ /* 0x800-0xffff: 3 bytes */
+ if (c < 0x10000) /* 0x800-0xffff: 3 bytes */
+ {
+ d[2] = 0x80 | (c & 0x3f);
+ c >>= 6;
+ d[1] = 0x80 | (c & 0x3f);
+ c >>= 6;
+ d[0] = 0xe0 | c;
+ *dst += 3;
+ return;
+ }
+
+ /* 0x10000-0x10ffff: 4 bytes */
+ d[3] = 0x80 | (c & 0x3f);
+ c >>= 6;
+ d[2] = 0x80 | (c & 0x3f);
+ c >>= 6;
+ d[1] = 0x80 | (c & 0x3f);
+ c >>= 6;
+ d[0] = 0xf0 | c;
+ *dst += 4;
+}
+
+static uint32_t vkd3d_utf16_read(const uint16_t **src)
+{
+ const uint16_t *s = *src;
+
+ if (s[0] < 0xd800 || s[0] > 0xdfff) /* Not a surrogate pair. */
+ {
+ *src += 1;
+ return s[0];
+ }
+
+ if (s[0] > 0xdbff /* Invalid high surrogate. */
+ || s[1] < 0xdc00 || s[1] > 0xdfff) /* Invalid low surrogate. */
+ {
+ *src += 1;
+ return 0;
+ }
+
+ *src += 2;
+ return 0x10000 + ((s[0] & 0x3ff) << 10) + (s[1] & 0x3ff);
+}
+
+static char *vkd3d_strdup_w16_utf8(const uint16_t *wstr)
+{
+ const uint16_t *src = wstr;
+ size_t dst_size = 0;
+ char *dst, *utf8;
+ uint32_t c;
+
+ while (*src)
+ {
+ if (!(c = vkd3d_utf16_read(&src)))
+ continue;
+ dst_size += vkd3d_utf8_len(c);
+ }
+ ++dst_size;
+
+ if (!(dst = vkd3d_malloc(dst_size)))
+ return NULL;
+
+ utf8 = dst;
+ src = wstr;
+ while (*src)
+ {
+ if (!(c = vkd3d_utf16_read(&src)))
+ continue;
+ vkd3d_utf8_append(&utf8, c);
+ }
+ *utf8 = 0;
+
+ return dst;
+}
+
+static char *vkd3d_strdup_w32_utf8(const uint32_t *wstr)
+{
+ const uint32_t *src = wstr;
+ size_t dst_size = 0;
+ char *dst, *utf8;
+
+ while (*src)
+ dst_size += vkd3d_utf8_len(*src++);
+ ++dst_size;
+
+ if (!(dst = vkd3d_malloc(dst_size)))
+ return NULL;
+
+ utf8 = dst;
+ src = wstr;
+ while (*src)
+ vkd3d_utf8_append(&utf8, *src++);
+ *utf8 = 0;
+
+ return dst;
+}
+
+char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t wchar_size)
+{
+ if (wchar_size == 2)
+ return vkd3d_strdup_w16_utf8((const uint16_t *)wstr);
+ return vkd3d_strdup_w32_utf8((const uint32_t *)wstr);
+}
diff --git a/dlls/vkd3d/libs/vkd3d-shader/checksum.c b/dlls/vkd3d/libs/vkd3d-shader/checksum.c
new file mode 100644
index 00000000000..b9a7140221e
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-shader/checksum.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Hans Leidekker
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * It is based on code in the public domain written by Colin
+ * Plumb in 1993. The algorithm is due to Ron Rivest.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * md5_ctx structure, pass it to md5_init, call md5_update as
+ * needed on buffers full of bytes, and then call md5_final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include "vkd3d_shader_private.h"
+
+#define DXBC_CHECKSUM_BLOCK_SIZE 64
+
+STATIC_ASSERT(sizeof(unsigned int) == 4);
+
+struct md5_ctx
+{
+ unsigned int i[2];
+ unsigned int buf[4];
+ unsigned char in[DXBC_CHECKSUM_BLOCK_SIZE];
+ unsigned char digest[16];
+};
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. md5_update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void md5_transform(unsigned int buf[4], const unsigned int in[16])
+{
+ unsigned int a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byte_reverse(unsigned char *buf, unsigned longs)
+{
+ unsigned int t;
+
+ do
+ {
+ t = ((unsigned)buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned)buf[1] << 8 | buf[0]);
+ *(unsigned int *)buf = t;
+ buf += 4;
+ } while (--longs);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+static void md5_init(struct md5_ctx *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->i[0] = ctx->i[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+static void md5_update(struct md5_ctx *ctx, const unsigned char *buf, unsigned int len)
+{
+ unsigned int t;
+
+ /* Update bitcount */
+ t = ctx->i[0];
+
+ if ((ctx->i[0] = t + (len << 3)) < t)
+ ctx->i[1]++; /* Carry from low to high */
+
+ ctx->i[1] += len >> 29;
+ t = (t >> 3) & 0x3f;
+
+ /* Handle any leading odd-sized chunks */
+ if (t)
+ {
+ unsigned char *p = (unsigned char *)ctx->in + t;
+ t = DXBC_CHECKSUM_BLOCK_SIZE - t;
+
+ if (len < t)
+ {
+ memcpy(p, buf, len);
+ return;
+ }
+
+ memcpy(p, buf, t);
+ byte_reverse(ctx->in, 16);
+
+ md5_transform(ctx->buf, (unsigned int *)ctx->in);
+
+ buf += t;
+ len -= t;
+ }
+
+ /* Process data in 64-byte chunks */
+ while (len >= DXBC_CHECKSUM_BLOCK_SIZE)
+ {
+ memcpy(ctx->in, buf, DXBC_CHECKSUM_BLOCK_SIZE);
+ byte_reverse(ctx->in, 16);
+
+ md5_transform(ctx->buf, (unsigned int *)ctx->in);
+
+ buf += DXBC_CHECKSUM_BLOCK_SIZE;
+ len -= DXBC_CHECKSUM_BLOCK_SIZE;
+ }
+
+ /* Handle any remaining bytes of data. */
+ memcpy(ctx->in, buf, len);
+}
+
+static void dxbc_checksum_final(struct md5_ctx *ctx)
+{
+ unsigned int padding;
+ unsigned int length;
+ unsigned int count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->i[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+ ++count;
+
+ /* Bytes of padding needed to make 64 bytes */
+ padding = DXBC_CHECKSUM_BLOCK_SIZE - count;
+
+ /* Pad out to 56 mod 64 */
+ if (padding < 8)
+ {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, padding);
+ byte_reverse(ctx->in, 16);
+ md5_transform(ctx->buf, (unsigned int *)ctx->in);
+
+ /* Now fill the next block */
+ memset(ctx->in, 0, DXBC_CHECKSUM_BLOCK_SIZE);
+ }
+ else
+ {
+ /* Make place for bitcount at the beginning of the block */
+ memmove(&ctx->in[4], ctx->in, count);
+
+ /* Pad block to 60 bytes */
+ memset(p + 4, 0, padding - 4);
+ }
+
+ /* Append length in bits and transform */
+ length = ctx->i[0];
+ memcpy(&ctx->in[0], &length, sizeof(length));
+ byte_reverse(&ctx->in[4], 14);
+ length = ctx->i[0] >> 2 | 0x1;
+ memcpy(&ctx->in[DXBC_CHECKSUM_BLOCK_SIZE - 4], &length, sizeof(length));
+
+ md5_transform(ctx->buf, (unsigned int *)ctx->in);
+ byte_reverse((unsigned char *)ctx->buf, 4);
+ memcpy(ctx->digest, ctx->buf, 16);
+}
+
+#define DXBC_CHECKSUM_SKIP_BYTE_COUNT 20
+
+void vkd3d_compute_dxbc_checksum(const void *dxbc, size_t size, uint32_t checksum[4])
+{
+ const uint8_t *ptr = dxbc;
+ struct md5_ctx ctx;
+
+ assert(size > DXBC_CHECKSUM_SKIP_BYTE_COUNT);
+ ptr += DXBC_CHECKSUM_SKIP_BYTE_COUNT;
+ size -= DXBC_CHECKSUM_SKIP_BYTE_COUNT;
+
+ md5_init(&ctx);
+ md5_update(&ctx, ptr, size);
+ dxbc_checksum_final(&ctx);
+
+ memcpy(checksum, ctx.digest, sizeof(ctx.digest));
+}
diff --git a/dlls/vkd3d/libs/vkd3d-shader/dxbc.c b/dlls/vkd3d/libs/vkd3d-shader/dxbc.c
new file mode 100644
index 00000000000..398cd9fbdcf
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-shader/dxbc.c
@@ -0,0 +1,3659 @@
+/*
+ * Copyright 2008-2009 Henri Verbeet for CodeWeavers
+ * Copyright 2017 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_shader_private.h"
+
+#define VKD3D_SM4_INSTRUCTION_MODIFIER (0x1u << 31)
+
+#define VKD3D_SM4_MODIFIER_MASK 0x3fu
+
+#define VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT 6
+#define VKD3D_SM5_MODIFIER_DATA_TYPE_MASK (0xffffu << VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT)
+
+#define VKD3D_SM5_MODIFIER_RESOURCE_TYPE_SHIFT 6
+#define VKD3D_SM5_MODIFIER_RESOURCE_TYPE_MASK (0xfu << VKD3D_SM5_MODIFIER_RESOURCE_TYPE_SHIFT)
+
+#define VKD3D_SM4_AOFFIMMI_U_SHIFT 9
+#define VKD3D_SM4_AOFFIMMI_U_MASK (0xfu << VKD3D_SM4_AOFFIMMI_U_SHIFT)
+#define VKD3D_SM4_AOFFIMMI_V_SHIFT 13
+#define VKD3D_SM4_AOFFIMMI_V_MASK (0xfu << VKD3D_SM4_AOFFIMMI_V_SHIFT)
+#define VKD3D_SM4_AOFFIMMI_W_SHIFT 17
+#define VKD3D_SM4_AOFFIMMI_W_MASK (0xfu << VKD3D_SM4_AOFFIMMI_W_SHIFT)
+
+#define VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT 24
+#define VKD3D_SM4_INSTRUCTION_LENGTH_MASK (0x1fu << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT)
+
+#define VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT 11
+#define VKD3D_SM4_INSTRUCTION_FLAGS_MASK (0x7u << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT)
+
+#define VKD3D_SM4_RESOURCE_TYPE_SHIFT 11
+#define VKD3D_SM4_RESOURCE_TYPE_MASK (0xfu << VKD3D_SM4_RESOURCE_TYPE_SHIFT)
+
+#define VKD3D_SM4_PRIMITIVE_TYPE_SHIFT 11
+#define VKD3D_SM4_PRIMITIVE_TYPE_MASK (0x3fu << VKD3D_SM4_PRIMITIVE_TYPE_SHIFT)
+
+#define VKD3D_SM4_INDEX_TYPE_SHIFT 11
+#define VKD3D_SM4_INDEX_TYPE_MASK (0x1u << VKD3D_SM4_INDEX_TYPE_SHIFT)
+
+#define VKD3D_SM4_SAMPLER_MODE_SHIFT 11
+#define VKD3D_SM4_SAMPLER_MODE_MASK (0xfu << VKD3D_SM4_SAMPLER_MODE_SHIFT)
+
+#define VKD3D_SM4_SHADER_DATA_TYPE_SHIFT 11
+#define VKD3D_SM4_SHADER_DATA_TYPE_MASK (0xfu << VKD3D_SM4_SHADER_DATA_TYPE_SHIFT)
+
+#define VKD3D_SM4_INTERPOLATION_MODE_SHIFT 11
+#define VKD3D_SM4_INTERPOLATION_MODE_MASK (0xfu << VKD3D_SM4_INTERPOLATION_MODE_SHIFT)
+
+#define VKD3D_SM4_GLOBAL_FLAGS_SHIFT 11
+#define VKD3D_SM4_GLOBAL_FLAGS_MASK (0xffu << VKD3D_SM4_GLOBAL_FLAGS_SHIFT)
+
+#define VKD3D_SM5_PRECISE_SHIFT 19
+#define VKD3D_SM5_PRECISE_MASK (0xfu << VKD3D_SM5_PRECISE_SHIFT)
+
+#define VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT 11
+#define VKD3D_SM5_CONTROL_POINT_COUNT_MASK (0xffu << VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT)
+
+#define VKD3D_SM5_FP_ARRAY_SIZE_SHIFT 16
+#define VKD3D_SM5_FP_TABLE_COUNT_MASK 0xffffu
+
+#define VKD3D_SM5_UAV_FLAGS_SHIFT 15
+#define VKD3D_SM5_UAV_FLAGS_MASK (0x1ffu << VKD3D_SM5_UAV_FLAGS_SHIFT)
+
+#define VKD3D_SM5_SYNC_FLAGS_SHIFT 11
+#define VKD3D_SM5_SYNC_FLAGS_MASK (0xffu << VKD3D_SM5_SYNC_FLAGS_SHIFT)
+
+#define VKD3D_SM5_TESSELLATOR_SHIFT 11
+#define VKD3D_SM5_TESSELLATOR_MASK (0xfu << VKD3D_SM5_TESSELLATOR_SHIFT)
+
+#define VKD3D_SM4_OPCODE_MASK 0xff
+
+#define VKD3D_SM4_REGISTER_MODIFIER (0x1u << 31)
+
+#define VKD3D_SM4_ADDRESSING_SHIFT2 28
+#define VKD3D_SM4_ADDRESSING_MASK2 (0x3u << VKD3D_SM4_ADDRESSING_SHIFT2)
+
+#define VKD3D_SM4_ADDRESSING_SHIFT1 25
+#define VKD3D_SM4_ADDRESSING_MASK1 (0x3u << VKD3D_SM4_ADDRESSING_SHIFT1)
+
+#define VKD3D_SM4_ADDRESSING_SHIFT0 22
+#define VKD3D_SM4_ADDRESSING_MASK0 (0x3u << VKD3D_SM4_ADDRESSING_SHIFT0)
+
+#define VKD3D_SM4_REGISTER_ORDER_SHIFT 20
+#define VKD3D_SM4_REGISTER_ORDER_MASK (0x3u << VKD3D_SM4_REGISTER_ORDER_SHIFT)
+
+#define VKD3D_SM4_REGISTER_TYPE_SHIFT 12
+#define VKD3D_SM4_REGISTER_TYPE_MASK (0xffu << VKD3D_SM4_REGISTER_TYPE_SHIFT)
+
+#define VKD3D_SM4_SWIZZLE_TYPE_SHIFT 2
+#define VKD3D_SM4_SWIZZLE_TYPE_MASK (0x3u << VKD3D_SM4_SWIZZLE_TYPE_SHIFT)
+
+#define VKD3D_SM4_DIMENSION_SHIFT 0
+#define VKD3D_SM4_DIMENSION_MASK (0x3u << VKD3D_SM4_DIMENSION_SHIFT)
+
+#define VKD3D_SM4_WRITEMASK_SHIFT 4
+#define VKD3D_SM4_WRITEMASK_MASK (0xfu << VKD3D_SM4_WRITEMASK_SHIFT)
+
+#define VKD3D_SM4_SWIZZLE_SHIFT 4
+#define VKD3D_SM4_SWIZZLE_MASK (0xffu << VKD3D_SM4_SWIZZLE_SHIFT)
+
+#define VKD3D_SM4_VERSION_MAJOR(version) (((version) >> 4) & 0xf)
+#define VKD3D_SM4_VERSION_MINOR(version) (((version) >> 0) & 0xf)
+
+#define VKD3D_SM4_ADDRESSING_RELATIVE 0x2
+#define VKD3D_SM4_ADDRESSING_OFFSET 0x1
+
+#define VKD3D_SM4_INSTRUCTION_FLAG_SATURATE 0x4
+
+#define VKD3D_SM4_CONDITIONAL_NZ (0x1u << 18)
+
+enum vkd3d_sm4_opcode
+{
+ VKD3D_SM4_OP_ADD = 0x00,
+ VKD3D_SM4_OP_AND = 0x01,
+ VKD3D_SM4_OP_BREAK = 0x02,
+ VKD3D_SM4_OP_BREAKC = 0x03,
+ VKD3D_SM4_OP_CASE = 0x06,
+ VKD3D_SM4_OP_CONTINUE = 0x07,
+ VKD3D_SM4_OP_CONTINUEC = 0x08,
+ VKD3D_SM4_OP_CUT = 0x09,
+ VKD3D_SM4_OP_DEFAULT = 0x0a,
+ VKD3D_SM4_OP_DERIV_RTX = 0x0b,
+ VKD3D_SM4_OP_DERIV_RTY = 0x0c,
+ VKD3D_SM4_OP_DISCARD = 0x0d,
+ VKD3D_SM4_OP_DIV = 0x0e,
+ VKD3D_SM4_OP_DP2 = 0x0f,
+ VKD3D_SM4_OP_DP3 = 0x10,
+ VKD3D_SM4_OP_DP4 = 0x11,
+ VKD3D_SM4_OP_ELSE = 0x12,
+ VKD3D_SM4_OP_EMIT = 0x13,
+ VKD3D_SM4_OP_ENDIF = 0x15,
+ VKD3D_SM4_OP_ENDLOOP = 0x16,
+ VKD3D_SM4_OP_ENDSWITCH = 0x17,
+ VKD3D_SM4_OP_EQ = 0x18,
+ VKD3D_SM4_OP_EXP = 0x19,
+ VKD3D_SM4_OP_FRC = 0x1a,
+ VKD3D_SM4_OP_FTOI = 0x1b,
+ VKD3D_SM4_OP_FTOU = 0x1c,
+ VKD3D_SM4_OP_GE = 0x1d,
+ VKD3D_SM4_OP_IADD = 0x1e,
+ VKD3D_SM4_OP_IF = 0x1f,
+ VKD3D_SM4_OP_IEQ = 0x20,
+ VKD3D_SM4_OP_IGE = 0x21,
+ VKD3D_SM4_OP_ILT = 0x22,
+ VKD3D_SM4_OP_IMAD = 0x23,
+ VKD3D_SM4_OP_IMAX = 0x24,
+ VKD3D_SM4_OP_IMIN = 0x25,
+ VKD3D_SM4_OP_IMUL = 0x26,
+ VKD3D_SM4_OP_INE = 0x27,
+ VKD3D_SM4_OP_INEG = 0x28,
+ VKD3D_SM4_OP_ISHL = 0x29,
+ VKD3D_SM4_OP_ISHR = 0x2a,
+ VKD3D_SM4_OP_ITOF = 0x2b,
+ VKD3D_SM4_OP_LABEL = 0x2c,
+ VKD3D_SM4_OP_LD = 0x2d,
+ VKD3D_SM4_OP_LD2DMS = 0x2e,
+ VKD3D_SM4_OP_LOG = 0x2f,
+ VKD3D_SM4_OP_LOOP = 0x30,
+ VKD3D_SM4_OP_LT = 0x31,
+ VKD3D_SM4_OP_MAD = 0x32,
+ VKD3D_SM4_OP_MIN = 0x33,
+ VKD3D_SM4_OP_MAX = 0x34,
+ VKD3D_SM4_OP_SHADER_DATA = 0x35,
+ VKD3D_SM4_OP_MOV = 0x36,
+ VKD3D_SM4_OP_MOVC = 0x37,
+ VKD3D_SM4_OP_MUL = 0x38,
+ VKD3D_SM4_OP_NE = 0x39,
+ VKD3D_SM4_OP_NOP = 0x3a,
+ VKD3D_SM4_OP_NOT = 0x3b,
+ VKD3D_SM4_OP_OR = 0x3c,
+ VKD3D_SM4_OP_RESINFO = 0x3d,
+ VKD3D_SM4_OP_RET = 0x3e,
+ VKD3D_SM4_OP_RETC = 0x3f,
+ VKD3D_SM4_OP_ROUND_NE = 0x40,
+ VKD3D_SM4_OP_ROUND_NI = 0x41,
+ VKD3D_SM4_OP_ROUND_PI = 0x42,
+ VKD3D_SM4_OP_ROUND_Z = 0x43,
+ VKD3D_SM4_OP_RSQ = 0x44,
+ VKD3D_SM4_OP_SAMPLE = 0x45,
+ VKD3D_SM4_OP_SAMPLE_C = 0x46,
+ VKD3D_SM4_OP_SAMPLE_C_LZ = 0x47,
+ VKD3D_SM4_OP_SAMPLE_LOD = 0x48,
+ VKD3D_SM4_OP_SAMPLE_GRAD = 0x49,
+ VKD3D_SM4_OP_SAMPLE_B = 0x4a,
+ VKD3D_SM4_OP_SQRT = 0x4b,
+ VKD3D_SM4_OP_SWITCH = 0x4c,
+ VKD3D_SM4_OP_SINCOS = 0x4d,
+ VKD3D_SM4_OP_UDIV = 0x4e,
+ VKD3D_SM4_OP_ULT = 0x4f,
+ VKD3D_SM4_OP_UGE = 0x50,
+ VKD3D_SM4_OP_UMUL = 0x51,
+ VKD3D_SM4_OP_UMAX = 0x53,
+ VKD3D_SM4_OP_UMIN = 0x54,
+ VKD3D_SM4_OP_USHR = 0x55,
+ VKD3D_SM4_OP_UTOF = 0x56,
+ VKD3D_SM4_OP_XOR = 0x57,
+ VKD3D_SM4_OP_DCL_RESOURCE = 0x58,
+ VKD3D_SM4_OP_DCL_CONSTANT_BUFFER = 0x59,
+ VKD3D_SM4_OP_DCL_SAMPLER = 0x5a,
+ VKD3D_SM4_OP_DCL_INDEX_RANGE = 0x5b,
+ VKD3D_SM4_OP_DCL_OUTPUT_TOPOLOGY = 0x5c,
+ VKD3D_SM4_OP_DCL_INPUT_PRIMITIVE = 0x5d,
+ VKD3D_SM4_OP_DCL_VERTICES_OUT = 0x5e,
+ VKD3D_SM4_OP_DCL_INPUT = 0x5f,
+ VKD3D_SM4_OP_DCL_INPUT_SGV = 0x60,
+ VKD3D_SM4_OP_DCL_INPUT_SIV = 0x61,
+ VKD3D_SM4_OP_DCL_INPUT_PS = 0x62,
+ VKD3D_SM4_OP_DCL_INPUT_PS_SGV = 0x63,
+ VKD3D_SM4_OP_DCL_INPUT_PS_SIV = 0x64,
+ VKD3D_SM4_OP_DCL_OUTPUT = 0x65,
+ VKD3D_SM4_OP_DCL_OUTPUT_SIV = 0x67,
+ VKD3D_SM4_OP_DCL_TEMPS = 0x68,
+ VKD3D_SM4_OP_DCL_INDEXABLE_TEMP = 0x69,
+ VKD3D_SM4_OP_DCL_GLOBAL_FLAGS = 0x6a,
+ VKD3D_SM4_OP_LOD = 0x6c,
+ VKD3D_SM4_OP_GATHER4 = 0x6d,
+ VKD3D_SM4_OP_SAMPLE_POS = 0x6e,
+ VKD3D_SM4_OP_SAMPLE_INFO = 0x6f,
+ VKD3D_SM5_OP_HS_DECLS = 0x71,
+ VKD3D_SM5_OP_HS_CONTROL_POINT_PHASE = 0x72,
+ VKD3D_SM5_OP_HS_FORK_PHASE = 0x73,
+ VKD3D_SM5_OP_HS_JOIN_PHASE = 0x74,
+ VKD3D_SM5_OP_EMIT_STREAM = 0x75,
+ VKD3D_SM5_OP_CUT_STREAM = 0x76,
+ VKD3D_SM5_OP_FCALL = 0x78,
+ VKD3D_SM5_OP_BUFINFO = 0x79,
+ VKD3D_SM5_OP_DERIV_RTX_COARSE = 0x7a,
+ VKD3D_SM5_OP_DERIV_RTX_FINE = 0x7b,
+ VKD3D_SM5_OP_DERIV_RTY_COARSE = 0x7c,
+ VKD3D_SM5_OP_DERIV_RTY_FINE = 0x7d,
+ VKD3D_SM5_OP_GATHER4_C = 0x7e,
+ VKD3D_SM5_OP_GATHER4_PO = 0x7f,
+ VKD3D_SM5_OP_GATHER4_PO_C = 0x80,
+ VKD3D_SM5_OP_RCP = 0x81,
+ VKD3D_SM5_OP_F32TOF16 = 0x82,
+ VKD3D_SM5_OP_F16TOF32 = 0x83,
+ VKD3D_SM5_OP_COUNTBITS = 0x86,
+ VKD3D_SM5_OP_FIRSTBIT_HI = 0x87,
+ VKD3D_SM5_OP_FIRSTBIT_LO = 0x88,
+ VKD3D_SM5_OP_FIRSTBIT_SHI = 0x89,
+ VKD3D_SM5_OP_UBFE = 0x8a,
+ VKD3D_SM5_OP_IBFE = 0x8b,
+ VKD3D_SM5_OP_BFI = 0x8c,
+ VKD3D_SM5_OP_BFREV = 0x8d,
+ VKD3D_SM5_OP_SWAPC = 0x8e,
+ VKD3D_SM5_OP_DCL_STREAM = 0x8f,
+ VKD3D_SM5_OP_DCL_FUNCTION_BODY = 0x90,
+ VKD3D_SM5_OP_DCL_FUNCTION_TABLE = 0x91,
+ VKD3D_SM5_OP_DCL_INTERFACE = 0x92,
+ VKD3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT = 0x93,
+ VKD3D_SM5_OP_DCL_OUTPUT_CONTROL_POINT_COUNT = 0x94,
+ VKD3D_SM5_OP_DCL_TESSELLATOR_DOMAIN = 0x95,
+ VKD3D_SM5_OP_DCL_TESSELLATOR_PARTITIONING = 0x96,
+ VKD3D_SM5_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE = 0x97,
+ VKD3D_SM5_OP_DCL_HS_MAX_TESSFACTOR = 0x98,
+ VKD3D_SM5_OP_DCL_HS_FORK_PHASE_INSTANCE_COUNT = 0x99,
+ VKD3D_SM5_OP_DCL_HS_JOIN_PHASE_INSTANCE_COUNT = 0x9a,
+ VKD3D_SM5_OP_DCL_THREAD_GROUP = 0x9b,
+ VKD3D_SM5_OP_DCL_UAV_TYPED = 0x9c,
+ VKD3D_SM5_OP_DCL_UAV_RAW = 0x9d,
+ VKD3D_SM5_OP_DCL_UAV_STRUCTURED = 0x9e,
+ VKD3D_SM5_OP_DCL_TGSM_RAW = 0x9f,
+ VKD3D_SM5_OP_DCL_TGSM_STRUCTURED = 0xa0,
+ VKD3D_SM5_OP_DCL_RESOURCE_RAW = 0xa1,
+ VKD3D_SM5_OP_DCL_RESOURCE_STRUCTURED = 0xa2,
+ VKD3D_SM5_OP_LD_UAV_TYPED = 0xa3,
+ VKD3D_SM5_OP_STORE_UAV_TYPED = 0xa4,
+ VKD3D_SM5_OP_LD_RAW = 0xa5,
+ VKD3D_SM5_OP_STORE_RAW = 0xa6,
+ VKD3D_SM5_OP_LD_STRUCTURED = 0xa7,
+ VKD3D_SM5_OP_STORE_STRUCTURED = 0xa8,
+ VKD3D_SM5_OP_ATOMIC_AND = 0xa9,
+ VKD3D_SM5_OP_ATOMIC_OR = 0xaa,
+ VKD3D_SM5_OP_ATOMIC_XOR = 0xab,
+ VKD3D_SM5_OP_ATOMIC_CMP_STORE = 0xac,
+ VKD3D_SM5_OP_ATOMIC_IADD = 0xad,
+ VKD3D_SM5_OP_ATOMIC_IMAX = 0xae,
+ VKD3D_SM5_OP_ATOMIC_IMIN = 0xaf,
+ VKD3D_SM5_OP_ATOMIC_UMAX = 0xb0,
+ VKD3D_SM5_OP_ATOMIC_UMIN = 0xb1,
+ VKD3D_SM5_OP_IMM_ATOMIC_ALLOC = 0xb2,
+ VKD3D_SM5_OP_IMM_ATOMIC_CONSUME = 0xb3,
+ VKD3D_SM5_OP_IMM_ATOMIC_IADD = 0xb4,
+ VKD3D_SM5_OP_IMM_ATOMIC_AND = 0xb5,
+ VKD3D_SM5_OP_IMM_ATOMIC_OR = 0xb6,
+ VKD3D_SM5_OP_IMM_ATOMIC_XOR = 0xb7,
+ VKD3D_SM5_OP_IMM_ATOMIC_EXCH = 0xb8,
+ VKD3D_SM5_OP_IMM_ATOMIC_CMP_EXCH = 0xb9,
+ VKD3D_SM5_OP_IMM_ATOMIC_IMAX = 0xba,
+ VKD3D_SM5_OP_IMM_ATOMIC_IMIN = 0xbb,
+ VKD3D_SM5_OP_IMM_ATOMIC_UMAX = 0xbc,
+ VKD3D_SM5_OP_IMM_ATOMIC_UMIN = 0xbd,
+ VKD3D_SM5_OP_SYNC = 0xbe,
+ VKD3D_SM5_OP_EVAL_SAMPLE_INDEX = 0xcc,
+ VKD3D_SM5_OP_EVAL_CENTROID = 0xcd,
+ VKD3D_SM5_OP_DCL_GS_INSTANCES = 0xce,
+};
+
+enum vkd3d_sm4_instruction_modifier
+{
+ VKD3D_SM4_MODIFIER_AOFFIMMI = 0x1,
+ VKD3D_SM5_MODIFIER_RESOURCE_TYPE = 0x2,
+ VKD3D_SM5_MODIFIER_DATA_TYPE = 0x3,
+};
+
+enum vkd3d_sm4_register_type
+{
+ VKD3D_SM4_RT_TEMP = 0x00,
+ VKD3D_SM4_RT_INPUT = 0x01,
+ VKD3D_SM4_RT_OUTPUT = 0x02,
+ VKD3D_SM4_RT_INDEXABLE_TEMP = 0x03,
+ VKD3D_SM4_RT_IMMCONST = 0x04,
+ VKD3D_SM4_RT_SAMPLER = 0x06,
+ VKD3D_SM4_RT_RESOURCE = 0x07,
+ VKD3D_SM4_RT_CONSTBUFFER = 0x08,
+ VKD3D_SM4_RT_IMMCONSTBUFFER = 0x09,
+ VKD3D_SM4_RT_PRIMID = 0x0b,
+ VKD3D_SM4_RT_DEPTHOUT = 0x0c,
+ VKD3D_SM4_RT_NULL = 0x0d,
+ VKD3D_SM4_RT_RASTERIZER = 0x0e,
+ VKD3D_SM4_RT_OMASK = 0x0f,
+ VKD3D_SM5_RT_STREAM = 0x10,
+ VKD3D_SM5_RT_FUNCTION_BODY = 0x11,
+ VKD3D_SM5_RT_FUNCTION_POINTER = 0x13,
+ VKD3D_SM5_RT_OUTPUT_CONTROL_POINT_ID = 0x16,
+ VKD3D_SM5_RT_FORK_INSTANCE_ID = 0x17,
+ VKD3D_SM5_RT_JOIN_INSTANCE_ID = 0x18,
+ VKD3D_SM5_RT_INPUT_CONTROL_POINT = 0x19,
+ VKD3D_SM5_RT_OUTPUT_CONTROL_POINT = 0x1a,
+ VKD3D_SM5_RT_PATCH_CONSTANT_DATA = 0x1b,
+ VKD3D_SM5_RT_DOMAIN_LOCATION = 0x1c,
+ VKD3D_SM5_RT_UAV = 0x1e,
+ VKD3D_SM5_RT_SHARED_MEMORY = 0x1f,
+ VKD3D_SM5_RT_THREAD_ID = 0x20,
+ VKD3D_SM5_RT_THREAD_GROUP_ID = 0x21,
+ VKD3D_SM5_RT_LOCAL_THREAD_ID = 0x22,
+ VKD3D_SM5_RT_COVERAGE = 0x23,
+ VKD3D_SM5_RT_LOCAL_THREAD_INDEX = 0x24,
+ VKD3D_SM5_RT_GS_INSTANCE_ID = 0x25,
+ VKD3D_SM5_RT_DEPTHOUT_GREATER_EQUAL = 0x26,
+ VKD3D_SM5_RT_DEPTHOUT_LESS_EQUAL = 0x27,
+};
+
+enum vkd3d_sm4_output_primitive_type
+{
+ VKD3D_SM4_OUTPUT_PT_POINTLIST = 0x1,
+ VKD3D_SM4_OUTPUT_PT_LINESTRIP = 0x3,
+ VKD3D_SM4_OUTPUT_PT_TRIANGLESTRIP = 0x5,
+};
+
+enum vkd3d_sm4_input_primitive_type
+{
+ VKD3D_SM4_INPUT_PT_POINT = 0x01,
+ VKD3D_SM4_INPUT_PT_LINE = 0x02,
+ VKD3D_SM4_INPUT_PT_TRIANGLE = 0x03,
+ VKD3D_SM4_INPUT_PT_LINEADJ = 0x06,
+ VKD3D_SM4_INPUT_PT_TRIANGLEADJ = 0x07,
+ VKD3D_SM5_INPUT_PT_PATCH1 = 0x08,
+ VKD3D_SM5_INPUT_PT_PATCH2 = 0x09,
+ VKD3D_SM5_INPUT_PT_PATCH3 = 0x0a,
+ VKD3D_SM5_INPUT_PT_PATCH4 = 0x0b,
+ VKD3D_SM5_INPUT_PT_PATCH5 = 0x0c,
+ VKD3D_SM5_INPUT_PT_PATCH6 = 0x0d,
+ VKD3D_SM5_INPUT_PT_PATCH7 = 0x0e,
+ VKD3D_SM5_INPUT_PT_PATCH8 = 0x0f,
+ VKD3D_SM5_INPUT_PT_PATCH9 = 0x10,
+ VKD3D_SM5_INPUT_PT_PATCH10 = 0x11,
+ VKD3D_SM5_INPUT_PT_PATCH11 = 0x12,
+ VKD3D_SM5_INPUT_PT_PATCH12 = 0x13,
+ VKD3D_SM5_INPUT_PT_PATCH13 = 0x14,
+ VKD3D_SM5_INPUT_PT_PATCH14 = 0x15,
+ VKD3D_SM5_INPUT_PT_PATCH15 = 0x16,
+ VKD3D_SM5_INPUT_PT_PATCH16 = 0x17,
+ VKD3D_SM5_INPUT_PT_PATCH17 = 0x18,
+ VKD3D_SM5_INPUT_PT_PATCH18 = 0x19,
+ VKD3D_SM5_INPUT_PT_PATCH19 = 0x1a,
+ VKD3D_SM5_INPUT_PT_PATCH20 = 0x1b,
+ VKD3D_SM5_INPUT_PT_PATCH21 = 0x1c,
+ VKD3D_SM5_INPUT_PT_PATCH22 = 0x1d,
+ VKD3D_SM5_INPUT_PT_PATCH23 = 0x1e,
+ VKD3D_SM5_INPUT_PT_PATCH24 = 0x1f,
+ VKD3D_SM5_INPUT_PT_PATCH25 = 0x20,
+ VKD3D_SM5_INPUT_PT_PATCH26 = 0x21,
+ VKD3D_SM5_INPUT_PT_PATCH27 = 0x22,
+ VKD3D_SM5_INPUT_PT_PATCH28 = 0x23,
+ VKD3D_SM5_INPUT_PT_PATCH29 = 0x24,
+ VKD3D_SM5_INPUT_PT_PATCH30 = 0x25,
+ VKD3D_SM5_INPUT_PT_PATCH31 = 0x26,
+ VKD3D_SM5_INPUT_PT_PATCH32 = 0x27,
+};
+
+enum vkd3d_sm4_swizzle_type
+{
+ VKD3D_SM4_SWIZZLE_NONE = 0x0,
+ VKD3D_SM4_SWIZZLE_VEC4 = 0x1,
+ VKD3D_SM4_SWIZZLE_SCALAR = 0x2,
+};
+
+enum vkd3d_sm4_dimension
+{
+ VKD3D_SM4_DIMENSION_NONE = 0x0,
+ VKD3D_SM4_DIMENSION_SCALAR = 0x1,
+ VKD3D_SM4_DIMENSION_VEC4 = 0x2,
+};
+
+enum vkd3d_sm4_resource_type
+{
+ VKD3D_SM4_RESOURCE_BUFFER = 0x1,
+ VKD3D_SM4_RESOURCE_TEXTURE_1D = 0x2,
+ VKD3D_SM4_RESOURCE_TEXTURE_2D = 0x3,
+ VKD3D_SM4_RESOURCE_TEXTURE_2DMS = 0x4,
+ VKD3D_SM4_RESOURCE_TEXTURE_3D = 0x5,
+ VKD3D_SM4_RESOURCE_TEXTURE_CUBE = 0x6,
+ VKD3D_SM4_RESOURCE_TEXTURE_1DARRAY = 0x7,
+ VKD3D_SM4_RESOURCE_TEXTURE_2DARRAY = 0x8,
+ VKD3D_SM4_RESOURCE_TEXTURE_2DMSARRAY = 0x9,
+ VKD3D_SM4_RESOURCE_TEXTURE_CUBEARRAY = 0xa,
+};
+
+enum vkd3d_sm4_data_type
+{
+ VKD3D_SM4_DATA_UNORM = 0x1,
+ VKD3D_SM4_DATA_SNORM = 0x2,
+ VKD3D_SM4_DATA_INT = 0x3,
+ VKD3D_SM4_DATA_UINT = 0x4,
+ VKD3D_SM4_DATA_FLOAT = 0x5,
+};
+
+enum vkd3d_sm4_sampler_mode
+{
+ VKD3D_SM4_SAMPLER_DEFAULT = 0x0,
+ VKD3D_SM4_SAMPLER_COMPARISON = 0x1,
+};
+
+enum vkd3d_sm4_shader_data_type
+{
+ VKD3D_SM4_SHADER_DATA_IMMEDIATE_CONSTANT_BUFFER = 0x3,
+ VKD3D_SM4_SHADER_DATA_MESSAGE = 0x4,
+};
+
+struct vkd3d_shader_src_param_entry
+{
+ struct list entry;
+ struct vkd3d_shader_src_param param;
+};
+
+struct vkd3d_sm4_data
+{
+ struct vkd3d_shader_version shader_version;
+ const DWORD *start, *end;
+
+ unsigned int output_map[MAX_REG_OUTPUT];
+
+ struct vkd3d_shader_src_param src_param[5];
+ struct vkd3d_shader_dst_param dst_param[2];
+ struct list src_free;
+ struct list src;
+ struct vkd3d_shader_immediate_constant_buffer icb;
+};
+
+struct vkd3d_sm4_opcode_info
+{
+ enum vkd3d_sm4_opcode opcode;
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+ const char *dst_info;
+ const char *src_info;
+ void (*read_opcode_func)(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv);
+};
+
+static const enum vkd3d_primitive_type output_primitive_type_table[] =
+{
+ /* UNKNOWN */ VKD3D_PT_UNDEFINED,
+ /* VKD3D_SM4_OUTPUT_PT_POINTLIST */ VKD3D_PT_POINTLIST,
+ /* UNKNOWN */ VKD3D_PT_UNDEFINED,
+ /* VKD3D_SM4_OUTPUT_PT_LINESTRIP */ VKD3D_PT_LINESTRIP,
+ /* UNKNOWN */ VKD3D_PT_UNDEFINED,
+ /* VKD3D_SM4_OUTPUT_PT_TRIANGLESTRIP */ VKD3D_PT_TRIANGLESTRIP,
+};
+
+static const enum vkd3d_primitive_type input_primitive_type_table[] =
+{
+ /* UNKNOWN */ VKD3D_PT_UNDEFINED,
+ /* VKD3D_SM4_INPUT_PT_POINT */ VKD3D_PT_POINTLIST,
+ /* VKD3D_SM4_INPUT_PT_LINE */ VKD3D_PT_LINELIST,
+ /* VKD3D_SM4_INPUT_PT_TRIANGLE */ VKD3D_PT_TRIANGLELIST,
+ /* UNKNOWN */ VKD3D_PT_UNDEFINED,
+ /* UNKNOWN */ VKD3D_PT_UNDEFINED,
+ /* VKD3D_SM4_INPUT_PT_LINEADJ */ VKD3D_PT_LINELIST_ADJ,
+ /* VKD3D_SM4_INPUT_PT_TRIANGLEADJ */ VKD3D_PT_TRIANGLELIST_ADJ,
+};
+
+static const enum vkd3d_shader_resource_type resource_type_table[] =
+{
+ /* 0 */ VKD3D_SHADER_RESOURCE_NONE,
+ /* VKD3D_SM4_RESOURCE_BUFFER */ VKD3D_SHADER_RESOURCE_BUFFER,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_1D */ VKD3D_SHADER_RESOURCE_TEXTURE_1D,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_2D */ VKD3D_SHADER_RESOURCE_TEXTURE_2D,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_2DMS */ VKD3D_SHADER_RESOURCE_TEXTURE_2DMS,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_3D */ VKD3D_SHADER_RESOURCE_TEXTURE_3D,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_CUBE */ VKD3D_SHADER_RESOURCE_TEXTURE_CUBE,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_1DARRAY */ VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_2DARRAY */ VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_2DMSARRAY */ VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY,
+ /* VKD3D_SM4_RESOURCE_TEXTURE_CUBEARRAY */ VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY,
+};
+
+static const enum vkd3d_data_type data_type_table[] =
+{
+ /* 0 */ VKD3D_DATA_FLOAT,
+ /* VKD3D_SM4_DATA_UNORM */ VKD3D_DATA_UNORM,
+ /* VKD3D_SM4_DATA_SNORM */ VKD3D_DATA_SNORM,
+ /* VKD3D_SM4_DATA_INT */ VKD3D_DATA_INT,
+ /* VKD3D_SM4_DATA_UINT */ VKD3D_DATA_UINT,
+ /* VKD3D_SM4_DATA_FLOAT */ VKD3D_DATA_FLOAT,
+};
+
+static bool shader_is_sm_5_1(const struct vkd3d_sm4_data *priv)
+{
+ const struct vkd3d_shader_version *version = &priv->shader_version;
+ return version->major >= 5 && version->minor >= 1;
+}
+
+static bool shader_sm4_read_src_param(struct vkd3d_sm4_data *priv, const DWORD **ptr, const DWORD *end,
+ enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param);
+static bool shader_sm4_read_dst_param(struct vkd3d_sm4_data *priv, const DWORD **ptr, const DWORD *end,
+ enum vkd3d_data_type data_type, struct vkd3d_shader_dst_param *dst_param);
+
+static bool shader_sm4_read_register_space(struct vkd3d_sm4_data *priv,
+ const DWORD **ptr, const DWORD *end, unsigned int *register_space)
+{
+ *register_space = 0;
+
+ if (!shader_is_sm_5_1(priv))
+ return true;
+
+ if (*ptr >= end)
+ {
+ WARN("Invalid ptr %p >= end %p.\n", *ptr, end);
+ return false;
+ }
+
+ *register_space = *(*ptr)++;
+ return true;
+}
+
+static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &priv->src_param[0]);
+ ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ?
+ VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z;
+}
+
+static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ enum vkd3d_sm4_shader_data_type type;
+ unsigned int icb_size;
+
+ type = (opcode_token & VKD3D_SM4_SHADER_DATA_TYPE_MASK) >> VKD3D_SM4_SHADER_DATA_TYPE_SHIFT;
+ if (type != VKD3D_SM4_SHADER_DATA_IMMEDIATE_CONSTANT_BUFFER)
+ {
+ FIXME("Ignoring shader data type %#x.\n", type);
+ ins->handler_idx = VKD3DSIH_NOP;
+ return;
+ }
+
+ ++tokens;
+ icb_size = token_count - 1;
+ if (icb_size % 4 || icb_size > MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE)
+ {
+ FIXME("Unexpected immediate constant buffer size %u.\n", icb_size);
+ ins->handler_idx = VKD3DSIH_INVALID;
+ return;
+ }
+
+ priv->icb.vec4_count = icb_size / 4;
+ memcpy(priv->icb.data, tokens, sizeof(*tokens) * icb_size);
+ ins->declaration.icb = &priv->icb;
+}
+
+static unsigned int shader_sm4_map_resource_idx(struct vkd3d_shader_register *reg, const struct vkd3d_sm4_data *priv)
+{
+ if (shader_is_sm_5_1(priv))
+ return reg->idx[1].offset;
+ else
+ return reg->idx[0].offset;
+}
+
+static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ struct vkd3d_shader_semantic *semantic = &ins->declaration.semantic;
+ enum vkd3d_sm4_resource_type resource_type;
+ const DWORD *end = &tokens[token_count];
+ enum vkd3d_sm4_data_type data_type;
+ enum vkd3d_data_type reg_data_type;
+ DWORD components;
+
+ resource_type = (opcode_token & VKD3D_SM4_RESOURCE_TYPE_MASK) >> VKD3D_SM4_RESOURCE_TYPE_SHIFT;
+ if (!resource_type || (resource_type >= ARRAY_SIZE(resource_type_table)))
+ {
+ FIXME("Unhandled resource type %#x.\n", resource_type);
+ semantic->resource_type = VKD3D_SHADER_RESOURCE_NONE;
+ }
+ else
+ {
+ semantic->resource_type = resource_type_table[resource_type];
+ }
+ reg_data_type = opcode == VKD3D_SM4_OP_DCL_RESOURCE ? VKD3D_DATA_RESOURCE : VKD3D_DATA_UAV;
+ shader_sm4_read_dst_param(priv, &tokens, end, reg_data_type, &semantic->resource.reg);
+ semantic->resource.register_index = shader_sm4_map_resource_idx(&semantic->resource.reg.reg, priv);
+
+ components = *tokens++;
+ if ((components & 0xfff0) != (components & 0xf) * 0x1110)
+ FIXME("Components (%#x) have different data types.\n", components);
+ data_type = components & 0xf;
+
+ if (!data_type || (data_type >= ARRAY_SIZE(data_type_table)))
+ {
+ FIXME("Unhandled data type %#x.\n", data_type);
+ semantic->resource_data_type = VKD3D_DATA_FLOAT;
+ }
+ else
+ {
+ semantic->resource_data_type = data_type_table[data_type];
+ }
+
+ if (reg_data_type == VKD3D_DATA_UAV)
+ ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT;
+
+ shader_sm4_read_register_space(priv, &tokens, end, &semantic->resource.register_space);
+}
+
+static void shader_sm4_read_dcl_constant_buffer(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ const DWORD *end = &tokens[token_count];
+
+ shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_FLOAT, &ins->declaration.cb.src);
+ ins->declaration.cb.register_index = shader_sm4_map_resource_idx(&ins->declaration.cb.src.reg, priv);
+ if (opcode_token & VKD3D_SM4_INDEX_TYPE_MASK)
+ ins->flags |= VKD3DSI_INDEXED_DYNAMIC;
+
+ ins->declaration.cb.size = ins->declaration.cb.src.reg.idx[2].offset;
+ ins->declaration.cb.register_space = 0;
+
+ if (shader_is_sm_5_1(priv))
+ {
+ if (tokens >= end)
+ {
+ FIXME("Invalid ptr %p >= end %p.\n", tokens, end);
+ return;
+ }
+
+ ins->declaration.cb.size = *tokens++;
+ shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.cb.register_space);
+ }
+}
+
+static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ const DWORD *end = &tokens[token_count];
+
+ ins->flags = (opcode_token & VKD3D_SM4_SAMPLER_MODE_MASK) >> VKD3D_SM4_SAMPLER_MODE_SHIFT;
+ if (ins->flags & ~VKD3D_SM4_SAMPLER_COMPARISON)
+ FIXME("Unhandled sampler mode %#x.\n", ins->flags);
+ shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_SAMPLER, &ins->declaration.sampler.src);
+ ins->declaration.sampler.register_index = shader_sm4_map_resource_idx(&ins->declaration.sampler.src.reg, priv);
+ shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.sampler.register_space);
+}
+
+static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE,
+ &ins->declaration.index_range.dst);
+ ins->declaration.index_range.register_count = *tokens;
+}
+
+static void shader_sm4_read_dcl_output_topology(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ enum vkd3d_sm4_output_primitive_type primitive_type;
+
+ primitive_type = (opcode_token & VKD3D_SM4_PRIMITIVE_TYPE_MASK) >> VKD3D_SM4_PRIMITIVE_TYPE_SHIFT;
+ if (primitive_type >= ARRAY_SIZE(output_primitive_type_table))
+ ins->declaration.primitive_type.type = VKD3D_PT_UNDEFINED;
+ else
+ ins->declaration.primitive_type.type = output_primitive_type_table[primitive_type];
+
+ if (ins->declaration.primitive_type.type == VKD3D_PT_UNDEFINED)
+ FIXME("Unhandled output primitive type %#x.\n", primitive_type);
+}
+
+static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ enum vkd3d_sm4_input_primitive_type primitive_type;
+
+ primitive_type = (opcode_token & VKD3D_SM4_PRIMITIVE_TYPE_MASK) >> VKD3D_SM4_PRIMITIVE_TYPE_SHIFT;
+ if (VKD3D_SM5_INPUT_PT_PATCH1 <= primitive_type && primitive_type <= VKD3D_SM5_INPUT_PT_PATCH32)
+ {
+ ins->declaration.primitive_type.type = VKD3D_PT_PATCH;
+ ins->declaration.primitive_type.patch_vertex_count = primitive_type - VKD3D_SM5_INPUT_PT_PATCH1 + 1;
+ }
+ else if (primitive_type >= ARRAY_SIZE(input_primitive_type_table))
+ {
+ ins->declaration.primitive_type.type = VKD3D_PT_UNDEFINED;
+ }
+ else
+ {
+ ins->declaration.primitive_type.type = input_primitive_type_table[primitive_type];
+ }
+
+ if (ins->declaration.primitive_type.type == VKD3D_PT_UNDEFINED)
+ FIXME("Unhandled input primitive type %#x.\n", primitive_type);
+}
+
+static void shader_sm4_read_declaration_count(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.count = *tokens;
+}
+
+static void shader_sm4_read_declaration_dst(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, &ins->declaration.dst);
+}
+
+static void shader_sm4_read_declaration_register_semantic(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT,
+ &ins->declaration.register_semantic.reg);
+ ins->declaration.register_semantic.sysval_semantic = *tokens;
+}
+
+static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->flags = (opcode_token & VKD3D_SM4_INTERPOLATION_MODE_MASK) >> VKD3D_SM4_INTERPOLATION_MODE_SHIFT;
+ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, &ins->declaration.dst);
+}
+
+static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->flags = (opcode_token & VKD3D_SM4_INTERPOLATION_MODE_MASK) >> VKD3D_SM4_INTERPOLATION_MODE_SHIFT;
+ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT,
+ &ins->declaration.register_semantic.reg);
+ ins->declaration.register_semantic.sysval_semantic = *tokens;
+}
+
+static void shader_sm4_read_dcl_indexable_temp(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.indexable_temp.register_idx = *tokens++;
+ ins->declaration.indexable_temp.register_size = *tokens++;
+ ins->declaration.indexable_temp.component_count = *tokens;
+}
+
+static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->flags = (opcode_token & VKD3D_SM4_GLOBAL_FLAGS_MASK) >> VKD3D_SM4_GLOBAL_FLAGS_SHIFT;
+}
+
+static void shader_sm5_read_fcall(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ priv->src_param[0].reg.u.fp_body_idx = *tokens++;
+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &priv->src_param[0]);
+}
+
+static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.index = *tokens;
+}
+
+static void shader_sm5_read_dcl_function_table(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.index = *tokens++;
+ FIXME("Ignoring set of function bodies (count %u).\n", *tokens);
+}
+
+static void shader_sm5_read_dcl_interface(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.fp.index = *tokens++;
+ ins->declaration.fp.body_count = *tokens++;
+ ins->declaration.fp.array_size = *tokens >> VKD3D_SM5_FP_ARRAY_SIZE_SHIFT;
+ ins->declaration.fp.table_count = *tokens++ & VKD3D_SM5_FP_TABLE_COUNT_MASK;
+ FIXME("Ignoring set of function tables (count %u).\n", ins->declaration.fp.table_count);
+}
+
+static void shader_sm5_read_control_point_count(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.count = (opcode_token & VKD3D_SM5_CONTROL_POINT_COUNT_MASK)
+ >> VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT;
+}
+
+static void shader_sm5_read_dcl_tessellator_domain(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.tessellator_domain = (opcode_token & VKD3D_SM5_TESSELLATOR_MASK)
+ >> VKD3D_SM5_TESSELLATOR_SHIFT;
+}
+
+static void shader_sm5_read_dcl_tessellator_partitioning(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.tessellator_partitioning = (opcode_token & VKD3D_SM5_TESSELLATOR_MASK)
+ >> VKD3D_SM5_TESSELLATOR_SHIFT;
+}
+
+static void shader_sm5_read_dcl_tessellator_output_primitive(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.tessellator_output_primitive = (opcode_token & VKD3D_SM5_TESSELLATOR_MASK)
+ >> VKD3D_SM5_TESSELLATOR_SHIFT;
+}
+
+static void shader_sm5_read_dcl_hs_max_tessfactor(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.max_tessellation_factor = *(float *)tokens;
+}
+
+static void shader_sm5_read_dcl_thread_group(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->declaration.thread_group_size.x = *tokens++;
+ ins->declaration.thread_group_size.y = *tokens++;
+ ins->declaration.thread_group_size.z = *tokens++;
+}
+
+static void shader_sm5_read_dcl_uav_raw(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource;
+ const DWORD *end = &tokens[token_count];
+
+ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->resource.reg);
+ resource->resource.register_index = shader_sm4_map_resource_idx(&resource->resource.reg.reg, priv);
+ ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT;
+ shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.register_space);
+}
+
+static void shader_sm5_read_dcl_uav_structured(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource;
+ const DWORD *end = &tokens[token_count];
+
+ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->resource.reg);
+ resource->resource.register_index = shader_sm4_map_resource_idx(&resource->resource.reg.reg, priv);
+ ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT;
+ resource->byte_stride = *tokens++;
+ if (resource->byte_stride % 4)
+ FIXME("Byte stride %u is not multiple of 4.\n", resource->byte_stride);
+ shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.register_space);
+}
+
+static void shader_sm5_read_dcl_tgsm_raw(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, &ins->declaration.tgsm_raw.reg);
+ ins->declaration.tgsm_raw.byte_count = *tokens;
+ if (ins->declaration.tgsm_raw.byte_count % 4)
+ FIXME("Byte count %u is not multiple of 4.\n", ins->declaration.tgsm_raw.byte_count);
+}
+
+static void shader_sm5_read_dcl_tgsm_structured(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT,
+ &ins->declaration.tgsm_structured.reg);
+ ins->declaration.tgsm_structured.byte_stride = *tokens++;
+ ins->declaration.tgsm_structured.structure_count = *tokens;
+ if (ins->declaration.tgsm_structured.byte_stride % 4)
+ FIXME("Byte stride %u is not multiple of 4.\n", ins->declaration.tgsm_structured.byte_stride);
+}
+
+static void shader_sm5_read_dcl_resource_structured(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource;
+ const DWORD *end = &tokens[token_count];
+
+ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->resource.reg);
+ resource->resource.register_index = shader_sm4_map_resource_idx(&resource->resource.reg.reg, priv);
+ resource->byte_stride = *tokens++;
+ if (resource->byte_stride % 4)
+ FIXME("Byte stride %u is not multiple of 4.\n", resource->byte_stride);
+ shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.register_space);
+}
+
+static void shader_sm5_read_dcl_resource_raw(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource;
+ const DWORD *end = &tokens[token_count];
+
+ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->resource.reg);
+ resource->resource.register_index = shader_sm4_map_resource_idx(&resource->resource.reg.reg, priv);
+ shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.register_space);
+}
+
+static void shader_sm5_read_sync(struct vkd3d_shader_instruction *ins,
+ DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count,
+ struct vkd3d_sm4_data *priv)
+{
+ ins->flags = (opcode_token & VKD3D_SM5_SYNC_FLAGS_MASK) >> VKD3D_SM5_SYNC_FLAGS_SHIFT;
+}
+
+/*
+ * f -> VKD3D_DATA_FLOAT
+ * i -> VKD3D_DATA_INT
+ * u -> VKD3D_DATA_UINT
+ * O -> VKD3D_DATA_OPAQUE
+ * R -> VKD3D_DATA_RESOURCE
+ * S -> VKD3D_DATA_SAMPLER
+ * U -> VKD3D_DATA_UAV
+ */
+static const struct vkd3d_sm4_opcode_info opcode_table[] =
+{
+ {VKD3D_SM4_OP_ADD, VKD3DSIH_ADD, "f", "ff"},
+ {VKD3D_SM4_OP_AND, VKD3DSIH_AND, "u", "uu"},
+ {VKD3D_SM4_OP_BREAK, VKD3DSIH_BREAK, "", ""},
+ {VKD3D_SM4_OP_BREAKC, VKD3DSIH_BREAKP, "", "u",
+ shader_sm4_read_conditional_op},
+ {VKD3D_SM4_OP_CASE, VKD3DSIH_CASE, "", "u"},
+ {VKD3D_SM4_OP_CONTINUE, VKD3DSIH_CONTINUE, "", ""},
+ {VKD3D_SM4_OP_CONTINUEC, VKD3DSIH_CONTINUEP, "", "u",
+ shader_sm4_read_conditional_op},
+ {VKD3D_SM4_OP_CUT, VKD3DSIH_CUT, "", ""},
+ {VKD3D_SM4_OP_DEFAULT, VKD3DSIH_DEFAULT, "", ""},
+ {VKD3D_SM4_OP_DERIV_RTX, VKD3DSIH_DSX, "f", "f"},
+ {VKD3D_SM4_OP_DERIV_RTY, VKD3DSIH_DSY, "f", "f"},
+ {VKD3D_SM4_OP_DISCARD, VKD3DSIH_TEXKILL, "", "u",
+ shader_sm4_read_conditional_op},
+ {VKD3D_SM4_OP_DIV, VKD3DSIH_DIV, "f", "ff"},
+ {VKD3D_SM4_OP_DP2, VKD3DSIH_DP2, "f", "ff"},
+ {VKD3D_SM4_OP_DP3, VKD3DSIH_DP3, "f", "ff"},
+ {VKD3D_SM4_OP_DP4, VKD3DSIH_DP4, "f", "ff"},
+ {VKD3D_SM4_OP_ELSE, VKD3DSIH_ELSE, "", ""},
+ {VKD3D_SM4_OP_EMIT, VKD3DSIH_EMIT, "", ""},
+ {VKD3D_SM4_OP_ENDIF, VKD3DSIH_ENDIF, "", ""},
+ {VKD3D_SM4_OP_ENDLOOP, VKD3DSIH_ENDLOOP, "", ""},
+ {VKD3D_SM4_OP_ENDSWITCH, VKD3DSIH_ENDSWITCH, "", ""},
+ {VKD3D_SM4_OP_EQ, VKD3DSIH_EQ, "u", "ff"},
+ {VKD3D_SM4_OP_EXP, VKD3DSIH_EXP, "f", "f"},
+ {VKD3D_SM4_OP_FRC, VKD3DSIH_FRC, "f", "f"},
+ {VKD3D_SM4_OP_FTOI, VKD3DSIH_FTOI, "i", "f"},
+ {VKD3D_SM4_OP_FTOU, VKD3DSIH_FTOU, "u", "f"},
+ {VKD3D_SM4_OP_GE, VKD3DSIH_GE, "u", "ff"},
+ {VKD3D_SM4_OP_IADD, VKD3DSIH_IADD, "i", "ii"},
+ {VKD3D_SM4_OP_IF, VKD3DSIH_IF, "", "u",
+ shader_sm4_read_conditional_op},
+ {VKD3D_SM4_OP_IEQ, VKD3DSIH_IEQ, "u", "ii"},
+ {VKD3D_SM4_OP_IGE, VKD3DSIH_IGE, "u", "ii"},
+ {VKD3D_SM4_OP_ILT, VKD3DSIH_ILT, "u", "ii"},
+ {VKD3D_SM4_OP_IMAD, VKD3DSIH_IMAD, "i", "iii"},
+ {VKD3D_SM4_OP_IMAX, VKD3DSIH_IMAX, "i", "ii"},
+ {VKD3D_SM4_OP_IMIN, VKD3DSIH_IMIN, "i", "ii"},
+ {VKD3D_SM4_OP_IMUL, VKD3DSIH_IMUL, "ii", "ii"},
+ {VKD3D_SM4_OP_INE, VKD3DSIH_INE, "u", "ii"},
+ {VKD3D_SM4_OP_INEG, VKD3DSIH_INEG, "i", "i"},
+ {VKD3D_SM4_OP_ISHL, VKD3DSIH_ISHL, "i", "ii"},
+ {VKD3D_SM4_OP_ISHR, VKD3DSIH_ISHR, "i", "ii"},
+ {VKD3D_SM4_OP_ITOF, VKD3DSIH_ITOF, "f", "i"},
+ {VKD3D_SM4_OP_LABEL, VKD3DSIH_LABEL, "", "O"},
+ {VKD3D_SM4_OP_LD, VKD3DSIH_LD, "u", "iR"},
+ {VKD3D_SM4_OP_LD2DMS, VKD3DSIH_LD2DMS, "u", "iRi"},
+ {VKD3D_SM4_OP_LOG, VKD3DSIH_LOG, "f", "f"},
+ {VKD3D_SM4_OP_LOOP, VKD3DSIH_LOOP, "", ""},
+ {VKD3D_SM4_OP_LT, VKD3DSIH_LT, "u", "ff"},
+ {VKD3D_SM4_OP_MAD, VKD3DSIH_MAD, "f", "fff"},
+ {VKD3D_SM4_OP_MIN, VKD3DSIH_MIN, "f", "ff"},
+ {VKD3D_SM4_OP_MAX, VKD3DSIH_MAX, "f", "ff"},
+ {VKD3D_SM4_OP_SHADER_DATA, VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER, "", "",
+ shader_sm4_read_shader_data},
+ {VKD3D_SM4_OP_MOV, VKD3DSIH_MOV, "f", "f"},
+ {VKD3D_SM4_OP_MOVC, VKD3DSIH_MOVC, "f", "uff"},
+ {VKD3D_SM4_OP_MUL, VKD3DSIH_MUL, "f", "ff"},
+ {VKD3D_SM4_OP_NE, VKD3DSIH_NE, "u", "ff"},
+ {VKD3D_SM4_OP_NOP, VKD3DSIH_NOP, "", ""},
+ {VKD3D_SM4_OP_NOT, VKD3DSIH_NOT, "u", "u"},
+ {VKD3D_SM4_OP_OR, VKD3DSIH_OR, "u", "uu"},
+ {VKD3D_SM4_OP_RESINFO, VKD3DSIH_RESINFO, "f", "iR"},
+ {VKD3D_SM4_OP_RET, VKD3DSIH_RET, "", ""},
+ {VKD3D_SM4_OP_RETC, VKD3DSIH_RETP, "", "u",
+ shader_sm4_read_conditional_op},
+ {VKD3D_SM4_OP_ROUND_NE, VKD3DSIH_ROUND_NE, "f", "f"},
+ {VKD3D_SM4_OP_ROUND_NI, VKD3DSIH_ROUND_NI, "f", "f"},
+ {VKD3D_SM4_OP_ROUND_PI, VKD3DSIH_ROUND_PI, "f", "f"},
+ {VKD3D_SM4_OP_ROUND_Z, VKD3DSIH_ROUND_Z, "f", "f"},
+ {VKD3D_SM4_OP_RSQ, VKD3DSIH_RSQ, "f", "f"},
+ {VKD3D_SM4_OP_SAMPLE, VKD3DSIH_SAMPLE, "u", "fRS"},
+ {VKD3D_SM4_OP_SAMPLE_C, VKD3DSIH_SAMPLE_C, "f", "fRSf"},
+ {VKD3D_SM4_OP_SAMPLE_C_LZ, VKD3DSIH_SAMPLE_C_LZ, "f", "fRSf"},
+ {VKD3D_SM4_OP_SAMPLE_LOD, VKD3DSIH_SAMPLE_LOD, "u", "fRSf"},
+ {VKD3D_SM4_OP_SAMPLE_GRAD, VKD3DSIH_SAMPLE_GRAD, "u", "fRSff"},
+ {VKD3D_SM4_OP_SAMPLE_B, VKD3DSIH_SAMPLE_B, "u", "fRSf"},
+ {VKD3D_SM4_OP_SQRT, VKD3DSIH_SQRT, "f", "f"},
+ {VKD3D_SM4_OP_SWITCH, VKD3DSIH_SWITCH, "", "i"},
+ {VKD3D_SM4_OP_SINCOS, VKD3DSIH_SINCOS, "ff", "f"},
+ {VKD3D_SM4_OP_UDIV, VKD3DSIH_UDIV, "uu", "uu"},
+ {VKD3D_SM4_OP_ULT, VKD3DSIH_ULT, "u", "uu"},
+ {VKD3D_SM4_OP_UGE, VKD3DSIH_UGE, "u", "uu"},
+ {VKD3D_SM4_OP_UMUL, VKD3DSIH_UMUL, "uu", "uu"},
+ {VKD3D_SM4_OP_UMAX, VKD3DSIH_UMAX, "u", "uu"},
+ {VKD3D_SM4_OP_UMIN, VKD3DSIH_UMIN, "u", "uu"},
+ {VKD3D_SM4_OP_USHR, VKD3DSIH_USHR, "u", "uu"},
+ {VKD3D_SM4_OP_UTOF, VKD3DSIH_UTOF, "f", "u"},
+ {VKD3D_SM4_OP_XOR, VKD3DSIH_XOR, "u", "uu"},
+ {VKD3D_SM4_OP_DCL_RESOURCE, VKD3DSIH_DCL, "R", "",
+ shader_sm4_read_dcl_resource},
+ {VKD3D_SM4_OP_DCL_CONSTANT_BUFFER, VKD3DSIH_DCL_CONSTANT_BUFFER, "", "",
+ shader_sm4_read_dcl_constant_buffer},
+ {VKD3D_SM4_OP_DCL_SAMPLER, VKD3DSIH_DCL_SAMPLER, "", "",
+ shader_sm4_read_dcl_sampler},
+ {VKD3D_SM4_OP_DCL_INDEX_RANGE, VKD3DSIH_DCL_INDEX_RANGE, "", "",
+ shader_sm4_read_dcl_index_range},
+ {VKD3D_SM4_OP_DCL_OUTPUT_TOPOLOGY, VKD3DSIH_DCL_OUTPUT_TOPOLOGY, "", "",
+ shader_sm4_read_dcl_output_topology},
+ {VKD3D_SM4_OP_DCL_INPUT_PRIMITIVE, VKD3DSIH_DCL_INPUT_PRIMITIVE, "", "",
+ shader_sm4_read_dcl_input_primitive},
+ {VKD3D_SM4_OP_DCL_VERTICES_OUT, VKD3DSIH_DCL_VERTICES_OUT, "", "",
+ shader_sm4_read_declaration_count},
+ {VKD3D_SM4_OP_DCL_INPUT, VKD3DSIH_DCL_INPUT, "", "",
+ shader_sm4_read_declaration_dst},
+ {VKD3D_SM4_OP_DCL_INPUT_SGV, VKD3DSIH_DCL_INPUT_SGV, "", "",
+ shader_sm4_read_declaration_register_semantic},
+ {VKD3D_SM4_OP_DCL_INPUT_SIV, VKD3DSIH_DCL_INPUT_SIV, "", "",
+ shader_sm4_read_declaration_register_semantic},
+ {VKD3D_SM4_OP_DCL_INPUT_PS, VKD3DSIH_DCL_INPUT_PS, "", "",
+ shader_sm4_read_dcl_input_ps},
+ {VKD3D_SM4_OP_DCL_INPUT_PS_SGV, VKD3DSIH_DCL_INPUT_PS_SGV, "", "",
+ shader_sm4_read_declaration_register_semantic},
+ {VKD3D_SM4_OP_DCL_INPUT_PS_SIV, VKD3DSIH_DCL_INPUT_PS_SIV, "", "",
+ shader_sm4_read_dcl_input_ps_siv},
+ {VKD3D_SM4_OP_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT, "", "",
+ shader_sm4_read_declaration_dst},
+ {VKD3D_SM4_OP_DCL_OUTPUT_SIV, VKD3DSIH_DCL_OUTPUT_SIV, "", "",
+ shader_sm4_read_declaration_register_semantic},
+ {VKD3D_SM4_OP_DCL_TEMPS, VKD3DSIH_DCL_TEMPS, "", "",
+ shader_sm4_read_declaration_count},
+ {VKD3D_SM4_OP_DCL_INDEXABLE_TEMP, VKD3DSIH_DCL_INDEXABLE_TEMP, "", "",
+ shader_sm4_read_dcl_indexable_temp},
+ {VKD3D_SM4_OP_DCL_GLOBAL_FLAGS, VKD3DSIH_DCL_GLOBAL_FLAGS, "", "",
+ shader_sm4_read_dcl_global_flags},
+ {VKD3D_SM4_OP_LOD, VKD3DSIH_LOD, "f", "fRS"},
+ {VKD3D_SM4_OP_GATHER4, VKD3DSIH_GATHER4, "u", "fRS"},
+ {VKD3D_SM4_OP_SAMPLE_POS, VKD3DSIH_SAMPLE_POS, "f", "Ru"},
+ {VKD3D_SM4_OP_SAMPLE_INFO, VKD3DSIH_SAMPLE_INFO, "f", "R"},
+ {VKD3D_SM5_OP_HS_DECLS, VKD3DSIH_HS_DECLS, "", ""},
+ {VKD3D_SM5_OP_HS_CONTROL_POINT_PHASE, VKD3DSIH_HS_CONTROL_POINT_PHASE, "", ""},
+ {VKD3D_SM5_OP_HS_FORK_PHASE, VKD3DSIH_HS_FORK_PHASE, "", ""},
+ {VKD3D_SM5_OP_HS_JOIN_PHASE, VKD3DSIH_HS_JOIN_PHASE, "", ""},
+ {VKD3D_SM5_OP_EMIT_STREAM, VKD3DSIH_EMIT_STREAM, "", "f"},
+ {VKD3D_SM5_OP_CUT_STREAM, VKD3DSIH_CUT_STREAM, "", "f"},
+ {VKD3D_SM5_OP_FCALL, VKD3DSIH_FCALL, "", "O",
+ shader_sm5_read_fcall},
+ {VKD3D_SM5_OP_BUFINFO, VKD3DSIH_BUFINFO, "i", "U"},
+ {VKD3D_SM5_OP_DERIV_RTX_COARSE, VKD3DSIH_DSX_COARSE, "f", "f"},
+ {VKD3D_SM5_OP_DERIV_RTX_FINE, VKD3DSIH_DSX_FINE, "f", "f"},
+ {VKD3D_SM5_OP_DERIV_RTY_COARSE, VKD3DSIH_DSY_COARSE, "f", "f"},
+ {VKD3D_SM5_OP_DERIV_RTY_FINE, VKD3DSIH_DSY_FINE, "f", "f"},
+ {VKD3D_SM5_OP_GATHER4_C, VKD3DSIH_GATHER4_C, "f", "fRSf"},
+ {VKD3D_SM5_OP_GATHER4_PO, VKD3DSIH_GATHER4_PO, "f", "fiRS"},
+ {VKD3D_SM5_OP_GATHER4_PO_C, VKD3DSIH_GATHER4_PO_C, "f", "fiRSf"},
+ {VKD3D_SM5_OP_RCP, VKD3DSIH_RCP, "f", "f"},
+ {VKD3D_SM5_OP_F32TOF16, VKD3DSIH_F32TOF16, "u", "f"},
+ {VKD3D_SM5_OP_F16TOF32, VKD3DSIH_F16TOF32, "f", "u"},
+ {VKD3D_SM5_OP_COUNTBITS, VKD3DSIH_COUNTBITS, "u", "u"},
+ {VKD3D_SM5_OP_FIRSTBIT_HI, VKD3DSIH_FIRSTBIT_HI, "u", "u"},
+ {VKD3D_SM5_OP_FIRSTBIT_LO, VKD3DSIH_FIRSTBIT_LO, "u", "u"},
+ {VKD3D_SM5_OP_FIRSTBIT_SHI, VKD3DSIH_FIRSTBIT_SHI, "u", "i"},
+ {VKD3D_SM5_OP_UBFE, VKD3DSIH_UBFE, "u", "iiu"},
+ {VKD3D_SM5_OP_IBFE, VKD3DSIH_IBFE, "i", "iii"},
+ {VKD3D_SM5_OP_BFI, VKD3DSIH_BFI, "u", "iiuu"},
+ {VKD3D_SM5_OP_BFREV, VKD3DSIH_BFREV, "u", "u"},
+ {VKD3D_SM5_OP_SWAPC, VKD3DSIH_SWAPC, "ff", "uff"},
+ {VKD3D_SM5_OP_DCL_STREAM, VKD3DSIH_DCL_STREAM, "", "O"},
+ {VKD3D_SM5_OP_DCL_FUNCTION_BODY, VKD3DSIH_DCL_FUNCTION_BODY, "", "",
+ shader_sm5_read_dcl_function_body},
+ {VKD3D_SM5_OP_DCL_FUNCTION_TABLE, VKD3DSIH_DCL_FUNCTION_TABLE, "", "",
+ shader_sm5_read_dcl_function_table},
+ {VKD3D_SM5_OP_DCL_INTERFACE, VKD3DSIH_DCL_INTERFACE, "", "",
+ shader_sm5_read_dcl_interface},
+ {VKD3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT, VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT, "", "",
+ shader_sm5_read_control_point_count},
+ {VKD3D_SM5_OP_DCL_OUTPUT_CONTROL_POINT_COUNT, VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT, "", "",
+ shader_sm5_read_control_point_count},
+ {VKD3D_SM5_OP_DCL_TESSELLATOR_DOMAIN, VKD3DSIH_DCL_TESSELLATOR_DOMAIN, "", "",
+ shader_sm5_read_dcl_tessellator_domain},
+ {VKD3D_SM5_OP_DCL_TESSELLATOR_PARTITIONING, VKD3DSIH_DCL_TESSELLATOR_PARTITIONING, "", "",
+ shader_sm5_read_dcl_tessellator_partitioning},
+ {VKD3D_SM5_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE, VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE, "", "",
+ shader_sm5_read_dcl_tessellator_output_primitive},
+ {VKD3D_SM5_OP_DCL_HS_MAX_TESSFACTOR, VKD3DSIH_DCL_HS_MAX_TESSFACTOR, "", "",
+ shader_sm5_read_dcl_hs_max_tessfactor},
+ {VKD3D_SM5_OP_DCL_HS_FORK_PHASE_INSTANCE_COUNT, VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT, "", "",
+ shader_sm4_read_declaration_count},
+ {VKD3D_SM5_OP_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, "", "",
+ shader_sm4_read_declaration_count},
+ {VKD3D_SM5_OP_DCL_THREAD_GROUP, VKD3DSIH_DCL_THREAD_GROUP, "", "",
+ shader_sm5_read_dcl_thread_group},
+ {VKD3D_SM5_OP_DCL_UAV_TYPED, VKD3DSIH_DCL_UAV_TYPED, "", "",
+ shader_sm4_read_dcl_resource},
+ {VKD3D_SM5_OP_DCL_UAV_RAW, VKD3DSIH_DCL_UAV_RAW, "", "",
+ shader_sm5_read_dcl_uav_raw},
+ {VKD3D_SM5_OP_DCL_UAV_STRUCTURED, VKD3DSIH_DCL_UAV_STRUCTURED, "", "",
+ shader_sm5_read_dcl_uav_structured},
+ {VKD3D_SM5_OP_DCL_TGSM_RAW, VKD3DSIH_DCL_TGSM_RAW, "", "",
+ shader_sm5_read_dcl_tgsm_raw},
+ {VKD3D_SM5_OP_DCL_TGSM_STRUCTURED, VKD3DSIH_DCL_TGSM_STRUCTURED, "", "",
+ shader_sm5_read_dcl_tgsm_structured},
+ {VKD3D_SM5_OP_DCL_RESOURCE_RAW, VKD3DSIH_DCL_RESOURCE_RAW, "", "",
+ shader_sm5_read_dcl_resource_raw},
+ {VKD3D_SM5_OP_DCL_RESOURCE_STRUCTURED, VKD3DSIH_DCL_RESOURCE_STRUCTURED, "", "",
+ shader_sm5_read_dcl_resource_structured},
+ {VKD3D_SM5_OP_LD_UAV_TYPED, VKD3DSIH_LD_UAV_TYPED, "u", "iU"},
+ {VKD3D_SM5_OP_STORE_UAV_TYPED, VKD3DSIH_STORE_UAV_TYPED, "U", "iu"},
+ {VKD3D_SM5_OP_LD_RAW, VKD3DSIH_LD_RAW, "u", "iU"},
+ {VKD3D_SM5_OP_STORE_RAW, VKD3DSIH_STORE_RAW, "U", "uu"},
+ {VKD3D_SM5_OP_LD_STRUCTURED, VKD3DSIH_LD_STRUCTURED, "u", "iiR"},
+ {VKD3D_SM5_OP_STORE_STRUCTURED, VKD3DSIH_STORE_STRUCTURED, "U", "iiu"},
+ {VKD3D_SM5_OP_ATOMIC_AND, VKD3DSIH_ATOMIC_AND, "U", "iu"},
+ {VKD3D_SM5_OP_ATOMIC_OR, VKD3DSIH_ATOMIC_OR, "U", "iu"},
+ {VKD3D_SM5_OP_ATOMIC_XOR, VKD3DSIH_ATOMIC_XOR, "U", "iu"},
+ {VKD3D_SM5_OP_ATOMIC_CMP_STORE, VKD3DSIH_ATOMIC_CMP_STORE, "U", "iuu"},
+ {VKD3D_SM5_OP_ATOMIC_IADD, VKD3DSIH_ATOMIC_IADD, "U", "ii"},
+ {VKD3D_SM5_OP_ATOMIC_IMAX, VKD3DSIH_ATOMIC_IMAX, "U", "ii"},
+ {VKD3D_SM5_OP_ATOMIC_IMIN, VKD3DSIH_ATOMIC_IMIN, "U", "ii"},
+ {VKD3D_SM5_OP_ATOMIC_UMAX, VKD3DSIH_ATOMIC_UMAX, "U", "iu"},
+ {VKD3D_SM5_OP_ATOMIC_UMIN, VKD3DSIH_ATOMIC_UMIN, "U", "iu"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_ALLOC, VKD3DSIH_IMM_ATOMIC_ALLOC, "u", "U"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_CONSUME, VKD3DSIH_IMM_ATOMIC_CONSUME, "u", "U"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_IADD, VKD3DSIH_IMM_ATOMIC_IADD, "uU", "ii"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_AND, VKD3DSIH_IMM_ATOMIC_AND, "uU", "iu"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_OR, VKD3DSIH_IMM_ATOMIC_OR, "uU", "iu"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_XOR, VKD3DSIH_IMM_ATOMIC_XOR, "uU", "iu"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_EXCH, VKD3DSIH_IMM_ATOMIC_EXCH, "uU", "iu"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_CMP_EXCH, VKD3DSIH_IMM_ATOMIC_CMP_EXCH, "uU", "iuu"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_IMAX, VKD3DSIH_IMM_ATOMIC_IMAX, "iU", "ii"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_IMIN, VKD3DSIH_IMM_ATOMIC_IMIN, "iU", "ii"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_UMAX, VKD3DSIH_IMM_ATOMIC_UMAX, "uU", "iu"},
+ {VKD3D_SM5_OP_IMM_ATOMIC_UMIN, VKD3DSIH_IMM_ATOMIC_UMIN, "uU", "iu"},
+ {VKD3D_SM5_OP_SYNC, VKD3DSIH_SYNC, "", "",
+ shader_sm5_read_sync},
+ {VKD3D_SM5_OP_EVAL_SAMPLE_INDEX, VKD3DSIH_EVAL_SAMPLE_INDEX, "f", "fi"},
+ {VKD3D_SM5_OP_EVAL_CENTROID, VKD3DSIH_EVAL_CENTROID, "f", "f"},
+ {VKD3D_SM5_OP_DCL_GS_INSTANCES, VKD3DSIH_DCL_GS_INSTANCES, "", "",
+ shader_sm4_read_declaration_count},
+};
+
+static const enum vkd3d_shader_register_type register_type_table[] =
+{
+ /* VKD3D_SM4_RT_TEMP */ VKD3DSPR_TEMP,
+ /* VKD3D_SM4_RT_INPUT */ VKD3DSPR_INPUT,
+ /* VKD3D_SM4_RT_OUTPUT */ VKD3DSPR_OUTPUT,
+ /* VKD3D_SM4_RT_INDEXABLE_TEMP */ VKD3DSPR_IDXTEMP,
+ /* VKD3D_SM4_RT_IMMCONST */ VKD3DSPR_IMMCONST,
+ /* UNKNOWN */ ~0u,
+ /* VKD3D_SM4_RT_SAMPLER */ VKD3DSPR_SAMPLER,
+ /* VKD3D_SM4_RT_RESOURCE */ VKD3DSPR_RESOURCE,
+ /* VKD3D_SM4_RT_CONSTBUFFER */ VKD3DSPR_CONSTBUFFER,
+ /* VKD3D_SM4_RT_IMMCONSTBUFFER */ VKD3DSPR_IMMCONSTBUFFER,
+ /* UNKNOWN */ ~0u,
+ /* VKD3D_SM4_RT_PRIMID */ VKD3DSPR_PRIMID,
+ /* VKD3D_SM4_RT_DEPTHOUT */ VKD3DSPR_DEPTHOUT,
+ /* VKD3D_SM4_RT_NULL */ VKD3DSPR_NULL,
+ /* VKD3D_SM4_RT_RASTERIZER */ VKD3DSPR_RASTERIZER,
+ /* VKD3D_SM4_RT_OMASK */ VKD3DSPR_SAMPLEMASK,
+ /* VKD3D_SM5_RT_STREAM */ VKD3DSPR_STREAM,
+ /* VKD3D_SM5_RT_FUNCTION_BODY */ VKD3DSPR_FUNCTIONBODY,
+ /* UNKNOWN */ ~0u,
+ /* VKD3D_SM5_RT_FUNCTION_POINTER */ VKD3DSPR_FUNCTIONPOINTER,
+ /* UNKNOWN */ ~0u,
+ /* UNKNOWN */ ~0u,
+ /* VKD3D_SM5_RT_OUTPUT_CONTROL_POINT_ID */ VKD3DSPR_OUTPOINTID,
+ /* VKD3D_SM5_RT_FORK_INSTANCE_ID */ VKD3DSPR_FORKINSTID,
+ /* VKD3D_SM5_RT_JOIN_INSTANCE_ID */ VKD3DSPR_JOININSTID,
+ /* VKD3D_SM5_RT_INPUT_CONTROL_POINT */ VKD3DSPR_INCONTROLPOINT,
+ /* VKD3D_SM5_RT_OUTPUT_CONTROL_POINT */ VKD3DSPR_OUTCONTROLPOINT,
+ /* VKD3D_SM5_RT_PATCH_CONSTANT_DATA */ VKD3DSPR_PATCHCONST,
+ /* VKD3D_SM5_RT_DOMAIN_LOCATION */ VKD3DSPR_TESSCOORD,
+ /* UNKNOWN */ ~0u,
+ /* VKD3D_SM5_RT_UAV */ VKD3DSPR_UAV,
+ /* VKD3D_SM5_RT_SHARED_MEMORY */ VKD3DSPR_GROUPSHAREDMEM,
+ /* VKD3D_SM5_RT_THREAD_ID */ VKD3DSPR_THREADID,
+ /* VKD3D_SM5_RT_THREAD_GROUP_ID */ VKD3DSPR_THREADGROUPID,
+ /* VKD3D_SM5_RT_LOCAL_THREAD_ID */ VKD3DSPR_LOCALTHREADID,
+ /* VKD3D_SM5_RT_COVERAGE */ VKD3DSPR_COVERAGE,
+ /* VKD3D_SM5_RT_LOCAL_THREAD_INDEX */ VKD3DSPR_LOCALTHREADINDEX,
+ /* VKD3D_SM5_RT_GS_INSTANCE_ID */ VKD3DSPR_GSINSTID,
+ /* VKD3D_SM5_RT_DEPTHOUT_GREATER_EQUAL */ VKD3DSPR_DEPTHOUTGE,
+ /* VKD3D_SM5_RT_DEPTHOUT_LESS_EQUAL */ VKD3DSPR_DEPTHOUTLE,
+};
+
+static const struct vkd3d_sm4_opcode_info *get_opcode_info(enum vkd3d_sm4_opcode opcode)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(opcode_table) / sizeof(*opcode_table); ++i)
+ {
+ if (opcode == opcode_table[i].opcode) return &opcode_table[i];
+ }
+
+ return NULL;
+}
+
+static void map_register(const struct vkd3d_sm4_data *priv, struct vkd3d_shader_register *reg)
+{
+ switch (priv->shader_version.type)
+ {
+ case VKD3D_SHADER_TYPE_PIXEL:
+ if (reg->type == VKD3DSPR_OUTPUT)
+ {
+ unsigned int reg_idx = reg->idx[0].offset;
+
+ if (reg_idx >= ARRAY_SIZE(priv->output_map))
+ {
+ ERR("Invalid output index %u.\n", reg_idx);
+ break;
+ }
+
+ reg->type = VKD3DSPR_COLOROUT;
+ reg->idx[0].offset = priv->output_map[reg_idx];
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static enum vkd3d_data_type map_data_type(char t)
+{
+ switch (t)
+ {
+ case 'f':
+ return VKD3D_DATA_FLOAT;
+ case 'i':
+ return VKD3D_DATA_INT;
+ case 'u':
+ return VKD3D_DATA_UINT;
+ case 'O':
+ return VKD3D_DATA_OPAQUE;
+ case 'R':
+ return VKD3D_DATA_RESOURCE;
+ case 'S':
+ return VKD3D_DATA_SAMPLER;
+ case 'U':
+ return VKD3D_DATA_UAV;
+ default:
+ ERR("Invalid data type '%c'.\n", t);
+ return VKD3D_DATA_FLOAT;
+ }
+}
+
+void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
+ const struct vkd3d_shader_signature *output_signature)
+{
+ DWORD version_token, token_count;
+ struct vkd3d_sm4_data *priv;
+ unsigned int i;
+
+ if (byte_code_size / sizeof(*byte_code) < 2)
+ {
+ WARN("Invalid byte code size %lu.\n", (long)byte_code_size);
+ return NULL;
+ }
+
+ version_token = byte_code[0];
+ TRACE("Version: 0x%08x.\n", version_token);
+ token_count = byte_code[1];
+ TRACE("Token count: %u.\n", token_count);
+
+ if (token_count < 2 || byte_code_size / sizeof(*byte_code) < token_count)
+ {
+ WARN("Invalid token count %u.\n", token_count);
+ return NULL;
+ }
+
+ if (!(priv = vkd3d_malloc(sizeof(*priv))))
+ {
+ ERR("Failed to allocate private data\n");
+ return NULL;
+ }
+
+ priv->start = &byte_code[2];
+ priv->end = &byte_code[token_count];
+
+ switch (version_token >> 16)
+ {
+ case VKD3D_SM4_PS:
+ priv->shader_version.type = VKD3D_SHADER_TYPE_PIXEL;
+ break;
+
+ case VKD3D_SM4_VS:
+ priv->shader_version.type = VKD3D_SHADER_TYPE_VERTEX;
+ break;
+
+ case VKD3D_SM4_GS:
+ priv->shader_version.type = VKD3D_SHADER_TYPE_GEOMETRY;
+ break;
+
+ case VKD3D_SM5_HS:
+ priv->shader_version.type = VKD3D_SHADER_TYPE_HULL;
+ break;
+
+ case VKD3D_SM5_DS:
+ priv->shader_version.type = VKD3D_SHADER_TYPE_DOMAIN;
+ break;
+
+ case VKD3D_SM5_CS:
+ priv->shader_version.type = VKD3D_SHADER_TYPE_COMPUTE;
+ break;
+
+ default:
+ FIXME("Unrecognised shader type %#x.\n", version_token >> 16);
+ }
+ priv->shader_version.major = VKD3D_SM4_VERSION_MAJOR(version_token);
+ priv->shader_version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
+
+ memset(priv->output_map, 0xff, sizeof(priv->output_map));
+ for (i = 0; i < output_signature->element_count; ++i)
+ {
+ struct vkd3d_shader_signature_element *e = &output_signature->elements[i];
+
+ if (e->register_index >= ARRAY_SIZE(priv->output_map))
+ {
+ WARN("Invalid output index %u.\n", e->register_index);
+ continue;
+ }
+
+ priv->output_map[e->register_index] = e->semantic_index;
+ }
+
+ list_init(&priv->src_free);
+ list_init(&priv->src);
+
+ return priv;
+}
+
+void shader_sm4_free(void *data)
+{
+ struct vkd3d_shader_src_param_entry *e1, *e2;
+ struct vkd3d_sm4_data *priv = data;
+
+ list_move_head(&priv->src_free, &priv->src);
+ LIST_FOR_EACH_ENTRY_SAFE(e1, e2, &priv->src_free, struct vkd3d_shader_src_param_entry, entry)
+ {
+ vkd3d_free(e1);
+ }
+ vkd3d_free(priv);
+}
+
+static struct vkd3d_shader_src_param *get_src_param(struct vkd3d_sm4_data *priv)
+{
+ struct vkd3d_shader_src_param_entry *e;
+ struct list *elem;
+
+ if (!list_empty(&priv->src_free))
+ {
+ elem = list_head(&priv->src_free);
+ list_remove(elem);
+ }
+ else
+ {
+ if (!(e = vkd3d_malloc(sizeof(*e))))
+ return NULL;
+ elem = &e->entry;
+ }
+
+ list_add_tail(&priv->src, elem);
+ e = LIST_ENTRY(elem, struct vkd3d_shader_src_param_entry, entry);
+ return &e->param;
+}
+
+void shader_sm4_read_header(void *data, const DWORD **ptr, struct vkd3d_shader_version *shader_version)
+{
+ struct vkd3d_sm4_data *priv = data;
+
+ *ptr = priv->start;
+ *shader_version = priv->shader_version;
+}
+
+static bool shader_sm4_read_reg_idx(struct vkd3d_sm4_data *priv, const DWORD **ptr, const DWORD *end,
+ DWORD addressing, struct vkd3d_shader_register_index *reg_idx)
+{
+ if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE)
+ {
+ struct vkd3d_shader_src_param *rel_addr = get_src_param(priv);
+
+ if (!(reg_idx->rel_addr = rel_addr))
+ {
+ ERR("Failed to get src param for relative addressing.\n");
+ return false;
+ }
+
+ if (addressing & VKD3D_SM4_ADDRESSING_OFFSET)
+ reg_idx->offset = *(*ptr)++;
+ else
+ reg_idx->offset = 0;
+ shader_sm4_read_src_param(priv, ptr, end, VKD3D_DATA_INT, rel_addr);
+ }
+ else
+ {
+ reg_idx->rel_addr = NULL;
+ reg_idx->offset = *(*ptr)++;
+ }
+
+ return true;
+}
+
+static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr, const DWORD *end,
+ enum vkd3d_data_type data_type, struct vkd3d_shader_register *param,
+ enum vkd3d_shader_src_modifier *modifier)
+{
+ enum vkd3d_sm4_register_type register_type;
+ DWORD token, order;
+
+ if (*ptr >= end)
+ {
+ WARN("Invalid ptr %p >= end %p.\n", *ptr, end);
+ return false;
+ }
+ token = *(*ptr)++;
+
+ register_type = (token & VKD3D_SM4_REGISTER_TYPE_MASK) >> VKD3D_SM4_REGISTER_TYPE_SHIFT;
+ if (register_type >= ARRAY_SIZE(register_type_table)
+ || register_type_table[register_type] == VKD3DSPR_INVALID)
+ {
+ FIXME("Unhandled register type %#x.\n", register_type);
+ param->type = VKD3DSPR_TEMP;
+ }
+ else
+ {
+ param->type = register_type_table[register_type];
+ }
+ param->data_type = data_type;
+
+ if (token & VKD3D_SM4_REGISTER_MODIFIER)
+ {
+ DWORD m;
+
+ if (*ptr >= end)
+ {
+ WARN("Invalid ptr %p >= end %p.\n", *ptr, end);
+ return false;
+ }
+ m = *(*ptr)++;
+
+ switch (m)
+ {
+ case 0x41:
+ *modifier = VKD3DSPSM_NEG;
+ break;
+
+ case 0x81:
+ *modifier = VKD3DSPSM_ABS;
+ break;
+
+ case 0xc1:
+ *modifier = VKD3DSPSM_ABSNEG;
+ break;
+
+ default:
+ FIXME("Skipping modifier 0x%08x.\n", m);
+ *modifier = VKD3DSPSM_NONE;
+ break;
+ }
+ }
+ else
+ {
+ *modifier = VKD3DSPSM_NONE;
+ }
+
+ order = (token & VKD3D_SM4_REGISTER_ORDER_MASK) >> VKD3D_SM4_REGISTER_ORDER_SHIFT;
+
+ if (order < 1)
+ {
+ param->idx[0].offset = ~0u;
+ param->idx[0].rel_addr = NULL;
+ }
+ else
+ {
+ DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0;
+ if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[0])))
+ {
+ ERR("Failed to read register index.\n");
+ return false;
+ }
+ }
+
+ if (order < 2)
+ {
+ param->idx[1].offset = ~0u;
+ param->idx[1].rel_addr = NULL;
+ }
+ else
+ {
+ DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1;
+ if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[1])))
+ {
+ ERR("Failed to read register index.\n");
+ return false;
+ }
+ }
+
+ if (order < 3)
+ {
+ param->idx[2].offset = ~0u;
+ param->idx[2].rel_addr = NULL;
+ }
+ else
+ {
+ DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2;
+ if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[2])))
+ {
+ ERR("Failed to read register index.\n");
+ return false;
+ }
+ }
+
+ if (order > 3)
+ {
+ WARN("Unhandled order %u.\n", order);
+ return false;
+ }
+
+ if (register_type == VKD3D_SM4_RT_IMMCONST)
+ {
+ enum vkd3d_sm4_dimension dimension = (token & VKD3D_SM4_DIMENSION_MASK) >> VKD3D_SM4_DIMENSION_SHIFT;
+
+ switch (dimension)
+ {
+ case VKD3D_SM4_DIMENSION_SCALAR:
+ param->immconst_type = VKD3D_IMMCONST_SCALAR;
+ if (end - *ptr < 1)
+ {
+ WARN("Invalid ptr %p, end %p.\n", *ptr, end);
+ return false;
+ }
+ memcpy(param->u.immconst_uint, *ptr, 1 * sizeof(DWORD));
+ *ptr += 1;
+ break;
+
+ case VKD3D_SM4_DIMENSION_VEC4:
+ param->immconst_type = VKD3D_IMMCONST_VEC4;
+ if (end - *ptr < VKD3D_VEC4_SIZE)
+ {
+ WARN("Invalid ptr %p, end %p.\n", *ptr, end);
+ return false;
+ }
+ memcpy(param->u.immconst_uint, *ptr, VKD3D_VEC4_SIZE * sizeof(DWORD));
+ *ptr += 4;
+ break;
+
+ default:
+ FIXME("Unhandled dimension %#x.\n", dimension);
+ break;
+ }
+ }
+ else if (register_type == VKD3D_SM4_RT_CONSTBUFFER && order == 2)
+ {
+ /* SM5.1 places the buffer offset in idx[2]; earlier versions place it
+ * in idx[1]. Normalize to SM5.1. */
+ param->idx[2] = param->idx[1];
+ param->idx[1].rel_addr = NULL;
+ param->idx[1].offset = 0;
+ }
+
+ map_register(priv, param);
+
+ return true;
+}
+
+static bool shader_sm4_is_scalar_register(const struct vkd3d_shader_register *reg)
+{
+ switch (reg->type)
+ {
+ case VKD3DSPR_COVERAGE:
+ case VKD3DSPR_DEPTHOUT:
+ case VKD3DSPR_DEPTHOUTGE:
+ case VKD3DSPR_DEPTHOUTLE:
+ case VKD3DSPR_GSINSTID:
+ case VKD3DSPR_LOCALTHREADINDEX:
+ case VKD3DSPR_OUTPOINTID:
+ case VKD3DSPR_PRIMID:
+ case VKD3DSPR_SAMPLEMASK:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static uint32_t swizzle_from_sm4(uint32_t s)
+{
+ return vkd3d_shader_create_swizzle(s & 0x3, (s >> 2) & 0x3, (s >> 4) & 0x3, (s >> 6) & 0x3);
+}
+
+static bool shader_sm4_read_src_param(struct vkd3d_sm4_data *priv, const DWORD **ptr, const DWORD *end,
+ enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param)
+{
+ DWORD token;
+
+ if (*ptr >= end)
+ {
+ WARN("Invalid ptr %p >= end %p.\n", *ptr, end);
+ return false;
+ }
+ token = **ptr;
+
+ if (!shader_sm4_read_param(priv, ptr, end, data_type, &src_param->reg, &src_param->modifiers))
+ {
+ ERR("Failed to read parameter.\n");
+ return false;
+ }
+
+ if (src_param->reg.type == VKD3DSPR_IMMCONST)
+ {
+ src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE;
+ }
+ else
+ {
+ enum vkd3d_sm4_swizzle_type swizzle_type =
+ (token & VKD3D_SM4_SWIZZLE_TYPE_MASK) >> VKD3D_SM4_SWIZZLE_TYPE_SHIFT;
+
+ switch (swizzle_type)
+ {
+ case VKD3D_SM4_SWIZZLE_NONE:
+ if (shader_sm4_is_scalar_register(&src_param->reg))
+ src_param->swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
+ else
+ src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE;
+ break;
+
+ case VKD3D_SM4_SWIZZLE_SCALAR:
+ src_param->swizzle = (token & VKD3D_SM4_SWIZZLE_MASK) >> VKD3D_SM4_SWIZZLE_SHIFT;
+ src_param->swizzle = (src_param->swizzle & 0x3) * 0x01010101;
+ break;
+
+ case VKD3D_SM4_SWIZZLE_VEC4:
+ src_param->swizzle = swizzle_from_sm4((token & VKD3D_SM4_SWIZZLE_MASK) >> VKD3D_SM4_SWIZZLE_SHIFT);
+ break;
+
+ default:
+ FIXME("Unhandled swizzle type %#x.\n", swizzle_type);
+ break;
+ }
+ }
+
+ return true;
+}
+
+static bool shader_sm4_read_dst_param(struct vkd3d_sm4_data *priv, const DWORD **ptr, const DWORD *end,
+ enum vkd3d_data_type data_type, struct vkd3d_shader_dst_param *dst_param)
+{
+ enum vkd3d_shader_src_modifier modifier;
+ DWORD token;
+
+ if (*ptr >= end)
+ {
+ WARN("Invalid ptr %p >= end %p.\n", *ptr, end);
+ return false;
+ }
+ token = **ptr;
+
+ if (!shader_sm4_read_param(priv, ptr, end, data_type, &dst_param->reg, &modifier))
+ {
+ ERR("Failed to read parameter.\n");
+ return false;
+ }
+
+ if (modifier != VKD3DSPSM_NONE)
+ {
+ ERR("Invalid source modifier %#x on destination register.\n", modifier);
+ return false;
+ }
+
+ dst_param->write_mask = (token & VKD3D_SM4_WRITEMASK_MASK) >> VKD3D_SM4_WRITEMASK_SHIFT;
+ /* Scalar registers are declared with no write mask in shader bytecode. */
+ if (!dst_param->write_mask && shader_sm4_is_scalar_register(&dst_param->reg))
+ dst_param->write_mask = VKD3DSP_WRITEMASK_0;
+ dst_param->modifiers = 0;
+ dst_param->shift = 0;
+
+ return true;
+}
+
+static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_shader_instruction *ins)
+{
+ enum vkd3d_sm4_instruction_modifier modifier_type = modifier & VKD3D_SM4_MODIFIER_MASK;
+
+ switch (modifier_type)
+ {
+ case VKD3D_SM4_MODIFIER_AOFFIMMI:
+ {
+ static const DWORD recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER
+ | VKD3D_SM4_MODIFIER_MASK
+ | VKD3D_SM4_AOFFIMMI_U_MASK
+ | VKD3D_SM4_AOFFIMMI_V_MASK
+ | VKD3D_SM4_AOFFIMMI_W_MASK;
+
+ /* Bit fields are used for sign extension. */
+ struct
+ {
+ int u : 4;
+ int v : 4;
+ int w : 4;
+ } aoffimmi;
+
+ if (modifier & ~recognized_bits)
+ FIXME("Unhandled instruction modifier %#x.\n", modifier);
+
+ aoffimmi.u = (modifier & VKD3D_SM4_AOFFIMMI_U_MASK) >> VKD3D_SM4_AOFFIMMI_U_SHIFT;
+ aoffimmi.v = (modifier & VKD3D_SM4_AOFFIMMI_V_MASK) >> VKD3D_SM4_AOFFIMMI_V_SHIFT;
+ aoffimmi.w = (modifier & VKD3D_SM4_AOFFIMMI_W_MASK) >> VKD3D_SM4_AOFFIMMI_W_SHIFT;
+ ins->texel_offset.u = aoffimmi.u;
+ ins->texel_offset.v = aoffimmi.v;
+ ins->texel_offset.w = aoffimmi.w;
+ break;
+ }
+
+ case VKD3D_SM5_MODIFIER_DATA_TYPE:
+ {
+ DWORD components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT;
+ enum vkd3d_sm4_data_type data_type = components & 0xf;
+
+ if ((components & 0xfff0) != (components & 0xf) * 0x1110)
+ FIXME("Components (%#x) have different data types.\n", components);
+ if (data_type < ARRAY_SIZE(data_type_table))
+ ins->resource_data_type = data_type_table[data_type];
+ else
+ {
+ FIXME("Unhandled data type %#x.\n", data_type);
+ ins->resource_data_type = VKD3D_DATA_FLOAT;
+ }
+ break;
+ }
+
+ case VKD3D_SM5_MODIFIER_RESOURCE_TYPE:
+ {
+ enum vkd3d_sm4_resource_type resource_type
+ = (modifier & VKD3D_SM5_MODIFIER_RESOURCE_TYPE_MASK) >> VKD3D_SM5_MODIFIER_RESOURCE_TYPE_SHIFT;
+
+ if (resource_type < ARRAY_SIZE(resource_type_table))
+ ins->resource_type = resource_type_table[resource_type];
+ else
+ {
+ FIXME("Unhandled resource type %#x.\n", resource_type);
+ ins->resource_type = VKD3D_SHADER_RESOURCE_NONE;
+ }
+ break;
+ }
+
+ default:
+ FIXME("Unhandled instruction modifier %#x.\n", modifier);
+ }
+}
+
+void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct vkd3d_shader_instruction *ins)
+{
+ const struct vkd3d_sm4_opcode_info *opcode_info;
+ DWORD opcode_token, opcode, previous_token;
+ struct vkd3d_sm4_data *priv = data;
+ unsigned int i, len;
+ size_t remaining;
+ const DWORD *p;
+ DWORD precise;
+
+ list_move_head(&priv->src_free, &priv->src);
+
+ if (*ptr >= priv->end)
+ {
+ WARN("End of byte-code, failed to read opcode.\n");
+ goto fail;
+ }
+ remaining = priv->end - *ptr;
+
+ opcode_token = *(*ptr)++;
+ opcode = opcode_token & VKD3D_SM4_OPCODE_MASK;
+
+ len = ((opcode_token & VKD3D_SM4_INSTRUCTION_LENGTH_MASK) >> VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT);
+ if (!len)
+ {
+ if (remaining < 2)
+ {
+ WARN("End of byte-code, failed to read length token.\n");
+ goto fail;
+ }
+ len = **ptr;
+ }
+ if (!len || remaining < len)
+ {
+ WARN("Read invalid length %u (remaining %zu).\n", len, remaining);
+ goto fail;
+ }
+ --len;
+
+ if (!(opcode_info = get_opcode_info(opcode)))
+ {
+ FIXME("Unrecognized opcode %#x, opcode_token 0x%08x.\n", opcode, opcode_token);
+ ins->handler_idx = VKD3DSIH_INVALID;
+ *ptr += len;
+ return;
+ }
+
+ ins->handler_idx = opcode_info->handler_idx;
+ ins->flags = 0;
+ ins->coissue = false;
+ ins->predicate = NULL;
+ ins->dst_count = strlen(opcode_info->dst_info);
+ ins->dst = priv->dst_param;
+ ins->src_count = strlen(opcode_info->src_info);
+ ins->src = priv->src_param;
+ ins->resource_type = VKD3D_SHADER_RESOURCE_NONE;
+ ins->resource_data_type = VKD3D_DATA_FLOAT;
+ memset(&ins->texel_offset, 0, sizeof(ins->texel_offset));
+
+ p = *ptr;
+ *ptr += len;
+
+ if (opcode_info->read_opcode_func)
+ {
+ opcode_info->read_opcode_func(ins, opcode, opcode_token, p, len, priv);
+ }
+ else
+ {
+ enum vkd3d_shader_dst_modifier instruction_dst_modifier = VKD3DSPDM_NONE;
+
+ previous_token = opcode_token;
+ while (previous_token & VKD3D_SM4_INSTRUCTION_MODIFIER && p != *ptr)
+ shader_sm4_read_instruction_modifier(previous_token = *p++, ins);
+
+ ins->flags = (opcode_token & VKD3D_SM4_INSTRUCTION_FLAGS_MASK) >> VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT;
+ if (ins->flags & VKD3D_SM4_INSTRUCTION_FLAG_SATURATE)
+ {
+ ins->flags &= ~VKD3D_SM4_INSTRUCTION_FLAG_SATURATE;
+ instruction_dst_modifier = VKD3DSPDM_SATURATE;
+ }
+ precise = (opcode_token & VKD3D_SM5_PRECISE_MASK) >> VKD3D_SM5_PRECISE_SHIFT;
+ ins->flags |= precise << VKD3DSI_PRECISE_SHIFT;
+
+ for (i = 0; i < ins->dst_count; ++i)
+ {
+ if (!(shader_sm4_read_dst_param(priv, &p, *ptr, map_data_type(opcode_info->dst_info[i]),
+ &priv->dst_param[i])))
+ {
+ ins->handler_idx = VKD3DSIH_INVALID;
+ return;
+ }
+ priv->dst_param[i].modifiers |= instruction_dst_modifier;
+ }
+
+ for (i = 0; i < ins->src_count; ++i)
+ {
+ if (!(shader_sm4_read_src_param(priv, &p, *ptr, map_data_type(opcode_info->src_info[i]),
+ &priv->src_param[i])))
+ {
+ ins->handler_idx = VKD3DSIH_INVALID;
+ return;
+ }
+ }
+ }
+
+ return;
+
+fail:
+ *ptr = priv->end;
+ ins->handler_idx = VKD3DSIH_INVALID;
+ return;
+}
+
+bool shader_sm4_is_end(void *data, const DWORD **ptr)
+{
+ struct vkd3d_sm4_data *priv = data;
+ return *ptr == priv->end;
+}
+
+#define MAKE_TAG(ch0, ch1, ch2, ch3) \
+ ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \
+ ((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 ))
+#define TAG_DXBC MAKE_TAG('D', 'X', 'B', 'C')
+#define TAG_ISGN MAKE_TAG('I', 'S', 'G', 'N')
+#define TAG_ISG1 MAKE_TAG('I', 'S', 'G', '1')
+#define TAG_OSGN MAKE_TAG('O', 'S', 'G', 'N')
+#define TAG_OSG5 MAKE_TAG('O', 'S', 'G', '5')
+#define TAG_OSG1 MAKE_TAG('O', 'S', 'G', '1')
+#define TAG_PCSG MAKE_TAG('P', 'C', 'S', 'G')
+#define TAG_PSG1 MAKE_TAG('P', 'S', 'G', '1')
+#define TAG_SHDR MAKE_TAG('S', 'H', 'D', 'R')
+#define TAG_SHEX MAKE_TAG('S', 'H', 'E', 'X')
+#define TAG_AON9 MAKE_TAG('A', 'o', 'n', '9')
+#define TAG_RTS0 MAKE_TAG('R', 'T', 'S', '0')
+
+static bool require_space(size_t offset, size_t count, size_t size, size_t data_size)
+{
+ return !count || (data_size - offset) / count >= size;
+}
+
+static void read_dword(const char **ptr, DWORD *d)
+{
+ memcpy(d, *ptr, sizeof(*d));
+ *ptr += sizeof(*d);
+}
+
+static void read_float(const char **ptr, float *f)
+{
+ STATIC_ASSERT(sizeof(float) == sizeof(DWORD));
+ read_dword(ptr, (DWORD *)f);
+}
+
+static void skip_dword_unknown(const char **ptr, unsigned int count)
+{
+ unsigned int i;
+ DWORD d;
+
+ WARN("Skipping %u unknown DWORDs:\n", count);
+ for (i = 0; i < count; ++i)
+ {
+ read_dword(ptr, &d);
+ WARN("\t0x%08x\n", d);
+ }
+}
+
+static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
+{
+ size_t len, max_len;
+
+ if (offset >= data_size)
+ {
+ WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size);
+ return NULL;
+ }
+
+ max_len = data_size - offset;
+ len = strnlen(data + offset, max_len);
+
+ if (len == max_len)
+ return NULL;
+
+ return data + offset;
+}
+
+static int parse_dxbc(const char *data, size_t data_size, struct vkd3d_shader_message_context *message_context,
+ int (*chunk_handler)(const char *data, DWORD data_size, DWORD tag, void *ctx), void *ctx)
+{
+ uint32_t checksum[4], calculated_checksum[4];
+ const char *ptr = data;
+ int ret = VKD3D_OK;
+ DWORD chunk_count;
+ DWORD total_size;
+ unsigned int i;
+ DWORD version;
+ DWORD tag;
+
+ if (data_size < VKD3D_DXBC_HEADER_SIZE)
+ {
+ WARN("Invalid data size %zu.\n", data_size);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_DXBC_INVALID_SIZE,
+ "DXBC size %zu is smaller than the DXBC header size.", data_size);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ read_dword(&ptr, &tag);
+ TRACE("tag: %#x.\n", tag);
+
+ if (tag != TAG_DXBC)
+ {
+ WARN("Wrong tag.\n");
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_DXBC_INVALID_MAGIC, "Invalid DXBC magic.");
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ read_dword(&ptr, &checksum[0]);
+ read_dword(&ptr, &checksum[1]);
+ read_dword(&ptr, &checksum[2]);
+ read_dword(&ptr, &checksum[3]);
+ vkd3d_compute_dxbc_checksum(data, data_size, calculated_checksum);
+ if (memcmp(checksum, calculated_checksum, sizeof(checksum)))
+ {
+ WARN("Checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x} does not match "
+ "calculated checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
+ checksum[0], checksum[1], checksum[2], checksum[3],
+ calculated_checksum[0], calculated_checksum[1],
+ calculated_checksum[2], calculated_checksum[3]);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM, "Invalid DXBC checksum.");
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ read_dword(&ptr, &version);
+ TRACE("version: %#x.\n", version);
+ if (version != 0x00000001)
+ {
+ WARN("Got unexpected DXBC version %#x.\n", version);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_DXBC_INVALID_VERSION,
+ "DXBC version %#x is not supported.", version);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ read_dword(&ptr, &total_size);
+ TRACE("total size: %#x\n", total_size);
+
+ read_dword(&ptr, &chunk_count);
+ TRACE("chunk count: %#x\n", chunk_count);
+
+ for (i = 0; i < chunk_count; ++i)
+ {
+ DWORD chunk_tag, chunk_size;
+ const char *chunk_ptr;
+ DWORD chunk_offset;
+
+ read_dword(&ptr, &chunk_offset);
+ TRACE("chunk %u at offset %#x\n", i, chunk_offset);
+
+ if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(DWORD), data_size))
+ {
+ WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET,
+ "DXBC chunk %u has invalid offset %#x (data size %#zx).", i, chunk_offset, data_size);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ chunk_ptr = data + chunk_offset;
+
+ read_dword(&chunk_ptr, &chunk_tag);
+ read_dword(&chunk_ptr, &chunk_size);
+
+ if (!require_space(chunk_ptr - data, 1, chunk_size, data_size))
+ {
+ WARN("Invalid chunk size %#x (data size %zu, chunk offset %#x).\n",
+ chunk_size, data_size, chunk_offset);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE,
+ "DXBC chunk %u has invalid size %#x (data size %#zx, chunk offset %#x).",
+ i, chunk_offset, data_size, chunk_offset);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ if ((ret = chunk_handler(chunk_ptr, chunk_size, chunk_tag, ctx)) < 0)
+ break;
+ }
+
+ return ret;
+}
+
+static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
+ struct vkd3d_shader_signature *s)
+{
+ bool has_stream_index, has_min_precision;
+ struct vkd3d_shader_signature_element *e;
+ const char *ptr = data;
+ unsigned int i;
+ DWORD count;
+
+ if (!require_space(0, 2, sizeof(DWORD), data_size))
+ {
+ WARN("Invalid data size %#x.\n", data_size);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ read_dword(&ptr, &count);
+ TRACE("%u elements.\n", count);
+
+ skip_dword_unknown(&ptr, 1); /* It seems to always be 0x00000008. */
+
+ if (!require_space(ptr - data, count, 6 * sizeof(DWORD), data_size))
+ {
+ WARN("Invalid count %#x (data size %#x).\n", count, data_size);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (!(e = vkd3d_calloc(count, sizeof(*e))))
+ {
+ ERR("Failed to allocate input signature memory.\n");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ }
+
+ has_min_precision = tag == TAG_OSG1 || tag == TAG_PSG1 || tag == TAG_ISG1;
+ has_stream_index = tag == TAG_OSG5 || has_min_precision;
+
+ for (i = 0; i < count; ++i)
+ {
+ DWORD name_offset, mask;
+
+ if (has_stream_index)
+ read_dword(&ptr, &e[i].stream_index);
+ else
+ e[i].stream_index = 0;
+
+ read_dword(&ptr, &name_offset);
+ if (!(e[i].semantic_name = shader_get_string(data, data_size, name_offset)))
+ {
+ WARN("Invalid name offset %#x (data size %#x).\n", name_offset, data_size);
+ vkd3d_free(e);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ read_dword(&ptr, &e[i].semantic_index);
+ read_dword(&ptr, &e[i].sysval_semantic);
+ read_dword(&ptr, &e[i].component_type);
+ read_dword(&ptr, &e[i].register_index);
+ read_dword(&ptr, &mask);
+ e[i].mask = mask & 0xff;
+ e[i].used_mask = (mask >> 8) & 0xff;
+ switch (tag)
+ {
+ case TAG_OSGN:
+ case TAG_OSG1:
+ case TAG_OSG5:
+ case TAG_PCSG:
+ case TAG_PSG1:
+ e[i].used_mask = e[i].mask & ~e[i].used_mask;
+ break;
+ }
+
+ if (has_min_precision)
+ read_dword(&ptr, &e[i].min_precision);
+ else
+ e[i].min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE;
+
+ TRACE("Stream: %u, semantic: %s, semantic idx: %u, sysval_semantic %#x, "
+ "type %u, register idx: %u, use_mask %#x, input_mask %#x, precision %u.\n",
+ e[i].stream_index, debugstr_a(e[i].semantic_name), e[i].semantic_index, e[i].sysval_semantic,
+ e[i].component_type, e[i].register_index, e[i].used_mask, e[i].mask, e[i].min_precision);
+ }
+
+ s->elements = e;
+ s->element_count = count;
+
+ return VKD3D_OK;
+}
+
+static int isgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
+{
+ struct vkd3d_shader_signature *is = ctx;
+
+ if (tag != TAG_ISGN)
+ return VKD3D_OK;
+
+ if (is->elements)
+ {
+ FIXME("Multiple input signatures.\n");
+ vkd3d_shader_free_shader_signature(is);
+ }
+ return shader_parse_signature(tag, data, data_size, is);
+}
+
+int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
+ struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature)
+{
+ int ret;
+
+ memset(signature, 0, sizeof(*signature));
+ if ((ret = parse_dxbc(dxbc, dxbc_length, message_context, isgn_handler, signature)) < 0)
+ ERR("Failed to parse input signature.\n");
+
+ return ret;
+}
+
+static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *context)
+{
+ struct vkd3d_shader_desc *desc = context;
+ int ret;
+
+ switch (tag)
+ {
+ case TAG_ISGN:
+ case TAG_ISG1:
+ if (desc->input_signature.elements)
+ {
+ FIXME("Multiple input signatures.\n");
+ break;
+ }
+ if ((ret = shader_parse_signature(tag, data, data_size, &desc->input_signature)) < 0)
+ return ret;
+ break;
+
+ case TAG_OSGN:
+ case TAG_OSG5:
+ case TAG_OSG1:
+ if (desc->output_signature.elements)
+ {
+ FIXME("Multiple output signatures.\n");
+ break;
+ }
+ if ((ret = shader_parse_signature(tag, data, data_size, &desc->output_signature)) < 0)
+ return ret;
+ break;
+
+ case TAG_PCSG:
+ case TAG_PSG1:
+ if (desc->patch_constant_signature.elements)
+ {
+ FIXME("Multiple patch constant signatures.\n");
+ break;
+ }
+ if ((ret = shader_parse_signature(tag, data, data_size, &desc->patch_constant_signature)) < 0)
+ return ret;
+ break;
+
+ case TAG_SHDR:
+ case TAG_SHEX:
+ if (desc->byte_code)
+ FIXME("Multiple shader code chunks.\n");
+ desc->byte_code = (const DWORD *)data;
+ desc->byte_code_size = data_size;
+ break;
+
+ case TAG_AON9:
+ TRACE("Skipping AON9 shader code chunk.\n");
+ break;
+
+ default:
+ TRACE("Skipping chunk %#x.\n", tag);
+ break;
+ }
+
+ return VKD3D_OK;
+}
+
+void free_shader_desc(struct vkd3d_shader_desc *desc)
+{
+ vkd3d_shader_free_shader_signature(&desc->input_signature);
+ vkd3d_shader_free_shader_signature(&desc->output_signature);
+ vkd3d_shader_free_shader_signature(&desc->patch_constant_signature);
+}
+
+int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
+ struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_desc *desc)
+{
+ int ret;
+
+ desc->byte_code = NULL;
+ desc->byte_code_size = 0;
+ memset(&desc->input_signature, 0, sizeof(desc->input_signature));
+ memset(&desc->output_signature, 0, sizeof(desc->output_signature));
+ memset(&desc->patch_constant_signature, 0, sizeof(desc->patch_constant_signature));
+
+ ret = parse_dxbc(dxbc, dxbc_length, message_context, shdr_handler, desc);
+ if (!desc->byte_code)
+ ret = VKD3D_ERROR_INVALID_ARGUMENT;
+
+ if (ret < 0)
+ {
+ WARN("Failed to parse shader, vkd3d result %d.\n", ret);
+ free_shader_desc(desc);
+ }
+
+ return ret;
+}
+
+/* root signatures */
+#define VKD3D_ROOT_SIGNATURE_1_0_ROOT_DESCRIPTOR_FLAGS VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE
+
+#define VKD3D_ROOT_SIGNATURE_1_0_DESCRIPTOR_RANGE_FLAGS \
+ (VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE)
+
+struct root_signature_parser_context
+{
+ const char *data;
+ unsigned int data_size;
+};
+
+static int shader_parse_descriptor_ranges(struct root_signature_parser_context *context,
+ unsigned int offset, unsigned int count, struct vkd3d_shader_descriptor_range *ranges)
+{
+ const char *ptr;
+ unsigned int i;
+
+ if (!require_space(offset, 5 * count, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ for (i = 0; i < count; ++i)
+ {
+ read_dword(&ptr, &ranges[i].range_type);
+ read_dword(&ptr, &ranges[i].descriptor_count);
+ read_dword(&ptr, &ranges[i].base_shader_register);
+ read_dword(&ptr, &ranges[i].register_space);
+ read_dword(&ptr, &ranges[i].descriptor_table_offset);
+
+ TRACE("Type %#x, descriptor count %u, base shader register %u, "
+ "register space %u, offset %u.\n",
+ ranges[i].range_type, ranges[i].descriptor_count,
+ ranges[i].base_shader_register, ranges[i].register_space,
+ ranges[i].descriptor_table_offset);
+ }
+
+ return VKD3D_OK;
+}
+
+static void shader_validate_descriptor_range1(const struct vkd3d_shader_descriptor_range1 *range)
+{
+ unsigned int unknown_flags = range->flags & ~(VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_NONE
+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE
+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE
+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE
+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);
+
+ if (unknown_flags)
+ FIXME("Unknown descriptor range flags %#x.\n", unknown_flags);
+}
+
+static int shader_parse_descriptor_ranges1(struct root_signature_parser_context *context,
+ unsigned int offset, unsigned int count, struct vkd3d_shader_descriptor_range1 *ranges)
+{
+ const char *ptr;
+ unsigned int i;
+
+ if (!require_space(offset, 6 * count, sizeof(uint32_t), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ for (i = 0; i < count; ++i)
+ {
+ read_dword(&ptr, &ranges[i].range_type);
+ read_dword(&ptr, &ranges[i].descriptor_count);
+ read_dword(&ptr, &ranges[i].base_shader_register);
+ read_dword(&ptr, &ranges[i].register_space);
+ read_dword(&ptr, &ranges[i].flags);
+ read_dword(&ptr, &ranges[i].descriptor_table_offset);
+
+ TRACE("Type %#x, descriptor count %u, base shader register %u, "
+ "register space %u, flags %#x, offset %u.\n",
+ ranges[i].range_type, ranges[i].descriptor_count,
+ ranges[i].base_shader_register, ranges[i].register_space,
+ ranges[i].flags, ranges[i].descriptor_table_offset);
+
+ shader_validate_descriptor_range1(&ranges[i]);
+ }
+
+ return VKD3D_OK;
+}
+
+static int shader_parse_descriptor_table(struct root_signature_parser_context *context,
+ unsigned int offset, struct vkd3d_shader_root_descriptor_table *table)
+{
+ struct vkd3d_shader_descriptor_range *ranges;
+ unsigned int count;
+ const char *ptr;
+
+ if (!require_space(offset, 2, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ read_dword(&ptr, &count);
+ read_dword(&ptr, &offset);
+
+ TRACE("Descriptor range count %u.\n", count);
+
+ table->descriptor_range_count = count;
+
+ if (!(ranges = vkd3d_calloc(count, sizeof(*ranges))))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ table->descriptor_ranges = ranges;
+ return shader_parse_descriptor_ranges(context, offset, count, ranges);
+}
+
+static int shader_parse_descriptor_table1(struct root_signature_parser_context *context,
+ unsigned int offset, struct vkd3d_shader_root_descriptor_table1 *table)
+{
+ struct vkd3d_shader_descriptor_range1 *ranges;
+ unsigned int count;
+ const char *ptr;
+
+ if (!require_space(offset, 2, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ read_dword(&ptr, &count);
+ read_dword(&ptr, &offset);
+
+ TRACE("Descriptor range count %u.\n", count);
+
+ table->descriptor_range_count = count;
+
+ if (!(ranges = vkd3d_calloc(count, sizeof(*ranges))))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ table->descriptor_ranges = ranges;
+ return shader_parse_descriptor_ranges1(context, offset, count, ranges);
+}
+
+static int shader_parse_root_constants(struct root_signature_parser_context *context,
+ unsigned int offset, struct vkd3d_shader_root_constants *constants)
+{
+ const char *ptr;
+
+ if (!require_space(offset, 3, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ read_dword(&ptr, &constants->shader_register);
+ read_dword(&ptr, &constants->register_space);
+ read_dword(&ptr, &constants->value_count);
+
+ TRACE("Shader register %u, register space %u, 32-bit value count %u.\n",
+ constants->shader_register, constants->register_space, constants->value_count);
+
+ return VKD3D_OK;
+}
+
+static int shader_parse_root_descriptor(struct root_signature_parser_context *context,
+ unsigned int offset, struct vkd3d_shader_root_descriptor *descriptor)
+{
+ const char *ptr;
+
+ if (!require_space(offset, 2, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ read_dword(&ptr, &descriptor->shader_register);
+ read_dword(&ptr, &descriptor->register_space);
+
+ TRACE("Shader register %u, register space %u.\n",
+ descriptor->shader_register, descriptor->register_space);
+
+ return VKD3D_OK;
+}
+
+static void shader_validate_root_descriptor1(const struct vkd3d_shader_root_descriptor1 *descriptor)
+{
+ unsigned int unknown_flags = descriptor->flags & ~(VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_NONE
+ | VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE
+ | VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE
+ | VKD3D_SHADER_ROOT_DESCRIPTOR_FLAG_DATA_STATIC);
+
+ if (unknown_flags)
+ FIXME("Unknown root descriptor flags %#x.\n", unknown_flags);
+}
+
+static int shader_parse_root_descriptor1(struct root_signature_parser_context *context,
+ unsigned int offset, struct vkd3d_shader_root_descriptor1 *descriptor)
+{
+ const char *ptr;
+
+ if (!require_space(offset, 3, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ read_dword(&ptr, &descriptor->shader_register);
+ read_dword(&ptr, &descriptor->register_space);
+ read_dword(&ptr, &descriptor->flags);
+
+ TRACE("Shader register %u, register space %u, flags %#x.\n",
+ descriptor->shader_register, descriptor->register_space, descriptor->flags);
+
+ shader_validate_root_descriptor1(descriptor);
+
+ return VKD3D_OK;
+}
+
+static int shader_parse_root_parameters(struct root_signature_parser_context *context,
+ unsigned int offset, unsigned int count, struct vkd3d_shader_root_parameter *parameters)
+{
+ const char *ptr;
+ unsigned int i;
+ int ret;
+
+ if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ for (i = 0; i < count; ++i)
+ {
+ read_dword(&ptr, ¶meters[i].parameter_type);
+ read_dword(&ptr, ¶meters[i].shader_visibility);
+ read_dword(&ptr, &offset);
+
+ TRACE("Type %#x, shader visibility %#x.\n",
+ parameters[i].parameter_type, parameters[i].shader_visibility);
+
+ switch (parameters[i].parameter_type)
+ {
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
+ ret = shader_parse_descriptor_table(context, offset, ¶meters[i].u.descriptor_table);
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
+ ret = shader_parse_root_constants(context, offset, ¶meters[i].u.constants);
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_CBV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_SRV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_UAV:
+ ret = shader_parse_root_descriptor(context, offset, ¶meters[i].u.descriptor);
+ break;
+ default:
+ FIXME("Unrecognized type %#x.\n", parameters[i].parameter_type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (ret < 0)
+ return ret;
+ }
+
+ return VKD3D_OK;
+}
+
+static int shader_parse_root_parameters1(struct root_signature_parser_context *context,
+ DWORD offset, DWORD count, struct vkd3d_shader_root_parameter1 *parameters)
+{
+ const char *ptr;
+ unsigned int i;
+ int ret;
+
+ if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ for (i = 0; i < count; ++i)
+ {
+ read_dword(&ptr, ¶meters[i].parameter_type);
+ read_dword(&ptr, ¶meters[i].shader_visibility);
+ read_dword(&ptr, &offset);
+
+ TRACE("Type %#x, shader visibility %#x.\n",
+ parameters[i].parameter_type, parameters[i].shader_visibility);
+
+ switch (parameters[i].parameter_type)
+ {
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
+ ret = shader_parse_descriptor_table1(context, offset, ¶meters[i].u.descriptor_table);
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
+ ret = shader_parse_root_constants(context, offset, ¶meters[i].u.constants);
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_CBV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_SRV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_UAV:
+ ret = shader_parse_root_descriptor1(context, offset, ¶meters[i].u.descriptor);
+ break;
+ default:
+ FIXME("Unrecognized type %#x.\n", parameters[i].parameter_type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (ret < 0)
+ return ret;
+ }
+
+ return VKD3D_OK;
+}
+
+static int shader_parse_static_samplers(struct root_signature_parser_context *context,
+ unsigned int offset, unsigned int count, struct vkd3d_shader_static_sampler_desc *sampler_descs)
+{
+ const char *ptr;
+ unsigned int i;
+
+ if (!require_space(offset, 13 * count, sizeof(DWORD), context->data_size))
+ {
+ WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ ptr = &context->data[offset];
+
+ for (i = 0; i < count; ++i)
+ {
+ read_dword(&ptr, &sampler_descs[i].filter);
+ read_dword(&ptr, &sampler_descs[i].address_u);
+ read_dword(&ptr, &sampler_descs[i].address_v);
+ read_dword(&ptr, &sampler_descs[i].address_w);
+ read_float(&ptr, &sampler_descs[i].mip_lod_bias);
+ read_dword(&ptr, &sampler_descs[i].max_anisotropy);
+ read_dword(&ptr, &sampler_descs[i].comparison_func);
+ read_dword(&ptr, &sampler_descs[i].border_colour);
+ read_float(&ptr, &sampler_descs[i].min_lod);
+ read_float(&ptr, &sampler_descs[i].max_lod);
+ read_dword(&ptr, &sampler_descs[i].shader_register);
+ read_dword(&ptr, &sampler_descs[i].register_space);
+ read_dword(&ptr, &sampler_descs[i].shader_visibility);
+ }
+
+ return VKD3D_OK;
+}
+
+static int shader_parse_root_signature(const char *data, unsigned int data_size,
+ struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ struct vkd3d_shader_root_signature_desc *v_1_0 = &desc->u.v_1_0;
+ struct root_signature_parser_context context;
+ unsigned int count, offset, version;
+ const char *ptr = data;
+ int ret;
+
+ context.data = data;
+ context.data_size = data_size;
+
+ if (!require_space(0, 6, sizeof(DWORD), data_size))
+ {
+ WARN("Invalid data size %#x.\n", data_size);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ read_dword(&ptr, &version);
+ TRACE("Version %#x.\n", version);
+ if (version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0 && version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1)
+ {
+ FIXME("Unknown version %#x.\n", version);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ desc->version = version;
+
+ read_dword(&ptr, &count);
+ read_dword(&ptr, &offset);
+ TRACE("Parameter count %u, offset %u.\n", count, offset);
+
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ {
+ v_1_0->parameter_count = count;
+ if (v_1_0->parameter_count)
+ {
+ struct vkd3d_shader_root_parameter *parameters;
+ if (!(parameters = vkd3d_calloc(v_1_0->parameter_count, sizeof(*parameters))))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ v_1_0->parameters = parameters;
+ if ((ret = shader_parse_root_parameters(&context, offset, count, parameters)) < 0)
+ return ret;
+ }
+ }
+ else
+ {
+ struct vkd3d_shader_root_signature_desc1 *v_1_1 = &desc->u.v_1_1;
+
+ assert(version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1);
+
+ v_1_1->parameter_count = count;
+ if (v_1_1->parameter_count)
+ {
+ struct vkd3d_shader_root_parameter1 *parameters;
+ if (!(parameters = vkd3d_calloc(v_1_1->parameter_count, sizeof(*parameters))))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ v_1_1->parameters = parameters;
+ if ((ret = shader_parse_root_parameters1(&context, offset, count, parameters)) < 0)
+ return ret;
+ }
+ }
+
+ read_dword(&ptr, &count);
+ read_dword(&ptr, &offset);
+ TRACE("Static sampler count %u, offset %u.\n", count, offset);
+
+ v_1_0->static_sampler_count = count;
+ if (v_1_0->static_sampler_count)
+ {
+ struct vkd3d_shader_static_sampler_desc *samplers;
+ if (!(samplers = vkd3d_calloc(v_1_0->static_sampler_count, sizeof(*samplers))))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ v_1_0->static_samplers = samplers;
+ if ((ret = shader_parse_static_samplers(&context, offset, count, samplers)) < 0)
+ return ret;
+ }
+
+ read_dword(&ptr, &v_1_0->flags);
+ TRACE("Flags %#x.\n", v_1_0->flags);
+
+ return VKD3D_OK;
+}
+
+static int rts0_handler(const char *data, DWORD data_size, DWORD tag, void *context)
+{
+ struct vkd3d_shader_versioned_root_signature_desc *desc = context;
+
+ if (tag != TAG_RTS0)
+ return VKD3D_OK;
+
+ return shader_parse_root_signature(data, data_size, desc);
+}
+
+int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
+ struct vkd3d_shader_versioned_root_signature_desc *root_signature, char **messages)
+{
+ struct vkd3d_shader_message_context message_context;
+ int ret;
+
+ TRACE("dxbc {%p, %zu}, root_signature %p, messages %p.\n", dxbc->code, dxbc->size, root_signature, messages);
+
+ memset(root_signature, 0, sizeof(*root_signature));
+ if (messages)
+ *messages = NULL;
+ if (!vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO, NULL))
+ return VKD3D_ERROR;
+
+ ret = parse_dxbc(dxbc->code, dxbc->size, &message_context, rts0_handler, root_signature);
+ vkd3d_shader_message_context_trace_messages(&message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+
+ vkd3d_shader_message_context_cleanup(&message_context);
+ if (ret < 0)
+ vkd3d_shader_free_root_signature(root_signature);
+
+ return ret;
+}
+
+static unsigned int versioned_root_signature_get_parameter_count(
+ const struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ return desc->u.v_1_0.parameter_count;
+ else
+ return desc->u.v_1_1.parameter_count;
+}
+
+static enum vkd3d_shader_root_parameter_type versioned_root_signature_get_parameter_type(
+ const struct vkd3d_shader_versioned_root_signature_desc *desc, unsigned int i)
+{
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ return desc->u.v_1_0.parameters[i].parameter_type;
+ else
+ return desc->u.v_1_1.parameters[i].parameter_type;
+}
+
+static enum vkd3d_shader_visibility versioned_root_signature_get_parameter_shader_visibility(
+ const struct vkd3d_shader_versioned_root_signature_desc *desc, unsigned int i)
+{
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ return desc->u.v_1_0.parameters[i].shader_visibility;
+ else
+ return desc->u.v_1_1.parameters[i].shader_visibility;
+}
+
+static const struct vkd3d_shader_root_constants *versioned_root_signature_get_root_constants(
+ const struct vkd3d_shader_versioned_root_signature_desc *desc, unsigned int i)
+{
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ return &desc->u.v_1_0.parameters[i].u.constants;
+ else
+ return &desc->u.v_1_1.parameters[i].u.constants;
+}
+
+static unsigned int versioned_root_signature_get_static_sampler_count(
+ const struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ return desc->u.v_1_0.static_sampler_count;
+ else
+ return desc->u.v_1_1.static_sampler_count;
+}
+
+static const struct vkd3d_shader_static_sampler_desc *versioned_root_signature_get_static_samplers(
+ const struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ return desc->u.v_1_0.static_samplers;
+ else
+ return desc->u.v_1_1.static_samplers;
+}
+
+static unsigned int versioned_root_signature_get_flags(const struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ return desc->u.v_1_0.flags;
+ else
+ return desc->u.v_1_1.flags;
+}
+
+struct root_signature_writer_context
+{
+ struct vkd3d_shader_message_context message_context;
+
+ DWORD *data;
+ size_t position;
+ size_t capacity;
+
+ size_t total_size_position;
+ size_t chunk_position;
+};
+
+static bool write_dwords(struct root_signature_writer_context *context,
+ unsigned int count, DWORD d)
+{
+ unsigned int i;
+
+ if (!vkd3d_array_reserve((void **)&context->data, &context->capacity,
+ context->position + count, sizeof(*context->data)))
+ return false;
+ for (i = 0; i < count; ++i)
+ context->data[context->position++] = d;
+ return true;
+}
+
+static bool write_dword(struct root_signature_writer_context *context, DWORD d)
+{
+ return write_dwords(context, 1, d);
+}
+
+static bool write_float(struct root_signature_writer_context *context, float f)
+{
+ union
+ {
+ float f;
+ DWORD d;
+ } u;
+ u.f = f;
+ return write_dword(context, u.d);
+}
+
+static size_t get_chunk_offset(struct root_signature_writer_context *context)
+{
+ return (context->position - context->chunk_position) * sizeof(DWORD);
+}
+
+static int shader_write_root_signature_header(struct root_signature_writer_context *context)
+{
+ if (!write_dword(context, TAG_DXBC))
+ goto fail;
+
+ /* The checksum is computed when all data is generated. */
+ if (!write_dwords(context, 4, 0x00000000))
+ goto fail;
+
+ if (!write_dword(context, 0x00000001))
+ goto fail;
+
+ context->total_size_position = context->position;
+ if (!write_dword(context, 0xffffffff)) /* total size */
+ goto fail;
+
+ if (!write_dword(context, 1)) /* chunk count */
+ goto fail;
+
+ /* chunk offset */
+ if (!write_dword(context, (context->position + 1) * sizeof(DWORD)))
+ goto fail;
+
+ if (!write_dword(context, TAG_RTS0))
+ goto fail;
+ if (!write_dword(context, 0xffffffff)) /* chunk size */
+ goto fail;
+ context->chunk_position = context->position;
+
+ return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature header.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_descriptor_ranges(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_root_descriptor_table *table)
+{
+ const struct vkd3d_shader_descriptor_range *ranges = table->descriptor_ranges;
+ unsigned int i;
+
+ for (i = 0; i < table->descriptor_range_count; ++i)
+ {
+ if (!write_dword(context, ranges[i].range_type))
+ goto fail;
+ if (!write_dword(context, ranges[i].descriptor_count))
+ goto fail;
+ if (!write_dword(context, ranges[i].base_shader_register))
+ goto fail;
+ if (!write_dword(context, ranges[i].register_space))
+ goto fail;
+ if (!write_dword(context, ranges[i].descriptor_table_offset))
+ goto fail;
+ }
+
+ return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature descriptor ranges.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_descriptor_ranges1(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_root_descriptor_table1 *table)
+{
+ const struct vkd3d_shader_descriptor_range1 *ranges = table->descriptor_ranges;
+ unsigned int i;
+
+ for (i = 0; i < table->descriptor_range_count; ++i)
+ {
+ if (!write_dword(context, ranges[i].range_type))
+ goto fail;
+ if (!write_dword(context, ranges[i].descriptor_count))
+ goto fail;
+ if (!write_dword(context, ranges[i].base_shader_register))
+ goto fail;
+ if (!write_dword(context, ranges[i].register_space))
+ goto fail;
+ if (!write_dword(context, ranges[i].flags))
+ goto fail;
+ if (!write_dword(context, ranges[i].descriptor_table_offset))
+ goto fail;
+ }
+
+ return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature descriptor ranges.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_descriptor_table(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_root_descriptor_table *table)
+{
+ if (!write_dword(context, table->descriptor_range_count))
+ goto fail;
+ if (!write_dword(context, get_chunk_offset(context) + sizeof(DWORD))) /* offset */
+ goto fail;
+
+ return shader_write_descriptor_ranges(context, table);
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root descriptor table.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_descriptor_table1(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_root_descriptor_table1 *table)
+{
+ if (!write_dword(context, table->descriptor_range_count))
+ goto fail;
+ if (!write_dword(context, get_chunk_offset(context) + sizeof(DWORD))) /* offset */
+ goto fail;
+
+ return shader_write_descriptor_ranges1(context, table);
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root descriptor table.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_root_constants(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_root_constants *constants)
+{
+ if (!write_dword(context, constants->shader_register))
+ goto fail;
+ if (!write_dword(context, constants->register_space))
+ goto fail;
+ if (!write_dword(context, constants->value_count))
+ goto fail;
+
+ return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root constants.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_root_descriptor(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_root_descriptor *descriptor)
+{
+ if (!write_dword(context, descriptor->shader_register))
+ goto fail;
+ if (!write_dword(context, descriptor->register_space))
+ goto fail;
+
+ return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root descriptor.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_root_descriptor1(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_root_descriptor1 *descriptor)
+{
+ if (!write_dword(context, descriptor->shader_register))
+ goto fail;
+ if (!write_dword(context, descriptor->register_space))
+ goto fail;
+ if (!write_dword(context, descriptor->flags))
+ goto fail;
+
+ return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root descriptor.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_root_parameters(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ unsigned int parameter_count = versioned_root_signature_get_parameter_count(desc);
+ size_t parameters_position;
+ unsigned int i;
+ int ret;
+
+ parameters_position = context->position;
+ for (i = 0; i < parameter_count; ++i)
+ {
+ if (!write_dword(context, versioned_root_signature_get_parameter_type(desc, i)))
+ goto fail;
+ if (!write_dword(context, versioned_root_signature_get_parameter_shader_visibility(desc, i)))
+ goto fail;
+ if (!write_dword(context, 0xffffffff)) /* offset */
+ goto fail;
+ }
+
+ for (i = 0; i < parameter_count; ++i)
+ {
+ context->data[parameters_position + 3 * i + 2] = get_chunk_offset(context); /* offset */
+
+ switch (versioned_root_signature_get_parameter_type(desc, i))
+ {
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ ret = shader_write_descriptor_table(context, &desc->u.v_1_0.parameters[i].u.descriptor_table);
+ else
+ ret = shader_write_descriptor_table1(context, &desc->u.v_1_1.parameters[i].u.descriptor_table);
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
+ ret = shader_write_root_constants(context, versioned_root_signature_get_root_constants(desc, i));
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_CBV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_SRV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_UAV:
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ ret = shader_write_root_descriptor(context, &desc->u.v_1_0.parameters[i].u.descriptor);
+ else
+ ret = shader_write_root_descriptor1(context, &desc->u.v_1_1.parameters[i].u.descriptor);
+ break;
+ default:
+ FIXME("Unrecognized type %#x.\n", versioned_root_signature_get_parameter_type(desc, i));
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_INVALID_ROOT_PARAMETER_TYPE,
+ "Invalid/unrecognised root signature root parameter type %#x.",
+ versioned_root_signature_get_parameter_type(desc, i));
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (ret < 0)
+ return ret;
+ }
+
+ return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root parameters.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_static_samplers(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ const struct vkd3d_shader_static_sampler_desc *samplers = versioned_root_signature_get_static_samplers(desc);
+ unsigned int i;
+
+ for (i = 0; i < versioned_root_signature_get_static_sampler_count(desc); ++i)
+ {
+ if (!write_dword(context, samplers[i].filter))
+ goto fail;
+ if (!write_dword(context, samplers[i].address_u))
+ goto fail;
+ if (!write_dword(context, samplers[i].address_v))
+ goto fail;
+ if (!write_dword(context, samplers[i].address_w))
+ goto fail;
+ if (!write_float(context, samplers[i].mip_lod_bias))
+ goto fail;
+ if (!write_dword(context, samplers[i].max_anisotropy))
+ goto fail;
+ if (!write_dword(context, samplers[i].comparison_func))
+ goto fail;
+ if (!write_dword(context, samplers[i].border_colour))
+ goto fail;
+ if (!write_float(context, samplers[i].min_lod))
+ goto fail;
+ if (!write_float(context, samplers[i].max_lod))
+ goto fail;
+ if (!write_dword(context, samplers[i].shader_register))
+ goto fail;
+ if (!write_dword(context, samplers[i].register_space))
+ goto fail;
+ if (!write_dword(context, samplers[i].shader_visibility))
+ goto fail;
+ }
+
+ return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature static samplers.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int shader_write_root_signature(struct root_signature_writer_context *context,
+ const struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ size_t samplers_offset_position;
+ int ret;
+
+ if (!write_dword(context, desc->version))
+ goto fail;
+
+ if (!write_dword(context, versioned_root_signature_get_parameter_count(desc)))
+ goto fail;
+ if (!write_dword(context, get_chunk_offset(context) + 4 * sizeof(DWORD))) /* offset */
+ goto fail;
+
+ if (!write_dword(context, versioned_root_signature_get_static_sampler_count(desc)))
+ goto fail;
+ samplers_offset_position = context->position;
+ if (!write_dword(context, 0xffffffff)) /* offset */
+ goto fail;
+
+ if (!write_dword(context, versioned_root_signature_get_flags(desc)))
+ goto fail;
+
+ if ((ret = shader_write_root_parameters(context, desc)) < 0)
+ return ret;
+
+ context->data[samplers_offset_position] = get_chunk_offset(context);
+ return shader_write_static_samplers(context, desc);
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+}
+
+static int validate_descriptor_table_v_1_0(const struct vkd3d_shader_root_descriptor_table *descriptor_table,
+ struct vkd3d_shader_message_context *message_context)
+{
+ bool have_srv_uav_cbv = false;
+ bool have_sampler = false;
+ unsigned int i;
+
+ for (i = 0; i < descriptor_table->descriptor_range_count; ++i)
+ {
+ const struct vkd3d_shader_descriptor_range *r = &descriptor_table->descriptor_ranges[i];
+
+ if (r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV
+ || r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV
+ || r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV)
+ {
+ have_srv_uav_cbv = true;
+ }
+ else if (r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER)
+ {
+ have_sampler = true;
+ }
+ else
+ {
+ WARN("Invalid descriptor range type %#x.\n", r->range_type);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_RS_INVALID_DESCRIPTOR_RANGE_TYPE,
+ "Invalid root signature descriptor range type %#x.", r->range_type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ }
+
+ if (have_srv_uav_cbv && have_sampler)
+ {
+ WARN("Samplers cannot be mixed with CBVs/SRVs/UAVs in descriptor tables.\n");
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_RS_MIXED_DESCRIPTOR_RANGE_TYPES,
+ "Encountered both CBV/SRV/UAV and sampler descriptor ranges in the same root descriptor table.");
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ return VKD3D_OK;
+}
+
+static int validate_descriptor_table_v_1_1(const struct vkd3d_shader_root_descriptor_table1 *descriptor_table,
+ struct vkd3d_shader_message_context *message_context)
+{
+ bool have_srv_uav_cbv = false;
+ bool have_sampler = false;
+ unsigned int i;
+
+ for (i = 0; i < descriptor_table->descriptor_range_count; ++i)
+ {
+ const struct vkd3d_shader_descriptor_range1 *r = &descriptor_table->descriptor_ranges[i];
+
+ if (r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV
+ || r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV
+ || r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV)
+ {
+ have_srv_uav_cbv = true;
+ }
+ else if (r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER)
+ {
+ have_sampler = true;
+ }
+ else
+ {
+ WARN("Invalid descriptor range type %#x.\n", r->range_type);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_RS_INVALID_DESCRIPTOR_RANGE_TYPE,
+ "Invalid root signature descriptor range type %#x.", r->range_type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ }
+
+ if (have_srv_uav_cbv && have_sampler)
+ {
+ WARN("Samplers cannot be mixed with CBVs/SRVs/UAVs in descriptor tables.\n");
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_RS_MIXED_DESCRIPTOR_RANGE_TYPES,
+ "Encountered both CBV/SRV/UAV and sampler descriptor ranges in the same root descriptor table.");
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ return VKD3D_OK;
+}
+
+static int validate_root_signature_desc(const struct vkd3d_shader_versioned_root_signature_desc *desc,
+ struct vkd3d_shader_message_context *message_context)
+{
+ int ret = VKD3D_OK;
+ unsigned int i;
+
+ for (i = 0; i < versioned_root_signature_get_parameter_count(desc); ++i)
+ {
+ enum vkd3d_shader_root_parameter_type type;
+
+ type = versioned_root_signature_get_parameter_type(desc, i);
+ if (type == VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
+ {
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ ret = validate_descriptor_table_v_1_0(&desc->u.v_1_0.parameters[i].u.descriptor_table, message_context);
+ else
+ ret = validate_descriptor_table_v_1_1(&desc->u.v_1_1.parameters[i].u.descriptor_table, message_context);
+ }
+
+ if (ret < 0)
+ break;
+ }
+
+ return ret;
+}
+
+int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_root_signature_desc *root_signature,
+ struct vkd3d_shader_code *dxbc, char **messages)
+{
+ struct root_signature_writer_context context;
+ size_t total_size, chunk_size;
+ uint32_t checksum[4];
+ int ret;
+
+ TRACE("root_signature %p, dxbc %p, messages %p.\n", root_signature, dxbc, messages);
+
+ if (messages)
+ *messages = NULL;
+
+ memset(&context, 0, sizeof(context));
+ if (!vkd3d_shader_message_context_init(&context.message_context, VKD3D_SHADER_LOG_INFO, NULL))
+ return VKD3D_ERROR;
+
+ if (root_signature->version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0
+ && root_signature->version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1)
+ {
+ ret = VKD3D_ERROR_INVALID_ARGUMENT;
+ WARN("Root signature version %#x not supported.\n", root_signature->version);
+ vkd3d_shader_error(&context.message_context, VKD3D_SHADER_ERROR_RS_INVALID_VERSION,
+ "Root signature version %#x is not supported.", root_signature->version);
+ goto done;
+ }
+
+ if ((ret = validate_root_signature_desc(root_signature, &context.message_context)) < 0)
+ goto done;
+
+ memset(dxbc, 0, sizeof(*dxbc));
+ if ((ret = shader_write_root_signature_header(&context)) < 0)
+ {
+ vkd3d_free(context.data);
+ goto done;
+ }
+
+ if ((ret = shader_write_root_signature(&context, root_signature)) < 0)
+ {
+ vkd3d_free(context.data);
+ goto done;
+ }
+
+ total_size = context.position * sizeof(DWORD);
+ chunk_size = get_chunk_offset(&context);
+ context.data[context.total_size_position] = total_size;
+ context.data[context.chunk_position - 1] = chunk_size;
+
+ dxbc->code = context.data;
+ dxbc->size = total_size;
+
+ vkd3d_compute_dxbc_checksum(dxbc->code, dxbc->size, checksum);
+ memcpy((uint32_t *)dxbc->code + 1, checksum, sizeof(checksum));
+
+ ret = VKD3D_OK;
+
+done:
+ vkd3d_shader_message_context_trace_messages(&context.message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&context.message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ vkd3d_shader_message_context_cleanup(&context.message_context);
+ return ret;
+}
+
+static void free_descriptor_ranges(const struct vkd3d_shader_root_parameter *parameters, unsigned int count)
+{
+ unsigned int i;
+
+ if (!parameters)
+ return;
+
+ for (i = 0; i < count; ++i)
+ {
+ const struct vkd3d_shader_root_parameter *p = ¶meters[i];
+
+ if (p->parameter_type == VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
+ vkd3d_free((void *)p->u.descriptor_table.descriptor_ranges);
+ }
+}
+
+static int convert_root_parameters_to_v_1_0(struct vkd3d_shader_root_parameter *dst,
+ const struct vkd3d_shader_root_parameter1 *src, unsigned int count)
+{
+ const struct vkd3d_shader_descriptor_range1 *ranges1;
+ struct vkd3d_shader_descriptor_range *ranges;
+ unsigned int i, j;
+ int ret;
+
+ for (i = 0; i < count; ++i)
+ {
+ const struct vkd3d_shader_root_parameter1 *p1 = &src[i];
+ struct vkd3d_shader_root_parameter *p = &dst[i];
+
+ p->parameter_type = p1->parameter_type;
+ switch (p->parameter_type)
+ {
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
+ ranges = NULL;
+ if ((p->u.descriptor_table.descriptor_range_count = p1->u.descriptor_table.descriptor_range_count))
+ {
+ if (!(ranges = vkd3d_calloc(p->u.descriptor_table.descriptor_range_count, sizeof(*ranges))))
+ {
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
+ p->u.descriptor_table.descriptor_ranges = ranges;
+ ranges1 = p1->u.descriptor_table.descriptor_ranges;
+ for (j = 0; j < p->u.descriptor_table.descriptor_range_count; ++j)
+ {
+ ranges[j].range_type = ranges1[j].range_type;
+ ranges[j].descriptor_count = ranges1[j].descriptor_count;
+ ranges[j].base_shader_register = ranges1[j].base_shader_register;
+ ranges[j].register_space = ranges1[j].register_space;
+ ranges[j].descriptor_table_offset = ranges1[j].descriptor_table_offset;
+ }
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
+ p->u.constants = p1->u.constants;
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_CBV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_SRV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_UAV:
+ p->u.descriptor.shader_register = p1->u.descriptor.shader_register;
+ p->u.descriptor.register_space = p1->u.descriptor.register_space;
+ break;
+ default:
+ WARN("Invalid root parameter type %#x.\n", p->parameter_type);
+ ret = VKD3D_ERROR_INVALID_ARGUMENT;
+ goto fail;
+
+ }
+ p->shader_visibility = p1->shader_visibility;
+ }
+
+ return VKD3D_OK;
+
+fail:
+ free_descriptor_ranges(dst, i);
+ return ret;
+}
+
+static int convert_root_signature_to_v1_0(struct vkd3d_shader_versioned_root_signature_desc *dst,
+ const struct vkd3d_shader_versioned_root_signature_desc *src)
+{
+ const struct vkd3d_shader_root_signature_desc1 *src_desc = &src->u.v_1_1;
+ struct vkd3d_shader_root_signature_desc *dst_desc = &dst->u.v_1_0;
+ struct vkd3d_shader_static_sampler_desc *samplers = NULL;
+ struct vkd3d_shader_root_parameter *parameters = NULL;
+ int ret;
+
+ if ((dst_desc->parameter_count = src_desc->parameter_count))
+ {
+ if (!(parameters = vkd3d_calloc(dst_desc->parameter_count, sizeof(*parameters))))
+ {
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ if ((ret = convert_root_parameters_to_v_1_0(parameters, src_desc->parameters, src_desc->parameter_count)) < 0)
+ goto fail;
+ }
+ dst_desc->parameters = parameters;
+ if ((dst_desc->static_sampler_count = src_desc->static_sampler_count))
+ {
+ if (!(samplers = vkd3d_calloc(dst_desc->static_sampler_count, sizeof(*samplers))))
+ {
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ memcpy(samplers, src_desc->static_samplers, src_desc->static_sampler_count * sizeof(*samplers));
+ }
+ dst_desc->static_samplers = samplers;
+ dst_desc->flags = src_desc->flags;
+
+ return VKD3D_OK;
+
+fail:
+ free_descriptor_ranges(parameters, dst_desc->parameter_count);
+ vkd3d_free(parameters);
+ vkd3d_free(samplers);
+ return ret;
+}
+
+static void free_descriptor_ranges1(const struct vkd3d_shader_root_parameter1 *parameters, unsigned int count)
+{
+ unsigned int i;
+
+ if (!parameters)
+ return;
+
+ for (i = 0; i < count; ++i)
+ {
+ const struct vkd3d_shader_root_parameter1 *p = ¶meters[i];
+
+ if (p->parameter_type == VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
+ vkd3d_free((void *)p->u.descriptor_table.descriptor_ranges);
+ }
+}
+
+static int convert_root_parameters_to_v_1_1(struct vkd3d_shader_root_parameter1 *dst,
+ const struct vkd3d_shader_root_parameter *src, unsigned int count)
+{
+ const struct vkd3d_shader_descriptor_range *ranges;
+ struct vkd3d_shader_descriptor_range1 *ranges1;
+ unsigned int i, j;
+ int ret;
+
+ for (i = 0; i < count; ++i)
+ {
+ const struct vkd3d_shader_root_parameter *p = &src[i];
+ struct vkd3d_shader_root_parameter1 *p1 = &dst[i];
+
+ p1->parameter_type = p->parameter_type;
+ switch (p1->parameter_type)
+ {
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
+ ranges1 = NULL;
+ if ((p1->u.descriptor_table.descriptor_range_count = p->u.descriptor_table.descriptor_range_count))
+ {
+ if (!(ranges1 = vkd3d_calloc(p1->u.descriptor_table.descriptor_range_count, sizeof(*ranges1))))
+ {
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ }
+ p1->u.descriptor_table.descriptor_ranges = ranges1;
+ ranges = p->u.descriptor_table.descriptor_ranges;
+ for (j = 0; j < p1->u.descriptor_table.descriptor_range_count; ++j)
+ {
+ ranges1[j].range_type = ranges[j].range_type;
+ ranges1[j].descriptor_count = ranges[j].descriptor_count;
+ ranges1[j].base_shader_register = ranges[j].base_shader_register;
+ ranges1[j].register_space = ranges[j].register_space;
+ ranges1[j].flags = VKD3D_ROOT_SIGNATURE_1_0_DESCRIPTOR_RANGE_FLAGS;
+ ranges1[j].descriptor_table_offset = ranges[j].descriptor_table_offset;
+ }
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
+ p1->u.constants = p->u.constants;
+ break;
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_CBV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_SRV:
+ case VKD3D_SHADER_ROOT_PARAMETER_TYPE_UAV:
+ p1->u.descriptor.shader_register = p->u.descriptor.shader_register;
+ p1->u.descriptor.register_space = p->u.descriptor.register_space;
+ p1->u.descriptor.flags = VKD3D_ROOT_SIGNATURE_1_0_ROOT_DESCRIPTOR_FLAGS;
+ break;
+ default:
+ WARN("Invalid root parameter type %#x.\n", p1->parameter_type);
+ ret = VKD3D_ERROR_INVALID_ARGUMENT;
+ goto fail;
+
+ }
+ p1->shader_visibility = p->shader_visibility;
+ }
+
+ return VKD3D_OK;
+
+fail:
+ free_descriptor_ranges1(dst, i);
+ return ret;
+}
+
+static int convert_root_signature_to_v1_1(struct vkd3d_shader_versioned_root_signature_desc *dst,
+ const struct vkd3d_shader_versioned_root_signature_desc *src)
+{
+ const struct vkd3d_shader_root_signature_desc *src_desc = &src->u.v_1_0;
+ struct vkd3d_shader_root_signature_desc1 *dst_desc = &dst->u.v_1_1;
+ struct vkd3d_shader_static_sampler_desc *samplers = NULL;
+ struct vkd3d_shader_root_parameter1 *parameters = NULL;
+ int ret;
+
+ if ((dst_desc->parameter_count = src_desc->parameter_count))
+ {
+ if (!(parameters = vkd3d_calloc(dst_desc->parameter_count, sizeof(*parameters))))
+ {
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ if ((ret = convert_root_parameters_to_v_1_1(parameters, src_desc->parameters, src_desc->parameter_count)) < 0)
+ goto fail;
+ }
+ dst_desc->parameters = parameters;
+ if ((dst_desc->static_sampler_count = src_desc->static_sampler_count))
+ {
+ if (!(samplers = vkd3d_calloc(dst_desc->static_sampler_count, sizeof(*samplers))))
+ {
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
+ }
+ memcpy(samplers, src_desc->static_samplers, src_desc->static_sampler_count * sizeof(*samplers));
+ }
+ dst_desc->static_samplers = samplers;
+ dst_desc->flags = src_desc->flags;
+
+ return VKD3D_OK;
+
+fail:
+ free_descriptor_ranges1(parameters, dst_desc->parameter_count);
+ vkd3d_free(parameters);
+ vkd3d_free(samplers);
+ return ret;
+}
+
+int vkd3d_shader_convert_root_signature(struct vkd3d_shader_versioned_root_signature_desc *dst,
+ enum vkd3d_shader_root_signature_version version, const struct vkd3d_shader_versioned_root_signature_desc *src)
+{
+ int ret;
+
+ TRACE("dst %p, version %#x, src %p.\n", dst, version, src);
+
+ if (src->version == version)
+ {
+ WARN("Nothing to convert.\n");
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0 && version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1)
+ {
+ WARN("Root signature version %#x not supported.\n", version);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (src->version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0
+ && src->version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1)
+ {
+ WARN("Root signature version %#x not supported.\n", src->version);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ memset(dst, 0, sizeof(*dst));
+ dst->version = version;
+
+ if (version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ {
+ ret = convert_root_signature_to_v1_0(dst, src);
+ }
+ else
+ {
+ assert(version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1);
+ ret = convert_root_signature_to_v1_1(dst, src);
+ }
+
+ return ret;
+}
diff --git a/dlls/vkd3d/libs/vkd3d-shader/libvkd3d-shader.pc.in b/dlls/vkd3d/libs/vkd3d-shader/libvkd3d-shader.pc.in
new file mode 100644
index 00000000000..b93e6ed9c6d
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-shader/libvkd3d-shader.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: vkd3d-shader
+Description: The vkd3d Shader Translation Library
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}/vkd3d
+Libs: -L${libdir} -lvkd3d-shader
diff --git a/dlls/vkd3d/libs/vkd3d-shader/spirv.c b/dlls/vkd3d/libs/vkd3d-shader/spirv.c
new file mode 100644
index 00000000000..44fe35c72c5
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-shader/spirv.c
@@ -0,0 +1,9281 @@
+/*
+ * Copyright 2017 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_shader_private.h"
+#include "rbtree.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#ifdef HAVE_SPIRV_UNIFIED1_SPIRV_H
+# include "spirv/unified1/spirv.h"
+#else
+# include "vulkan/spirv.h"
+#endif /* HAVE_SPIRV_UNIFIED1_SPIRV_H */
+#ifdef HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H
+# include "spirv/unified1/GLSL.std.450.h"
+#else
+# include "vulkan/GLSL.std.450.h"
+#endif /* HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H */
+
+#ifdef HAVE_SPIRV_TOOLS
+# include "spirv-tools/libspirv.h"
+
+static spv_target_env spv_target_env_from_vkd3d(enum vkd3d_shader_spirv_environment environment)
+{
+ switch (environment)
+ {
+ case VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5:
+ return SPV_ENV_OPENGL_4_5;
+ case VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0:
+ return SPV_ENV_VULKAN_1_0;
+ default:
+ ERR("Invalid environment %#x.\n", environment);
+ return SPV_ENV_VULKAN_1_0;
+ }
+}
+
+static uint32_t get_binary_to_text_options(enum vkd3d_shader_compile_option_formatting_flags formatting)
+{
+ uint32_t out = 0;
+ unsigned int i;
+
+ static const struct
+ {
+ enum vkd3d_shader_compile_option_formatting_flags vkd3d;
+ uint32_t spv;
+ bool invert;
+ }
+ valuemap[] =
+ {
+ {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_COLOUR, SPV_BINARY_TO_TEXT_OPTION_COLOR },
+ {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT, SPV_BINARY_TO_TEXT_OPTION_INDENT },
+ {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_OFFSETS, SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET},
+ {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER, true},
+ {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_RAW_IDS, SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES, true},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(valuemap); ++i)
+ {
+ if (valuemap[i].invert == !(formatting & valuemap[i].vkd3d))
+ out |= valuemap[i].spv;
+ }
+
+ return out;
+}
+
+static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_code *spirv,
+ enum vkd3d_shader_spirv_environment environment, uint32_t options, struct vkd3d_shader_code *out)
+{
+ spv_diagnostic diagnostic = NULL;
+ spv_text text = NULL;
+ spv_context context;
+ spv_result_t spvret;
+ enum vkd3d_result result = VKD3D_OK;
+
+ context = spvContextCreate(spv_target_env_from_vkd3d(environment));
+
+ if (!(spvret = spvBinaryToText(context, spirv->code, spirv->size / sizeof(uint32_t),
+ options, &text, &diagnostic)))
+ {
+ void *code = vkd3d_malloc(text->length);
+ if (code)
+ {
+ memcpy(code, text->str, text->length);
+ out->size = text->length;
+ out->code = code;
+ }
+ else
+ result = VKD3D_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ FIXME("Failed to convert SPIR-V binary to text, ret %d.\n", spvret);
+ FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error));
+ result = VKD3D_ERROR;
+ }
+
+ spvTextDestroy(text);
+ spvDiagnosticDestroy(diagnostic);
+ spvContextDestroy(context);
+
+ return result;
+}
+
+static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
+ enum vkd3d_shader_spirv_environment environment)
+{
+ const static uint32_t options
+ = SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT;
+ struct vkd3d_shader_code text;
+
+ if (!vkd3d_spirv_binary_to_text(spirv, environment, options, &text))
+ {
+ const char *str, *current = text.code;
+ while ((str = strchr(current, '\n')))
+ {
+ TRACE("%.*s\n", (int)(str - current), current);
+ current = str + 1;
+ }
+
+ vkd3d_shader_free_shader_code(&text);
+ }
+}
+
+static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
+ enum vkd3d_shader_spirv_environment environment)
+{
+ spv_diagnostic diagnostic = NULL;
+ spv_context context;
+ spv_result_t ret;
+
+ context = spvContextCreate(spv_target_env_from_vkd3d(environment));
+
+ if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t),
+ &diagnostic)))
+ {
+ FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret);
+ FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error));
+ }
+
+ spvDiagnosticDestroy(diagnostic);
+ spvContextDestroy(context);
+}
+
+#else
+
+static uint32_t get_binary_to_text_options(enum vkd3d_shader_compile_option_formatting_flags formatting)
+{
+ return 0;
+}
+static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_code *spirv,
+ enum vkd3d_shader_spirv_environment environment, uint32_t options, struct vkd3d_shader_code *out)
+{
+ return VKD3D_ERROR;
+}
+static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
+ enum vkd3d_shader_spirv_environment environment) {}
+static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
+ enum vkd3d_shader_spirv_environment environment) {}
+
+#endif /* HAVE_SPIRV_TOOLS */
+
+static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval,
+ unsigned int index)
+{
+ switch (sysval)
+ {
+ case VKD3D_SHADER_SV_NONE:
+ return VKD3D_SIV_NONE;
+ case VKD3D_SHADER_SV_POSITION:
+ return VKD3D_SIV_POSITION;
+ case VKD3D_SHADER_SV_CLIP_DISTANCE:
+ return VKD3D_SIV_CLIP_DISTANCE;
+ case VKD3D_SHADER_SV_CULL_DISTANCE:
+ return VKD3D_SIV_CULL_DISTANCE;
+ case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE:
+ return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index;
+ case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT:
+ return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index;
+ case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE:
+ return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index;
+ case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT:
+ return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR;
+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET:
+ return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR;
+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN:
+ return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR;
+ default:
+ FIXME("Unhandled sysval %#x, index %u.\n", sysval, index);
+ return VKD3D_SIV_NONE;
+ }
+}
+
+static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum vkd3d_shader_sysval_semantic sysval)
+{
+ return vkd3d_siv_from_sysval_indexed(sysval, 0);
+}
+
+#define VKD3D_SPIRV_VERSION 0x00010000
+#define VKD3D_SPIRV_GENERATOR_ID 18
+#define VKD3D_SPIRV_GENERATOR_VERSION 2
+#define VKD3D_SPIRV_GENERATOR_MAGIC ((VKD3D_SPIRV_GENERATOR_ID << 16) | VKD3D_SPIRV_GENERATOR_VERSION)
+
+struct vkd3d_spirv_stream
+{
+ uint32_t *words;
+ size_t capacity;
+ size_t word_count;
+
+ struct list inserted_chunks;
+};
+
+static void vkd3d_spirv_stream_init(struct vkd3d_spirv_stream *stream)
+{
+ stream->capacity = 256;
+ if (!(stream->words = vkd3d_calloc(stream->capacity, sizeof(*stream->words))))
+ stream->capacity = 0;
+ stream->word_count = 0;
+
+ list_init(&stream->inserted_chunks);
+}
+
+struct vkd3d_spirv_chunk
+{
+ struct list entry;
+ size_t location;
+ size_t word_count;
+ uint32_t words[];
+};
+
+static void vkd3d_spirv_stream_clear(struct vkd3d_spirv_stream *stream)
+{
+ struct vkd3d_spirv_chunk *c1, *c2;
+
+ stream->word_count = 0;
+
+ LIST_FOR_EACH_ENTRY_SAFE(c1, c2, &stream->inserted_chunks, struct vkd3d_spirv_chunk, entry)
+ vkd3d_free(c1);
+
+ list_init(&stream->inserted_chunks);
+}
+
+static void vkd3d_spirv_stream_free(struct vkd3d_spirv_stream *stream)
+{
+ vkd3d_free(stream->words);
+
+ vkd3d_spirv_stream_clear(stream);
+}
+
+static size_t vkd3d_spirv_stream_current_location(struct vkd3d_spirv_stream *stream)
+{
+ return stream->word_count;
+}
+
+static void vkd3d_spirv_stream_insert(struct vkd3d_spirv_stream *stream,
+ size_t location, const uint32_t *words, unsigned int word_count)
+{
+ struct vkd3d_spirv_chunk *chunk, *current;
+
+ if (!(chunk = vkd3d_malloc(offsetof(struct vkd3d_spirv_chunk, words[word_count]))))
+ return;
+
+ chunk->location = location;
+ chunk->word_count = word_count;
+ memcpy(chunk->words, words, word_count * sizeof(*words));
+
+ LIST_FOR_EACH_ENTRY(current, &stream->inserted_chunks, struct vkd3d_spirv_chunk, entry)
+ {
+ if (current->location > location)
+ {
+ list_add_before(¤t->entry, &chunk->entry);
+ return;
+ }
+ }
+
+ list_add_tail(&stream->inserted_chunks, &chunk->entry);
+}
+
+static bool vkd3d_spirv_stream_append(struct vkd3d_spirv_stream *dst_stream,
+ const struct vkd3d_spirv_stream *src_stream)
+{
+ size_t word_count, src_word_count = src_stream->word_count;
+ struct vkd3d_spirv_chunk *chunk;
+ size_t src_location = 0;
+
+ assert(list_empty(&dst_stream->inserted_chunks));
+
+ LIST_FOR_EACH_ENTRY(chunk, &src_stream->inserted_chunks, struct vkd3d_spirv_chunk, entry)
+ src_word_count += chunk->word_count;
+
+ if (!vkd3d_array_reserve((void **)&dst_stream->words, &dst_stream->capacity,
+ dst_stream->word_count + src_word_count, sizeof(*dst_stream->words)))
+ return false;
+
+ assert(dst_stream->word_count + src_word_count <= dst_stream->capacity);
+ LIST_FOR_EACH_ENTRY(chunk, &src_stream->inserted_chunks, struct vkd3d_spirv_chunk, entry)
+ {
+ assert(src_location <= chunk->location);
+ word_count = chunk->location - src_location;
+ memcpy(&dst_stream->words[dst_stream->word_count], &src_stream->words[src_location],
+ word_count * sizeof(*src_stream->words));
+ dst_stream->word_count += word_count;
+ src_location += word_count;
+ assert(src_location == chunk->location);
+
+ memcpy(&dst_stream->words[dst_stream->word_count], chunk->words,
+ chunk->word_count * sizeof(*chunk->words));
+ dst_stream->word_count += chunk->word_count;
+ }
+
+ word_count = src_stream->word_count - src_location;
+ memcpy(&dst_stream->words[dst_stream->word_count], &src_stream->words[src_location],
+ word_count * sizeof(*src_stream->words));
+ dst_stream->word_count += word_count;
+ return true;
+}
+
+struct vkd3d_spirv_builder
+{
+ uint64_t capability_mask;
+ uint64_t capability_draw_parameters : 1;
+ uint64_t capability_demote_to_helper_invocation : 1;
+ uint32_t ext_instr_set_glsl_450;
+ uint32_t invocation_count;
+ SpvExecutionModel execution_model;
+
+ uint32_t current_id;
+ uint32_t main_function_id;
+ struct rb_tree declarations;
+ uint32_t type_sampler_id;
+ uint32_t type_bool_id;
+ uint32_t type_void_id;
+
+ struct vkd3d_spirv_stream debug_stream; /* debug instructions */
+ struct vkd3d_spirv_stream annotation_stream; /* decoration instructions */
+ struct vkd3d_spirv_stream global_stream; /* types, constants, global variables */
+ struct vkd3d_spirv_stream function_stream; /* function definitions */
+
+ struct vkd3d_spirv_stream execution_mode_stream; /* execution mode instructions */
+
+ struct vkd3d_spirv_stream original_function_stream;
+ struct vkd3d_spirv_stream insertion_stream;
+ size_t insertion_location;
+
+ size_t main_function_location;
+
+ /* entry point interface */
+ uint32_t *iface;
+ size_t iface_capacity;
+ size_t iface_element_count;
+};
+
+static uint32_t vkd3d_spirv_alloc_id(struct vkd3d_spirv_builder *builder)
+{
+ return builder->current_id++;
+}
+
+static void vkd3d_spirv_enable_capability(struct vkd3d_spirv_builder *builder,
+ SpvCapability cap)
+{
+ if (cap < sizeof(builder->capability_mask) * CHAR_BIT)
+ {
+ builder->capability_mask |= 1ull << cap;
+ }
+ else if (cap == SpvCapabilityDrawParameters)
+ {
+ builder->capability_draw_parameters = 1;
+ }
+ else if (cap == SpvCapabilityDemoteToHelperInvocationEXT)
+ {
+ builder->capability_demote_to_helper_invocation = 1;
+ }
+ else
+ {
+ FIXME("Unhandled capability %#x.\n", cap);
+ }
+}
+
+static uint32_t vkd3d_spirv_get_glsl_std450_instr_set(struct vkd3d_spirv_builder *builder)
+{
+ if (!builder->ext_instr_set_glsl_450)
+ builder->ext_instr_set_glsl_450 = vkd3d_spirv_alloc_id(builder);
+
+ return builder->ext_instr_set_glsl_450;
+}
+
+static void vkd3d_spirv_add_iface_variable(struct vkd3d_spirv_builder *builder,
+ uint32_t id)
+{
+ if (!vkd3d_array_reserve((void **)&builder->iface, &builder->iface_capacity,
+ builder->iface_element_count + 1, sizeof(*builder->iface)))
+ return;
+
+ builder->iface[builder->iface_element_count++] = id;
+}
+
+static void vkd3d_spirv_set_execution_model(struct vkd3d_spirv_builder *builder,
+ SpvExecutionModel model)
+{
+ builder->execution_model = model;
+
+ switch (model)
+ {
+ case SpvExecutionModelVertex:
+ case SpvExecutionModelFragment:
+ case SpvExecutionModelGLCompute:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityShader);
+ break;
+ case SpvExecutionModelTessellationControl:
+ case SpvExecutionModelTessellationEvaluation:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityTessellation);
+ break;
+ case SpvExecutionModelGeometry:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityGeometry);
+ break;
+ default:
+ ERR("Unhandled execution model %#x.\n", model);
+ }
+}
+
+static uint32_t vkd3d_spirv_opcode_word(SpvOp op, unsigned int word_count)
+{
+ assert(!(op & ~SpvOpCodeMask));
+ return (word_count << SpvWordCountShift) | op;
+}
+
+static void vkd3d_spirv_build_word(struct vkd3d_spirv_stream *stream, uint32_t word)
+{
+ if (!vkd3d_array_reserve((void **)&stream->words, &stream->capacity,
+ stream->word_count + 1, sizeof(*stream->words)))
+ return;
+
+ stream->words[stream->word_count++] = word;
+}
+
+static unsigned int vkd3d_spirv_string_word_count(const char *str)
+{
+ return align(strlen(str) + 1, sizeof(uint32_t)) / sizeof(uint32_t);
+}
+
+static void vkd3d_spirv_build_string(struct vkd3d_spirv_stream *stream,
+ const char *str, unsigned int word_count)
+{
+ unsigned int word_idx, i;
+ const char *ptr = str;
+
+ for (word_idx = 0; word_idx < word_count; ++word_idx)
+ {
+ uint32_t word = 0;
+ for (i = 0; i < sizeof(uint32_t) && *ptr; ++i)
+ word |= (uint32_t)*ptr++ << (8 * i);
+ vkd3d_spirv_build_word(stream, word);
+ }
+}
+
+typedef uint32_t (*vkd3d_spirv_build_pfn)(struct vkd3d_spirv_builder *builder);
+typedef uint32_t (*vkd3d_spirv_build1_pfn)(struct vkd3d_spirv_builder *builder,
+ uint32_t operand0);
+typedef uint32_t (*vkd3d_spirv_build1v_pfn)(struct vkd3d_spirv_builder *builder,
+ uint32_t operand0, const uint32_t *operands, unsigned int operand_count);
+typedef uint32_t (*vkd3d_spirv_build2_pfn)(struct vkd3d_spirv_builder *builder,
+ uint32_t operand0, uint32_t operand1);
+typedef uint32_t (*vkd3d_spirv_build7_pfn)(struct vkd3d_spirv_builder *builder,
+ uint32_t operand0, uint32_t operand1, uint32_t operand2, uint32_t operand3,
+ uint32_t operand4, uint32_t operand5, uint32_t operand6);
+
+static uint32_t vkd3d_spirv_build_once(struct vkd3d_spirv_builder *builder,
+ uint32_t *id, vkd3d_spirv_build_pfn build_pfn)
+{
+ if (!(*id))
+ *id = build_pfn(builder);
+ return *id;
+}
+
+#define MAX_SPIRV_DECLARATION_PARAMETER_COUNT 7
+
+struct vkd3d_spirv_declaration
+{
+ struct rb_entry entry;
+
+ SpvOp op;
+ unsigned int parameter_count;
+ uint32_t parameters[MAX_SPIRV_DECLARATION_PARAMETER_COUNT];
+ uint32_t id;
+};
+
+static int vkd3d_spirv_declaration_compare(const void *key, const struct rb_entry *e)
+{
+ const struct vkd3d_spirv_declaration *a = key;
+ const struct vkd3d_spirv_declaration *b = RB_ENTRY_VALUE(e, const struct vkd3d_spirv_declaration, entry);
+
+ if (a->op != b->op)
+ return a->op - b->op;
+ if (a->parameter_count != b->parameter_count)
+ return a->parameter_count - b->parameter_count;
+ assert(a->parameter_count <= ARRAY_SIZE(a->parameters));
+ return memcmp(&a->parameters, &b->parameters, a->parameter_count * sizeof(*a->parameters));
+}
+
+static void vkd3d_spirv_declaration_free(struct rb_entry *entry, void *context)
+{
+ struct vkd3d_spirv_declaration *d = RB_ENTRY_VALUE(entry, struct vkd3d_spirv_declaration, entry);
+
+ vkd3d_free(d);
+}
+
+static void vkd3d_spirv_insert_declaration(struct vkd3d_spirv_builder *builder,
+ const struct vkd3d_spirv_declaration *declaration)
+{
+ struct vkd3d_spirv_declaration *d;
+
+ assert(declaration->parameter_count <= ARRAY_SIZE(declaration->parameters));
+
+ if (!(d = vkd3d_malloc(sizeof(*d))))
+ return;
+ memcpy(d, declaration, sizeof(*d));
+ if (rb_put(&builder->declarations, d, &d->entry) == -1)
+ {
+ ERR("Failed to insert declaration entry.\n");
+ vkd3d_free(d);
+ }
+}
+
+static uint32_t vkd3d_spirv_build_once1(struct vkd3d_spirv_builder *builder,
+ SpvOp op, uint32_t operand0, vkd3d_spirv_build1_pfn build_pfn)
+{
+ struct vkd3d_spirv_declaration declaration;
+ struct rb_entry *entry;
+
+ declaration.op = op;
+ declaration.parameter_count = 1;
+ declaration.parameters[0] = operand0;
+
+ if ((entry = rb_get(&builder->declarations, &declaration)))
+ return RB_ENTRY_VALUE(entry, struct vkd3d_spirv_declaration, entry)->id;
+
+ declaration.id = build_pfn(builder, operand0);
+ vkd3d_spirv_insert_declaration(builder, &declaration);
+ return declaration.id;
+}
+
+static uint32_t vkd3d_spirv_build_once1v(struct vkd3d_spirv_builder *builder,
+ SpvOp op, uint32_t operand0, const uint32_t *operands, unsigned int operand_count,
+ vkd3d_spirv_build1v_pfn build_pfn)
+{
+ struct vkd3d_spirv_declaration declaration;
+ unsigned int i, param_idx = 0;
+ struct rb_entry *entry;
+
+ if (operand_count >= ARRAY_SIZE(declaration.parameters))
+ {
+ WARN("Unsupported parameter count %u (opcode %#x).\n", operand_count + 1, op);
+ return build_pfn(builder, operand0, operands, operand_count);
+ }
+
+ declaration.op = op;
+ declaration.parameters[param_idx++] = operand0;
+ for (i = 0; i < operand_count; ++i)
+ declaration.parameters[param_idx++] = operands[i];
+ declaration.parameter_count = param_idx;
+
+ if ((entry = rb_get(&builder->declarations, &declaration)))
+ return RB_ENTRY_VALUE(entry, struct vkd3d_spirv_declaration, entry)->id;
+
+ declaration.id = build_pfn(builder, operand0, operands, operand_count);
+ vkd3d_spirv_insert_declaration(builder, &declaration);
+ return declaration.id;
+}
+
+static uint32_t vkd3d_spirv_build_once2(struct vkd3d_spirv_builder *builder,
+ SpvOp op, uint32_t operand0, uint32_t operand1, vkd3d_spirv_build2_pfn build_pfn)
+{
+ struct vkd3d_spirv_declaration declaration;
+ struct rb_entry *entry;
+
+ declaration.op = op;
+ declaration.parameter_count = 2;
+ declaration.parameters[0] = operand0;
+ declaration.parameters[1] = operand1;
+
+ if ((entry = rb_get(&builder->declarations, &declaration)))
+ return RB_ENTRY_VALUE(entry, struct vkd3d_spirv_declaration, entry)->id;
+
+ declaration.id = build_pfn(builder, operand0, operand1);
+ vkd3d_spirv_insert_declaration(builder, &declaration);
+ return declaration.id;
+}
+
+static uint32_t vkd3d_spirv_build_once7(struct vkd3d_spirv_builder *builder,
+ SpvOp op, const uint32_t *operands, vkd3d_spirv_build7_pfn build_pfn)
+{
+ struct vkd3d_spirv_declaration declaration;
+ struct rb_entry *entry;
+
+ declaration.op = op;
+ declaration.parameter_count = 7;
+ memcpy(&declaration.parameters, operands, declaration.parameter_count * sizeof(*operands));
+
+ if ((entry = rb_get(&builder->declarations, &declaration)))
+ return RB_ENTRY_VALUE(entry, struct vkd3d_spirv_declaration, entry)->id;
+
+ declaration.id = build_pfn(builder, operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5], operands[6]);
+ vkd3d_spirv_insert_declaration(builder, &declaration);
+ return declaration.id;
+}
+
+/*
+ * vkd3d_spirv_build_op[1-3][v]()
+ * vkd3d_spirv_build_op_[t][r][1-3][v]()
+ *
+ * t - result type
+ * r - result id
+ * 1-3 - the number of operands
+ * v - variable number of operands
+ */
+static void vkd3d_spirv_build_op(struct vkd3d_spirv_stream *stream, SpvOp op)
+{
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(op, 1));
+}
+
+static void vkd3d_spirv_build_op1(struct vkd3d_spirv_stream *stream,
+ SpvOp op, uint32_t operand)
+{
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(op, 2));
+ vkd3d_spirv_build_word(stream, operand);
+}
+
+static void vkd3d_spirv_build_op1v(struct vkd3d_spirv_stream *stream,
+ SpvOp op, uint32_t operand0, const uint32_t *operands, unsigned int operand_count)
+{
+ unsigned int i;
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(op, 2 + operand_count));
+ vkd3d_spirv_build_word(stream, operand0);
+ for (i = 0; i < operand_count; ++i)
+ vkd3d_spirv_build_word(stream, operands[i]);
+}
+
+static void vkd3d_spirv_build_op2v(struct vkd3d_spirv_stream *stream,
+ SpvOp op, uint32_t operand0, uint32_t operand1,
+ const uint32_t *operands, unsigned int operand_count)
+{
+ unsigned int i;
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(op, 3 + operand_count));
+ vkd3d_spirv_build_word(stream, operand0);
+ vkd3d_spirv_build_word(stream, operand1);
+ for (i = 0; i < operand_count; ++i)
+ vkd3d_spirv_build_word(stream, operands[i]);
+}
+
+static void vkd3d_spirv_build_op3v(struct vkd3d_spirv_stream *stream,
+ SpvOp op, uint32_t operand0, uint32_t operand1, uint32_t operand2,
+ const uint32_t *operands, unsigned int operand_count)
+{
+ unsigned int i;
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(op, 4 + operand_count));
+ vkd3d_spirv_build_word(stream, operand0);
+ vkd3d_spirv_build_word(stream, operand1);
+ vkd3d_spirv_build_word(stream, operand2);
+ for (i = 0; i < operand_count; ++i)
+ vkd3d_spirv_build_word(stream, operands[i]);
+}
+
+static void vkd3d_spirv_build_op2(struct vkd3d_spirv_stream *stream,
+ SpvOp op, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op2v(stream, op, operand0, operand1, NULL, 0);
+}
+
+static void vkd3d_spirv_build_op3(struct vkd3d_spirv_stream *stream,
+ SpvOp op, uint32_t operand0, uint32_t operand1, uint32_t operand2)
+{
+ return vkd3d_spirv_build_op2v(stream, op, operand0, operand1, &operand2, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_rv(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op,
+ const uint32_t *operands, unsigned int operand_count)
+{
+ uint32_t result_id = vkd3d_spirv_alloc_id(builder);
+ vkd3d_spirv_build_op1v(stream, op, result_id, operands, operand_count);
+ return result_id;
+}
+
+static uint32_t vkd3d_spirv_build_op_r(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op)
+{
+ return vkd3d_spirv_build_op_rv(builder, stream, op, NULL, 0);
+}
+
+static uint32_t vkd3d_spirv_build_op_r1(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t operand0)
+{
+ return vkd3d_spirv_build_op_rv(builder, stream, op, &operand0, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_r2(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t operand0, uint32_t operand1)
+{
+ uint32_t operands[] = {operand0, operand1};
+ return vkd3d_spirv_build_op_rv(builder, stream, op, operands, ARRAY_SIZE(operands));
+}
+
+static uint32_t vkd3d_spirv_build_op_r1v(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t operand0,
+ const uint32_t *operands, unsigned int operand_count)
+{
+ uint32_t result_id = vkd3d_spirv_alloc_id(builder);
+ vkd3d_spirv_build_op2v(stream, op, result_id, operand0, operands, operand_count);
+ return result_id;
+}
+
+static uint32_t vkd3d_spirv_build_op_trv(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t result_type,
+ const uint32_t *operands, unsigned int operand_count)
+{
+ uint32_t result_id = vkd3d_spirv_alloc_id(builder);
+ vkd3d_spirv_build_op2v(stream, op, result_type, result_id, operands, operand_count);
+ return result_id;
+}
+
+static uint32_t vkd3d_spirv_build_op_tr(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t result_type)
+{
+ return vkd3d_spirv_build_op_trv(builder, stream, op, result_type, NULL, 0);
+}
+
+static uint32_t vkd3d_spirv_build_op_tr1(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t result_type,
+ uint32_t operand0)
+{
+ return vkd3d_spirv_build_op_trv(builder, stream, op, result_type, &operand0, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_tr2(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t result_type,
+ uint32_t operand0, uint32_t operand1)
+{
+ uint32_t operands[] = {operand0, operand1};
+ return vkd3d_spirv_build_op_trv(builder, stream, op, result_type,
+ operands, ARRAY_SIZE(operands));
+}
+
+static uint32_t vkd3d_spirv_build_op_tr3(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t result_type,
+ uint32_t operand0, uint32_t operand1, uint32_t operand2)
+{
+ uint32_t operands[] = {operand0, operand1, operand2};
+ return vkd3d_spirv_build_op_trv(builder, stream, op, result_type,
+ operands, ARRAY_SIZE(operands));
+}
+
+static uint32_t vkd3d_spirv_build_op_tr1v(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t result_type,
+ uint32_t operand0, const uint32_t *operands, unsigned int operand_count)
+{
+ uint32_t result_id = vkd3d_spirv_alloc_id(builder);
+ vkd3d_spirv_build_op3v(stream, op, result_type, result_id, operand0, operands, operand_count);
+ return result_id;
+}
+
+static uint32_t vkd3d_spirv_build_op_tr2v(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, SpvOp op, uint32_t result_type,
+ uint32_t operand0, uint32_t operand1, const uint32_t *operands, unsigned int operand_count)
+{
+ uint32_t result_id = vkd3d_spirv_alloc_id(builder);
+ unsigned int i;
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(op, 5 + operand_count));
+ vkd3d_spirv_build_word(stream, result_type);
+ vkd3d_spirv_build_word(stream, result_id);
+ vkd3d_spirv_build_word(stream, operand0);
+ vkd3d_spirv_build_word(stream, operand1);
+ for (i = 0; i < operand_count; ++i)
+ vkd3d_spirv_build_word(stream, operands[i]);
+ return result_id;
+}
+
+static void vkd3d_spirv_begin_function_stream_insertion(struct vkd3d_spirv_builder *builder,
+ size_t location)
+{
+ assert(builder->insertion_location == ~(size_t)0);
+
+ if (vkd3d_spirv_stream_current_location(&builder->function_stream) == location)
+ return;
+
+ builder->original_function_stream = builder->function_stream;
+ builder->function_stream = builder->insertion_stream;
+ builder->insertion_location = location;
+}
+
+static void vkd3d_spirv_end_function_stream_insertion(struct vkd3d_spirv_builder *builder)
+{
+ struct vkd3d_spirv_stream *insertion_stream = &builder->insertion_stream;
+
+ if (builder->insertion_location == ~(size_t)0)
+ return;
+
+ builder->insertion_stream = builder->function_stream;
+ builder->function_stream = builder->original_function_stream;
+
+ vkd3d_spirv_stream_insert(&builder->function_stream, builder->insertion_location,
+ insertion_stream->words, insertion_stream->word_count);
+ vkd3d_spirv_stream_clear(insertion_stream);
+ builder->insertion_location = ~(size_t)0;
+}
+
+struct vkd3d_spirv_op_branch_conditional
+{
+ uint32_t opcode;
+ uint32_t condition_id;
+ uint32_t true_label;
+ uint32_t false_label;
+};
+
+static struct vkd3d_spirv_op_branch_conditional *vkd3d_spirv_as_op_branch_conditional(
+ struct vkd3d_spirv_stream *stream, size_t location)
+{
+ return (struct vkd3d_spirv_op_branch_conditional *)&stream->words[location];
+}
+
+static void vkd3d_spirv_build_op_capability(struct vkd3d_spirv_stream *stream,
+ SpvCapability cap)
+{
+ vkd3d_spirv_build_op1(stream, SpvOpCapability, cap);
+}
+
+static void vkd3d_spirv_build_op_extension(struct vkd3d_spirv_stream *stream,
+ const char *name)
+{
+ unsigned int name_size = vkd3d_spirv_string_word_count(name);
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(SpvOpExtension, 1 + name_size));
+ vkd3d_spirv_build_string(stream, name, name_size);
+}
+
+static void vkd3d_spirv_build_op_ext_inst_import(struct vkd3d_spirv_stream *stream,
+ uint32_t result_id, const char *name)
+{
+ unsigned int name_size = vkd3d_spirv_string_word_count(name);
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(SpvOpExtInstImport, 2 + name_size));
+ vkd3d_spirv_build_word(stream, result_id);
+ vkd3d_spirv_build_string(stream, name, name_size);
+}
+
+static uint32_t vkd3d_spirv_build_op_ext_inst(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t inst_set, uint32_t inst_number,
+ uint32_t *operands, unsigned int operand_count)
+{
+ return vkd3d_spirv_build_op_tr2v(builder, &builder->function_stream,
+ SpvOpExtInst, result_type, inst_set, inst_number, operands, operand_count);
+}
+
+static void vkd3d_spirv_build_op_memory_model(struct vkd3d_spirv_stream *stream,
+ SpvAddressingModel addressing_model, SpvMemoryModel memory_model)
+{
+ vkd3d_spirv_build_op2(stream, SpvOpMemoryModel, addressing_model, memory_model);
+}
+
+static void vkd3d_spirv_build_op_entry_point(struct vkd3d_spirv_stream *stream,
+ SpvExecutionModel model, uint32_t function_id, const char *name,
+ uint32_t *interface_list, unsigned int interface_size)
+{
+ unsigned int i, name_size = vkd3d_spirv_string_word_count(name);
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(SpvOpEntryPoint, 3 + name_size + interface_size));
+ vkd3d_spirv_build_word(stream, model);
+ vkd3d_spirv_build_word(stream, function_id);
+ vkd3d_spirv_build_string(stream, name, name_size);
+ for (i = 0; i < interface_size; ++i)
+ vkd3d_spirv_build_word(stream, interface_list[i]);
+}
+
+static void vkd3d_spirv_build_op_execution_mode(struct vkd3d_spirv_stream *stream,
+ uint32_t entry_point, SpvExecutionMode mode, const uint32_t *literals, unsigned int literal_count)
+{
+ vkd3d_spirv_build_op2v(stream, SpvOpExecutionMode, entry_point, mode, literals, literal_count);
+}
+
+static void vkd3d_spirv_build_op_name(struct vkd3d_spirv_builder *builder,
+ uint32_t id, const char *fmt, ...)
+{
+ struct vkd3d_spirv_stream *stream = &builder->debug_stream;
+ unsigned int name_size;
+ char name[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(name, ARRAY_SIZE(name), fmt, args);
+ name[ARRAY_SIZE(name) - 1] = '\0';
+ va_end(args);
+
+ name_size = vkd3d_spirv_string_word_count(name);
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(SpvOpName, 2 + name_size));
+ vkd3d_spirv_build_word(stream, id);
+ vkd3d_spirv_build_string(stream, name, name_size);
+}
+
+static void vkd3d_spirv_build_op_member_name(struct vkd3d_spirv_builder *builder,
+ uint32_t type_id, uint32_t member, const char *fmt, ...)
+{
+ struct vkd3d_spirv_stream *stream = &builder->debug_stream;
+ unsigned int name_size;
+ char name[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(name, ARRAY_SIZE(name), fmt, args);
+ name[ARRAY_SIZE(name) - 1] = '\0';
+ va_end(args);
+
+ name_size = vkd3d_spirv_string_word_count(name);
+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(SpvOpMemberName, 3 + name_size));
+ vkd3d_spirv_build_word(stream, type_id);
+ vkd3d_spirv_build_word(stream, member);
+ vkd3d_spirv_build_string(stream, name, name_size);
+}
+
+static void vkd3d_spirv_build_op_decorate(struct vkd3d_spirv_builder *builder,
+ uint32_t target_id, SpvDecoration decoration,
+ uint32_t *literals, uint32_t literal_count)
+{
+ vkd3d_spirv_build_op2v(&builder->annotation_stream,
+ SpvOpDecorate, target_id, decoration, literals, literal_count);
+}
+
+static void vkd3d_spirv_build_op_decorate1(struct vkd3d_spirv_builder *builder,
+ uint32_t target_id, SpvDecoration decoration, uint32_t operand0)
+{
+ return vkd3d_spirv_build_op_decorate(builder, target_id, decoration, &operand0, 1);
+}
+
+static void vkd3d_spirv_build_op_member_decorate(struct vkd3d_spirv_builder *builder,
+ uint32_t structure_type_id, uint32_t member_idx, SpvDecoration decoration,
+ uint32_t *literals, uint32_t literal_count)
+{
+ vkd3d_spirv_build_op3v(&builder->annotation_stream, SpvOpMemberDecorate,
+ structure_type_id, member_idx, decoration, literals, literal_count);
+}
+
+static void vkd3d_spirv_build_op_member_decorate1(struct vkd3d_spirv_builder *builder,
+ uint32_t structure_type_id, uint32_t member_idx, SpvDecoration decoration, uint32_t operand0)
+{
+ vkd3d_spirv_build_op_member_decorate(builder, structure_type_id, member_idx, decoration, &operand0, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_void(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_op_r(builder, &builder->global_stream, SpvOpTypeVoid);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_void(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_once(builder, &builder->type_void_id, vkd3d_spirv_build_op_type_void);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_bool(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_op_r(builder, &builder->global_stream, SpvOpTypeBool);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_bool(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_once(builder, &builder->type_bool_id, vkd3d_spirv_build_op_type_bool);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_float(struct vkd3d_spirv_builder *builder,
+ uint32_t width)
+{
+ return vkd3d_spirv_build_op_r1(builder, &builder->global_stream, SpvOpTypeFloat, width);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_float(struct vkd3d_spirv_builder *builder,
+ uint32_t width)
+{
+ return vkd3d_spirv_build_once1(builder, SpvOpTypeFloat, width, vkd3d_spirv_build_op_type_float);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_int(struct vkd3d_spirv_builder *builder,
+ uint32_t width, uint32_t signedness)
+{
+ return vkd3d_spirv_build_op_r2(builder, &builder->global_stream, SpvOpTypeInt, width, signedness);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_int(struct vkd3d_spirv_builder *builder,
+ uint32_t width, uint32_t signedness)
+{
+ return vkd3d_spirv_build_once2(builder, SpvOpTypeInt, width, signedness,
+ vkd3d_spirv_build_op_type_int);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_vector(struct vkd3d_spirv_builder *builder,
+ uint32_t component_type, uint32_t component_count)
+{
+ return vkd3d_spirv_build_op_r2(builder, &builder->global_stream,
+ SpvOpTypeVector, component_type, component_count);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_vector(struct vkd3d_spirv_builder *builder,
+ uint32_t component_type, uint32_t component_count)
+{
+ return vkd3d_spirv_build_once2(builder, SpvOpTypeVector, component_type, component_count,
+ vkd3d_spirv_build_op_type_vector);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_array(struct vkd3d_spirv_builder *builder,
+ uint32_t element_type, uint32_t length_id)
+{
+ return vkd3d_spirv_build_op_r2(builder, &builder->global_stream,
+ SpvOpTypeArray, element_type, length_id);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_array(struct vkd3d_spirv_builder *builder,
+ uint32_t element_type, uint32_t length_id)
+{
+ return vkd3d_spirv_build_once2(builder, SpvOpTypeArray, element_type, length_id,
+ vkd3d_spirv_build_op_type_array);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_runtime_array(struct vkd3d_spirv_builder *builder, uint32_t element_type)
+{
+ return vkd3d_spirv_build_op_r1(builder, &builder->global_stream, SpvOpTypeRuntimeArray, element_type);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_runtime_array(struct vkd3d_spirv_builder *builder, uint32_t element_type)
+{
+ return vkd3d_spirv_build_once1(builder, SpvOpTypeRuntimeArray,
+ element_type, vkd3d_spirv_build_op_type_runtime_array);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_struct(struct vkd3d_spirv_builder *builder,
+ uint32_t *members, unsigned int member_count)
+{
+ return vkd3d_spirv_build_op_rv(builder, &builder->global_stream,
+ SpvOpTypeStruct, members, member_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_sampler(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_op_r(builder, &builder->global_stream, SpvOpTypeSampler);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_sampler(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_once(builder, &builder->type_sampler_id, vkd3d_spirv_build_op_type_sampler);
+}
+
+/* Access qualifiers are not supported. */
+static uint32_t vkd3d_spirv_build_op_type_image(struct vkd3d_spirv_builder *builder,
+ uint32_t sampled_type_id, SpvDim dim, uint32_t depth, uint32_t arrayed,
+ uint32_t ms, uint32_t sampled, SpvImageFormat format)
+{
+ uint32_t operands[] = {sampled_type_id, dim, depth, arrayed, ms, sampled, format};
+ return vkd3d_spirv_build_op_rv(builder, &builder->global_stream,
+ SpvOpTypeImage, operands, ARRAY_SIZE(operands));
+}
+
+static uint32_t vkd3d_spirv_get_op_type_image(struct vkd3d_spirv_builder *builder,
+ uint32_t sampled_type_id, SpvDim dim, uint32_t depth, uint32_t arrayed,
+ uint32_t ms, uint32_t sampled, SpvImageFormat format)
+{
+ uint32_t operands[] = {sampled_type_id, dim, depth, arrayed, ms, sampled, format};
+ return vkd3d_spirv_build_once7(builder, SpvOpTypeImage, operands,
+ vkd3d_spirv_build_op_type_image);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_sampled_image(struct vkd3d_spirv_builder *builder,
+ uint32_t image_type_id)
+{
+ return vkd3d_spirv_build_op_r1(builder, &builder->global_stream,
+ SpvOpTypeSampledImage, image_type_id);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_sampled_image(struct vkd3d_spirv_builder *builder,
+ uint32_t image_type_id)
+{
+ return vkd3d_spirv_build_once1(builder, SpvOpTypeSampledImage, image_type_id,
+ vkd3d_spirv_build_op_type_sampled_image);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_function(struct vkd3d_spirv_builder *builder,
+ uint32_t return_type, const uint32_t *param_types, unsigned int param_count)
+{
+ return vkd3d_spirv_build_op_r1v(builder, &builder->global_stream,
+ SpvOpTypeFunction, return_type, param_types, param_count);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_function(struct vkd3d_spirv_builder *builder,
+ uint32_t return_type, const uint32_t *param_types, unsigned int param_count)
+{
+ return vkd3d_spirv_build_once1v(builder, SpvOpTypeFunction, return_type,
+ param_types, param_count, vkd3d_spirv_build_op_type_function);
+}
+
+static uint32_t vkd3d_spirv_build_op_type_pointer(struct vkd3d_spirv_builder *builder,
+ uint32_t storage_class, uint32_t type_id)
+{
+ return vkd3d_spirv_build_op_r2(builder, &builder->global_stream,
+ SpvOpTypePointer, storage_class, type_id);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_pointer(struct vkd3d_spirv_builder *builder,
+ uint32_t storage_class, uint32_t type_id)
+{
+ return vkd3d_spirv_build_once2(builder, SpvOpTypePointer, storage_class, type_id,
+ vkd3d_spirv_build_op_type_pointer);
+}
+
+/* Types larger than 32-bits are not supported. */
+static uint32_t vkd3d_spirv_build_op_constant(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t value)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->global_stream,
+ SpvOpConstant, result_type, value);
+}
+
+static uint32_t vkd3d_spirv_get_op_constant(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t value)
+{
+ return vkd3d_spirv_build_once2(builder, SpvOpConstant, result_type, value,
+ vkd3d_spirv_build_op_constant);
+}
+
+static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count)
+{
+ return vkd3d_spirv_build_op_trv(builder, &builder->global_stream,
+ SpvOpConstantComposite, result_type, constituents, constituent_count);
+}
+
+static uint32_t vkd3d_spirv_get_op_constant_composite(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count)
+{
+ return vkd3d_spirv_build_once1v(builder, SpvOpConstantComposite, result_type,
+ constituents, constituent_count, vkd3d_spirv_build_op_constant_composite);
+}
+
+static uint32_t vkd3d_spirv_build_op_spec_constant(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t value)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->global_stream,
+ SpvOpSpecConstant, result_type, value);
+}
+
+static uint32_t vkd3d_spirv_build_op_variable(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, uint32_t type_id, uint32_t storage_class, uint32_t initializer)
+{
+ return vkd3d_spirv_build_op_tr1v(builder, stream,
+ SpvOpVariable, type_id, storage_class, &initializer, !!initializer);
+}
+
+static uint32_t vkd3d_spirv_build_op_function(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t result_id, uint32_t function_control, uint32_t function_type)
+{
+ vkd3d_spirv_build_op3v(&builder->function_stream,
+ SpvOpFunction, result_type, result_id, function_control, &function_type, 1);
+ return result_id;
+}
+
+static uint32_t vkd3d_spirv_build_op_function_parameter(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type)
+{
+ return vkd3d_spirv_build_op_tr(builder, &builder->function_stream,
+ SpvOpFunctionParameter, result_type);
+}
+
+static void vkd3d_spirv_build_op_function_end(struct vkd3d_spirv_builder *builder)
+{
+ vkd3d_spirv_build_op(&builder->function_stream, SpvOpFunctionEnd);
+}
+
+static uint32_t vkd3d_spirv_build_op_function_call(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t function_id, const uint32_t *arguments, unsigned int argument_count)
+{
+ return vkd3d_spirv_build_op_tr1v(builder, &builder->function_stream,
+ SpvOpFunctionCall, result_type, function_id, arguments, argument_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_undef(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_spirv_stream *stream, uint32_t type_id)
+{
+ return vkd3d_spirv_build_op_tr(builder, stream, SpvOpUndef, type_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_access_chain(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t base_id, uint32_t *indexes, uint32_t index_count)
+{
+ return vkd3d_spirv_build_op_tr1v(builder, &builder->function_stream,
+ SpvOpAccessChain, result_type, base_id, indexes, index_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_access_chain1(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t base_id, uint32_t index)
+{
+ return vkd3d_spirv_build_op_access_chain(builder, result_type, base_id, &index, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_in_bounds_access_chain(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t base_id, uint32_t *indexes, uint32_t index_count)
+{
+ return vkd3d_spirv_build_op_tr1v(builder, &builder->function_stream,
+ SpvOpInBoundsAccessChain, result_type, base_id, indexes, index_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_in_bounds_access_chain1(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t base_id, uint32_t index)
+{
+ return vkd3d_spirv_build_op_in_bounds_access_chain(builder, result_type, base_id, &index, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_vector_shuffle(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t vector1_id, uint32_t vector2_id,
+ const uint32_t *components, uint32_t component_count)
+{
+ return vkd3d_spirv_build_op_tr2v(builder, &builder->function_stream, SpvOpVectorShuffle,
+ result_type, vector1_id, vector2_id, components, component_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_composite_construct(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count)
+{
+ return vkd3d_spirv_build_op_trv(builder, &builder->function_stream, SpvOpCompositeConstruct,
+ result_type, constituents, constituent_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_composite_extract(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t composite_id, const uint32_t *indexes, unsigned int index_count)
+{
+ return vkd3d_spirv_build_op_tr1v(builder, &builder->function_stream, SpvOpCompositeExtract,
+ result_type, composite_id, indexes, index_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_composite_extract1(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t composite_id, uint32_t index)
+{
+ return vkd3d_spirv_build_op_composite_extract(builder, result_type, composite_id, &index, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_composite_insert(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t object_id, uint32_t composite_id,
+ const uint32_t *indexes, unsigned int index_count)
+{
+ return vkd3d_spirv_build_op_tr2v(builder, &builder->function_stream, SpvOpCompositeInsert,
+ result_type, object_id, composite_id, indexes, index_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_composite_insert1(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t object_id, uint32_t composite_id, uint32_t index)
+{
+ return vkd3d_spirv_build_op_composite_insert(builder, result_type, object_id, composite_id, &index, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_load(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t pointer_id, uint32_t memory_access)
+{
+ if (!memory_access)
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpLoad,
+ result_type, pointer_id);
+ else
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpLoad,
+ result_type, pointer_id, memory_access);
+}
+
+static void vkd3d_spirv_build_op_store(struct vkd3d_spirv_builder *builder,
+ uint32_t pointer_id, uint32_t object_id, uint32_t memory_access)
+{
+ if (!memory_access)
+ return vkd3d_spirv_build_op2(&builder->function_stream, SpvOpStore,
+ pointer_id, object_id);
+ else
+ return vkd3d_spirv_build_op3(&builder->function_stream, SpvOpStore,
+ pointer_id, object_id, memory_access);
+}
+
+static void vkd3d_spirv_build_op_copy_memory(struct vkd3d_spirv_builder *builder,
+ uint32_t target_id, uint32_t source_id, uint32_t memory_access)
+{
+ if (!memory_access)
+ return vkd3d_spirv_build_op2(&builder->function_stream, SpvOpCopyMemory,
+ target_id, source_id);
+ else
+ return vkd3d_spirv_build_op3(&builder->function_stream, SpvOpCopyMemory,
+ target_id, source_id, memory_access);
+}
+
+static uint32_t vkd3d_spirv_build_op_select(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t condition_id, uint32_t object0_id, uint32_t object1_id)
+{
+ return vkd3d_spirv_build_op_tr3(builder, &builder->function_stream,
+ SpvOpSelect, result_type, condition_id, object0_id, object1_id);
+}
+
+static void vkd3d_spirv_build_op_kill(struct vkd3d_spirv_builder *builder)
+{
+ vkd3d_spirv_build_op(&builder->function_stream, SpvOpKill);
+}
+
+static void vkd3d_spirv_build_op_demote_to_helper_invocation(struct vkd3d_spirv_builder *builder)
+{
+ vkd3d_spirv_build_op(&builder->function_stream, SpvOpDemoteToHelperInvocationEXT);
+}
+
+static void vkd3d_spirv_build_op_return(struct vkd3d_spirv_builder *builder)
+{
+ vkd3d_spirv_build_op(&builder->function_stream, SpvOpReturn);
+}
+
+static uint32_t vkd3d_spirv_build_op_label(struct vkd3d_spirv_builder *builder,
+ uint32_t label_id)
+{
+ vkd3d_spirv_build_op1(&builder->function_stream, SpvOpLabel, label_id);
+ return label_id;
+}
+
+/* Loop control parameters are not supported. */
+static void vkd3d_spirv_build_op_loop_merge(struct vkd3d_spirv_builder *builder,
+ uint32_t merge_block, uint32_t continue_target, SpvLoopControlMask loop_control)
+{
+ vkd3d_spirv_build_op3(&builder->function_stream, SpvOpLoopMerge,
+ merge_block, continue_target, loop_control);
+}
+
+static void vkd3d_spirv_build_op_selection_merge(struct vkd3d_spirv_builder *builder,
+ uint32_t merge_block, uint32_t selection_control)
+{
+ vkd3d_spirv_build_op2(&builder->function_stream, SpvOpSelectionMerge,
+ merge_block, selection_control);
+}
+
+static void vkd3d_spirv_build_op_branch(struct vkd3d_spirv_builder *builder, uint32_t label)
+{
+ vkd3d_spirv_build_op1(&builder->function_stream, SpvOpBranch, label);
+}
+
+/* Branch weights are not supported. */
+static void vkd3d_spirv_build_op_branch_conditional(struct vkd3d_spirv_builder *builder,
+ uint32_t condition, uint32_t true_label, uint32_t false_label)
+{
+ vkd3d_spirv_build_op3(&builder->function_stream, SpvOpBranchConditional,
+ condition, true_label, false_label);
+}
+
+static void vkd3d_spirv_build_op_switch(struct vkd3d_spirv_builder *builder,
+ uint32_t selector, uint32_t default_label, uint32_t *targets, unsigned int target_count)
+{
+ vkd3d_spirv_build_op2v(&builder->function_stream, SpvOpSwitch,
+ selector, default_label, targets, 2 * target_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_iadd(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpIAdd, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_imul(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpIMul, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_udiv(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpUDiv, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_umod(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpUMod, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_isub(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpISub, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_fdiv(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpFDiv, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_fnegate(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
+ SpvOpFNegate, result_type, operand);
+}
+
+static uint32_t vkd3d_spirv_build_op_snegate(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
+ SpvOpSNegate, result_type, operand);
+}
+
+static uint32_t vkd3d_spirv_build_op_and(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpBitwiseAnd, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_shift_left_logical(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t base, uint32_t shift)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpShiftLeftLogical, result_type, base, shift);
+}
+
+static uint32_t vkd3d_spirv_build_op_shift_right_logical(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t base, uint32_t shift)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpShiftRightLogical, result_type, base, shift);
+}
+
+static uint32_t vkd3d_spirv_build_op_logical_and(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpLogicalAnd, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_uless_than(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpULessThan, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_uless_than_equal(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpULessThanEqual, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_convert_utof(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t unsigned_value)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
+ SpvOpConvertUToF, result_type, unsigned_value);
+}
+
+static uint32_t vkd3d_spirv_build_op_bitcast(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
+ SpvOpBitcast, result_type, operand);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_texel_pointer(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id, uint32_t coordinate_id, uint32_t sample_id)
+{
+ return vkd3d_spirv_build_op_tr3(builder, &builder->function_stream,
+ SpvOpImageTexelPointer, result_type, image_id, coordinate_id, sample_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_sampled_image(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id, uint32_t sampler_id)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpSampledImage, result_type, image_id, sampler_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_image(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t sampled_image_id)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
+ SpvOpImage, result_type, sampled_image_id);
+}
+
+static uint32_t vkd3d_spirv_build_image_instruction(struct vkd3d_spirv_builder *builder,
+ SpvOp op, uint32_t result_type, const uint32_t *operands, unsigned int operand_count,
+ uint32_t image_operands_mask, const uint32_t *image_operands, unsigned int image_operand_count)
+{
+ unsigned int index = 0, i;
+ uint32_t w[10];
+
+ assert(operand_count <= ARRAY_SIZE(w));
+ for (i = 0; i < operand_count; ++i)
+ w[index++] = operands[i];
+
+ if (image_operands_mask)
+ {
+ assert(index + 1 + image_operand_count <= ARRAY_SIZE(w));
+ w[index++] = image_operands_mask;
+ for (i = 0; i < image_operand_count; ++i)
+ w[index++] = image_operands[i];
+ }
+
+ return vkd3d_spirv_build_op_trv(builder, &builder->function_stream,
+ op, result_type, w, index);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_sample(struct vkd3d_spirv_builder *builder,
+ SpvOp op, uint32_t result_type, uint32_t sampled_image_id, uint32_t coordinate_id,
+ uint32_t image_operands_mask, const uint32_t *image_operands, unsigned int image_operand_count)
+{
+ const uint32_t operands[] = {sampled_image_id, coordinate_id};
+
+ if (op == SpvOpImageSampleExplicitLod)
+ assert(image_operands_mask & (SpvImageOperandsLodMask | SpvImageOperandsGradMask));
+ else
+ assert(op == SpvOpImageSampleImplicitLod);
+
+ return vkd3d_spirv_build_image_instruction(builder, op, result_type,
+ operands, ARRAY_SIZE(operands), image_operands_mask, image_operands, image_operand_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_sample_dref(struct vkd3d_spirv_builder *builder,
+ SpvOp op, uint32_t result_type, uint32_t sampled_image_id, uint32_t coordinate_id, uint32_t dref_id,
+ uint32_t image_operands_mask, const uint32_t *image_operands, unsigned int image_operand_count)
+{
+ const uint32_t operands[] = {sampled_image_id, coordinate_id, dref_id};
+
+ if (op == SpvOpImageSampleDrefExplicitLod)
+ assert(image_operands_mask & (SpvImageOperandsLodMask | SpvImageOperandsGradMask));
+ else
+ assert(op == SpvOpImageSampleDrefImplicitLod);
+
+ return vkd3d_spirv_build_image_instruction(builder, op, result_type,
+ operands, ARRAY_SIZE(operands), image_operands_mask, image_operands, image_operand_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_gather(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t sampled_image_id, uint32_t coordinate_id, uint32_t component_id,
+ uint32_t image_operands_mask, const uint32_t *image_operands, unsigned int image_operand_count)
+{
+ const uint32_t operands[] = {sampled_image_id, coordinate_id, component_id};
+ return vkd3d_spirv_build_image_instruction(builder, SpvOpImageGather, result_type,
+ operands, ARRAY_SIZE(operands), image_operands_mask, image_operands, image_operand_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_dref_gather(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t sampled_image_id, uint32_t coordinate_id, uint32_t dref_id,
+ uint32_t image_operands_mask, const uint32_t *image_operands, unsigned int image_operand_count)
+{
+ const uint32_t operands[] = {sampled_image_id, coordinate_id, dref_id};
+ return vkd3d_spirv_build_image_instruction(builder, SpvOpImageDrefGather, result_type,
+ operands, ARRAY_SIZE(operands), image_operands_mask, image_operands, image_operand_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_fetch(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id, uint32_t coordinate_id,
+ uint32_t image_operands_mask, const uint32_t *image_operands, unsigned int image_operand_count)
+{
+ const uint32_t operands[] = {image_id, coordinate_id};
+ return vkd3d_spirv_build_image_instruction(builder, SpvOpImageFetch, result_type,
+ operands, ARRAY_SIZE(operands), image_operands_mask, image_operands, image_operand_count);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_read(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id, uint32_t coordinate_id,
+ uint32_t image_operands_mask, const uint32_t *image_operands, unsigned int image_operand_count)
+{
+ const uint32_t operands[] = {image_id, coordinate_id};
+ return vkd3d_spirv_build_image_instruction(builder, SpvOpImageRead, result_type,
+ operands, ARRAY_SIZE(operands), image_operands_mask, image_operands, image_operand_count);
+}
+
+static void vkd3d_spirv_build_op_image_write(struct vkd3d_spirv_builder *builder,
+ uint32_t image_id, uint32_t coordinate_id, uint32_t texel_id,
+ uint32_t image_operands, const uint32_t *operands, unsigned int operand_count)
+{
+ if (image_operands)
+ FIXME("Image operands not supported.\n");
+
+ vkd3d_spirv_build_op3(&builder->function_stream, SpvOpImageWrite,
+ image_id, coordinate_id, texel_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_array_length(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t struct_id, uint32_t member_id)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpArrayLength, result_type, struct_id, member_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_query_size_lod(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id, uint32_t lod_id)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpImageQuerySizeLod, result_type, image_id, lod_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_query_size(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
+ SpvOpImageQuerySize, result_type, image_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_query_levels(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
+ SpvOpImageQueryLevels, result_type, image_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_query_samples(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id)
+{
+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream,
+ SpvOpImageQuerySamples, result_type, image_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_image_query_lod(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t image_id, uint32_t coordinate_id)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpImageQueryLod, result_type, image_id, coordinate_id);
+}
+
+static void vkd3d_spirv_build_op_emit_vertex(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_op(&builder->function_stream, SpvOpEmitVertex);
+}
+
+static void vkd3d_spirv_build_op_end_primitive(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_op(&builder->function_stream, SpvOpEndPrimitive);
+}
+
+static void vkd3d_spirv_build_op_control_barrier(struct vkd3d_spirv_builder *builder,
+ uint32_t execution_id, uint32_t memory_id, uint32_t memory_semantics_id)
+{
+ vkd3d_spirv_build_op3(&builder->function_stream,
+ SpvOpControlBarrier, execution_id, memory_id, memory_semantics_id);
+}
+
+static void vkd3d_spirv_build_op_memory_barrier(struct vkd3d_spirv_builder *builder,
+ uint32_t memory_id, uint32_t memory_semantics_id)
+{
+ vkd3d_spirv_build_op2(&builder->function_stream,
+ SpvOpMemoryBarrier, memory_id, memory_semantics_id);
+}
+
+static uint32_t vkd3d_spirv_build_op_glsl_std450_tr1(struct vkd3d_spirv_builder *builder,
+ enum GLSLstd450 op, uint32_t result_type, uint32_t operand)
+{
+ uint32_t id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
+ return vkd3d_spirv_build_op_ext_inst(builder, result_type, id, op, &operand, 1);
+}
+
+static uint32_t vkd3d_spirv_build_op_glsl_std450_fabs(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand)
+{
+ return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450FAbs, result_type, operand);
+}
+
+static uint32_t vkd3d_spirv_build_op_glsl_std450_sin(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand)
+{
+ return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450Sin, result_type, operand);
+}
+
+static uint32_t vkd3d_spirv_build_op_glsl_std450_cos(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand)
+{
+ return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450Cos, result_type, operand);
+}
+
+static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t x, uint32_t min, uint32_t max)
+{
+ uint32_t glsl_std450_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
+ uint32_t operands[] = {x, min, max};
+ return vkd3d_spirv_build_op_ext_inst(builder, result_type, glsl_std450_id,
+ GLSLstd450NClamp, operands, ARRAY_SIZE(operands));
+}
+
+static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder,
+ enum vkd3d_shader_component_type component_type, unsigned int component_count)
+{
+ uint32_t scalar_id;
+
+ if (component_count == 1)
+ {
+ switch (component_type)
+ {
+ case VKD3D_SHADER_COMPONENT_VOID:
+ return vkd3d_spirv_get_op_type_void(builder);
+ break;
+ case VKD3D_SHADER_COMPONENT_FLOAT:
+ return vkd3d_spirv_get_op_type_float(builder, 32);
+ break;
+ case VKD3D_SHADER_COMPONENT_INT:
+ case VKD3D_SHADER_COMPONENT_UINT:
+ return vkd3d_spirv_get_op_type_int(builder, 32, component_type == VKD3D_SHADER_COMPONENT_INT);
+ break;
+ case VKD3D_SHADER_COMPONENT_BOOL:
+ return vkd3d_spirv_get_op_type_bool(builder);
+ break;
+ default:
+ FIXME("Unhandled component type %#x.\n", component_type);
+ return 0;
+ }
+ }
+ else
+ {
+ assert(component_type != VKD3D_SHADER_COMPONENT_VOID);
+ scalar_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ return vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count);
+ }
+}
+
+static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const char *entry_point)
+{
+ vkd3d_spirv_stream_init(&builder->debug_stream);
+ vkd3d_spirv_stream_init(&builder->annotation_stream);
+ vkd3d_spirv_stream_init(&builder->global_stream);
+ vkd3d_spirv_stream_init(&builder->function_stream);
+ vkd3d_spirv_stream_init(&builder->execution_mode_stream);
+
+ vkd3d_spirv_stream_init(&builder->insertion_stream);
+ builder->insertion_location = ~(size_t)0;
+
+ builder->current_id = 1;
+
+ rb_init(&builder->declarations, vkd3d_spirv_declaration_compare);
+
+ builder->main_function_id = vkd3d_spirv_alloc_id(builder);
+ vkd3d_spirv_build_op_name(builder, builder->main_function_id, entry_point);
+}
+
+static void vkd3d_spirv_builder_begin_main_function(struct vkd3d_spirv_builder *builder)
+{
+ uint32_t void_id, function_type_id;
+
+ void_id = vkd3d_spirv_get_op_type_void(builder);
+ function_type_id = vkd3d_spirv_get_op_type_function(builder, void_id, NULL, 0);
+
+ vkd3d_spirv_build_op_function(builder, void_id,
+ builder->main_function_id, SpvFunctionControlMaskNone, function_type_id);
+ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
+ builder->main_function_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
+}
+
+static void vkd3d_spirv_builder_free(struct vkd3d_spirv_builder *builder)
+{
+ vkd3d_spirv_stream_free(&builder->debug_stream);
+ vkd3d_spirv_stream_free(&builder->annotation_stream);
+ vkd3d_spirv_stream_free(&builder->global_stream);
+ vkd3d_spirv_stream_free(&builder->function_stream);
+ vkd3d_spirv_stream_free(&builder->execution_mode_stream);
+
+ vkd3d_spirv_stream_free(&builder->insertion_stream);
+
+ rb_destroy(&builder->declarations, vkd3d_spirv_declaration_free, NULL);
+
+ vkd3d_free(builder->iface);
+}
+
+static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder,
+ struct vkd3d_shader_code *spirv, const char *entry_point)
+{
+ uint64_t capability_mask = builder->capability_mask;
+ struct vkd3d_spirv_stream stream;
+ uint32_t *code;
+ unsigned int i;
+ size_t size;
+
+ vkd3d_spirv_stream_init(&stream);
+
+ vkd3d_spirv_build_word(&stream, SpvMagicNumber);
+ vkd3d_spirv_build_word(&stream, VKD3D_SPIRV_VERSION);
+ vkd3d_spirv_build_word(&stream, VKD3D_SPIRV_GENERATOR_MAGIC);
+ vkd3d_spirv_build_word(&stream, builder->current_id); /* bound */
+ vkd3d_spirv_build_word(&stream, 0); /* schema, reserved */
+
+ /* capabilities */
+ for (i = 0; capability_mask; ++i)
+ {
+ if (capability_mask & 1)
+ vkd3d_spirv_build_op_capability(&stream, i);
+ capability_mask >>= 1;
+ }
+ if (builder->capability_draw_parameters)
+ vkd3d_spirv_build_op_capability(&stream, SpvCapabilityDrawParameters);
+ if (builder->capability_demote_to_helper_invocation)
+ vkd3d_spirv_build_op_capability(&stream, SpvCapabilityDemoteToHelperInvocationEXT);
+
+ /* extensions */
+ if (builder->capability_draw_parameters)
+ vkd3d_spirv_build_op_extension(&stream, "SPV_KHR_shader_draw_parameters");
+ if (builder->capability_demote_to_helper_invocation)
+ vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_demote_to_helper_invocation");
+
+ if (builder->ext_instr_set_glsl_450)
+ vkd3d_spirv_build_op_ext_inst_import(&stream, builder->ext_instr_set_glsl_450, "GLSL.std.450");
+
+ /* entry point declarations */
+ vkd3d_spirv_build_op_memory_model(&stream, SpvAddressingModelLogical, SpvMemoryModelGLSL450);
+ vkd3d_spirv_build_op_entry_point(&stream, builder->execution_model, builder->main_function_id,
+ entry_point, builder->iface, builder->iface_element_count);
+
+ /* execution mode declarations */
+ if (builder->invocation_count)
+ vkd3d_spirv_build_op_execution_mode(&builder->execution_mode_stream,
+ builder->main_function_id, SpvExecutionModeInvocations, &builder->invocation_count, 1);
+ vkd3d_spirv_stream_append(&stream, &builder->execution_mode_stream);
+
+ vkd3d_spirv_stream_append(&stream, &builder->debug_stream);
+ vkd3d_spirv_stream_append(&stream, &builder->annotation_stream);
+ vkd3d_spirv_stream_append(&stream, &builder->global_stream);
+ vkd3d_spirv_stream_append(&stream, &builder->function_stream);
+
+ if (!(code = vkd3d_calloc(stream.word_count, sizeof(*code))))
+ {
+ vkd3d_spirv_stream_free(&stream);
+ return false;
+ }
+
+ size = stream.word_count * sizeof(*code);
+ memcpy(code, stream.words, size);
+ vkd3d_spirv_stream_free(&stream);
+
+ spirv->code = code;
+ spirv->size = size;
+
+ return true;
+}
+
+static const struct vkd3d_spirv_resource_type
+{
+ enum vkd3d_shader_resource_type resource_type;
+
+ SpvDim dim;
+ uint32_t arrayed;
+ uint32_t ms;
+
+ unsigned int coordinate_component_count;
+ unsigned int offset_component_count;
+
+ SpvCapability capability;
+ SpvCapability uav_capability;
+}
+vkd3d_spirv_resource_type_table[] =
+{
+ {VKD3D_SHADER_RESOURCE_BUFFER, SpvDimBuffer, 0, 0, 1, 0,
+ SpvCapabilitySampledBuffer, SpvCapabilityImageBuffer},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_1D, SpvDim1D, 0, 0, 1, 1,
+ SpvCapabilitySampled1D, SpvCapabilityImage1D},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_2DMS, SpvDim2D, 0, 1, 2, 2},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_2D, SpvDim2D, 0, 0, 2, 2},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_3D, SpvDim3D, 0, 0, 3, 3},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_CUBE, SpvDimCube, 0, 0, 3, 0},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY, SpvDim1D, 1, 0, 2, 1,
+ SpvCapabilitySampled1D, SpvCapabilityImage1D},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY, SpvDim2D, 1, 0, 3, 2},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY, SpvDim2D, 1, 1, 3, 2},
+ {VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY, SpvDimCube, 1, 0, 4, 0,
+ SpvCapabilitySampledCubeArray, SpvCapabilityImageCubeArray},
+};
+
+static const struct vkd3d_spirv_resource_type *vkd3d_get_spirv_resource_type(
+ enum vkd3d_shader_resource_type resource_type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_spirv_resource_type_table); ++i)
+ {
+ const struct vkd3d_spirv_resource_type* current = &vkd3d_spirv_resource_type_table[i];
+
+ if (current->resource_type == resource_type)
+ return current;
+ }
+
+ FIXME("Unhandled resource type %#x.\n", resource_type);
+ return NULL;
+}
+
+struct vkd3d_symbol_register
+{
+ enum vkd3d_shader_register_type type;
+ unsigned int idx;
+};
+
+struct vkd3d_symbol_resource
+{
+ enum vkd3d_shader_register_type type;
+ unsigned int idx;
+};
+
+struct vkd3d_symbol_sampler
+{
+ unsigned int id;
+};
+
+struct vkd3d_symbol_combined_sampler
+{
+ enum vkd3d_shader_register_type resource_type;
+ unsigned int resource_id;
+ unsigned int sampler_space;
+ unsigned int sampler_index;
+};
+
+struct vkd3d_symbol_register_data
+{
+ SpvStorageClass storage_class;
+ uint32_t member_idx;
+ enum vkd3d_shader_component_type component_type;
+ unsigned int write_mask;
+ unsigned int structure_stride;
+ bool is_aggregate; /* An aggregate, i.e. a structure or an array. */
+ bool is_dynamically_indexed; /* If member_idx is a variable ID instead of a constant. */
+};
+
+struct vkd3d_symbol_resource_data
+{
+ unsigned int register_space;
+ unsigned int register_index;
+ enum vkd3d_shader_component_type sampled_type;
+ uint32_t type_id;
+ const struct vkd3d_spirv_resource_type *resource_type_info;
+ unsigned int structure_stride;
+ bool raw;
+ uint32_t uav_counter_id;
+};
+
+struct vkd3d_symbol_sampler_data
+{
+ unsigned int register_space;
+ unsigned int register_index;
+};
+
+struct vkd3d_symbol
+{
+ struct rb_entry entry;
+
+ enum
+ {
+ VKD3D_SYMBOL_REGISTER,
+ VKD3D_SYMBOL_RESOURCE,
+ VKD3D_SYMBOL_SAMPLER,
+ VKD3D_SYMBOL_COMBINED_SAMPLER,
+ } type;
+
+ union
+ {
+ struct vkd3d_symbol_register reg;
+ struct vkd3d_symbol_resource resource;
+ struct vkd3d_symbol_sampler sampler;
+ struct vkd3d_symbol_combined_sampler combined_sampler;
+ } key;
+
+ uint32_t id;
+ union
+ {
+ struct vkd3d_symbol_register_data reg;
+ struct vkd3d_symbol_resource_data resource;
+ struct vkd3d_symbol_sampler_data sampler;
+ } info;
+};
+
+static int vkd3d_symbol_compare(const void *key, const struct rb_entry *entry)
+{
+ const struct vkd3d_symbol *a = key;
+ const struct vkd3d_symbol *b = RB_ENTRY_VALUE(entry, const struct vkd3d_symbol, entry);
+
+ if (a->type != b->type)
+ return a->type - b->type;
+ return memcmp(&a->key, &b->key, sizeof(a->key));
+}
+
+static void vkd3d_symbol_free(struct rb_entry *entry, void *context)
+{
+ struct vkd3d_symbol *s = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
+
+ vkd3d_free(s);
+}
+
+static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol,
+ const struct vkd3d_shader_register *reg)
+{
+ symbol->type = VKD3D_SYMBOL_REGISTER;
+ memset(&symbol->key, 0, sizeof(symbol->key));
+ symbol->key.reg.type = reg->type;
+ if (vkd3d_shader_register_is_input(reg) && reg->idx[1].offset != ~0u)
+ symbol->key.reg.idx = reg->idx[1].offset;
+ else if (reg->type != VKD3DSPR_IMMCONSTBUFFER)
+ symbol->key.reg.idx = reg->idx[0].offset;
+}
+
+static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol,
+ uint32_t val_id, SpvStorageClass storage_class,
+ enum vkd3d_shader_component_type component_type, DWORD write_mask)
+{
+ symbol->id = val_id;
+ symbol->info.reg.storage_class = storage_class;
+ symbol->info.reg.member_idx = 0;
+ symbol->info.reg.component_type = component_type;
+ symbol->info.reg.write_mask = write_mask;
+ symbol->info.reg.structure_stride = 0;
+ symbol->info.reg.is_aggregate = false;
+ symbol->info.reg.is_dynamically_indexed = false;
+}
+
+static void vkd3d_symbol_make_resource(struct vkd3d_symbol *symbol,
+ const struct vkd3d_shader_register *reg)
+{
+ symbol->type = VKD3D_SYMBOL_RESOURCE;
+ memset(&symbol->key, 0, sizeof(symbol->key));
+ symbol->key.resource.type = reg->type;
+ symbol->key.resource.idx = reg->idx[0].offset;
+}
+
+static void vkd3d_symbol_make_sampler(struct vkd3d_symbol *symbol,
+ const struct vkd3d_shader_register *reg)
+{
+ symbol->type = VKD3D_SYMBOL_SAMPLER;
+ memset(&symbol->key, 0, sizeof(symbol->key));
+ symbol->key.sampler.id = reg->idx[0].offset;
+}
+
+static void vkd3d_symbol_make_combined_sampler(struct vkd3d_symbol *symbol,
+ const struct vkd3d_shader_register *resource_reg, unsigned int sampler_space, unsigned int sampler_index)
+{
+ symbol->type = VKD3D_SYMBOL_COMBINED_SAMPLER;
+ memset(&symbol->key, 0, sizeof(symbol->key));
+ symbol->key.combined_sampler.resource_type = resource_reg->type;
+ symbol->key.combined_sampler.resource_id = resource_reg->idx[0].offset;
+ symbol->key.combined_sampler.sampler_space = sampler_space;
+ symbol->key.combined_sampler.sampler_index = sampler_index;
+}
+
+static struct vkd3d_symbol *vkd3d_symbol_dup(const struct vkd3d_symbol *symbol)
+{
+ struct vkd3d_symbol *s;
+
+ if (!(s = vkd3d_malloc(sizeof(*s))))
+ return NULL;
+
+ return memcpy(s, symbol, sizeof(*s));
+}
+
+static const char *debug_vkd3d_symbol(const struct vkd3d_symbol *symbol)
+{
+ switch (symbol->type)
+ {
+ case VKD3D_SYMBOL_REGISTER:
+ return vkd3d_dbg_sprintf("register %#x, %u",
+ symbol->key.reg.type, symbol->key.reg.idx);
+ case VKD3D_SYMBOL_RESOURCE:
+ return vkd3d_dbg_sprintf("resource %#x, %u",
+ symbol->key.resource.type, symbol->key.resource.idx);
+ case VKD3D_SYMBOL_SAMPLER:
+ return vkd3d_dbg_sprintf("sampler %u",
+ symbol->key.sampler.id);
+ default:
+ return vkd3d_dbg_sprintf("type %#x", symbol->type);
+ }
+}
+
+struct vkd3d_if_cf_info
+{
+ size_t stream_location;
+ unsigned int id;
+ uint32_t merge_block_id;
+ uint32_t else_block_id;
+};
+
+struct vkd3d_loop_cf_info
+{
+ uint32_t header_block_id;
+ uint32_t continue_block_id;
+ uint32_t merge_block_id;
+};
+
+struct vkd3d_switch_cf_info
+{
+ size_t stream_location;
+ unsigned int id;
+ uint32_t selector_id;
+ uint32_t merge_block_id;
+ uint32_t default_block_id;
+ uint32_t *case_blocks;
+ size_t case_blocks_size;
+ unsigned int case_block_count;
+};
+
+struct vkd3d_control_flow_info
+{
+ union
+ {
+ struct vkd3d_if_cf_info if_;
+ struct vkd3d_loop_cf_info loop;
+ struct vkd3d_switch_cf_info switch_;
+ } u;
+
+ enum
+ {
+ VKD3D_BLOCK_IF,
+ VKD3D_BLOCK_LOOP,
+ VKD3D_BLOCK_SWITCH,
+ } current_block;
+ bool inside_block;
+};
+
+struct vkd3d_push_constant_buffer_binding
+{
+ struct vkd3d_shader_register reg;
+ struct vkd3d_shader_push_constant_buffer pc;
+ unsigned int size;
+};
+
+struct vkd3d_shader_phase
+{
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER type;
+ unsigned int idx;
+ unsigned int instance_count;
+ uint32_t function_id;
+ uint32_t instance_id;
+ size_t function_location;
+};
+
+struct vkd3d_shader_spec_constant
+{
+ enum vkd3d_shader_parameter_name name;
+ uint32_t id;
+};
+
+struct vkd3d_hull_shader_variables
+{
+ uint32_t tess_level_outer_id;
+ uint32_t tess_level_inner_id;
+ uint32_t patch_constants_id;
+};
+
+struct vkd3d_dxbc_compiler
+{
+ struct vkd3d_spirv_builder spirv_builder;
+
+ struct vkd3d_shader_message_context *message_context;
+ bool failed;
+
+ bool strip_debug;
+ bool ssbo_uavs;
+
+ struct rb_tree symbol_table;
+ uint32_t temp_id;
+ unsigned int temp_count;
+ struct vkd3d_hull_shader_variables hs;
+ uint32_t sample_positions_id;
+
+ enum vkd3d_shader_type shader_type;
+
+ unsigned int branch_id;
+ unsigned int loop_id;
+ unsigned int switch_id;
+ unsigned int control_flow_depth;
+ struct vkd3d_control_flow_info *control_flow_info;
+ size_t control_flow_info_size;
+
+ struct vkd3d_shader_interface_info shader_interface;
+ struct vkd3d_push_constant_buffer_binding *push_constants;
+ const struct vkd3d_shader_spirv_target_info *spirv_target_info;
+
+ bool after_declarations_section;
+ const struct vkd3d_shader_signature *input_signature;
+ const struct vkd3d_shader_signature *output_signature;
+ const struct vkd3d_shader_signature *patch_constant_signature;
+ const struct vkd3d_shader_transform_feedback_info *xfb_info;
+ struct vkd3d_shader_output_info
+ {
+ uint32_t id;
+ enum vkd3d_shader_component_type component_type;
+ uint32_t array_element_mask;
+ } *output_info;
+ uint32_t private_output_variable[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */
+ uint32_t private_output_variable_array_idx[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */
+ uint32_t private_output_variable_write_mask[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */
+ uint32_t epilogue_function_id;
+
+ uint32_t binding_idx;
+
+ const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info;
+ unsigned int input_control_point_count;
+ unsigned int output_control_point_count;
+ bool use_vocp;
+
+ unsigned int shader_phase_count;
+ struct vkd3d_shader_phase *shader_phases;
+ size_t shader_phases_size;
+
+ uint32_t current_spec_constant_id;
+ unsigned int spec_constant_count;
+ struct vkd3d_shader_spec_constant *spec_constants;
+ size_t spec_constants_size;
+ enum vkd3d_shader_compile_option_formatting_flags formatting;
+};
+
+static bool is_control_point_phase(const struct vkd3d_shader_phase *phase)
+{
+ return phase && phase->type == VKD3DSIH_HS_CONTROL_POINT_PHASE;
+}
+
+static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_compiler *compiler);
+
+static const char *vkd3d_dxbc_compiler_get_entry_point_name(const struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
+
+ return info && info->entry_point ? info->entry_point : "main";
+}
+
+struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
+ const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
+ const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info,
+ struct vkd3d_shader_message_context *message_context)
+{
+ const struct vkd3d_shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature;
+ const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature;
+ const struct vkd3d_shader_interface_info *shader_interface;
+ const struct vkd3d_shader_spirv_target_info *target_info;
+ struct vkd3d_dxbc_compiler *compiler;
+ unsigned int max_element_count;
+ unsigned int i;
+
+ if (!(compiler = vkd3d_malloc(sizeof(*compiler))))
+ return NULL;
+
+ memset(compiler, 0, sizeof(*compiler));
+ compiler->message_context = message_context;
+
+ if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO)))
+ {
+ switch (target_info->environment)
+ {
+ case VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5:
+ case VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0:
+ break;
+ default:
+ WARN("Invalid target environment %#x.\n", target_info->environment);
+ vkd3d_free(compiler);
+ return NULL;
+ }
+
+ compiler->spirv_target_info = target_info;
+ }
+
+ max_element_count = max(output_signature->element_count, patch_constant_signature->element_count);
+ if (!(compiler->output_info = vkd3d_calloc(max_element_count, sizeof(*compiler->output_info))))
+ {
+ vkd3d_free(compiler);
+ return NULL;
+ }
+
+ vkd3d_spirv_builder_init(&compiler->spirv_builder, vkd3d_dxbc_compiler_get_entry_point_name(compiler));
+
+ compiler->formatting = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT
+ | VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER;
+
+ for (i = 0; i < compile_info->option_count; ++i)
+ {
+ const struct vkd3d_shader_compile_option *option = &compile_info->options[i];
+
+ switch (option->name)
+ {
+ case VKD3D_SHADER_COMPILE_OPTION_STRIP_DEBUG:
+ compiler->strip_debug = !!option->value;
+ break;
+
+ case VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV:
+ if (option->value == VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_TEXEL_BUFFER)
+ compiler->ssbo_uavs = false;
+ else if (option->value == VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_BUFFER)
+ compiler->ssbo_uavs = true;
+ else
+ WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name);
+ break;
+
+ case VKD3D_SHADER_COMPILE_OPTION_FORMATTING:
+ compiler->formatting = option->value;
+ break;
+
+ default:
+ WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value);
+ break;
+ }
+ }
+
+ rb_init(&compiler->symbol_table, vkd3d_symbol_compare);
+
+ compiler->shader_type = shader_version->type;
+
+ compiler->input_signature = &shader_desc->input_signature;
+ compiler->output_signature = &shader_desc->output_signature;
+ compiler->patch_constant_signature = &shader_desc->patch_constant_signature;
+
+ if ((shader_interface = vkd3d_find_struct(compile_info->next, INTERFACE_INFO)))
+ {
+ compiler->xfb_info = vkd3d_find_struct(compile_info->next, TRANSFORM_FEEDBACK_INFO);
+
+ compiler->shader_interface = *shader_interface;
+ if (shader_interface->push_constant_buffer_count)
+ {
+ if (!(compiler->push_constants = vkd3d_calloc(shader_interface->push_constant_buffer_count,
+ sizeof(*compiler->push_constants))))
+ {
+ vkd3d_dxbc_compiler_destroy(compiler);
+ return NULL;
+ }
+ for (i = 0; i < shader_interface->push_constant_buffer_count; ++i)
+ compiler->push_constants[i].pc = shader_interface->push_constant_buffers[i];
+ }
+ }
+
+ compiler->scan_descriptor_info = scan_descriptor_info;
+
+ vkd3d_dxbc_compiler_emit_initial_declarations(compiler);
+
+ return compiler;
+}
+
+static bool vkd3d_dxbc_compiler_use_storage_buffer(const struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_symbol_resource_data *resource)
+{
+ return compiler->ssbo_uavs && resource->resource_type_info->resource_type == VKD3D_SHADER_RESOURCE_BUFFER;
+}
+
+static enum vkd3d_shader_spirv_environment vkd3d_dxbc_compiler_get_target_environment(
+ const struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
+
+ return info ? info->environment : VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0;
+}
+
+static bool vkd3d_dxbc_compiler_is_opengl_target(const struct vkd3d_dxbc_compiler *compiler)
+{
+ return vkd3d_dxbc_compiler_get_target_environment(compiler) == VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5;
+}
+
+static bool vkd3d_dxbc_compiler_is_target_extension_supported(const struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_spirv_extension extension)
+{
+ const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
+ unsigned int i;
+
+ for (i = 0; info && i < info->extension_count; ++i)
+ {
+ if (info->extensions[i] == extension)
+ return true;
+ }
+
+ return false;
+}
+
+static bool vkd3d_dxbc_compiler_check_shader_visibility(const struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_visibility visibility)
+{
+ switch (visibility)
+ {
+ case VKD3D_SHADER_VISIBILITY_ALL:
+ return true;
+ case VKD3D_SHADER_VISIBILITY_VERTEX:
+ return compiler->shader_type == VKD3D_SHADER_TYPE_VERTEX;
+ case VKD3D_SHADER_VISIBILITY_HULL:
+ return compiler->shader_type == VKD3D_SHADER_TYPE_HULL;
+ case VKD3D_SHADER_VISIBILITY_DOMAIN:
+ return compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN;
+ case VKD3D_SHADER_VISIBILITY_GEOMETRY:
+ return compiler->shader_type == VKD3D_SHADER_TYPE_GEOMETRY;
+ case VKD3D_SHADER_VISIBILITY_PIXEL:
+ return compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL;
+ case VKD3D_SHADER_VISIBILITY_COMPUTE:
+ return compiler->shader_type == VKD3D_SHADER_TYPE_COMPUTE;
+ default:
+ ERR("Invalid shader visibility %#x.\n", visibility);
+ return false;
+ }
+}
+
+static struct vkd3d_push_constant_buffer_binding *vkd3d_dxbc_compiler_find_push_constant_buffer(
+ const struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_constant_buffer *cb)
+{
+ unsigned int register_space = cb->register_space;
+ unsigned int reg_idx = cb->register_index;
+ unsigned int i;
+
+ for (i = 0; i < compiler->shader_interface.push_constant_buffer_count; ++i)
+ {
+ struct vkd3d_push_constant_buffer_binding *current = &compiler->push_constants[i];
+
+ if (!vkd3d_dxbc_compiler_check_shader_visibility(compiler, current->pc.shader_visibility))
+ continue;
+
+ if (current->pc.register_space == register_space && current->pc.register_index == reg_idx)
+ return current;
+ }
+
+ return NULL;
+}
+
+static bool vkd3d_dxbc_compiler_has_combined_sampler(const struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_resource *resource, const struct vkd3d_shader_sampler *sampler)
+{
+ const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface;
+ const struct vkd3d_shader_combined_resource_sampler *combined_sampler;
+ unsigned int i;
+
+ if (!shader_interface->combined_sampler_count)
+ return false;
+
+ if (resource && resource->reg.reg.type == VKD3DSPR_UAV)
+ return false;
+
+ for (i = 0; i < shader_interface->combined_sampler_count; ++i)
+ {
+ combined_sampler = &shader_interface->combined_samplers[i];
+
+ if (!vkd3d_dxbc_compiler_check_shader_visibility(compiler, combined_sampler->shader_visibility))
+ continue;
+
+ if ((!resource || (combined_sampler->resource_space == resource->register_space
+ && combined_sampler->resource_index == resource->register_index))
+ && (!sampler || (combined_sampler->sampler_space == sampler->register_space
+ && combined_sampler->sampler_index == sampler->register_index)))
+ return true;
+ }
+
+ return false;
+}
+
+static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_dxbc_compiler_error(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_error error, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vkd3d_shader_verror(compiler->message_context, error, format, args);
+ va_end(args);
+ compiler->failed = true;
+}
+
+static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding(
+ struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, unsigned int register_space,
+ unsigned int reg_idx, enum vkd3d_shader_resource_type resource_type, bool is_uav_counter)
+{
+ const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface;
+ enum vkd3d_shader_descriptor_type descriptor_type;
+ enum vkd3d_shader_binding_flag resource_type_flag;
+ struct vkd3d_shader_descriptor_binding binding;
+ unsigned int i;
+
+ if (reg->type == VKD3DSPR_CONSTBUFFER)
+ descriptor_type = VKD3D_SHADER_DESCRIPTOR_TYPE_CBV;
+ else if (reg->type == VKD3DSPR_RESOURCE)
+ descriptor_type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
+ else if (reg->type == VKD3DSPR_UAV)
+ descriptor_type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
+ else if (reg->type == VKD3DSPR_SAMPLER)
+ descriptor_type = VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER;
+ else
+ {
+ FIXME("Unhandled register type %#x.\n", reg->type);
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE,
+ "Encountered invalid/unhandled register type %#x.", reg->type);
+ goto done;
+ }
+
+ resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER
+ ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE;
+
+ if (is_uav_counter)
+ {
+ assert(descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV);
+ for (i = 0; i < shader_interface->uav_counter_count; ++i)
+ {
+ const struct vkd3d_shader_uav_counter_binding *current = &shader_interface->uav_counters[i];
+
+ if (!vkd3d_dxbc_compiler_check_shader_visibility(compiler, current->shader_visibility))
+ continue;
+
+ if (current->register_space != register_space || current->register_index != reg_idx)
+ continue;
+
+ if (current->offset)
+ {
+ FIXME("Atomic counter offsets are not supported yet.\n");
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING,
+ "Descriptor binding for UAV counter %u, space %u has unsupported ‘offset’ %u.",
+ reg_idx, register_space, current->offset);
+ }
+
+ if (current->binding.count != 1)
+ {
+ FIXME("Descriptor arrays are not supported.\n");
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING,
+ "Descriptor binding for UAV counter %u, space %u has unsupported ‘count’ %u.",
+ reg_idx, register_space, current->binding.count);
+ }
+
+ return current->binding;
+ }
+ if (shader_interface->uav_counter_count)
+ {
+ FIXME("Could not find descriptor binding for UAV counter %u, space %u.\n", reg_idx, register_space);
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND,
+ "Could not find descriptor binding for UAV counter %u, space %u.", reg_idx, register_space);
+ }
+ }
+ else
+ {
+ for (i = 0; i < shader_interface->binding_count; ++i)
+ {
+ const struct vkd3d_shader_resource_binding *current = &shader_interface->bindings[i];
+
+ if (!(current->flags & resource_type_flag))
+ continue;
+
+ if (!vkd3d_dxbc_compiler_check_shader_visibility(compiler, current->shader_visibility))
+ continue;
+
+ if (current->type != descriptor_type || current->register_space != register_space
+ || current->register_index != reg_idx)
+ continue;
+
+ if (current->binding.count != 1)
+ {
+ FIXME("Descriptor arrays are not supported.\n");
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING,
+ "Descriptor binding for type %#x, space %u, register %u, "
+ "shader type %#x has unsupported ‘count’ %u.",
+ descriptor_type, register_space, reg_idx, compiler->shader_type, current->binding.count);
+ }
+
+ return current->binding;
+ }
+ if (shader_interface->binding_count)
+ {
+ FIXME("Could not find binding for type %#x, space %u, register %u, shader type %#x.\n",
+ descriptor_type, register_space, reg_idx, compiler->shader_type);
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND,
+ "Could not find descriptor binding for type %#x, space %u, register %u, shader type %#x.",
+ descriptor_type, register_space, reg_idx, compiler->shader_type);
+ }
+ }
+
+done:
+ binding.set = 0;
+ binding.count = 1;
+ binding.binding = compiler->binding_idx++;
+ return binding;
+}
+
+static void vkd3d_dxbc_compiler_emit_descriptor_binding(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t variable_id, const struct vkd3d_shader_descriptor_binding *binding)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ vkd3d_spirv_build_op_decorate1(builder, variable_id, SpvDecorationDescriptorSet, binding->set);
+ vkd3d_spirv_build_op_decorate1(builder, variable_id, SpvDecorationBinding, binding->binding);
+}
+
+static void vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t variable_id, const struct vkd3d_shader_register *reg, unsigned int register_space,
+ unsigned int register_index, enum vkd3d_shader_resource_type resource_type, bool is_uav_counter)
+{
+ struct vkd3d_shader_descriptor_binding binding;
+
+ binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, register_space,
+ register_index, resource_type, is_uav_counter);
+ vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, variable_id, &binding);
+}
+
+static void vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_symbol *symbol)
+{
+ struct vkd3d_symbol *s;
+
+ s = vkd3d_symbol_dup(symbol);
+ if (rb_put(&compiler->symbol_table, s, &s->entry) == -1)
+ {
+ ERR("Failed to insert symbol entry (%s).\n", debug_vkd3d_symbol(symbol));
+ vkd3d_free(s);
+ }
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_constant(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_component_type component_type, unsigned int component_count, const uint32_t *values)
+{
+ uint32_t type_id, scalar_type_id, component_ids[VKD3D_VEC4_SIZE];
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int i;
+
+ assert(0 < component_count && component_count <= VKD3D_VEC4_SIZE);
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+
+ switch (component_type)
+ {
+ case VKD3D_SHADER_COMPONENT_UINT:
+ case VKD3D_SHADER_COMPONENT_INT:
+ case VKD3D_SHADER_COMPONENT_FLOAT:
+ break;
+ default:
+ FIXME("Unhandled component_type %#x.\n", component_type);
+ return vkd3d_spirv_build_op_undef(builder, &builder->global_stream, type_id);
+ }
+
+ if (component_count == 1)
+ {
+ return vkd3d_spirv_get_op_constant(builder, type_id, *values);
+ }
+ else
+ {
+ scalar_type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ for (i = 0; i < component_count; ++i)
+ component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]);
+ return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count);
+ }
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_constant_uint(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t value)
+{
+ return vkd3d_dxbc_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_UINT, 1, &value);
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_constant_float(struct vkd3d_dxbc_compiler *compiler,
+ float value)
+{
+ return vkd3d_dxbc_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_FLOAT, 1, (uint32_t *)&value);
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_constant_vector(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_component_type component_type, unsigned int component_count, uint32_t value)
+{
+ const uint32_t values[] = {value, value, value, value};
+ return vkd3d_dxbc_compiler_get_constant(compiler, component_type, component_count, values);
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_constant_uint_vector(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t value, unsigned int component_count)
+{
+ return vkd3d_dxbc_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, component_count, value);
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_constant_float_vector(struct vkd3d_dxbc_compiler *compiler,
+ float value, unsigned int component_count)
+{
+ const float values[] = {value, value, value, value};
+ return vkd3d_dxbc_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_FLOAT,
+ component_count, (const uint32_t *)values);
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_type_id_for_reg(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, DWORD write_mask)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ return vkd3d_spirv_get_type_id(builder,
+ vkd3d_component_type_from_data_type(reg->data_type),
+ vkd3d_write_mask_component_count(write_mask));
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_type_id_for_dst(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst)
+{
+ return vkd3d_dxbc_compiler_get_type_id_for_reg(compiler, &dst->reg, dst->write_mask);
+}
+
+static bool vkd3d_dxbc_compiler_get_register_name(char *buffer, unsigned int buffer_size,
+ const struct vkd3d_shader_register *reg)
+{
+ unsigned int idx;
+
+ idx = reg->idx[1].offset != ~0u ? reg->idx[1].offset : reg->idx[0].offset;
+ switch (reg->type)
+ {
+ case VKD3DSPR_RESOURCE:
+ snprintf(buffer, buffer_size, "t%u", reg->idx[0].offset);
+ break;
+ case VKD3DSPR_UAV:
+ snprintf(buffer, buffer_size, "u%u", reg->idx[0].offset);
+ break;
+ case VKD3DSPR_SAMPLER:
+ snprintf(buffer, buffer_size, "s%u", reg->idx[0].offset);
+ break;
+ case VKD3DSPR_CONSTBUFFER:
+ snprintf(buffer, buffer_size, "cb%u_%u", reg->idx[0].offset, reg->idx[1].offset);
+ break;
+ case VKD3DSPR_INPUT:
+ snprintf(buffer, buffer_size, "v%u", idx);
+ break;
+ case VKD3DSPR_INCONTROLPOINT:
+ snprintf(buffer, buffer_size, "vicp%u", idx);
+ break;
+ case VKD3DSPR_OUTPUT:
+ case VKD3DSPR_COLOROUT:
+ snprintf(buffer, buffer_size, "o%u", idx);
+ break;
+ case VKD3DSPR_DEPTHOUT:
+ case VKD3DSPR_DEPTHOUTGE:
+ case VKD3DSPR_DEPTHOUTLE:
+ snprintf(buffer, buffer_size, "oDepth");
+ break;
+ case VKD3DSPR_FORKINSTID:
+ snprintf(buffer, buffer_size, "vForkInstanceId");
+ break;
+ case VKD3DSPR_JOININSTID:
+ snprintf(buffer, buffer_size, "vJoinInstanceId");
+ break;
+ case VKD3DSPR_GSINSTID:
+ snprintf(buffer, buffer_size, "vGSInstanceID");
+ break;
+ case VKD3DSPR_PATCHCONST:
+ snprintf(buffer, buffer_size, "vpc%u", idx);
+ break;
+ case VKD3DSPR_TESSCOORD:
+ snprintf(buffer, buffer_size, "vDomainLocation");
+ break;
+ case VKD3DSPR_THREADID:
+ snprintf(buffer, buffer_size, "vThreadID");
+ break;
+ case VKD3DSPR_LOCALTHREADID:
+ snprintf(buffer, buffer_size, "vThreadIDInGroup");
+ break;
+ case VKD3DSPR_LOCALTHREADINDEX:
+ snprintf(buffer, buffer_size, "vThreadIDInGroupFlattened");
+ break;
+ case VKD3DSPR_THREADGROUPID:
+ snprintf(buffer, buffer_size, "vThreadGroupID");
+ break;
+ case VKD3DSPR_GROUPSHAREDMEM:
+ snprintf(buffer, buffer_size, "g%u", reg->idx[0].offset);
+ break;
+ case VKD3DSPR_IDXTEMP:
+ snprintf(buffer, buffer_size, "x%u", idx);
+ break;
+ case VKD3DSPR_COVERAGE:
+ snprintf(buffer, buffer_size, "vCoverage");
+ break;
+ case VKD3DSPR_SAMPLEMASK:
+ snprintf(buffer, buffer_size, "oMask");
+ break;
+ case VKD3DSPR_OUTPOINTID:
+ case VKD3DSPR_PRIMID:
+ /* SPIRV-Tools disassembler generates names for SPIR-V built-ins. */
+ return false;
+ default:
+ FIXME("Unhandled register %#x.\n", reg->type);
+ snprintf(buffer, buffer_size, "unrecognized_%#x", reg->type);
+ return false;
+ }
+
+ return true;
+}
+
+static void vkd3d_dxbc_compiler_emit_register_debug_name(struct vkd3d_spirv_builder *builder,
+ uint32_t id, const struct vkd3d_shader_register *reg)
+{
+ char debug_name[256];
+ if (vkd3d_dxbc_compiler_get_register_name(debug_name, ARRAY_SIZE(debug_name), reg))
+ vkd3d_spirv_build_op_name(builder, id, "%s", debug_name);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_variable(struct vkd3d_dxbc_compiler *compiler,
+ struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class,
+ enum vkd3d_shader_component_type component_type, unsigned int component_count)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, ptr_type_id;
+
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
+ return vkd3d_spirv_build_op_variable(builder, stream, ptr_type_id, storage_class, 0);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_array_variable(struct vkd3d_dxbc_compiler *compiler,
+ struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class,
+ enum vkd3d_shader_component_type component_type, unsigned int component_count, unsigned int array_length)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, length_id, ptr_type_id;
+
+ if (!array_length)
+ return vkd3d_dxbc_compiler_emit_variable(compiler,
+ stream, storage_class, component_type, component_count);
+
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, array_length);
+ type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
+ return vkd3d_spirv_build_op_variable(builder, stream, ptr_type_id, storage_class, 0);
+}
+
+static const struct vkd3d_shader_parameter *vkd3d_dxbc_compiler_get_shader_parameter(
+ struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_parameter_name name)
+{
+ const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
+ unsigned int i;
+
+ for (i = 0; info && i < info->parameter_count; ++i)
+ {
+ if (info->parameters[i].name == name)
+ return &info->parameters[i];
+ }
+
+ return NULL;
+}
+
+static const struct vkd3d_spec_constant_info
+{
+ enum vkd3d_shader_parameter_name name;
+ uint32_t default_value;
+ const char *debug_name;
+}
+vkd3d_shader_parameters[] =
+{
+ {VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, 1, "sample_count"},
+};
+
+static const struct vkd3d_spec_constant_info *get_spec_constant_info(enum vkd3d_shader_parameter_name name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_shader_parameters); ++i)
+ {
+ if (vkd3d_shader_parameters[i].name == name)
+ return &vkd3d_shader_parameters[i];
+ }
+
+ FIXME("Unhandled parameter name %#x.\n", name);
+ return NULL;
+}
+
+static uint32_t vkd3d_dxbc_compiler_alloc_spec_constant_id(struct vkd3d_dxbc_compiler *compiler)
+{
+ if (!compiler->current_spec_constant_id)
+ {
+ const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
+ unsigned int i, id = 0;
+
+ for (i = 0; info && i < info->parameter_count; ++i)
+ {
+ const struct vkd3d_shader_parameter *current = &info->parameters[i];
+
+ if (current->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT)
+ id = max(current->u.specialization_constant.id + 1, id);
+ }
+
+ compiler->current_spec_constant_id = id;
+ }
+
+ return compiler->current_spec_constant_id++;
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_spec_constant(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_parameter_name name, uint32_t spec_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_spec_constant_info *info;
+ uint32_t type_id, id, default_value;
+
+ info = get_spec_constant_info(name);
+ default_value = info ? info->default_value : 0;
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ id = vkd3d_spirv_build_op_spec_constant(builder, type_id, default_value);
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationSpecId, spec_id);
+
+ if (info)
+ vkd3d_spirv_build_op_name(builder, id, "%s", info->debug_name);
+
+ if (vkd3d_array_reserve((void **)&compiler->spec_constants, &compiler->spec_constants_size,
+ compiler->spec_constant_count + 1, sizeof(*compiler->spec_constants)))
+ {
+ struct vkd3d_shader_spec_constant *constant = &compiler->spec_constants[compiler->spec_constant_count++];
+ constant->name = name;
+ constant->id = id;
+ }
+
+ return id;
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_spec_constant(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_parameter_name name, uint32_t spec_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < compiler->spec_constant_count; ++i)
+ {
+ if (compiler->spec_constants[i].name == name)
+ return compiler->spec_constants[i].id;
+ }
+
+ return vkd3d_dxbc_compiler_emit_spec_constant(compiler, name, spec_id);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_uint_shader_parameter(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_parameter_name name)
+{
+ const struct vkd3d_shader_parameter *parameter;
+
+ if (!(parameter = vkd3d_dxbc_compiler_get_shader_parameter(compiler, name)))
+ {
+ WARN("Unresolved shader parameter %#x.\n", name);
+ goto default_parameter;
+ }
+
+ if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT)
+ return vkd3d_dxbc_compiler_get_constant_uint(compiler, parameter->u.immediate_constant.u.u32);
+ if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT)
+ return vkd3d_dxbc_compiler_get_spec_constant(compiler, name, parameter->u.specialization_constant.id);
+
+ FIXME("Unhandled parameter type %#x.\n", parameter->type);
+
+default_parameter:
+ return vkd3d_dxbc_compiler_get_spec_constant(compiler,
+ name, vkd3d_dxbc_compiler_alloc_spec_constant_id(compiler));
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_construct_vector(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_component_type component_type, unsigned int component_count,
+ uint32_t val_id, unsigned int val_component_idx, unsigned int val_component_count)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t components[VKD3D_VEC4_SIZE];
+ uint32_t type_id, result_id;
+ unsigned int i;
+
+ assert(val_component_idx < val_component_count);
+
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+ if (val_component_count == 1)
+ {
+ for (i = 0; i < component_count; ++i)
+ components[i] = val_id;
+ result_id = vkd3d_spirv_build_op_composite_construct(builder,
+ type_id, components, component_count);
+ }
+ else
+ {
+ for (i = 0; i < component_count; ++i)
+ components[i] = val_component_idx;
+ result_id = vkd3d_spirv_build_op_vector_shuffle(builder,
+ type_id, val_id, val_id, components, component_count);
+ }
+ return result_id;
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_load_src(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_src_param *src, DWORD write_mask);
+
+static uint32_t vkd3d_dxbc_compiler_emit_register_addressing(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register_index *reg_index)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, addr_id;
+
+ if (!reg_index->rel_addr)
+ return vkd3d_dxbc_compiler_get_constant_uint(compiler, reg_index->offset);
+
+ addr_id = vkd3d_dxbc_compiler_emit_load_src(compiler, reg_index->rel_addr, VKD3DSP_WRITEMASK_0);
+ if (reg_index->offset)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ addr_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ addr_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, reg_index->offset));
+ }
+ return addr_id;
+}
+
+struct vkd3d_shader_register_info
+{
+ uint32_t id;
+ SpvStorageClass storage_class;
+ enum vkd3d_shader_component_type component_type;
+ unsigned int write_mask;
+ uint32_t member_idx;
+ unsigned int structure_stride;
+ bool is_aggregate;
+ bool is_dynamically_indexed;
+};
+
+static bool vkd3d_dxbc_compiler_get_register_info(const struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, struct vkd3d_shader_register_info *register_info)
+{
+ struct vkd3d_symbol reg_symbol, *symbol;
+ struct rb_entry *entry;
+
+ assert(reg->type != VKD3DSPR_IMMCONST);
+
+ if (reg->type == VKD3DSPR_TEMP)
+ {
+ assert(reg->idx[0].offset < compiler->temp_count);
+ register_info->id = compiler->temp_id + reg->idx[0].offset;
+ register_info->storage_class = SpvStorageClassFunction;
+ register_info->member_idx = 0;
+ register_info->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
+ register_info->write_mask = VKD3DSP_WRITEMASK_ALL;
+ register_info->structure_stride = 0;
+ register_info->is_aggregate = false;
+ register_info->is_dynamically_indexed = false;
+ return true;
+ }
+
+ vkd3d_symbol_make_register(®_symbol, reg);
+ if (!(entry = rb_get(&compiler->symbol_table, ®_symbol)))
+ {
+ FIXME("Unrecognized register (%s).\n", debug_vkd3d_symbol(®_symbol));
+ memset(register_info, 0, sizeof(*register_info));
+ return false;
+ }
+
+ symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
+ register_info->id = symbol->id;
+ register_info->storage_class = symbol->info.reg.storage_class;
+ register_info->member_idx = symbol->info.reg.member_idx;
+ register_info->component_type = symbol->info.reg.component_type;
+ register_info->write_mask = symbol->info.reg.write_mask;
+ register_info->structure_stride = symbol->info.reg.structure_stride;
+ register_info->is_aggregate = symbol->info.reg.is_aggregate;
+ register_info->is_dynamically_indexed = symbol->info.reg.is_dynamically_indexed;
+
+ return true;
+}
+
+static bool register_is_descriptor(const struct vkd3d_shader_register *reg)
+{
+ switch (reg->type)
+ {
+ case VKD3DSPR_SAMPLER:
+ case VKD3DSPR_RESOURCE:
+ case VKD3DSPR_CONSTBUFFER:
+ case VKD3DSPR_UAV:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_dereference_register(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, struct vkd3d_shader_register_info *register_info)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int component_count, index_count = 0;
+ uint32_t type_id, ptr_type_id;
+ uint32_t indexes[2];
+
+ if (reg->type == VKD3DSPR_CONSTBUFFER)
+ {
+ assert(!reg->idx[0].rel_addr);
+ indexes[index_count++] = vkd3d_dxbc_compiler_get_constant_uint(compiler, register_info->member_idx);
+ indexes[index_count++] = vkd3d_dxbc_compiler_emit_register_addressing(compiler, ®->idx[2]);
+ }
+ else if (reg->type == VKD3DSPR_IMMCONSTBUFFER)
+ {
+ indexes[index_count++] = vkd3d_dxbc_compiler_emit_register_addressing(compiler, ®->idx[0]);
+ }
+ else if (reg->type == VKD3DSPR_IDXTEMP)
+ {
+ indexes[index_count++] = vkd3d_dxbc_compiler_emit_register_addressing(compiler, ®->idx[1]);
+ }
+ else if (register_info->is_aggregate)
+ {
+ struct vkd3d_shader_register_index reg_idx = reg->idx[0];
+
+ if (reg->idx[1].rel_addr)
+ FIXME("Relative addressing not implemented.\n");
+
+ if (register_info->is_dynamically_indexed)
+ {
+ indexes[index_count++] = vkd3d_spirv_build_op_load(builder,
+ vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, 1),
+ register_info->member_idx, SpvMemoryAccessMaskNone);
+ }
+ else
+ {
+ reg_idx.offset = register_info->member_idx;
+ indexes[index_count++] = vkd3d_dxbc_compiler_emit_register_addressing(compiler, ®_idx);
+ }
+ }
+ else
+ {
+ if (reg->idx[1].rel_addr || (reg->idx[1].offset == ~0u && reg->idx[0].rel_addr))
+ FIXME("Relative addressing not implemented.\n");
+
+ /* Handle arrayed registers, e.g. v[3][0]. */
+ if (reg->idx[1].offset != ~0u && !register_is_descriptor(reg))
+ indexes[index_count++] = vkd3d_dxbc_compiler_emit_register_addressing(compiler, ®->idx[0]);
+ }
+
+ if (index_count)
+ {
+ component_count = vkd3d_write_mask_component_count(register_info->write_mask);
+ type_id = vkd3d_spirv_get_type_id(builder, register_info->component_type, component_count);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id);
+ register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id,
+ register_info->id, indexes, index_count);
+ }
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_register_id(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ struct vkd3d_shader_register_info register_info;
+
+ if (vkd3d_dxbc_compiler_get_register_info(compiler, reg, ®ister_info))
+ {
+ vkd3d_dxbc_compiler_emit_dereference_register(compiler, reg, ®ister_info);
+ return register_info.id;
+ }
+
+ return vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream,
+ SpvStorageClassPrivate, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+}
+
+static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask,
+ unsigned int swizzle, unsigned int write_mask)
+{
+ return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_swizzle(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t val_id, unsigned int val_write_mask, enum vkd3d_shader_component_type component_type,
+ unsigned int swizzle, unsigned int write_mask)
+{
+ unsigned int i, component_idx, component_count, val_component_count;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, components[VKD3D_VEC4_SIZE];
+
+ component_count = vkd3d_write_mask_component_count(write_mask);
+ val_component_count = vkd3d_write_mask_component_count(val_write_mask);
+
+ if (component_count == val_component_count
+ && (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask)))
+ return val_id;
+
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+
+ if (component_count == 1)
+ {
+ component_idx = vkd3d_write_mask_get_component_idx(write_mask);
+ component_idx = vkd3d_swizzle_get_component(swizzle, component_idx);
+ component_idx -= vkd3d_write_mask_get_component_idx(val_write_mask);
+ return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx);
+ }
+
+ if (val_component_count == 1)
+ {
+ for (i = 0, component_idx = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
+ {
+ assert(VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(swizzle, i) == val_write_mask);
+ components[component_idx++] = val_id;
+ }
+ }
+ return vkd3d_spirv_build_op_composite_construct(builder, type_id, components, component_count);
+ }
+
+ for (i = 0, component_idx = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
+ components[component_idx++] = vkd3d_swizzle_get_component(swizzle, i);
+ }
+ return vkd3d_spirv_build_op_vector_shuffle(builder,
+ type_id, val_id, val_id, components, component_count);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_vector_shuffle(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t vector1_id, uint32_t vector2_id, unsigned int swizzle, unsigned int write_mask,
+ enum vkd3d_shader_component_type component_type, unsigned int component_count)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t components[VKD3D_VEC4_SIZE];
+ uint32_t type_id;
+ unsigned int i;
+
+ assert(component_count <= ARRAY_SIZE(components));
+
+ for (i = 0; i < component_count; ++i)
+ {
+ if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
+ components[i] = vkd3d_swizzle_get_component(swizzle, i);
+ else
+ components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(swizzle, i);
+ }
+
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+ return vkd3d_spirv_build_op_vector_shuffle(builder,
+ type_id, vector1_id, vector2_id, components, component_count);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_load_constant(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask)
+{
+ unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
+ uint32_t values[VKD3D_VEC4_SIZE] = {0};
+ unsigned int i, j;
+
+ assert(reg->type == VKD3DSPR_IMMCONST);
+
+ if (reg->immconst_type == VKD3D_IMMCONST_SCALAR)
+ {
+ for (i = 0; i < component_count; ++i)
+ values[i] = *reg->u.immconst_uint;
+ }
+ else
+ {
+ for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
+ values[j++] = reg->u.immconst_uint[vkd3d_swizzle_get_component(swizzle, i)];
+ }
+ }
+
+ return vkd3d_dxbc_compiler_get_constant(compiler,
+ vkd3d_component_type_from_data_type(reg->data_type), component_count, values);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_load_scalar(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask,
+ const struct vkd3d_shader_register_info *reg_info)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, ptr_type_id, index, reg_id, val_id;
+ unsigned int component_idx, reg_component_count;
+ enum vkd3d_shader_component_type component_type;
+ unsigned int skipped_component_mask;
+
+ assert(reg->type != VKD3DSPR_IMMCONST);
+ assert(vkd3d_write_mask_component_count(write_mask) == 1);
+
+ component_idx = vkd3d_write_mask_get_component_idx(write_mask);
+ component_idx = vkd3d_swizzle_get_component(swizzle, component_idx);
+ skipped_component_mask = ~reg_info->write_mask & ((VKD3DSP_WRITEMASK_0 << component_idx) - 1);
+ if (skipped_component_mask)
+ component_idx -= vkd3d_write_mask_component_count(skipped_component_mask);
+ component_type = vkd3d_component_type_from_data_type(reg->data_type);
+
+ reg_component_count = vkd3d_write_mask_component_count(reg_info->write_mask);
+
+ if (component_idx >= vkd3d_write_mask_component_count(reg_info->write_mask))
+ {
+ ERR("Invalid component_idx %u for register %#x, %u (write_mask %#x).\n",
+ component_idx, reg->type, reg->idx[0].offset, reg_info->write_mask);
+ }
+
+ type_id = vkd3d_spirv_get_type_id(builder, reg_info->component_type, 1);
+ reg_id = reg_info->id;
+ if (reg_component_count != 1)
+ {
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info->storage_class, type_id);
+ index = vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx);
+ reg_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, reg_id, index);
+ }
+
+ val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_id, SpvMemoryAccessMaskNone);
+
+ if (component_type != reg_info->component_type)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
+ }
+
+ return val_id;
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_load_reg(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ enum vkd3d_shader_component_type component_type;
+ struct vkd3d_shader_register_info reg_info;
+ unsigned int component_count;
+ uint32_t type_id, val_id;
+
+ if (reg->type == VKD3DSPR_IMMCONST)
+ return vkd3d_dxbc_compiler_emit_load_constant(compiler, reg, swizzle, write_mask);
+
+ component_count = vkd3d_write_mask_component_count(write_mask);
+ component_type = vkd3d_component_type_from_data_type(reg->data_type);
+ if (!vkd3d_dxbc_compiler_get_register_info(compiler, reg, ®_info))
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+ return vkd3d_spirv_build_op_undef(builder, &builder->global_stream, type_id);
+ }
+ vkd3d_dxbc_compiler_emit_dereference_register(compiler, reg, ®_info);
+
+ /* Intermediate value (no storage class). */
+ if (reg_info.storage_class == SpvStorageClassMax)
+ {
+ val_id = reg_info.id;
+ }
+ else if (component_count == 1)
+ {
+ return vkd3d_dxbc_compiler_emit_load_scalar(compiler, reg, swizzle, write_mask, ®_info);
+ }
+ else
+ {
+ type_id = vkd3d_spirv_get_type_id(builder,
+ reg_info.component_type, vkd3d_write_mask_component_count(reg_info.write_mask));
+ val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone);
+ }
+
+ val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler,
+ val_id, reg_info.write_mask, reg_info.component_type, swizzle, write_mask);
+
+ if (component_type != reg_info.component_type)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
+ }
+
+ return val_id;
+}
+
+static void vkd3d_dxbc_compiler_emit_execution_mode(struct vkd3d_dxbc_compiler *compiler,
+ SpvExecutionMode mode, const uint32_t *literals, unsigned int literal_count)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ vkd3d_spirv_build_op_execution_mode(&builder->execution_mode_stream,
+ builder->main_function_id, mode, literals, literal_count);
+}
+
+static void vkd3d_dxbc_compiler_emit_execution_mode1(struct vkd3d_dxbc_compiler *compiler,
+ SpvExecutionMode mode, const uint32_t literal)
+{
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, mode, &literal, 1);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_abs(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id)
+{
+ unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id;
+
+ if (reg->data_type == VKD3D_DATA_FLOAT)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count);
+ return vkd3d_spirv_build_op_glsl_std450_fabs(builder, type_id, val_id);
+ }
+
+ FIXME("Unhandled data type %#x.\n", reg->data_type);
+ return val_id;
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_neg(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id;
+
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_reg(compiler, reg, write_mask);
+ if (reg->data_type == VKD3D_DATA_FLOAT)
+ return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id);
+ else if (reg->data_type == VKD3D_DATA_INT)
+ return vkd3d_spirv_build_op_snegate(builder, type_id, val_id);
+
+ FIXME("Unhandled data type %#x.\n", reg->data_type);
+ return val_id;
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_src_modifier(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, DWORD write_mask,
+ enum vkd3d_shader_src_modifier modifier, uint32_t val_id)
+{
+ switch (modifier)
+ {
+ case VKD3DSPSM_NONE:
+ break;
+ case VKD3DSPSM_NEG:
+ return vkd3d_dxbc_compiler_emit_neg(compiler, reg, write_mask, val_id);
+ case VKD3DSPSM_ABS:
+ return vkd3d_dxbc_compiler_emit_abs(compiler, reg, write_mask, val_id);
+ case VKD3DSPSM_ABSNEG:
+ val_id = vkd3d_dxbc_compiler_emit_abs(compiler, reg, write_mask, val_id);
+ return vkd3d_dxbc_compiler_emit_neg(compiler, reg, write_mask, val_id);
+ default:
+ FIXME("Unhandled src modifier %#x.\n", modifier);
+ break;
+ }
+
+ return val_id;
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_load_src(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_src_param *src, DWORD write_mask)
+{
+ uint32_t val_id;
+
+ val_id = vkd3d_dxbc_compiler_emit_load_reg(compiler, &src->reg, src->swizzle, write_mask);
+ return vkd3d_dxbc_compiler_emit_src_modifier(compiler, &src->reg, write_mask, src->modifiers, val_id);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_load_src_with_type(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_src_param *src, DWORD write_mask, enum vkd3d_shader_component_type component_type)
+{
+ struct vkd3d_shader_src_param src_param = *src;
+
+ src_param.reg.data_type = vkd3d_data_type_from_component_type(component_type);
+ return vkd3d_dxbc_compiler_emit_load_src(compiler, &src_param, write_mask);
+}
+
+static void vkd3d_dxbc_compiler_emit_store_scalar(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type,
+ SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, ptr_type_id, index;
+ unsigned int component_idx;
+
+ if (vkd3d_write_mask_component_count(dst_write_mask) > 1)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
+ component_idx = vkd3d_write_mask_get_component_idx(write_mask);
+ component_idx -= vkd3d_write_mask_get_component_idx(dst_write_mask);
+ index = vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx);
+ dst_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, dst_id, index);
+ }
+
+ vkd3d_spirv_build_op_store(builder, dst_id, val_id, SpvMemoryAccessMaskNone);
+}
+
+static void vkd3d_dxbc_compiler_emit_store(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type,
+ SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int component_count, dst_component_count;
+ uint32_t components[VKD3D_VEC4_SIZE];
+ unsigned int i, src_idx, dst_idx;
+ uint32_t type_id, dst_val_id;
+
+ assert(write_mask);
+
+ component_count = vkd3d_write_mask_component_count(write_mask);
+ dst_component_count = vkd3d_write_mask_component_count(dst_write_mask);
+
+ if (dst_component_count == 1 && component_count != 1)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id,
+ vkd3d_write_mask_get_component_idx(dst_write_mask));
+ write_mask &= dst_write_mask;
+ component_count = 1;
+ }
+
+ if (component_count == 1)
+ {
+ return vkd3d_dxbc_compiler_emit_store_scalar(compiler,
+ dst_id, dst_write_mask, component_type, storage_class, write_mask, val_id);
+ }
+
+ if (dst_component_count != component_count)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, dst_component_count);
+ dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone);
+
+ assert(component_count <= ARRAY_SIZE(components));
+
+ for (i = 0, src_idx = 0, dst_idx = 0; dst_idx < VKD3D_VEC4_SIZE; ++dst_idx)
+ {
+ if (write_mask & (VKD3DSP_WRITEMASK_0 << dst_idx))
+ components[i] = dst_component_count + src_idx++;
+ else
+ components[i] = i;
+
+ if (dst_write_mask & (VKD3DSP_WRITEMASK_0 << dst_idx))
+ ++i;
+ }
+
+ val_id = vkd3d_spirv_build_op_vector_shuffle(builder,
+ type_id, dst_val_id, val_id, components, dst_component_count);
+ }
+
+ vkd3d_spirv_build_op_store(builder, dst_id, val_id, SpvMemoryAccessMaskNone);
+}
+
+static void vkd3d_dxbc_compiler_emit_store_reg(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, unsigned int write_mask, uint32_t val_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ enum vkd3d_shader_component_type component_type;
+ struct vkd3d_shader_register_info reg_info;
+ uint32_t type_id;
+
+ assert(reg->type != VKD3DSPR_IMMCONST);
+
+ if (!vkd3d_dxbc_compiler_get_register_info(compiler, reg, ®_info))
+ return;
+ vkd3d_dxbc_compiler_emit_dereference_register(compiler, reg, ®_info);
+
+ component_type = vkd3d_component_type_from_data_type(reg->data_type);
+ if (component_type != reg_info.component_type)
+ {
+ unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
+ type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, component_count);
+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
+ component_type = reg_info.component_type;
+ }
+
+ vkd3d_dxbc_compiler_emit_store(compiler,
+ reg_info.id, reg_info.write_mask, component_type, reg_info.storage_class, write_mask, val_id);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_sat(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id)
+{
+ unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, zero_id, one_id;
+
+ zero_id = vkd3d_dxbc_compiler_get_constant_float_vector(compiler, 0.0f, component_count);
+ one_id = vkd3d_dxbc_compiler_get_constant_float_vector(compiler, 1.0f, component_count);
+
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_reg(compiler, reg, write_mask);
+ if (reg->data_type == VKD3D_DATA_FLOAT)
+ return vkd3d_spirv_build_op_glsl_std450_nclamp(builder, type_id, val_id, zero_id, one_id);
+
+ FIXME("Unhandled data type %#x.\n", reg->data_type);
+ return val_id;
+}
+
+static void vkd3d_dxbc_compiler_emit_store_dst(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst, uint32_t val_id)
+{
+ assert(!(dst->modifiers & ~VKD3DSPDM_SATURATE));
+ if (dst->modifiers & VKD3DSPDM_SATURATE)
+ val_id = vkd3d_dxbc_compiler_emit_sat(compiler, &dst->reg, dst->write_mask, val_id);
+
+ vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_store_dst_swizzled(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst, uint32_t val_id,
+ enum vkd3d_shader_component_type component_type, DWORD swizzle)
+{
+ struct vkd3d_shader_dst_param typed_dst = *dst;
+ val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler,
+ val_id, VKD3DSP_WRITEMASK_ALL, component_type, swizzle, dst->write_mask);
+ /* XXX: The register data type could be fixed by the shader parser. For SM5
+ * shaders the data types are stored in instructions modifiers.
+ */
+ typed_dst.reg.data_type = vkd3d_data_type_from_component_type(component_type);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, &typed_dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_store_dst_components(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_component_type component_type,
+ uint32_t *component_ids)
+{
+ unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, val_id;
+
+ if (component_count > 1)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+ val_id = vkd3d_spirv_build_op_composite_construct(builder,
+ type_id, component_ids, component_count);
+ }
+ else
+ {
+ val_id = *component_ids;
+ }
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_store_dst_scalar(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst, uint32_t val_id,
+ enum vkd3d_shader_component_type component_type, DWORD swizzle)
+{
+ unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ uint32_t component_ids[VKD3D_VEC4_SIZE];
+ unsigned int component_idx, i;
+
+ component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask);
+ for (i = 0; i < component_count; ++i)
+ {
+ if (vkd3d_swizzle_get_component(swizzle, component_idx + i))
+ ERR("Invalid swizzle %#x for scalar value, write mask %#x.\n", swizzle, dst->write_mask);
+
+ component_ids[i] = val_id;
+ }
+ vkd3d_dxbc_compiler_emit_store_dst_components(compiler, dst, component_type, component_ids);
+}
+
+static void vkd3d_dxbc_compiler_decorate_builtin(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t target_id, SpvBuiltIn builtin)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ switch (builtin)
+ {
+ case SpvBuiltInPrimitiveId:
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL)
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityGeometry);
+ break;
+ case SpvBuiltInFragDepth:
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthReplacing, NULL, 0);
+ break;
+ case SpvBuiltInLayer:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityGeometry);
+ break;
+ case SpvBuiltInViewportIndex:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityMultiViewport);
+ break;
+ case SpvBuiltInSampleId:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilitySampleRateShading);
+ break;
+ case SpvBuiltInClipDistance:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityClipDistance);
+ break;
+ case SpvBuiltInCullDistance:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityCullDistance);
+ break;
+ default:
+ break;
+ }
+
+ vkd3d_spirv_build_op_decorate1(builder, target_id, SpvDecorationBuiltIn, builtin);
+}
+
+static void vkd3d_dxbc_compiler_emit_interpolation_decorations(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t id, enum vkd3d_shader_interpolation_mode mode)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ switch (mode)
+ {
+ case VKD3DSIM_NONE:
+ break;
+ case VKD3DSIM_CONSTANT:
+ vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0);
+ break;
+ case VKD3DSIM_LINEAR:
+ break;
+ case VKD3DSIM_LINEAR_CENTROID:
+ vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationCentroid, NULL, 0);
+ break;
+ case VKD3DSIM_LINEAR_NOPERSPECTIVE:
+ vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationNoPerspective, NULL, 0);
+ break;
+ case VKD3DSIM_LINEAR_SAMPLE:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilitySampleRateShading);
+ vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationSample, NULL, 0);
+ break;
+ default:
+ FIXME("Unhandled interpolation mode %#x.\n", mode);
+ break;
+ }
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_int_to_bool(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_conditional_op condition, unsigned int component_count, uint32_t val_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id;
+ SpvOp op;
+
+ assert(!(condition & ~(VKD3D_SHADER_CONDITIONAL_OP_NZ | VKD3D_SHADER_CONDITIONAL_OP_Z)));
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count);
+ op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual;
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id,
+ vkd3d_dxbc_compiler_get_constant_uint_vector(compiler, 0, component_count));
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_bool_to_int(struct vkd3d_dxbc_compiler *compiler,
+ unsigned int component_count, uint32_t val_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, true_id, false_id;
+
+ true_id = vkd3d_dxbc_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count);
+ false_id = vkd3d_dxbc_compiler_get_constant_uint_vector(compiler, 0, component_count);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count);
+ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id);
+}
+
+typedef uint32_t (*vkd3d_spirv_builtin_fixup_pfn)(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t val_id);
+
+static uint32_t vkd3d_dxbc_compiler_emit_draw_parameter_fixup(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t index_id, SpvBuiltIn base)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t base_var_id, base_id, type_id;
+
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityDrawParameters);
+
+ base_var_id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream,
+ SpvStorageClassInput, VKD3D_SHADER_COMPONENT_INT, 1);
+ vkd3d_spirv_add_iface_variable(builder, base_var_id);
+ vkd3d_dxbc_compiler_decorate_builtin(compiler, base_var_id, base);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, 1);
+ base_id = vkd3d_spirv_build_op_load(builder,
+ type_id, base_var_id, SpvMemoryAccessMaskNone);
+
+ return vkd3d_spirv_build_op_isub(builder, type_id, index_id, base_id);
+}
+
+/* Substitute "VertexIndex - BaseVertex" for SV_VertexID. */
+static uint32_t sv_vertex_id_fixup(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t vertex_index_id)
+{
+ return vkd3d_dxbc_compiler_emit_draw_parameter_fixup(compiler,
+ vertex_index_id, SpvBuiltInBaseVertex);
+}
+
+/* Substitute "InstanceIndex - BaseInstance" for SV_InstanceID. */
+static uint32_t sv_instance_id_fixup(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t instance_index_id)
+{
+ return vkd3d_dxbc_compiler_emit_draw_parameter_fixup(compiler,
+ instance_index_id, SpvBuiltInBaseInstance);
+}
+
+static uint32_t sv_front_face_fixup(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t front_facing_id)
+{
+ return vkd3d_dxbc_compiler_emit_bool_to_int(compiler, 1, front_facing_id);
+}
+
+/* frag_coord.w = 1.0f / frag_coord.w */
+static uint32_t frag_coord_fixup(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t frag_coord_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, w_id;
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 1);
+ w_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, frag_coord_id, 3);
+ w_id = vkd3d_spirv_build_op_fdiv(builder, type_id,
+ vkd3d_dxbc_compiler_get_constant_float(compiler, 1.0f), w_id);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+ return vkd3d_spirv_build_op_composite_insert1(builder, type_id, w_id, frag_coord_id, 3);
+}
+
+struct vkd3d_spirv_builtin
+{
+ enum vkd3d_shader_component_type component_type;
+ unsigned int component_count;
+ SpvBuiltIn spirv_builtin;
+ vkd3d_spirv_builtin_fixup_pfn fixup_pfn;
+ unsigned int spirv_array_size;
+ unsigned int member_idx;
+};
+
+/*
+ * The following tables are based on the "14.6. Built-In Variables" section
+ * from the Vulkan spec.
+ */
+static const struct
+{
+ enum vkd3d_shader_input_sysval_semantic sysval;
+ struct vkd3d_spirv_builtin builtin;
+ enum vkd3d_shader_spirv_environment environment;
+}
+vkd3d_system_value_builtins[] =
+{
+ {VKD3D_SIV_VERTEX_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInVertexId},
+ VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5},
+ {VKD3D_SIV_INSTANCE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInstanceId},
+ VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5},
+
+ {VKD3D_SIV_POSITION, {VKD3D_SHADER_COMPONENT_FLOAT, 4, SpvBuiltInPosition}},
+ {VKD3D_SIV_VERTEX_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInVertexIndex, sv_vertex_id_fixup}},
+ {VKD3D_SIV_INSTANCE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInstanceIndex, sv_instance_id_fixup}},
+
+ {VKD3D_SIV_PRIMITIVE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInPrimitiveId}},
+
+ {VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInLayer}},
+ {VKD3D_SIV_VIEWPORT_ARRAY_INDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInViewportIndex}},
+
+ {VKD3D_SIV_IS_FRONT_FACE, {VKD3D_SHADER_COMPONENT_BOOL, 1, SpvBuiltInFrontFacing, sv_front_face_fixup}},
+
+ {VKD3D_SIV_SAMPLE_INDEX, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSampleId}},
+
+ {VKD3D_SIV_CLIP_DISTANCE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInClipDistance, NULL, 1}},
+ {VKD3D_SIV_CULL_DISTANCE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInCullDistance, NULL, 1}},
+
+ {VKD3D_SIV_QUAD_U0_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}},
+ {VKD3D_SIV_QUAD_V0_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}},
+ {VKD3D_SIV_QUAD_U1_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 2}},
+ {VKD3D_SIV_QUAD_V1_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 3}},
+ {VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2, 0}},
+ {VKD3D_SIV_QUAD_V_INNER_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2, 1}},
+
+ {VKD3D_SIV_TRIANGLE_U_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}},
+ {VKD3D_SIV_TRIANGLE_V_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}},
+ {VKD3D_SIV_TRIANGLE_W_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 2}},
+ {VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2, 0}},
+
+ {VKD3D_SIV_LINE_DETAIL_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}},
+ {VKD3D_SIV_LINE_DENSITY_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}},
+};
+static const struct vkd3d_spirv_builtin vkd3d_pixel_shader_position_builtin =
+{
+ VKD3D_SHADER_COMPONENT_FLOAT, 4, SpvBuiltInFragCoord, frag_coord_fixup,
+};
+static const struct
+{
+ enum vkd3d_shader_register_type reg_type;
+ struct vkd3d_spirv_builtin builtin;
+}
+vkd3d_register_builtins[] =
+{
+ {VKD3DSPR_THREADID, {VKD3D_SHADER_COMPONENT_INT, 3, SpvBuiltInGlobalInvocationId}},
+ {VKD3DSPR_LOCALTHREADID, {VKD3D_SHADER_COMPONENT_INT, 3, SpvBuiltInLocalInvocationId}},
+ {VKD3DSPR_LOCALTHREADINDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInLocalInvocationIndex}},
+ {VKD3DSPR_THREADGROUPID, {VKD3D_SHADER_COMPONENT_INT, 3, SpvBuiltInWorkgroupId}},
+
+ {VKD3DSPR_GSINSTID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInvocationId}},
+ {VKD3DSPR_OUTPOINTID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInvocationId}},
+
+ {VKD3DSPR_PRIMID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInPrimitiveId}},
+
+ {VKD3DSPR_TESSCOORD, {VKD3D_SHADER_COMPONENT_FLOAT, 3, SpvBuiltInTessCoord}},
+
+ {VKD3DSPR_COVERAGE, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSampleMask, NULL, 1}},
+ {VKD3DSPR_SAMPLEMASK, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSampleMask, NULL, 1}},
+
+ {VKD3DSPR_DEPTHOUT, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInFragDepth}},
+ {VKD3DSPR_DEPTHOUTGE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInFragDepth}},
+ {VKD3DSPR_DEPTHOUTLE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInFragDepth}},
+};
+
+static void vkd3d_dxbc_compiler_emit_register_execution_mode(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg)
+{
+ switch (reg->type)
+ {
+ case VKD3DSPR_DEPTHOUTGE:
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthGreater, NULL, 0);
+ break;
+ case VKD3DSPR_DEPTHOUTLE:
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthLess, NULL, 0);
+ break;
+ default:
+ return;
+ }
+}
+
+static const struct vkd3d_spirv_builtin *get_spirv_builtin_for_sysval(
+ const struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_input_sysval_semantic sysval)
+{
+ enum vkd3d_shader_spirv_environment environment;
+ unsigned int i;
+
+ if (!sysval)
+ return NULL;
+
+ /* In pixel shaders, SV_Position is mapped to SpvBuiltInFragCoord. */
+ if (sysval == VKD3D_SIV_POSITION && compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL)
+ return &vkd3d_pixel_shader_position_builtin;
+
+ environment = vkd3d_dxbc_compiler_get_target_environment(compiler);
+ for (i = 0; i < ARRAY_SIZE(vkd3d_system_value_builtins); ++i)
+ {
+ if (vkd3d_system_value_builtins[i].sysval == sysval
+ && (!vkd3d_system_value_builtins[i].environment
+ || vkd3d_system_value_builtins[i].environment == environment))
+ return &vkd3d_system_value_builtins[i].builtin;
+ }
+
+ FIXME("Unhandled builtin (sysval %#x).\n", sysval);
+
+ return NULL;
+}
+
+static const struct vkd3d_spirv_builtin *get_spirv_builtin_for_register(
+ enum vkd3d_shader_register_type reg_type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_register_builtins); ++i)
+ {
+ if (vkd3d_register_builtins[i].reg_type == reg_type)
+ return &vkd3d_register_builtins[i].builtin;
+ }
+
+ return NULL;
+}
+
+static const struct vkd3d_spirv_builtin *vkd3d_get_spirv_builtin(const struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_register_type reg_type, enum vkd3d_shader_input_sysval_semantic sysval)
+{
+ const struct vkd3d_spirv_builtin *builtin;
+
+ if ((builtin = get_spirv_builtin_for_sysval(compiler, sysval)))
+ return builtin;
+ if ((builtin = get_spirv_builtin_for_register(reg_type)))
+ return builtin;
+
+ if (sysval != VKD3D_SIV_NONE || (reg_type != VKD3DSPR_OUTPUT && reg_type != VKD3DSPR_COLOROUT))
+ FIXME("Unhandled builtin (register type %#x, sysval %#x).\n", reg_type, sysval);
+ return NULL;
+}
+
+static const struct vkd3d_shader_signature_element *vkd3d_find_signature_element_for_reg(
+ const struct vkd3d_shader_signature *signature, unsigned int *signature_element_index,
+ unsigned int reg_idx, DWORD write_mask)
+{
+ unsigned int signature_idx;
+
+ for (signature_idx = 0; signature_idx < signature->element_count; ++signature_idx)
+ {
+ if (signature->elements[signature_idx].register_index == reg_idx
+ && (signature->elements[signature_idx].mask & write_mask) == write_mask)
+ {
+ if (signature_element_index)
+ *signature_element_index = signature_idx;
+ return &signature->elements[signature_idx];
+ }
+ }
+
+ FIXME("Could not find shader signature element (register %u, write mask %#x).\n",
+ reg_idx, write_mask);
+ if (signature_element_index)
+ *signature_element_index = ~0u;
+ return NULL;
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_invocation_id(struct vkd3d_dxbc_compiler *compiler)
+{
+ struct vkd3d_shader_register r;
+
+ assert(compiler->shader_type == VKD3D_SHADER_TYPE_HULL);
+
+ memset(&r, 0, sizeof(r));
+ r.type = VKD3DSPR_OUTPOINTID;
+ r.idx[0].offset = ~0u;
+ r.idx[1].offset = ~0u;
+ return vkd3d_dxbc_compiler_get_register_id(compiler, &r);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_load_invocation_id(struct vkd3d_dxbc_compiler *compiler)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, id;
+
+ id = vkd3d_dxbc_compiler_get_invocation_id(compiler);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, 1);
+ return vkd3d_spirv_build_op_load(builder, type_id, id, SpvMemoryAccessMaskNone);
+}
+
+static void vkd3d_dxbc_compiler_emit_shader_phase_name(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t id, const struct vkd3d_shader_phase *phase, const char *suffix)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const char *name;
+
+ if (!suffix)
+ suffix = "";
+
+ switch (phase->type)
+ {
+ case VKD3DSIH_HS_CONTROL_POINT_PHASE:
+ name = "control";
+ break;
+ case VKD3DSIH_HS_FORK_PHASE:
+ name = "fork";
+ break;
+ case VKD3DSIH_HS_JOIN_PHASE:
+ name = "join";
+ break;
+ default:
+ ERR("Invalid phase type %#x.\n", phase->type);
+ return;
+ }
+ vkd3d_spirv_build_op_name(builder, id, "%s%u%s", name, phase->idx, suffix);
+}
+
+static void vkd3d_dxbc_compiler_begin_shader_phase(struct vkd3d_dxbc_compiler *compiler,
+ struct vkd3d_shader_phase *phase)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t void_id, function_type_id;
+ unsigned int param_count;
+ uint32_t param_type_id;
+
+ if (phase->instance_count)
+ {
+ param_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ param_count = 1;
+ }
+ else
+ {
+ param_count = 0;
+ }
+
+ phase->function_id = vkd3d_spirv_alloc_id(builder);
+
+ void_id = vkd3d_spirv_get_op_type_void(builder);
+ function_type_id = vkd3d_spirv_get_op_type_function(builder, void_id, ¶m_type_id, param_count);
+ vkd3d_spirv_build_op_function(builder, void_id, phase->function_id,
+ SpvFunctionControlMaskNone, function_type_id);
+
+ if (phase->instance_count)
+ phase->instance_id = vkd3d_spirv_build_op_function_parameter(builder, param_type_id);
+
+ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
+ phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
+
+ vkd3d_dxbc_compiler_emit_shader_phase_name(compiler, phase->function_id, phase, NULL);
+}
+
+static const struct vkd3d_shader_phase *vkd3d_dxbc_compiler_get_current_shader_phase(
+ struct vkd3d_dxbc_compiler *compiler)
+{
+ struct vkd3d_shader_phase *phase;
+
+ if (!compiler->shader_phase_count)
+ return NULL;
+
+ phase = &compiler->shader_phases[compiler->shader_phase_count - 1];
+ if (!phase->function_id)
+ vkd3d_dxbc_compiler_begin_shader_phase(compiler, phase);
+ return phase;
+}
+
+static void vkd3d_dxbc_compiler_decorate_xfb_output(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t id, unsigned int component_count, const struct vkd3d_shader_signature_element *signature_element)
+{
+ const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info;
+ const struct vkd3d_shader_transform_feedback_element *xfb_element;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int offset, stride, i;
+
+ if (!xfb_info)
+ return;
+
+ offset = 0;
+ xfb_element = NULL;
+ for (i = 0; i < xfb_info->element_count; ++i)
+ {
+ const struct vkd3d_shader_transform_feedback_element *e = &xfb_info->elements[i];
+
+ if (e->stream_index == signature_element->stream_index
+ && !ascii_strcasecmp(e->semantic_name, signature_element->semantic_name)
+ && e->semantic_index == signature_element->semantic_index)
+ {
+ xfb_element = e;
+ break;
+ }
+
+ offset += 4 * e->component_count;
+ }
+
+ if (!xfb_element)
+ return;
+
+ if (xfb_element->component_index || xfb_element->component_count > component_count)
+ {
+ FIXME("Unhandled component range %u, %u.\n", xfb_element->component_index, xfb_element->component_count);
+ return;
+ }
+
+ if (xfb_element->output_slot < xfb_info->buffer_stride_count)
+ {
+ stride = xfb_info->buffer_strides[xfb_element->output_slot];
+ }
+ else
+ {
+ stride = 0;
+ for (i = 0; i < xfb_info->element_count; ++i)
+ {
+ const struct vkd3d_shader_transform_feedback_element *e = &xfb_info->elements[i];
+
+ if (e->stream_index == xfb_element->stream_index && e->output_slot == xfb_element->output_slot)
+ stride += 4 * e->component_count;
+ }
+ }
+
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationXfbBuffer, xfb_element->output_slot);
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationXfbStride, stride);
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationOffset, offset);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_builtin_variable(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_spirv_builtin *builtin, SpvStorageClass storage_class, unsigned int array_size)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t id;
+
+ array_size = max(array_size, builtin->spirv_array_size);
+
+ id = vkd3d_dxbc_compiler_emit_array_variable(compiler,
+ &builder->global_stream, storage_class,
+ builtin->component_type, builtin->component_count, array_size);
+ vkd3d_spirv_add_iface_variable(builder, id);
+ vkd3d_dxbc_compiler_decorate_builtin(compiler, id, builtin->spirv_builtin);
+
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && storage_class == SpvStorageClassInput
+ && builtin->component_type != VKD3D_SHADER_COMPONENT_FLOAT
+ && builtin->component_type != VKD3D_SHADER_COMPONENT_BOOL)
+ vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0);
+
+ return id;
+}
+
+static bool needs_private_io_variable(const struct vkd3d_shader_signature *signature,
+ unsigned int reg_idx, const struct vkd3d_spirv_builtin *builtin,
+ unsigned int *component_count, unsigned int *out_write_mask)
+{
+ unsigned int write_mask = 0;
+ bool have_sysval = false;
+ unsigned int i, count;
+
+ if (*component_count == VKD3D_VEC4_SIZE)
+ return false;
+
+ for (i = 0, count = 0; i < signature->element_count; ++i)
+ {
+ const struct vkd3d_shader_signature_element *current = &signature->elements[i];
+
+ if (current->register_index != reg_idx)
+ continue;
+
+ write_mask |= current->mask;
+ ++count;
+
+ if (current->sysval_semantic)
+ have_sysval = true;
+ }
+
+ if (count == 1)
+ return false;
+
+ if (builtin || have_sysval)
+ return true;
+
+ if (!vkd3d_bitmask_is_contiguous(write_mask))
+ {
+ FIXME("Write mask %#x is non-contiguous.\n", write_mask);
+ return true;
+ }
+
+ assert(vkd3d_write_mask_component_count(write_mask) >= *component_count);
+ *component_count = vkd3d_write_mask_component_count(write_mask);
+ *out_write_mask = write_mask;
+ return false;
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval,
+ enum vkd3d_shader_interpolation_mode interpolation_mode)
+{
+ unsigned int component_idx, component_count, input_component_count;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_signature_element *signature_element;
+ const struct vkd3d_shader_signature *shader_signature;
+ const struct vkd3d_shader_register *reg = &dst->reg;
+ enum vkd3d_shader_component_type component_type;
+ uint32_t type_id, ptr_type_id, float_type_id;
+ const struct vkd3d_spirv_builtin *builtin;
+ uint32_t val_id, input_id, var_id;
+ struct vkd3d_symbol reg_symbol;
+ struct vkd3d_symbol tmp_symbol;
+ SpvStorageClass storage_class;
+ struct rb_entry *entry = NULL;
+ bool use_private_var = false;
+ unsigned int write_mask;
+ unsigned int array_size;
+ unsigned int reg_idx;
+ uint32_t i, index;
+
+ assert(!reg->idx[0].rel_addr);
+ assert(!reg->idx[1].rel_addr);
+
+ if (reg->idx[1].offset != ~0u)
+ {
+ array_size = reg->idx[0].offset;
+ reg_idx = reg->idx[1].offset;
+ }
+ else
+ {
+ array_size = 0;
+ reg_idx = reg->idx[0].offset;
+ }
+
+ shader_signature = reg->type == VKD3DSPR_PATCHCONST
+ ? compiler->patch_constant_signature : compiler->input_signature;
+
+ if (!(signature_element = vkd3d_find_signature_element_for_reg(shader_signature,
+ NULL, reg_idx, dst->write_mask)))
+ {
+ FIXME("No signature element for shader input, ignoring shader input.\n");
+ return 0;
+ }
+
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && !sysval && signature_element->sysval_semantic)
+ sysval = vkd3d_siv_from_sysval(signature_element->sysval_semantic);
+
+ builtin = get_spirv_builtin_for_sysval(compiler, sysval);
+
+ write_mask = signature_element->mask;
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ if (builtin)
+ {
+ component_type = builtin->component_type;
+ input_component_count = builtin->component_count;
+ component_idx = 0;
+ }
+ else
+ {
+ component_type = signature_element->component_type;
+ input_component_count = vkd3d_write_mask_component_count(signature_element->mask);
+ component_idx = vkd3d_write_mask_get_component_idx(signature_element->mask);
+ }
+
+ if ((use_private_var = builtin && builtin->fixup_pfn))
+ {
+ component_count = VKD3D_VEC4_SIZE;
+ write_mask = VKD3DSP_WRITEMASK_ALL;
+ }
+ else if (needs_private_io_variable(shader_signature, reg_idx, builtin, &input_component_count, &write_mask))
+ {
+ use_private_var = true;
+ component_count = VKD3D_VEC4_SIZE;
+ write_mask = VKD3DSP_WRITEMASK_ALL;
+ }
+ else
+ {
+ component_idx = vkd3d_write_mask_get_component_idx(write_mask);
+ }
+
+ storage_class = SpvStorageClassInput;
+
+ vkd3d_symbol_make_register(®_symbol, reg);
+
+ if (builtin)
+ {
+ input_id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, storage_class, array_size);
+ entry = rb_get(&compiler->symbol_table, ®_symbol);
+ }
+ else if ((entry = rb_get(&compiler->symbol_table, ®_symbol)))
+ {
+ input_id = RB_ENTRY_VALUE(entry, const struct vkd3d_symbol, entry)->id;
+ }
+ else
+ {
+ input_id = 0;
+
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && reg->type == VKD3DSPR_INCONTROLPOINT)
+ {
+ tmp_symbol = reg_symbol;
+ tmp_symbol.key.reg.type = VKD3DSPR_INPUT;
+
+ if ((entry = rb_get(&compiler->symbol_table, &tmp_symbol)))
+ {
+ tmp_symbol = *RB_ENTRY_VALUE(entry, const struct vkd3d_symbol, entry);
+ tmp_symbol.key.reg.type = VKD3DSPR_INCONTROLPOINT;
+ vkd3d_dxbc_compiler_put_symbol(compiler, &tmp_symbol);
+
+ input_id = tmp_symbol.id;
+ }
+ }
+
+ if (!entry)
+ {
+ unsigned int location = reg_idx;
+
+ if (reg->type == VKD3DSPR_PATCHCONST)
+ location += compiler->input_signature->element_count;
+
+ input_id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream,
+ storage_class, component_type, input_component_count, array_size);
+ vkd3d_spirv_add_iface_variable(builder, input_id);
+ vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationLocation, location);
+ if (component_idx)
+ vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationComponent, component_idx);
+
+ vkd3d_dxbc_compiler_emit_interpolation_decorations(compiler, input_id, interpolation_mode);
+ }
+ }
+
+ if (reg->type == VKD3DSPR_PATCHCONST)
+ vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0);
+
+ if (entry || !use_private_var)
+ {
+ var_id = input_id;
+ }
+ else
+ {
+ storage_class = SpvStorageClassPrivate;
+ var_id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream,
+ storage_class, VKD3D_SHADER_COMPONENT_FLOAT, component_count, array_size);
+ }
+
+ if (!entry)
+ {
+ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class,
+ use_private_var ? VKD3D_SHADER_COMPONENT_FLOAT : component_type, write_mask);
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+ }
+
+ if (use_private_var)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count);
+ for (i = 0; i < max(array_size, 1); ++i)
+ {
+ struct vkd3d_shader_register dst_reg = *reg;
+ dst_reg.data_type = VKD3D_DATA_FLOAT;
+
+ val_id = input_id;
+ if (array_size)
+ {
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassInput, type_id);
+ index = vkd3d_dxbc_compiler_get_constant_uint(compiler, i);
+ val_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, input_id, index);
+ dst_reg.idx[0].offset = i;
+ }
+ val_id = vkd3d_spirv_build_op_load(builder, type_id, val_id, SpvMemoryAccessMaskNone);
+
+ if (builtin && builtin->fixup_pfn)
+ val_id = builtin->fixup_pfn(compiler, val_id);
+
+ if (component_type != VKD3D_SHADER_COMPONENT_FLOAT)
+ {
+ float_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, input_component_count);
+ val_id = vkd3d_spirv_build_op_bitcast(builder, float_type_id, val_id);
+ }
+
+ val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, val_id,
+ vkd3d_write_mask_from_component_count(input_component_count) << component_idx,
+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, dst->write_mask);
+
+ vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id);
+ }
+ }
+
+ return input_id;
+}
+
+static void vkd3d_dxbc_compiler_emit_input_register(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_register *reg = &dst->reg;
+ const struct vkd3d_spirv_builtin *builtin;
+ struct vkd3d_symbol reg_symbol;
+ struct rb_entry *entry;
+ uint32_t input_id;
+
+ assert(!reg->idx[0].rel_addr);
+ assert(!reg->idx[1].rel_addr);
+ assert(reg->idx[1].offset == ~0u);
+
+ if (!(builtin = get_spirv_builtin_for_register(reg->type)))
+ {
+ FIXME("Unhandled register %#x.\n", reg->type);
+ return;
+ }
+
+ /* vPrim may be declared in multiple hull shader phases. */
+ vkd3d_symbol_make_register(®_symbol, reg);
+ if ((entry = rb_get(&compiler->symbol_table, ®_symbol)))
+ return;
+
+ input_id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, SpvStorageClassInput, 0);
+
+ vkd3d_symbol_set_register_info(®_symbol, input_id, SpvStorageClassInput,
+ builtin->component_type, vkd3d_write_mask_from_component_count(builtin->component_count));
+ reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size;
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, input_id, reg);
+}
+
+static void vkd3d_dxbc_compiler_emit_shader_phase_input(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_phase *phase, const struct vkd3d_shader_dst_param *dst)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_register *reg = &dst->reg;
+ struct vkd3d_symbol reg_symbol;
+ uint32_t val_id;
+
+ switch (reg->type)
+ {
+ case VKD3DSPR_INPUT:
+ case VKD3DSPR_INCONTROLPOINT:
+ vkd3d_dxbc_compiler_emit_input(compiler, dst, VKD3D_SIV_NONE, VKD3DSIM_NONE);
+ return;
+ case VKD3DSPR_PRIMID:
+ vkd3d_dxbc_compiler_emit_input_register(compiler, dst);
+ return;
+ case VKD3DSPR_FORKINSTID:
+ case VKD3DSPR_JOININSTID:
+ val_id = phase->instance_id;
+ break;
+ case VKD3DSPR_OUTPOINTID: /* Emitted in vkd3d_dxbc_compiler_emit_initial_declarations(). */
+ case VKD3DSPR_OUTCONTROLPOINT: /* See vkd3d_dxbc_compiler_leave_shader_phase(). */
+ return;
+ default:
+ FIXME("Unhandled shader phase input register %#x.\n", reg->type);
+ return;
+ }
+
+ vkd3d_symbol_make_register(®_symbol, reg);
+ vkd3d_symbol_set_register_info(®_symbol, val_id,
+ SpvStorageClassMax /* Intermediate value */,
+ VKD3D_SHADER_COMPONENT_UINT, VKD3DSP_WRITEMASK_0);
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, val_id, reg);
+}
+
+static unsigned int vkd3d_dxbc_compiler_get_output_variable_index(
+ struct vkd3d_dxbc_compiler *compiler, unsigned int register_idx)
+{
+ if (register_idx == ~0u) /* oDepth */
+ return ARRAY_SIZE(compiler->private_output_variable) - 1;
+ assert(register_idx < ARRAY_SIZE(compiler->private_output_variable) - 1);
+ return register_idx;
+}
+
+static unsigned int get_shader_output_swizzle(const struct vkd3d_dxbc_compiler *compiler,
+ unsigned int register_idx)
+{
+ const struct vkd3d_shader_spirv_target_info *info;
+
+ if (!(info = compiler->spirv_target_info))
+ return VKD3D_SHADER_NO_SWIZZLE;
+ if (register_idx >= info->output_swizzle_count)
+ return VKD3D_SHADER_NO_SWIZZLE;
+ return info->output_swizzles[register_idx];
+}
+
+static bool is_dual_source_blending(const struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
+
+ return compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && info && info->dual_source_blending;
+}
+
+static void calculate_clip_or_cull_distance_mask(const struct vkd3d_shader_signature_element *e,
+ uint32_t *mask)
+{
+ if (e->semantic_index >= sizeof(*mask) * CHAR_BIT / VKD3D_VEC4_SIZE)
+ {
+ FIXME("Invalid semantic index %u for clip/cull distance.\n", e->semantic_index);
+ return;
+ }
+
+ *mask |= (e->mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index);
+}
+
+static uint32_t calculate_sysval_array_mask(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_signature *signature, enum vkd3d_shader_input_sysval_semantic sysval)
+{
+ const struct vkd3d_shader_signature_element *e;
+ const struct vkd3d_spirv_builtin *sig_builtin;
+ const struct vkd3d_spirv_builtin *builtin;
+ uint32_t signature_idx, mask = 0;
+
+ if (!(builtin = get_spirv_builtin_for_sysval(compiler, sysval)))
+ {
+ FIXME("Unhandled sysval %#x.\n", sysval);
+ return 0;
+ }
+
+ for (signature_idx = 0; signature_idx < signature->element_count; ++signature_idx)
+ {
+ e = &signature->elements[signature_idx];
+
+ sig_builtin = get_spirv_builtin_for_sysval(compiler,
+ vkd3d_siv_from_sysval_indexed(e->sysval_semantic, e->semantic_index));
+
+ if (sig_builtin && sig_builtin->spirv_builtin == builtin->spirv_builtin)
+ mask |= (e->mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * sig_builtin->member_idx);
+ }
+
+ return mask;
+}
+
+/* Emits arrayed SPIR-V built-in variables. */
+static void vkd3d_dxbc_compiler_emit_shader_signature_outputs(struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_shader_signature *output_signature = compiler->output_signature;
+ uint32_t clip_distance_mask = 0, clip_distance_id = 0;
+ uint32_t cull_distance_mask = 0, cull_distance_id = 0;
+ const struct vkd3d_spirv_builtin *builtin;
+ unsigned int i, count;
+
+ for (i = 0; i < output_signature->element_count; ++i)
+ {
+ const struct vkd3d_shader_signature_element *e = &output_signature->elements[i];
+
+ switch (e->sysval_semantic)
+ {
+ case VKD3D_SHADER_SV_CLIP_DISTANCE:
+ calculate_clip_or_cull_distance_mask(e, &clip_distance_mask);
+ break;
+
+ case VKD3D_SHADER_SV_CULL_DISTANCE:
+ calculate_clip_or_cull_distance_mask(e, &cull_distance_mask);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (clip_distance_mask)
+ {
+ count = vkd3d_popcount(clip_distance_mask);
+ builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SIV_CLIP_DISTANCE);
+ clip_distance_id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler,
+ builtin, SpvStorageClassOutput, count);
+ }
+
+ if (cull_distance_mask)
+ {
+ count = vkd3d_popcount(cull_distance_mask);
+ builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SIV_CULL_DISTANCE);
+ cull_distance_id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler,
+ builtin, SpvStorageClassOutput, count);
+ }
+
+ for (i = 0; i < output_signature->element_count; ++i)
+ {
+ const struct vkd3d_shader_signature_element *e = &output_signature->elements[i];
+
+ switch (e->sysval_semantic)
+ {
+ case VKD3D_SHADER_SV_CLIP_DISTANCE:
+ compiler->output_info[i].id = clip_distance_id;
+ compiler->output_info[i].component_type = VKD3D_SHADER_COMPONENT_FLOAT;
+ compiler->output_info[i].array_element_mask = clip_distance_mask;
+ break;
+
+ case VKD3D_SHADER_SV_CULL_DISTANCE:
+ compiler->output_info[i].id = cull_distance_id;
+ compiler->output_info[i].component_type = VKD3D_SHADER_COMPONENT_FLOAT;
+ compiler->output_info[i].array_element_mask = cull_distance_mask;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_output_register(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_register *reg = &dst->reg;
+ const struct vkd3d_spirv_builtin *builtin;
+ struct vkd3d_symbol reg_symbol;
+ uint32_t output_id;
+
+ assert(!reg->idx[0].rel_addr);
+ assert(!reg->idx[1].rel_addr);
+ assert(reg->idx[1].offset == ~0u);
+
+ if (!(builtin = get_spirv_builtin_for_register(reg->type)))
+ {
+ FIXME("Unhandled register %#x.\n", reg->type);
+ return;
+ }
+
+ output_id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, SpvStorageClassOutput, 0);
+
+ vkd3d_symbol_make_register(®_symbol, reg);
+ vkd3d_symbol_set_register_info(®_symbol, output_id, SpvStorageClassOutput,
+ builtin->component_type, vkd3d_write_mask_from_component_count(builtin->component_count));
+ reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size;
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, output_id, reg);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_shader_phase_builtin_variable(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_phase *phase, const struct vkd3d_spirv_builtin *builtin)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t *variable_id, id;
+
+ variable_id = NULL;
+
+ if (builtin->spirv_builtin == SpvBuiltInTessLevelOuter)
+ variable_id = &compiler->hs.tess_level_outer_id;
+ else if (builtin->spirv_builtin == SpvBuiltInTessLevelInner)
+ variable_id = &compiler->hs.tess_level_inner_id;
+
+ if (variable_id && *variable_id)
+ return *variable_id;
+
+ id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, SpvStorageClassOutput, 0);
+ if (phase->type == VKD3DSIH_HS_FORK_PHASE || phase->type == VKD3DSIH_HS_JOIN_PHASE)
+ vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationPatch, NULL, 0);
+
+ if (variable_id)
+ *variable_id = id;
+ return id;
+}
+
+static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_signature_element *signature_element;
+ const struct vkd3d_shader_signature *shader_signature;
+ const struct vkd3d_shader_register *reg = &dst->reg;
+ unsigned int component_idx, output_component_count;
+ enum vkd3d_shader_component_type component_type;
+ const struct vkd3d_spirv_builtin *builtin;
+ const struct vkd3d_shader_phase *phase;
+ struct vkd3d_symbol reg_symbol;
+ SpvStorageClass storage_class;
+ struct rb_entry *entry = NULL;
+ unsigned int signature_idx;
+ bool use_private_variable;
+ unsigned int write_mask;
+ unsigned int array_size;
+ bool is_patch_constant;
+ uint32_t id, var_id;
+
+ phase = vkd3d_dxbc_compiler_get_current_shader_phase(compiler);
+ is_patch_constant = phase && (phase->type == VKD3DSIH_HS_FORK_PHASE || phase->type == VKD3DSIH_HS_JOIN_PHASE);
+
+ shader_signature = is_patch_constant ? compiler->patch_constant_signature : compiler->output_signature;
+
+ array_size = is_control_point_phase(phase) ? compiler->output_control_point_count : 0;
+
+ if (!(signature_element = vkd3d_find_signature_element_for_reg(shader_signature,
+ &signature_idx, reg->idx[0].offset, dst->write_mask)))
+ {
+ FIXME("No signature element for shader output, ignoring shader output.\n");
+ return;
+ }
+
+ builtin = vkd3d_get_spirv_builtin(compiler, dst->reg.type, sysval);
+
+ write_mask = signature_element->mask;
+
+ component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask);
+ output_component_count = vkd3d_write_mask_component_count(signature_element->mask);
+ if (builtin)
+ {
+ component_type = builtin->component_type;
+ if (!builtin->spirv_array_size)
+ output_component_count = builtin->component_count;
+ }
+ else
+ {
+ component_type = signature_element->component_type;
+ }
+
+ storage_class = SpvStorageClassOutput;
+
+ if ((use_private_variable = builtin && builtin->spirv_array_size))
+ write_mask = VKD3DSP_WRITEMASK_ALL;
+ else if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE
+ || needs_private_io_variable(shader_signature, signature_element->register_index,
+ builtin, &output_component_count, &write_mask)
+ || is_patch_constant)
+ {
+ use_private_variable = true;
+ write_mask = VKD3DSP_WRITEMASK_ALL;
+ }
+ else
+ {
+ component_idx = vkd3d_write_mask_get_component_idx(write_mask);
+ }
+
+ vkd3d_symbol_make_register(®_symbol, reg);
+
+ if (compiler->output_info[signature_idx].id)
+ {
+ id = compiler->output_info[signature_idx].id;
+ if (compiler->output_info[signature_idx].array_element_mask)
+ {
+ use_private_variable = true;
+ write_mask = VKD3DSP_WRITEMASK_ALL;
+ entry = rb_get(&compiler->symbol_table, ®_symbol);
+ }
+ }
+ else if (!use_private_variable && (entry = rb_get(&compiler->symbol_table, ®_symbol)))
+ {
+ id = RB_ENTRY_VALUE(entry, const struct vkd3d_symbol, entry)->id;
+ }
+ else
+ {
+ if (builtin)
+ {
+ if (phase)
+ id = vkd3d_dxbc_compiler_emit_shader_phase_builtin_variable(compiler, phase, builtin);
+ else
+ id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, storage_class, array_size);
+
+ if (builtin->spirv_array_size)
+ compiler->output_info[signature_idx].array_element_mask =
+ calculate_sysval_array_mask(compiler, shader_signature, sysval);
+
+ vkd3d_dxbc_compiler_emit_register_execution_mode(compiler, &dst->reg);
+
+ if (component_idx)
+ FIXME("Unhandled component index %u.\n", component_idx);
+ }
+ else
+ {
+ unsigned int location = reg->idx[0].offset;
+
+ if (is_patch_constant)
+ location += compiler->output_signature->element_count;
+
+ id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream,
+ storage_class, component_type, output_component_count, array_size);
+ vkd3d_spirv_add_iface_variable(builder, id);
+
+ if (is_dual_source_blending(compiler) && reg->idx[0].offset < 2)
+ {
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationLocation, 0);
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationIndex, reg->idx[0].offset);
+ }
+ else
+ {
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationLocation, location);
+ }
+
+ if (component_idx)
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationComponent, component_idx);
+ }
+
+ if (is_patch_constant)
+ vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationPatch, NULL, 0);
+
+ vkd3d_dxbc_compiler_decorate_xfb_output(compiler, id, output_component_count, signature_element);
+ }
+
+ compiler->output_info[signature_idx].id = id;
+ compiler->output_info[signature_idx].component_type = component_type;
+
+ if (use_private_variable)
+ storage_class = SpvStorageClassPrivate;
+
+ if (entry)
+ var_id = RB_ENTRY_VALUE(entry, const struct vkd3d_symbol, entry)->id;
+ else if (!use_private_variable)
+ var_id = id;
+ else if (is_patch_constant)
+ var_id = compiler->hs.patch_constants_id;
+ else
+ var_id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream,
+ storage_class, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+ if (!entry)
+ {
+ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class,
+ use_private_variable ? VKD3D_SHADER_COMPONENT_FLOAT : component_type, write_mask);
+ reg_symbol.info.reg.is_aggregate = use_private_variable ? is_patch_constant : array_size;
+ if (!use_private_variable && is_control_point_phase(phase))
+ {
+ reg_symbol.info.reg.member_idx = vkd3d_dxbc_compiler_get_invocation_id(compiler);
+ reg_symbol.info.reg.is_dynamically_indexed = true;
+ }
+ else if (is_patch_constant)
+ {
+ reg_symbol.info.reg.member_idx = reg->idx[0].offset;
+ }
+
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+
+ if (!is_patch_constant)
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+ }
+
+ if (use_private_variable)
+ {
+ unsigned int idx = vkd3d_dxbc_compiler_get_output_variable_index(compiler, reg->idx[0].offset);
+ compiler->private_output_variable[idx] = var_id;
+ compiler->private_output_variable_write_mask[idx] |= dst->write_mask;
+ if (is_patch_constant)
+ compiler->private_output_variable_array_idx[idx] = vkd3d_dxbc_compiler_get_constant_uint(
+ compiler, reg->idx[0].offset);
+ if (!compiler->epilogue_function_id)
+ compiler->epilogue_function_id = vkd3d_spirv_alloc_id(builder);
+ }
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_output_array_index(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_signature_element *e)
+{
+ enum vkd3d_shader_input_sysval_semantic sysval;
+ const struct vkd3d_spirv_builtin *builtin;
+
+ sysval = vkd3d_siv_from_sysval_indexed(e->sysval_semantic, e->semantic_index);
+ builtin = get_spirv_builtin_for_sysval(compiler, sysval);
+
+ switch (sysval)
+ {
+ case VKD3D_SIV_LINE_DETAIL_TESS_FACTOR:
+ case VKD3D_SIV_LINE_DENSITY_TESS_FACTOR:
+ return builtin->member_idx;
+ default:
+ return e->semantic_index;
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_store_shader_output(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_signature_element *output,
+ const struct vkd3d_shader_output_info *output_info,
+ uint32_t output_index_id, uint32_t val_id, unsigned int write_mask)
+{
+ unsigned int dst_write_mask, use_mask, uninit_mask, swizzle, mask;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id;
+ unsigned int i, index, array_idx;
+ uint32_t output_id;
+
+ dst_write_mask = output->mask;
+ write_mask &= dst_write_mask;
+ use_mask = output->used_mask;
+
+ if (!write_mask)
+ return;
+
+ if (output_info->component_type != VKD3D_SHADER_COMPONENT_FLOAT)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, output_info->component_type, VKD3D_VEC4_SIZE);
+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
+ }
+
+ swizzle = get_shader_output_swizzle(compiler, output->register_index);
+ uninit_mask = dst_write_mask & ~use_mask;
+ if (uninit_mask)
+ {
+ /* Set values to 0 for not initialized shader output components. */
+ write_mask |= uninit_mask;
+ zero_id = vkd3d_dxbc_compiler_get_constant_vector(compiler,
+ output_info->component_type, VKD3D_VEC4_SIZE, 0);
+ val_id = vkd3d_dxbc_compiler_emit_vector_shuffle(compiler,
+ zero_id, val_id, swizzle, uninit_mask, output_info->component_type,
+ vkd3d_write_mask_component_count(write_mask));
+ }
+ else
+ {
+ val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler,
+ val_id, VKD3DSP_WRITEMASK_ALL, output_info->component_type, swizzle, write_mask);
+ }
+
+ output_id = output_info->id;
+ if (output_index_id)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder,
+ output_info->component_type, vkd3d_write_mask_component_count(dst_write_mask));
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id);
+ output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id);
+ }
+
+ if (!output_info->array_element_mask)
+ {
+ vkd3d_dxbc_compiler_emit_store(compiler,
+ output_id, dst_write_mask, output_info->component_type, SpvStorageClassOutput, write_mask, val_id);
+ return;
+ }
+
+ type_id = vkd3d_spirv_get_type_id(builder, output_info->component_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id);
+ mask = output_info->array_element_mask;
+ array_idx = vkd3d_dxbc_compiler_get_output_array_index(compiler, output);
+ mask &= (1u << (array_idx * VKD3D_VEC4_SIZE)) - 1;
+ for (i = 0, index = vkd3d_popcount(mask); i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
+
+ chain_id = vkd3d_spirv_build_op_access_chain1(builder,
+ ptr_type_id, output_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, index));
+ object_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, val_id, write_mask,
+ output_info->component_type, VKD3D_SHADER_NO_SWIZZLE, VKD3DSP_WRITEMASK_0 << i);
+ vkd3d_dxbc_compiler_emit_store(compiler, chain_id, VKD3DSP_WRITEMASK_0,
+ output_info->component_type, SpvStorageClassOutput, VKD3DSP_WRITEMASK_0 << i, object_id);
+ ++index;
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_shader_epilogue_function(struct vkd3d_dxbc_compiler *compiler)
+{
+ uint32_t param_type_id[MAX_REG_OUTPUT + 1], param_id[MAX_REG_OUTPUT + 1] = {0};
+ uint32_t void_id, type_id, ptr_type_id, function_type_id, function_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_signature *signature;
+ const struct vkd3d_shader_phase *phase;
+ uint32_t output_index_id = 0;
+ bool is_patch_constant;
+ unsigned int i, count;
+ DWORD variable_idx;
+
+ STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(param_id));
+ STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(param_type_id));
+ STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(compiler->private_output_variable_array_idx));
+ STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(compiler->private_output_variable_write_mask));
+
+ phase = vkd3d_dxbc_compiler_get_current_shader_phase(compiler);
+ is_patch_constant = phase && (phase->type == VKD3DSIH_HS_FORK_PHASE || phase->type == VKD3DSIH_HS_JOIN_PHASE);
+
+ signature = is_patch_constant ? compiler->patch_constant_signature : compiler->output_signature;
+
+ function_id = compiler->epilogue_function_id;
+
+ void_id = vkd3d_spirv_get_op_type_void(builder);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 4);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
+ for (i = 0, count = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
+ {
+ if (compiler->private_output_variable[i])
+ param_type_id[count++] = ptr_type_id;
+ }
+ function_type_id = vkd3d_spirv_get_op_type_function(builder, void_id, param_type_id, count);
+
+ vkd3d_spirv_build_op_function(builder, void_id, function_id,
+ SpvFunctionControlMaskNone, function_type_id);
+
+ for (i = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
+ {
+ if (compiler->private_output_variable[i])
+ param_id[i] = vkd3d_spirv_build_op_function_parameter(builder, ptr_type_id);
+ }
+
+ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
+
+ for (i = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
+ {
+ if (compiler->private_output_variable[i])
+ param_id[i] = vkd3d_spirv_build_op_load(builder, type_id, param_id[i], SpvMemoryAccessMaskNone);
+ }
+
+ if (is_control_point_phase(phase))
+ output_index_id = vkd3d_dxbc_compiler_emit_load_invocation_id(compiler);
+
+ for (i = 0; i < signature->element_count; ++i)
+ {
+ variable_idx = vkd3d_dxbc_compiler_get_output_variable_index(compiler,
+ signature->elements[i].register_index);
+
+ if (!param_id[variable_idx])
+ continue;
+
+ vkd3d_dxbc_compiler_emit_store_shader_output(compiler,
+ &signature->elements[i], &compiler->output_info[i], output_index_id,
+ param_id[variable_idx], compiler->private_output_variable_write_mask[variable_idx]);
+ }
+
+ vkd3d_spirv_build_op_return(&compiler->spirv_builder);
+ vkd3d_spirv_build_op_function_end(builder);
+
+ memset(compiler->private_output_variable, 0, sizeof(compiler->private_output_variable));
+ memset(compiler->private_output_variable_array_idx, 0, sizeof(compiler->private_output_variable_array_idx));
+ memset(compiler->private_output_variable_write_mask, 0, sizeof(compiler->private_output_variable_write_mask));
+ compiler->epilogue_function_id = 0;
+}
+
+static void vkd3d_dxbc_compiler_emit_hull_shader_builtins(struct vkd3d_dxbc_compiler *compiler)
+{
+ struct vkd3d_shader_dst_param dst;
+
+ memset(&dst, 0, sizeof(dst));
+ dst.reg.type = VKD3DSPR_OUTPOINTID;
+ dst.reg.idx[0].offset = ~0u;
+ dst.reg.idx[1].offset = ~0u;
+ dst.write_mask = VKD3DSP_WRITEMASK_0;
+ vkd3d_dxbc_compiler_emit_input_register(compiler, &dst);
+}
+
+static void vkd3d_dxbc_compiler_emit_hull_shader_patch_constants(struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_shader_signature *signature = compiler->patch_constant_signature;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t register_count = 0;
+ unsigned int signature_idx;
+
+ for (signature_idx = 0; signature_idx < signature->element_count; ++signature_idx)
+ register_count = max(register_count, signature->elements[signature_idx].register_index + 1);
+
+ if (!register_count)
+ return;
+
+ compiler->hs.patch_constants_id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream,
+ SpvStorageClassPrivate, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, register_count);
+ vkd3d_spirv_build_op_name(builder, compiler->hs.patch_constants_id, "opc");
+}
+
+static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ switch (compiler->shader_type)
+ {
+ case VKD3D_SHADER_TYPE_VERTEX:
+ vkd3d_spirv_set_execution_model(builder, SpvExecutionModelVertex);
+ break;
+ case VKD3D_SHADER_TYPE_HULL:
+ vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationControl);
+ vkd3d_dxbc_compiler_emit_hull_shader_builtins(compiler);
+ vkd3d_dxbc_compiler_emit_hull_shader_patch_constants(compiler);
+ break;
+ case VKD3D_SHADER_TYPE_DOMAIN:
+ vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationEvaluation);
+ break;
+ case VKD3D_SHADER_TYPE_GEOMETRY:
+ vkd3d_spirv_set_execution_model(builder, SpvExecutionModelGeometry);
+ builder->invocation_count = 1;
+ break;
+ case VKD3D_SHADER_TYPE_PIXEL:
+ vkd3d_spirv_set_execution_model(builder, SpvExecutionModelFragment);
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeOriginUpperLeft, NULL, 0);
+ break;
+ case VKD3D_SHADER_TYPE_COMPUTE:
+ vkd3d_spirv_set_execution_model(builder, SpvExecutionModelGLCompute);
+ break;
+ default:
+ ERR("Invalid shader type %#x.\n", compiler->shader_type);
+ }
+
+ if (xfb_info && xfb_info->element_count)
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityTransformFeedback);
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeXfb, NULL, 0);
+ }
+
+ if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
+ {
+ vkd3d_spirv_builder_begin_main_function(builder);
+
+ vkd3d_dxbc_compiler_emit_shader_signature_outputs(compiler);
+ }
+}
+
+static size_t vkd3d_dxbc_compiler_get_current_function_location(struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_phase *phase;
+
+ if ((phase = vkd3d_dxbc_compiler_get_current_shader_phase(compiler)))
+ return phase->function_location;
+
+ return builder->main_function_location;
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_global_flags(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ unsigned int flags = instruction->flags;
+
+ if (flags & VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL)
+ {
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeEarlyFragmentTests, NULL, 0);
+ flags &= ~VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL;
+ }
+
+ if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS))
+ FIXME("Unhandled global flags %#x.\n", flags);
+ else
+ WARN("Unhandled global flags %#x.\n", flags);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_temps(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ size_t function_location;
+ unsigned int i;
+ uint32_t id;
+
+ function_location = vkd3d_dxbc_compiler_get_current_function_location(compiler);
+ vkd3d_spirv_begin_function_stream_insertion(builder, function_location);
+
+ assert(!compiler->temp_count);
+ compiler->temp_count = instruction->declaration.count;
+ for (i = 0; i < compiler->temp_count; ++i)
+ {
+ id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->function_stream,
+ SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+ if (!i)
+ compiler->temp_id = id;
+ assert(id == compiler->temp_id + i);
+
+ vkd3d_spirv_build_op_name(builder, id, "r%u", i);
+ }
+
+ vkd3d_spirv_end_function_stream_insertion(builder);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_indexable_temp(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ struct vkd3d_shader_register reg;
+ struct vkd3d_symbol reg_symbol;
+ size_t function_location;
+ uint32_t id;
+
+ if (temp->component_count != 4)
+ FIXME("Unhandled component count %u.\n", temp->component_count);
+
+ memset(®, 0, sizeof(reg));
+ reg.type = VKD3DSPR_IDXTEMP;
+ reg.idx[0].offset = temp->register_idx;
+ reg.idx[1].offset = ~0u;
+
+ function_location = vkd3d_dxbc_compiler_get_current_function_location(compiler);
+ vkd3d_spirv_begin_function_stream_insertion(builder, function_location);
+
+ id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->function_stream,
+ SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, temp->register_size);
+
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, id, ®);
+
+ vkd3d_spirv_end_function_stream_insertion(builder);
+
+ vkd3d_symbol_make_register(®_symbol, ®);
+ vkd3d_symbol_set_register_info(®_symbol, id,
+ SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL);
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+}
+
+static void vkd3d_dxbc_compiler_emit_push_constant_buffers(struct vkd3d_dxbc_compiler *compiler)
+{
+ const SpvStorageClass storage_class = SpvStorageClassPushConstant;
+ uint32_t vec4_id, length_id, struct_id, pointer_type_id, var_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int i, j, count, reg_idx;
+ struct vkd3d_symbol reg_symbol;
+ uint32_t *member_ids;
+
+ count = 0;
+ for (i = 0; i < compiler->shader_interface.push_constant_buffer_count; ++i)
+ {
+ const struct vkd3d_push_constant_buffer_binding *cb = &compiler->push_constants[i];
+
+ if (cb->reg.type)
+ ++count;
+ }
+ if (!count)
+ return;
+
+ if (!(member_ids = vkd3d_calloc(count, sizeof(*member_ids))))
+ return;
+
+ vec4_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+
+ for (i = 0, j = 0; i < compiler->shader_interface.push_constant_buffer_count; ++i)
+ {
+ const struct vkd3d_push_constant_buffer_binding *cb = &compiler->push_constants[i];
+ if (!cb->reg.type)
+ continue;
+
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, cb->size);
+ member_ids[j] = vkd3d_spirv_build_op_type_array(builder, vec4_id, length_id);
+ vkd3d_spirv_build_op_decorate1(builder, member_ids[j], SpvDecorationArrayStride, 16);
+
+ ++j;
+ }
+
+ struct_id = vkd3d_spirv_build_op_type_struct(builder, member_ids, count);
+ vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0);
+ vkd3d_spirv_build_op_name(builder, struct_id, "push_cb");
+ vkd3d_free(member_ids);
+
+ pointer_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id);
+ var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ pointer_type_id, storage_class, 0);
+
+ for (i = 0, j = 0; i < compiler->shader_interface.push_constant_buffer_count; ++i)
+ {
+ const struct vkd3d_push_constant_buffer_binding *cb = &compiler->push_constants[i];
+ if (!cb->reg.type)
+ continue;
+
+ reg_idx = cb->reg.idx[0].offset;
+ vkd3d_spirv_build_op_member_decorate1(builder, struct_id, j,
+ SpvDecorationOffset, cb->pc.offset);
+ vkd3d_spirv_build_op_member_name(builder, struct_id, j, "cb%u", reg_idx);
+
+ vkd3d_symbol_make_register(®_symbol, &cb->reg);
+ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class,
+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL);
+ reg_symbol.info.reg.member_idx = j;
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+
+ ++j;
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t vec4_id, array_type_id, length_id, struct_id, pointer_type_id, var_id;
+ const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const SpvStorageClass storage_class = SpvStorageClassUniform;
+ const struct vkd3d_shader_register *reg = &cb->src.reg;
+ struct vkd3d_push_constant_buffer_binding *push_cb;
+ struct vkd3d_symbol reg_symbol;
+
+ assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC));
+
+ if ((push_cb = vkd3d_dxbc_compiler_find_push_constant_buffer(compiler, cb)))
+ {
+ /* Push constant buffers are handled in
+ * vkd3d_dxbc_compiler_emit_push_constant_buffers().
+ */
+ unsigned int cb_size_in_bytes = cb->size * VKD3D_VEC4_SIZE * sizeof(uint32_t);
+ push_cb->reg = *reg;
+ push_cb->size = cb->size;
+ if (cb_size_in_bytes > push_cb->pc.size)
+ {
+ WARN("Constant buffer size %u exceeds push constant size %u.\n",
+ cb_size_in_bytes, push_cb->pc.size);
+ }
+ return;
+ }
+
+ vec4_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, cb->size);
+ array_type_id = vkd3d_spirv_build_op_type_array(builder, vec4_id, length_id);
+ vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 16);
+
+ struct_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1);
+ vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0);
+ vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0);
+ vkd3d_spirv_build_op_name(builder, struct_id, "cb%u_struct", cb->size);
+
+ pointer_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id);
+ var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ pointer_type_id, storage_class, 0);
+
+ vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler,
+ var_id, reg, cb->register_space, cb->register_index, VKD3D_SHADER_RESOURCE_BUFFER, false);
+
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+
+ vkd3d_symbol_make_register(®_symbol, reg);
+ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class,
+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL);
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_immediate_constant_buffer(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb;
+ uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ struct vkd3d_shader_register reg;
+ struct vkd3d_symbol reg_symbol;
+ unsigned int i;
+
+ if (!(elements = vkd3d_calloc(icb->vec4_count, sizeof(*elements))))
+ return;
+ for (i = 0; i < icb->vec4_count; ++i)
+ elements[i] = vkd3d_dxbc_compiler_get_constant(compiler,
+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, icb->vec4_count);
+ type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id);
+ const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->vec4_count);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
+ icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ ptr_type_id, SpvStorageClassPrivate, const_id);
+ vkd3d_spirv_build_op_name(builder, icb_id, "icb");
+ vkd3d_free(elements);
+
+ memset(®, 0, sizeof(reg));
+ reg.type = VKD3DSPR_IMMCONSTBUFFER;
+ vkd3d_symbol_make_register(®_symbol, ®);
+ vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate,
+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL);
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_sampler *sampler = &instruction->declaration.sampler;
+ const SpvStorageClass storage_class = SpvStorageClassUniformConstant;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_register *reg = &sampler->src.reg;
+ uint32_t type_id, ptr_type_id, var_id;
+ struct vkd3d_symbol reg_symbol;
+
+ vkd3d_symbol_make_sampler(®_symbol, reg);
+ reg_symbol.info.sampler.register_space = sampler->register_space;
+ reg_symbol.info.sampler.register_index = sampler->register_index;
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+
+ if (vkd3d_dxbc_compiler_has_combined_sampler(compiler, NULL, sampler))
+ return;
+
+ type_id = vkd3d_spirv_get_op_type_sampler(builder);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
+ var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ ptr_type_id, storage_class, 0);
+
+ vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler, var_id, reg,
+ sampler->register_space, sampler->register_index, VKD3D_SHADER_RESOURCE_NONE, false);
+
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+
+ vkd3d_symbol_make_register(®_symbol, reg);
+ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class,
+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL);
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+}
+
+static const struct vkd3d_spirv_resource_type *vkd3d_dxbc_compiler_enable_resource_type(
+ struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_resource_type resource_type, bool is_uav)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_spirv_resource_type *resource_type_info;
+
+ if (!(resource_type_info = vkd3d_get_spirv_resource_type(resource_type)))
+ return NULL;
+
+ if (resource_type_info->capability)
+ vkd3d_spirv_enable_capability(builder, resource_type_info->capability);
+ if (is_uav && resource_type_info->uav_capability)
+ vkd3d_spirv_enable_capability(builder, resource_type_info->uav_capability);
+
+ return resource_type_info;
+}
+
+static SpvImageFormat image_format_for_image_read(enum vkd3d_shader_component_type data_type)
+{
+ /* The following formats are supported by Direct3D 11 hardware for UAV
+ * typed loads. A newer hardware may support more formats for UAV typed
+ * loads (see StorageImageReadWithoutFormat SPIR-V capability).
+ */
+ switch (data_type)
+ {
+ case VKD3D_SHADER_COMPONENT_FLOAT:
+ return SpvImageFormatR32f;
+ case VKD3D_SHADER_COMPONENT_INT:
+ return SpvImageFormatR32i;
+ case VKD3D_SHADER_COMPONENT_UINT:
+ return SpvImageFormatR32ui;
+ default:
+ FIXME("Unhandled type %#x.\n", data_type);
+ return SpvImageFormatUnknown;
+ }
+}
+
+static const struct vkd3d_shader_descriptor_info *vkd3d_dxbc_compiler_get_descriptor_info(
+ struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_descriptor_type type,
+ unsigned int register_space, unsigned int register_index)
+{
+ const struct vkd3d_shader_scan_descriptor_info *descriptor_info = compiler->scan_descriptor_info;
+ const struct vkd3d_shader_descriptor_info *d;
+ unsigned int i;
+
+ for (i = 0; i < descriptor_info->descriptor_count; ++i)
+ {
+ d = &descriptor_info->descriptors[i];
+ if (d->type == type && d->register_space == register_space && d->register_index == register_index)
+ return d;
+ }
+
+ return NULL;
+}
+
+static uint32_t vkd3d_dxbc_compiler_get_image_type_id(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, unsigned int register_space, unsigned int register_index,
+ const struct vkd3d_spirv_resource_type *resource_type_info, enum vkd3d_shader_component_type data_type,
+ bool raw_structured, uint32_t depth)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_descriptor_info *d;
+ uint32_t sampled_type_id;
+ SpvImageFormat format;
+
+ format = SpvImageFormatUnknown;
+ if (reg->type == VKD3DSPR_UAV)
+ {
+ d = vkd3d_dxbc_compiler_get_descriptor_info(compiler,
+ VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, register_space, register_index);
+ if (raw_structured || (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ))
+ format = image_format_for_image_read(data_type);
+ }
+
+ sampled_type_id = vkd3d_spirv_get_type_id(builder, data_type, 1);
+ return vkd3d_spirv_get_op_type_image(builder, sampled_type_id, resource_type_info->dim,
+ depth, resource_type_info->arrayed, resource_type_info->ms,
+ reg->type == VKD3DSPR_UAV ? 2 : 1, format);
+}
+
+static void vkd3d_dxbc_compiler_emit_combined_sampler_declarations(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *resource, unsigned int resource_space, unsigned int resource_index,
+ enum vkd3d_shader_resource_type resource_type, enum vkd3d_shader_component_type sampled_type,
+ unsigned int structure_stride, bool raw, const struct vkd3d_spirv_resource_type *resource_type_info)
+{
+ const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface;
+ const SpvStorageClass storage_class = SpvStorageClassUniformConstant;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_combined_resource_sampler *current;
+ uint32_t image_type_id, type_id, ptr_type_id, var_id;
+ enum vkd3d_shader_binding_flag resource_type_flag;
+ const struct vkd3d_shader_descriptor_info *d;
+ struct vkd3d_symbol symbol;
+ unsigned int i;
+ bool depth;
+
+ resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER
+ ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE;
+
+ for (i = 0; i < shader_interface->combined_sampler_count; ++i)
+ {
+ current = &shader_interface->combined_samplers[i];
+
+ if (current->resource_space != resource_space || current->resource_index != resource_index)
+ continue;
+
+ if (!(current->flags & resource_type_flag))
+ continue;
+
+ if (!vkd3d_dxbc_compiler_check_shader_visibility(compiler, current->shader_visibility))
+ continue;
+
+ if (current->binding.count != 1)
+ {
+ FIXME("Descriptor arrays are not supported.\n");
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING,
+ "Combined descriptor binding for resource %u, space %u, "
+ "and sampler %u, space %u has unsupported ‘count’ %u.",
+ resource_index, resource_space, current->sampler_index,
+ current->sampler_space, current->binding.count);
+ }
+
+ d = vkd3d_dxbc_compiler_get_descriptor_info(compiler,
+ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, current->sampler_space, current->sampler_index);
+ depth = current->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX
+ && (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE);
+
+ image_type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, resource, resource_space,
+ resource_index, resource_type_info, sampled_type, structure_stride || raw, depth);
+ type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image_type_id);
+
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
+ var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ ptr_type_id, storage_class, 0);
+
+ vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, ¤t->binding);
+
+ if (current->sampler_index == VKD3D_SHADER_DUMMY_SAMPLER_INDEX)
+ vkd3d_spirv_build_op_name(builder, var_id, "t%u_%u_dummy_sampler", resource_space, resource_index);
+ else
+ vkd3d_spirv_build_op_name(builder, var_id, "t%u_%u_s%u_%u", resource_space, resource_index,
+ current->sampler_space, current->sampler_index);
+
+ vkd3d_symbol_make_combined_sampler(&symbol, resource,
+ current->sampler_index == VKD3D_SHADER_DUMMY_SAMPLER_INDEX ? 0 : current->sampler_space,
+ current->sampler_index);
+ symbol.id = var_id;
+ symbol.info.resource.register_space = resource_space;
+ symbol.info.resource.register_index = resource_index;
+ symbol.info.resource.sampled_type = sampled_type;
+ symbol.info.resource.type_id = image_type_id;
+ symbol.info.resource.resource_type_info = resource_type_info;
+ symbol.info.resource.structure_stride = structure_stride;
+ symbol.info.resource.raw = raw;
+ symbol.info.resource.uav_counter_id = 0;
+ vkd3d_dxbc_compiler_put_symbol(compiler, &symbol);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_resource *resource, enum vkd3d_shader_resource_type resource_type,
+ enum vkd3d_data_type resource_data_type, unsigned int structure_stride, bool raw)
+{
+ uint32_t counter_type_id, type_id, ptr_type_id, var_id, counter_var_id = 0;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ SpvStorageClass storage_class = SpvStorageClassUniformConstant;
+ const struct vkd3d_shader_register *reg = &resource->reg.reg;
+ const struct vkd3d_spirv_resource_type *resource_type_info;
+ unsigned int register_space = resource->register_space;
+ unsigned int register_index = resource->register_index;
+ enum vkd3d_shader_component_type sampled_type;
+ struct vkd3d_symbol resource_symbol;
+ bool is_uav;
+
+ is_uav = reg->type == VKD3DSPR_UAV;
+ if (!(resource_type_info = vkd3d_dxbc_compiler_enable_resource_type(compiler,
+ resource_type, is_uav)))
+ {
+ FIXME("Unrecognized resource type.\n");
+ return;
+ }
+
+ sampled_type = vkd3d_component_type_from_data_type(resource_data_type);
+
+ if (vkd3d_dxbc_compiler_has_combined_sampler(compiler, resource, NULL))
+ {
+ vkd3d_dxbc_compiler_emit_combined_sampler_declarations(compiler, reg, register_space,
+ register_index, resource_type, sampled_type, structure_stride, raw, resource_type_info);
+ return;
+ }
+
+ if (compiler->ssbo_uavs && is_uav && resource_type == VKD3D_SHADER_RESOURCE_BUFFER)
+ {
+ uint32_t array_type_id, struct_id;
+
+ type_id = vkd3d_spirv_get_type_id(builder, sampled_type, 1);
+
+ array_type_id = vkd3d_spirv_get_op_type_runtime_array(builder, type_id);
+ vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4);
+
+ struct_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1);
+ vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBufferBlock, NULL, 0);
+ vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0);
+
+ type_id = struct_id;
+ storage_class = SpvStorageClassUniform;
+ }
+ else
+ {
+ type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, reg, register_space,
+ register_index, resource_type_info, sampled_type, structure_stride || raw, 0);
+ }
+
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
+ var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ ptr_type_id, storage_class, 0);
+
+ vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler, var_id, reg,
+ register_space, register_index, resource_type, false);
+
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+
+ if (is_uav)
+ {
+ const struct vkd3d_shader_descriptor_info *d;
+
+ d = vkd3d_dxbc_compiler_get_descriptor_info(compiler,
+ VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, register_space, register_index);
+
+ if (!(d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ))
+ vkd3d_spirv_build_op_decorate(builder, var_id, SpvDecorationNonReadable, NULL, 0);
+
+ if (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER)
+ {
+ assert(structure_stride); /* counters are valid only for structured buffers */
+
+ counter_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ if (vkd3d_dxbc_compiler_is_opengl_target(compiler))
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityAtomicStorage);
+ storage_class = SpvStorageClassAtomicCounter;
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, counter_type_id);
+ }
+ else if (compiler->ssbo_uavs)
+ {
+ uint32_t length_id, array_type_id, struct_id;
+
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 1);
+ array_type_id = vkd3d_spirv_build_op_type_array(builder, counter_type_id, length_id);
+ vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4);
+
+ struct_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1);
+ vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBufferBlock, NULL, 0);
+ vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0);
+
+ storage_class = SpvStorageClassUniform;
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id);
+ }
+
+ counter_var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ ptr_type_id, storage_class, 0);
+
+ vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler,
+ counter_var_id, reg, register_space, register_index, resource_type, true);
+
+ vkd3d_spirv_build_op_name(builder, counter_var_id, "u%u_counter", reg->idx[0].offset);
+ }
+ }
+
+ vkd3d_symbol_make_resource(&resource_symbol, reg);
+ resource_symbol.id = var_id;
+ resource_symbol.info.resource.register_space = register_space;
+ resource_symbol.info.resource.register_index = register_index;
+ resource_symbol.info.resource.sampled_type = sampled_type;
+ resource_symbol.info.resource.type_id = type_id;
+ resource_symbol.info.resource.resource_type_info = resource_type_info;
+ resource_symbol.info.resource.structure_stride = structure_stride;
+ resource_symbol.info.resource.raw = raw;
+ resource_symbol.info.resource.uav_counter_id = counter_var_id;
+ vkd3d_dxbc_compiler_put_symbol(compiler, &resource_symbol);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_resource(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_semantic *semantic = &instruction->declaration.semantic;
+
+ if (instruction->flags)
+ FIXME("Unhandled UAV flags %#x.\n", instruction->flags);
+
+ vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &semantic->resource,
+ semantic->resource_type, semantic->resource_data_type, 0, false);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_resource_raw(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_raw_resource *resource = &instruction->declaration.raw_resource;
+
+ if (instruction->flags)
+ FIXME("Unhandled UAV flags %#x.\n", instruction->flags);
+
+ vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &resource->resource,
+ VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_DATA_UINT, 0, true);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_resource_structured(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_structured_resource *resource = &instruction->declaration.structured_resource;
+ unsigned int stride = resource->byte_stride;
+
+ if (instruction->flags)
+ FIXME("Unhandled UAV flags %#x.\n", instruction->flags);
+
+ vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &resource->resource,
+ VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_DATA_UINT, stride / 4, false);
+}
+
+static void vkd3d_dxbc_compiler_emit_workgroup_memory(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, unsigned int size, unsigned int structure_stride)
+{
+ uint32_t type_id, array_type_id, length_id, pointer_type_id, var_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const SpvStorageClass storage_class = SpvStorageClassWorkgroup;
+ struct vkd3d_symbol reg_symbol;
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, size);
+ array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id);
+
+ pointer_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, array_type_id);
+ var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ pointer_type_id, storage_class, 0);
+
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+
+ vkd3d_symbol_make_register(®_symbol, reg);
+ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class,
+ VKD3D_SHADER_COMPONENT_UINT, VKD3DSP_WRITEMASK_0);
+ reg_symbol.info.reg.structure_stride = structure_stride;
+ vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_tgsm_raw(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_tgsm_raw *tgsm_raw = &instruction->declaration.tgsm_raw;
+ vkd3d_dxbc_compiler_emit_workgroup_memory(compiler, &tgsm_raw->reg.reg,
+ tgsm_raw->byte_count / 4, 0);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_tgsm_structured(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_tgsm_structured *tgsm_structured = &instruction->declaration.tgsm_structured;
+ unsigned int stride = tgsm_structured->byte_stride / 4;
+ vkd3d_dxbc_compiler_emit_workgroup_memory(compiler, &tgsm_structured->reg.reg,
+ tgsm_structured->structure_count * stride, stride);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_input(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst;
+ const struct vkd3d_shader_phase *phase;
+
+ if ((phase = vkd3d_dxbc_compiler_get_current_shader_phase(compiler)))
+ vkd3d_dxbc_compiler_emit_shader_phase_input(compiler, phase, dst);
+ else if (vkd3d_shader_register_is_input(&dst->reg) || dst->reg.type == VKD3DSPR_PATCHCONST)
+ vkd3d_dxbc_compiler_emit_input(compiler, dst, VKD3D_SIV_NONE, VKD3DSIM_NONE);
+ else
+ vkd3d_dxbc_compiler_emit_input_register(compiler, dst);
+
+ if (dst->reg.type == VKD3DSPR_OUTCONTROLPOINT)
+ compiler->use_vocp = true;
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_input_ps(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ vkd3d_dxbc_compiler_emit_input(compiler, &instruction->declaration.dst, VKD3D_SIV_NONE, instruction->flags);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_input_ps_sysval(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_register_semantic *semantic = &instruction->declaration.register_semantic;
+
+ vkd3d_dxbc_compiler_emit_input(compiler, &semantic->reg, semantic->sysval_semantic, instruction->flags);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_input_sysval(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ vkd3d_dxbc_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg,
+ instruction->declaration.register_semantic.sysval_semantic, VKD3DSIM_NONE);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_output(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst;
+
+ if (vkd3d_shader_register_is_output(&dst->reg))
+ vkd3d_dxbc_compiler_emit_output(compiler, dst, VKD3D_SIV_NONE);
+ else
+ vkd3d_dxbc_compiler_emit_output_register(compiler, dst);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_output_siv(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ enum vkd3d_shader_input_sysval_semantic sysval;
+ const struct vkd3d_shader_dst_param *dst;
+
+ dst = &instruction->declaration.register_semantic.reg;
+ sysval = instruction->declaration.register_semantic.sysval_semantic;
+
+ vkd3d_dxbc_compiler_emit_output(compiler, dst, sysval);
+}
+
+static bool vkd3d_dxbc_compiler_check_index_range(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_index_range *range)
+{
+ const struct vkd3d_shader_register *reg = &range->dst.reg;
+ struct vkd3d_shader_register_info reg_info;
+ struct vkd3d_shader_register current_reg;
+ struct vkd3d_symbol reg_symbol;
+ unsigned int i;
+ uint32_t id;
+
+ current_reg = *reg;
+ vkd3d_symbol_make_register(®_symbol, ¤t_reg);
+ if (!vkd3d_dxbc_compiler_get_register_info(compiler, ¤t_reg, ®_info))
+ {
+ ERR("Failed to get register info.\n");
+ return false;
+ }
+
+ /* FIXME: We should check if it's an array. */
+ if (!reg_info.is_aggregate)
+ {
+ FIXME("Unhandled register %#x.\n", reg->type);
+ return false;
+ }
+ id = reg_info.id;
+
+ for (i = reg->idx[0].offset; i < reg->idx[0].offset + range->register_count; ++i)
+ {
+ current_reg.idx[0].offset = i;
+ vkd3d_symbol_make_register(®_symbol, ¤t_reg);
+
+ if (range->dst.write_mask != reg_info.write_mask
+ || vkd3d_write_mask_component_count(reg_info.write_mask) != 1)
+ {
+ FIXME("Unhandled index range write mask %#x (%#x).\n",
+ range->dst.write_mask, reg_info.write_mask);
+ return false;
+ }
+
+ if (reg_info.id != id)
+ {
+ FIXME("Unhandled index range %#x, %u.\n", reg->type, i);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_index_range(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_index_range *range = &instruction->declaration.index_range;
+
+ if (!vkd3d_dxbc_compiler_check_index_range(compiler, range))
+ FIXME("Ignoring dcl_index_range %#x %u.\n", range->dst.reg.type, range->register_count);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_stream(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ unsigned int stream_idx = instruction->src[0].reg.idx[0].offset;
+
+ if (stream_idx)
+ FIXME("Multiple streams are not supported yet.\n");
+}
+
+static void vkd3d_dxbc_compiler_emit_output_vertex_count(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ vkd3d_dxbc_compiler_emit_execution_mode1(compiler,
+ SpvExecutionModeOutputVertices, instruction->declaration.count);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_input_primitive(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ enum vkd3d_primitive_type primitive_type = instruction->declaration.primitive_type.type;
+ SpvExecutionMode mode;
+
+ switch (primitive_type)
+ {
+ case VKD3D_PT_POINTLIST:
+ mode = SpvExecutionModeInputPoints;
+ break;
+ case VKD3D_PT_LINELIST:
+ mode = SpvExecutionModeInputLines;
+ break;
+ case VKD3D_PT_LINELIST_ADJ:
+ mode = SpvExecutionModeInputLinesAdjacency;
+ break;
+ case VKD3D_PT_TRIANGLELIST:
+ mode = SpvExecutionModeTriangles;
+ break;
+ case VKD3D_PT_TRIANGLELIST_ADJ:
+ mode = SpvExecutionModeInputTrianglesAdjacency;
+ break;
+ default:
+ FIXME("Unhandled primitive type %#x.\n", primitive_type);
+ return;
+ }
+
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, mode, NULL, 0);
+}
+
+static void vkd3d_dxbc_compiler_emit_point_size(struct vkd3d_dxbc_compiler *compiler)
+{
+ static const struct vkd3d_spirv_builtin point_size = {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInPointSize};
+
+ /* Set the point size. Point sprites are not supported in d3d10+, but
+ * point primitives can still be used with e.g. stream output. Vulkan
+ * requires the point size to always be explicitly defined when outputting
+ * points. */
+ vkd3d_spirv_build_op_store(&compiler->spirv_builder,
+ vkd3d_dxbc_compiler_emit_builtin_variable(compiler, &point_size, SpvStorageClassOutput, 0),
+ vkd3d_dxbc_compiler_get_constant_float(compiler, 1.0f), SpvMemoryAccessMaskNone);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_output_topology(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ enum vkd3d_primitive_type primitive_type = instruction->declaration.primitive_type.type;
+ SpvExecutionMode mode;
+
+ switch (primitive_type)
+ {
+ case VKD3D_PT_POINTLIST:
+ mode = SpvExecutionModeOutputPoints;
+ vkd3d_dxbc_compiler_emit_point_size(compiler);
+ break;
+ case VKD3D_PT_LINESTRIP:
+ mode = SpvExecutionModeOutputLineStrip;
+ break;
+ case VKD3D_PT_TRIANGLESTRIP:
+ mode = SpvExecutionModeOutputTriangleStrip;
+ break;
+ default:
+ ERR("Unexpected primitive type %#x.\n", primitive_type);
+ return;
+ }
+
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, mode, NULL, 0);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_gs_instances(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ compiler->spirv_builder.invocation_count = instruction->declaration.count;
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_tessellator_domain(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ enum vkd3d_tessellator_domain domain = instruction->declaration.tessellator_domain;
+ SpvExecutionMode mode;
+
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && vkd3d_dxbc_compiler_is_opengl_target(compiler))
+ return;
+
+ switch (domain)
+ {
+ case VKD3D_TESSELLATOR_DOMAIN_LINE:
+ mode = SpvExecutionModeIsolines;
+ break;
+ case VKD3D_TESSELLATOR_DOMAIN_TRIANGLE:
+ mode = SpvExecutionModeTriangles;
+ break;
+ case VKD3D_TESSELLATOR_DOMAIN_QUAD:
+ mode = SpvExecutionModeQuads;
+ break;
+ default:
+ FIXME("Invalid tessellator domain %#x.\n", domain);
+ return;
+ }
+
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, mode, NULL, 0);
+}
+
+static void vkd3d_dxbc_compiler_emit_tessellator_output_primitive(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_tessellator_output_primitive primitive)
+{
+ SpvExecutionMode mode;
+
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && vkd3d_dxbc_compiler_is_opengl_target(compiler))
+ return;
+
+ switch (primitive)
+ {
+ case VKD3D_SHADER_TESSELLATOR_OUTPUT_POINT:
+ mode = SpvExecutionModePointMode;
+ break;
+ case VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE:
+ return;
+ case VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CW:
+ mode = SpvExecutionModeVertexOrderCw;
+ break;
+ case VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW:
+ mode = SpvExecutionModeVertexOrderCcw;
+ break;
+ default:
+ FIXME("Invalid tessellator output primitive %#x.\n", primitive);
+ return;
+ }
+
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, mode, NULL, 0);
+}
+
+static void vkd3d_dxbc_compiler_emit_tessellator_partitioning(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_tessellator_partitioning partitioning)
+{
+ SpvExecutionMode mode;
+
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && vkd3d_dxbc_compiler_is_opengl_target(compiler))
+ return;
+
+ switch (partitioning)
+ {
+ case VKD3D_SHADER_TESSELLATOR_PARTITIONING_INTEGER:
+ case VKD3D_SHADER_TESSELLATOR_PARTITIONING_POW2:
+ mode = SpvExecutionModeSpacingEqual;
+ break;
+ case VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD:
+ mode = SpvExecutionModeSpacingFractionalOdd;
+ break;
+ case VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN:
+ mode = SpvExecutionModeSpacingFractionalEven;
+ break;
+ default:
+ FIXME("Invalid tessellator partitioning %#x.\n", partitioning);
+ return;
+ }
+
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, mode, NULL, 0);
+}
+
+static void vkd3d_dxbc_compiler_emit_dcl_thread_group(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_thread_group_size *group_size = &instruction->declaration.thread_group_size;
+ const uint32_t local_size[] = {group_size->x, group_size->y, group_size->z};
+
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler,
+ SpvExecutionModeLocalSize, local_size, ARRAY_SIZE(local_size));
+}
+
+static void vkd3d_dxbc_compiler_leave_shader_phase(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_phase *phase)
+{
+ const struct vkd3d_shader_signature *signature = compiler->output_signature;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ struct vkd3d_symbol reg_symbol, *symbol;
+ struct vkd3d_shader_register reg;
+ struct rb_entry *entry;
+ unsigned int i;
+
+ vkd3d_spirv_build_op_function_end(builder);
+
+ if (compiler->epilogue_function_id)
+ {
+ vkd3d_dxbc_compiler_emit_shader_phase_name(compiler, compiler->epilogue_function_id, phase, "_epilogue");
+ vkd3d_dxbc_compiler_emit_shader_epilogue_function(compiler);
+ }
+
+ compiler->temp_id = 0;
+ compiler->temp_count = 0;
+
+ /*
+ * vocp inputs in fork and join shader phases are outputs of the control
+ * point phase. Reinsert symbols for vocp registers while leaving the
+ * control point phase.
+ */
+ if (is_control_point_phase(phase))
+ {
+ memset(®, 0, sizeof(reg));
+ reg.idx[1].offset = ~0u;
+
+ /* Fork and join phases share output registers (patch constants).
+ * Control point phase has separate output registers. */
+ memset(compiler->output_info, 0, signature->element_count * sizeof(*compiler->output_info));
+ memset(compiler->private_output_variable, 0, sizeof(compiler->private_output_variable));
+ memset(compiler->private_output_variable_array_idx, 0, sizeof(compiler->private_output_variable_array_idx));
+ memset(compiler->private_output_variable_write_mask, 0, sizeof(compiler->private_output_variable_write_mask));
+
+ for (i = 0; i < signature->element_count; ++i)
+ {
+ const struct vkd3d_shader_signature_element *e = &signature->elements[i];
+
+ reg.type = VKD3DSPR_OUTPUT;
+ reg.idx[0].offset = e->register_index;
+ vkd3d_symbol_make_register(®_symbol, ®);
+ if ((entry = rb_get(&compiler->symbol_table, ®_symbol)))
+ {
+ rb_remove(&compiler->symbol_table, entry);
+
+ symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
+
+ reg.type = VKD3DSPR_OUTCONTROLPOINT;
+ reg.idx[1].offset = reg.idx[0].offset;
+ reg.idx[0].offset = compiler->output_control_point_count;
+ vkd3d_symbol_make_register(symbol, ®);
+ symbol->info.reg.is_aggregate = false;
+
+ if (rb_put(&compiler->symbol_table, symbol, entry) == -1)
+ {
+ ERR("Failed to insert vocp symbol entry (%s).\n", debug_vkd3d_symbol(symbol));
+ vkd3d_symbol_free(entry, NULL);
+ }
+ }
+ }
+ }
+
+ if (phase->type == VKD3DSIH_HS_FORK_PHASE || phase->type == VKD3DSIH_HS_JOIN_PHASE)
+ {
+ signature = compiler->patch_constant_signature;
+
+ memset(®, 0, sizeof(reg));
+ reg.idx[1].offset = ~0u;
+
+ for (i = 0; i < signature->element_count; ++i)
+ {
+ const struct vkd3d_shader_signature_element *e = &signature->elements[i];
+
+ reg.type = VKD3DSPR_OUTPUT;
+ reg.idx[0].offset = e->register_index;
+ vkd3d_symbol_make_register(®_symbol, ®);
+
+ if ((entry = rb_get(&compiler->symbol_table, ®_symbol)))
+ {
+ rb_remove(&compiler->symbol_table, entry);
+ vkd3d_symbol_free(entry, NULL);
+ }
+ }
+ }
+
+ if (phase->instance_count)
+ {
+ reg.type = phase->type == VKD3DSIH_HS_FORK_PHASE ? VKD3DSPR_FORKINSTID : VKD3DSPR_JOININSTID;
+ reg.idx[0].offset = ~0u;
+ vkd3d_symbol_make_register(®_symbol, ®);
+ if ((entry = rb_get(&compiler->symbol_table, ®_symbol)))
+ {
+ rb_remove(&compiler->symbol_table, entry);
+ vkd3d_symbol_free(entry, NULL);
+ }
+ }
+}
+
+static void vkd3d_dxbc_compiler_enter_shader_phase(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_phase *previous_phase;
+ struct vkd3d_shader_phase *phase;
+
+ if ((previous_phase = vkd3d_dxbc_compiler_get_current_shader_phase(compiler)))
+ vkd3d_dxbc_compiler_leave_shader_phase(compiler, previous_phase);
+
+ if (!vkd3d_array_reserve((void **)&compiler->shader_phases, &compiler->shader_phases_size,
+ compiler->shader_phase_count + 1, sizeof(*compiler->shader_phases)))
+ return;
+ phase = &compiler->shader_phases[compiler->shader_phase_count];
+
+ phase->type = instruction->handler_idx;
+ phase->idx = compiler->shader_phase_count;
+ phase->instance_count = 0;
+ phase->function_id = 0;
+ phase->instance_id = 0;
+ phase->function_location = 0;
+
+ ++compiler->shader_phase_count;
+}
+
+static int vkd3d_dxbc_compiler_emit_shader_phase_instance_count(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_shader_phase *phase = &compiler->shader_phases[compiler->shader_phase_count - 1];
+
+ if (!compiler->shader_phase_count
+ || (phase->type != VKD3DSIH_HS_FORK_PHASE && phase->type != VKD3DSIH_HS_JOIN_PHASE)
+ || phase->function_id)
+ {
+ WARN("Unexpected dcl_hs_{fork,join}_phase_instance_count instruction.\n");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ phase->instance_count = instruction->declaration.count;
+
+ vkd3d_dxbc_compiler_begin_shader_phase(compiler, phase);
+
+ return VKD3D_OK;
+}
+
+static const struct vkd3d_shader_phase *vkd3d_dxbc_compiler_get_control_point_phase(
+ struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_shader_phase *phase;
+
+ if (compiler->shader_phase_count < 1)
+ return NULL;
+
+ phase = &compiler->shader_phases[0];
+ if (is_control_point_phase(phase))
+ return phase;
+
+ return NULL;
+}
+
+static void vkd3d_dxbc_compiler_emit_default_control_point_phase(struct vkd3d_dxbc_compiler *compiler)
+{
+ const struct vkd3d_shader_signature *output_signature = compiler->output_signature;
+ const struct vkd3d_shader_signature *input_signature = compiler->input_signature;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, input_ptr_type_id, output_ptr_type_id;
+ const struct vkd3d_spirv_builtin *input_builtin;
+ enum vkd3d_shader_component_type component_type;
+ uint32_t input_id, output_id, dst_id, src_id;
+ unsigned int component_count;
+ uint32_t invocation_id;
+ unsigned int i;
+
+ invocation_id = vkd3d_dxbc_compiler_emit_load_invocation_id(compiler);
+
+ assert(input_signature->element_count == output_signature->element_count);
+ for (i = 0; i < output_signature->element_count; ++i)
+ {
+ const struct vkd3d_shader_signature_element *output = &output_signature->elements[i];
+ const struct vkd3d_shader_signature_element *input = &input_signature->elements[i];
+
+ assert(input->mask == output->mask);
+ assert(input->component_type == output->component_type);
+
+ if ((input_builtin = get_spirv_builtin_for_sysval(compiler, vkd3d_siv_from_sysval(input->sysval_semantic))))
+ {
+ component_type = input_builtin->component_type;
+ component_count = input_builtin->component_count;
+ }
+ else
+ {
+ component_type = input->component_type;
+ component_count = vkd3d_write_mask_component_count(input->mask);
+ }
+
+ if (input_builtin)
+ {
+ input_id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler,
+ input_builtin, SpvStorageClassInput, compiler->input_control_point_count);
+ }
+ else
+ {
+ input_id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream,
+ SpvStorageClassInput, component_type, component_count, compiler->input_control_point_count);
+ vkd3d_spirv_add_iface_variable(builder, input_id);
+ vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationLocation, input->register_index);
+ }
+ vkd3d_spirv_build_op_name(builder, input_id, "vicp%u", input->register_index);
+
+ output_id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream,
+ SpvStorageClassOutput, component_type, component_count, compiler->output_control_point_count);
+ vkd3d_spirv_add_iface_variable(builder, output_id);
+ vkd3d_spirv_build_op_decorate1(builder, output_id, SpvDecorationLocation, output->register_index);
+ vkd3d_spirv_build_op_name(builder, output_id, "vocp%u", output->register_index);
+
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
+ output_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id);
+ input_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassInput, type_id);
+
+ dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_id, invocation_id);
+ src_id = vkd3d_spirv_build_op_access_chain1(builder, input_ptr_type_id, input_id, invocation_id);
+ vkd3d_spirv_build_op_copy_memory(builder, dst_id, src_id, SpvMemoryAccessMaskNone);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_barrier(struct vkd3d_dxbc_compiler *compiler,
+ SpvScope execution_scope, SpvScope memory_scope, SpvMemorySemanticsMask semantics)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t execution_id, memory_id, semantics_id;
+
+ memory_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, memory_scope);
+ semantics_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, semantics);
+
+ if (execution_scope != SpvScopeMax)
+ {
+ execution_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, execution_scope);
+ vkd3d_spirv_build_op_control_barrier(builder, execution_id, memory_id, semantics_id);
+ }
+ else
+ {
+ vkd3d_spirv_build_op_memory_barrier(builder, memory_id, semantics_id);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_hull_shader_barrier(struct vkd3d_dxbc_compiler *compiler)
+{
+ vkd3d_dxbc_compiler_emit_barrier(compiler,
+ SpvScopeWorkgroup, SpvScopeInvocation, SpvMemorySemanticsMaskNone);
+}
+
+static void vkd3d_dxbc_compiler_emit_hull_shader_main(struct vkd3d_dxbc_compiler *compiler)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_phase *control_point_phase, *phase;
+ uint32_t phase_instance_id;
+ unsigned int i, j;
+ uint32_t void_id;
+
+ vkd3d_spirv_builder_begin_main_function(builder);
+
+ void_id = vkd3d_spirv_get_op_type_void(builder);
+
+ if ((control_point_phase = vkd3d_dxbc_compiler_get_control_point_phase(compiler)))
+ vkd3d_spirv_build_op_function_call(builder, void_id, control_point_phase->function_id, NULL, 0);
+ else
+ vkd3d_dxbc_compiler_emit_default_control_point_phase(compiler);
+
+ if (compiler->use_vocp)
+ vkd3d_dxbc_compiler_emit_hull_shader_barrier(compiler);
+
+ for (i = 0; i < compiler->shader_phase_count; ++i)
+ {
+ phase = &compiler->shader_phases[i];
+ if (is_control_point_phase(phase))
+ continue;
+
+ if (phase->instance_count)
+ {
+ for (j = 0; j < phase->instance_count; ++j)
+ {
+ phase_instance_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, j);
+ vkd3d_spirv_build_op_function_call(builder,
+ void_id, phase->function_id, &phase_instance_id, 1);
+ }
+ }
+ else
+ {
+ vkd3d_spirv_build_op_function_call(builder, void_id, phase->function_id, NULL, 0);
+ }
+ }
+
+ vkd3d_spirv_build_op_return(builder);
+ vkd3d_spirv_build_op_function_end(builder);
+}
+
+static SpvOp vkd3d_dxbc_compiler_map_alu_instruction(const struct vkd3d_shader_instruction *instruction)
+{
+ static const struct
+ {
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+ SpvOp spirv_op;
+ }
+ alu_ops[] =
+ {
+ {VKD3DSIH_ADD, SpvOpFAdd},
+ {VKD3DSIH_AND, SpvOpBitwiseAnd},
+ {VKD3DSIH_BFREV, SpvOpBitReverse},
+ {VKD3DSIH_COUNTBITS, SpvOpBitCount},
+ {VKD3DSIH_DIV, SpvOpFDiv},
+ {VKD3DSIH_FTOI, SpvOpConvertFToS},
+ {VKD3DSIH_FTOU, SpvOpConvertFToU},
+ {VKD3DSIH_IADD, SpvOpIAdd},
+ {VKD3DSIH_INEG, SpvOpSNegate},
+ {VKD3DSIH_ISHL, SpvOpShiftLeftLogical},
+ {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic},
+ {VKD3DSIH_ITOF, SpvOpConvertSToF},
+ {VKD3DSIH_MUL, SpvOpFMul},
+ {VKD3DSIH_NOT, SpvOpNot},
+ {VKD3DSIH_OR, SpvOpBitwiseOr},
+ {VKD3DSIH_USHR, SpvOpShiftRightLogical},
+ {VKD3DSIH_UTOF, SpvOpConvertUToF},
+ {VKD3DSIH_XOR, SpvOpBitwiseXor},
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(alu_ops); ++i)
+ {
+ if (alu_ops[i].handler_idx == instruction->handler_idx)
+ return alu_ops[i].spirv_op;
+ }
+
+ return SpvOpMax;
+}
+
+static void vkd3d_dxbc_compiler_emit_alu_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t src_ids[VKD3D_DXBC_MAX_SOURCE_COUNT];
+ uint32_t type_id, val_id;
+ unsigned int i;
+ SpvOp op;
+
+ op = vkd3d_dxbc_compiler_map_alu_instruction(instruction);
+ if (op == SpvOpMax)
+ {
+ ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ return;
+ }
+
+ assert(instruction->dst_count == 1);
+ assert(instruction->src_count <= VKD3D_DXBC_MAX_SOURCE_COUNT);
+
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, dst);
+
+ for (i = 0; i < instruction->src_count; ++i)
+ src_ids[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
+
+ val_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, op, type_id,
+ src_ids, instruction->src_count);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static enum GLSLstd450 vkd3d_dxbc_compiler_map_ext_glsl_instruction(
+ const struct vkd3d_shader_instruction *instruction)
+{
+ static const struct
+ {
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+ enum GLSLstd450 glsl_inst;
+ }
+ glsl_insts[] =
+ {
+ {VKD3DSIH_EXP, GLSLstd450Exp2},
+ {VKD3DSIH_FIRSTBIT_HI, GLSLstd450FindUMsb},
+ {VKD3DSIH_FIRSTBIT_LO, GLSLstd450FindILsb},
+ {VKD3DSIH_FIRSTBIT_SHI, GLSLstd450FindSMsb},
+ {VKD3DSIH_FRC, GLSLstd450Fract},
+ {VKD3DSIH_IMAX, GLSLstd450SMax},
+ {VKD3DSIH_IMIN, GLSLstd450SMin},
+ {VKD3DSIH_LOG, GLSLstd450Log2},
+ {VKD3DSIH_MAD, GLSLstd450Fma},
+ {VKD3DSIH_MAX, GLSLstd450NMax},
+ {VKD3DSIH_MIN, GLSLstd450NMin},
+ {VKD3DSIH_ROUND_NE, GLSLstd450RoundEven},
+ {VKD3DSIH_ROUND_NI, GLSLstd450Floor},
+ {VKD3DSIH_ROUND_PI, GLSLstd450Ceil},
+ {VKD3DSIH_ROUND_Z, GLSLstd450Trunc},
+ {VKD3DSIH_RSQ, GLSLstd450InverseSqrt},
+ {VKD3DSIH_SQRT, GLSLstd450Sqrt},
+ {VKD3DSIH_UMAX, GLSLstd450UMax},
+ {VKD3DSIH_UMIN, GLSLstd450UMin},
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(glsl_insts); ++i)
+ {
+ if (glsl_insts[i].handler_idx == instruction->handler_idx)
+ return glsl_insts[i].glsl_inst;
+ }
+
+ return GLSLstd450Bad;
+}
+
+static void vkd3d_dxbc_compiler_emit_ext_glsl_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t src_id[VKD3D_DXBC_MAX_SOURCE_COUNT];
+ uint32_t instr_set_id, type_id, val_id;
+ enum GLSLstd450 glsl_inst;
+ unsigned int i;
+
+ glsl_inst = vkd3d_dxbc_compiler_map_ext_glsl_instruction(instruction);
+ if (glsl_inst == GLSLstd450Bad)
+ {
+ ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ return;
+ }
+
+ instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
+
+ assert(instruction->dst_count == 1);
+ assert(instruction->src_count <= VKD3D_DXBC_MAX_SOURCE_COUNT);
+
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, dst);
+
+ for (i = 0; i < instruction->src_count; ++i)
+ src_id[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
+
+ val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id,
+ instr_set_id, glsl_inst, src_id, instruction->src_count);
+
+ if (instruction->handler_idx == VKD3DSIH_FIRSTBIT_HI
+ || instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI)
+ {
+ /* In D3D bits are numbered from the most significant bit. */
+ val_id = vkd3d_spirv_build_op_isub(builder, type_id,
+ vkd3d_dxbc_compiler_get_constant_uint(compiler, 31), val_id);
+ }
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_mov(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ struct vkd3d_shader_register_info dst_reg_info, src_reg_info;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t val_id, dst_val_id, type_id, dst_id, src_id;
+ uint32_t components[VKD3D_VEC4_SIZE];
+ unsigned int i, component_count;
+
+ if (src->reg.type == VKD3DSPR_IMMCONST || dst->modifiers || src->modifiers)
+ goto general_implementation;
+
+ vkd3d_dxbc_compiler_get_register_info(compiler, &dst->reg, &dst_reg_info);
+ vkd3d_dxbc_compiler_get_register_info(compiler, &src->reg, &src_reg_info);
+
+ if (dst_reg_info.component_type != src_reg_info.component_type
+ || dst_reg_info.write_mask != src_reg_info.write_mask)
+ goto general_implementation;
+
+ if (vkd3d_swizzle_is_equal(dst_reg_info.write_mask, src->swizzle, src_reg_info.write_mask))
+ {
+ dst_id = vkd3d_dxbc_compiler_get_register_id(compiler, &dst->reg);
+ src_id = vkd3d_dxbc_compiler_get_register_id(compiler, &src->reg);
+
+ vkd3d_spirv_build_op_copy_memory(builder, dst_id, src_id, SpvMemoryAccessMaskNone);
+ return;
+ }
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ if (component_count != 1 && component_count != VKD3D_VEC4_SIZE
+ && dst_reg_info.write_mask == VKD3DSP_WRITEMASK_ALL)
+ {
+ dst_id = vkd3d_dxbc_compiler_get_register_id(compiler, &dst->reg);
+ src_id = vkd3d_dxbc_compiler_get_register_id(compiler, &src->reg);
+
+ type_id = vkd3d_spirv_get_type_id(builder, dst_reg_info.component_type, VKD3D_VEC4_SIZE);
+ val_id = vkd3d_spirv_build_op_load(builder, type_id, src_id, SpvMemoryAccessMaskNone);
+ dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone);
+
+ for (i = 0; i < ARRAY_SIZE(components); ++i)
+ {
+ if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))
+ components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(src->swizzle, i);
+ else
+ components[i] = i;
+ }
+
+ val_id = vkd3d_spirv_build_op_vector_shuffle(builder,
+ type_id, dst_val_id, val_id, components, VKD3D_VEC4_SIZE);
+
+ vkd3d_spirv_build_op_store(builder, dst_id, val_id, SpvMemoryAccessMaskNone);
+ return;
+ }
+
+general_implementation:
+ val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst->write_mask);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_movc(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t condition_id, src1_id, src2_id, type_id, val_id;
+ unsigned int component_count;
+
+ condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
+ src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
+ src2_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[2], dst->write_mask);
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count);
+
+ condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler,
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id);
+ val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_swapc(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t condition_id, src1_id, src2_id, type_id, val_id;
+ unsigned int component_count;
+
+ assert(dst[0].write_mask == dst[1].write_mask);
+
+ condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
+ src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
+ src2_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[2], dst->write_mask);
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count);
+
+ condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler,
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id);
+
+ val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src2_id, src1_id);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, &dst[0], val_id);
+ val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, &dst[1], val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_dot(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ enum vkd3d_shader_component_type component_type;
+ uint32_t type_id, val_id, src_ids[2];
+ unsigned int component_count, i;
+ DWORD write_mask;
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_type = vkd3d_component_type_from_data_type(dst->reg.data_type);
+
+ if (instruction->handler_idx == VKD3DSIH_DP4)
+ write_mask = VKD3DSP_WRITEMASK_ALL;
+ else if (instruction->handler_idx == VKD3DSIH_DP3)
+ write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2;
+ else
+ write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1;
+
+ assert(instruction->src_count == ARRAY_SIZE(src_ids));
+ for (i = 0; i < ARRAY_SIZE(src_ids); ++i)
+ src_ids[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], write_mask);
+
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+
+ val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpDot, type_id, src_ids[0], src_ids[1]);
+ if (component_count > 1)
+ {
+ val_id = vkd3d_dxbc_compiler_emit_construct_vector(compiler,
+ component_type, component_count, val_id, 0, 1);
+ }
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_rcp(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t type_id, src_id, val_id;
+ unsigned int component_count;
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, dst);
+
+ src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst->write_mask);
+ val_id = vkd3d_spirv_build_op_fdiv(builder, type_id,
+ vkd3d_dxbc_compiler_get_constant_float_vector(compiler, 1.0f, component_count), src_id);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_sincos(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_dst_param *dst_sin = &instruction->dst[0];
+ const struct vkd3d_shader_dst_param *dst_cos = &instruction->dst[1];
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t type_id, src_id, sin_id = 0, cos_id = 0;
+
+ if (dst_sin->reg.type != VKD3DSPR_NULL)
+ {
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, dst_sin);
+ src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst_sin->write_mask);
+
+ sin_id = vkd3d_spirv_build_op_glsl_std450_sin(builder, type_id, src_id);
+ }
+
+ if (dst_cos->reg.type != VKD3DSPR_NULL)
+ {
+ if (dst_sin->reg.type == VKD3DSPR_NULL || dst_cos->write_mask != dst_sin->write_mask)
+ {
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, dst_cos);
+ src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst_cos->write_mask);
+ }
+
+ cos_id = vkd3d_spirv_build_op_glsl_std450_cos(builder, type_id, src_id);
+ }
+
+ if (sin_id)
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst_sin, sin_id);
+
+ if (cos_id)
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst_cos, cos_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_imul(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t type_id, val_id, src0_id, src1_id;
+
+ if (dst[0].reg.type != VKD3DSPR_NULL)
+ FIXME("Extended multiplies not implemented.\n"); /* SpvOpSMulExtended */
+
+ if (dst[1].reg.type == VKD3DSPR_NULL)
+ return;
+
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, &dst[1]);
+
+ src0_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask);
+ src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask);
+
+ val_id = vkd3d_spirv_build_op_imul(builder, type_id, src0_id, src1_id);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, &dst[1], val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_imad(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t type_id, val_id, src_ids[3];
+ unsigned int i, component_count;
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, component_count);
+
+ for (i = 0; i < ARRAY_SIZE(src_ids); ++i)
+ src_ids[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
+
+ val_id = vkd3d_spirv_build_op_imul(builder, type_id, src_ids[0], src_ids[1]);
+ val_id = vkd3d_spirv_build_op_iadd(builder, type_id, val_id, src_ids[2]);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_udiv(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t type_id, val_id, src0_id, src1_id, condition_id, uint_max_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ unsigned int component_count = 0;
+
+ if (dst[0].reg.type != VKD3DSPR_NULL)
+ {
+ component_count = vkd3d_write_mask_component_count(dst[0].write_mask);
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, &dst[0]);
+
+ src0_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst[0].write_mask);
+ src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst[0].write_mask);
+
+ condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler,
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id);
+ uint_max_id = vkd3d_dxbc_compiler_get_constant_uint_vector(compiler,
+ 0xffffffff, component_count);
+
+ val_id = vkd3d_spirv_build_op_udiv(builder, type_id, src0_id, src1_id);
+ /* The SPIR-V spec says: "The resulting value is undefined if Operand 2 is 0." */
+ val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, uint_max_id);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, &dst[0], val_id);
+ }
+
+ if (dst[1].reg.type != VKD3DSPR_NULL)
+ {
+ if (!component_count || dst[0].write_mask != dst[1].write_mask)
+ {
+ component_count = vkd3d_write_mask_component_count(dst[1].write_mask);
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, &dst[1]);
+
+ src0_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask);
+ src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask);
+
+ condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler,
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id);
+ uint_max_id = vkd3d_dxbc_compiler_get_constant_uint_vector(compiler,
+ 0xffffffff, component_count);
+ }
+
+ val_id = vkd3d_spirv_build_op_umod(builder, type_id, src0_id, src1_id);
+ /* The SPIR-V spec says: "The resulting value is undefined if Operand 2 is 0." */
+ val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, uint_max_id);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, &dst[1], val_id);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_bitfield_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ enum vkd3d_shader_component_type component_type;
+ unsigned int i, j, k, src_count;
+ DWORD write_mask;
+ SpvOp op;
+
+ src_count = instruction->src_count;
+ assert(2 <= src_count && src_count <= ARRAY_SIZE(src_ids));
+
+ component_type = vkd3d_component_type_from_data_type(dst->reg.data_type);
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ mask_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0x1f);
+
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_BFI: op = SpvOpBitFieldInsert; break;
+ case VKD3DSIH_IBFE: op = SpvOpBitFieldSExtract; break;
+ case VKD3DSIH_UBFE: op = SpvOpBitFieldUExtract; break;
+ default:
+ ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ return;
+ }
+
+ assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
+ for (i = 0, k = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(write_mask = dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
+
+ for (j = 0; j < src_count; ++j)
+ {
+ src_ids[src_count - j - 1] = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler,
+ &src[j], write_mask, component_type);
+ }
+
+ /* In SPIR-V, the last two operands are Offset and Count. */
+ for (j = src_count - 2; j < src_count; ++j)
+ {
+ src_ids[j] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[j], mask_id);
+ }
+
+ constituents[k++] = vkd3d_spirv_build_op_trv(builder, &builder->function_stream,
+ op, type_id, src_ids, src_count);
+ }
+
+ vkd3d_dxbc_compiler_emit_store_dst_components(compiler, dst, component_type, constituents);
+}
+
+static void vkd3d_dxbc_compiler_emit_f16tof32(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t instr_set_id, type_id, scalar_type_id, src_id, result_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t components[VKD3D_VEC4_SIZE];
+ unsigned int i, j;
+ DWORD write_mask;
+
+ instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2);
+ scalar_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 1);
+
+ /* FIXME: Consider a single UnpackHalf2x16 intruction per 2 components. */
+ assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
+ for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(write_mask = dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
+
+ src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, write_mask);
+ result_id = vkd3d_spirv_build_op_ext_inst(builder, type_id,
+ instr_set_id, GLSLstd450UnpackHalf2x16, &src_id, 1);
+ components[j++] = vkd3d_spirv_build_op_composite_extract1(builder,
+ scalar_type_id, result_id, 0);
+ }
+
+ vkd3d_dxbc_compiler_emit_store_dst_components(compiler,
+ dst, vkd3d_component_type_from_data_type(dst->reg.data_type), components);
+}
+
+static void vkd3d_dxbc_compiler_emit_f32tof16(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t instr_set_id, type_id, scalar_type_id, src_id, zero_id, constituents[2];
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t components[VKD3D_VEC4_SIZE];
+ unsigned int i, j;
+ DWORD write_mask;
+
+ instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2);
+ scalar_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ zero_id = vkd3d_dxbc_compiler_get_constant_float(compiler, 0.0f);
+
+ /* FIXME: Consider a single PackHalf2x16 intruction per 2 components. */
+ assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
+ for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(write_mask = dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
+
+ src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, write_mask);
+ constituents[0] = src_id;
+ constituents[1] = zero_id;
+ src_id = vkd3d_spirv_build_op_composite_construct(builder,
+ type_id, constituents, ARRAY_SIZE(constituents));
+ components[j++] = vkd3d_spirv_build_op_ext_inst(builder, scalar_type_id,
+ instr_set_id, GLSLstd450PackHalf2x16, &src_id, 1);
+ }
+
+ vkd3d_dxbc_compiler_emit_store_dst_components(compiler,
+ dst, vkd3d_component_type_from_data_type(dst->reg.data_type), components);
+}
+
+static void vkd3d_dxbc_compiler_emit_comparison_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t src0_id, src1_id, type_id, result_id;
+ unsigned int component_count;
+ SpvOp op;
+
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_EQ: op = SpvOpFOrdEqual; break;
+ case VKD3DSIH_GE: op = SpvOpFOrdGreaterThanEqual; break;
+ case VKD3DSIH_IEQ: op = SpvOpIEqual; break;
+ case VKD3DSIH_IGE: op = SpvOpSGreaterThanEqual; break;
+ case VKD3DSIH_ILT: op = SpvOpSLessThan; break;
+ case VKD3DSIH_INE: op = SpvOpINotEqual; break;
+ case VKD3DSIH_LT: op = SpvOpFOrdLessThan; break;
+ case VKD3DSIH_NE: op = SpvOpFUnordNotEqual; break;
+ case VKD3DSIH_UGE: op = SpvOpUGreaterThanEqual; break;
+ case VKD3DSIH_ULT: op = SpvOpULessThan; break;
+ default:
+ ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ return;
+ }
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+
+ src0_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
+ src1_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count);
+ result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ op, type_id, src0_id, src1_id);
+
+ result_id = vkd3d_dxbc_compiler_emit_bool_to_int(compiler, component_count, result_id);
+ vkd3d_dxbc_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_conditional_branch(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction, uint32_t target_block_id)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t condition_id, merge_block_id;
+
+ condition_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
+ condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler, instruction->flags, 1, condition_id);
+
+ merge_block_id = vkd3d_spirv_alloc_id(builder);
+
+ vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone);
+ vkd3d_spirv_build_op_branch_conditional(builder, condition_id, target_block_id, merge_block_id);
+
+ return merge_block_id;
+}
+
+static void vkd3d_dxbc_compiler_emit_shader_epilogue_invocation(struct vkd3d_dxbc_compiler *compiler)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t void_id, type_id, ptr_type_id, function_id;
+ uint32_t arguments[MAX_REG_OUTPUT];
+ unsigned int i, count;
+
+ if ((function_id = compiler->epilogue_function_id))
+ {
+ void_id = vkd3d_spirv_get_op_type_void(builder);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 4);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
+ for (i = 0, count = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
+ {
+ if (compiler->private_output_variable[i])
+ {
+ uint32_t argument_id = compiler->private_output_variable[i];
+ unsigned int argument_idx = count++;
+
+ if (compiler->private_output_variable_array_idx[i])
+ {
+ uint32_t tmp_id;
+
+ tmp_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id,
+ argument_id, compiler->private_output_variable_array_idx[i]);
+ tmp_id = vkd3d_spirv_build_op_load(builder, type_id, tmp_id, SpvMemoryAccessMaskNone);
+ argument_id = vkd3d_spirv_build_op_variable(builder,
+ &builder->global_stream, ptr_type_id, SpvStorageClassPrivate, 0);
+ vkd3d_spirv_build_op_store(builder, argument_id, tmp_id, SpvMemoryAccessMaskNone);
+ }
+
+ arguments[argument_idx] = argument_id;
+ }
+ }
+
+ vkd3d_spirv_build_op_function_call(builder, void_id, function_id, arguments, count);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_return(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ if (compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY)
+ vkd3d_dxbc_compiler_emit_shader_epilogue_invocation(compiler);
+
+ vkd3d_spirv_build_op_return(builder);
+}
+
+static void vkd3d_dxbc_compiler_emit_retc(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t target_id, merge_block_id;
+
+ target_id = vkd3d_spirv_alloc_id(builder);
+ merge_block_id = vkd3d_dxbc_compiler_emit_conditional_branch(compiler, instruction, target_id);
+
+ vkd3d_spirv_build_op_label(builder, target_id);
+ vkd3d_dxbc_compiler_emit_return(compiler, instruction);
+ vkd3d_spirv_build_op_label(builder, merge_block_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_kill(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t target_id, merge_block_id;
+
+ target_id = vkd3d_spirv_alloc_id(builder);
+ merge_block_id = vkd3d_dxbc_compiler_emit_conditional_branch(compiler, instruction, target_id);
+
+ vkd3d_spirv_build_op_label(builder, target_id);
+
+ if (vkd3d_dxbc_compiler_is_target_extension_supported(compiler,
+ VKD3D_SHADER_SPIRV_EXTENSION_EXT_DEMOTE_TO_HELPER_INVOCATION))
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityDemoteToHelperInvocationEXT);
+ vkd3d_spirv_build_op_demote_to_helper_invocation(builder);
+ vkd3d_spirv_build_op_branch(builder, merge_block_id);
+ }
+ else
+ {
+ vkd3d_spirv_build_op_kill(builder);
+ }
+
+ vkd3d_spirv_build_op_label(builder, merge_block_id);
+}
+
+static struct vkd3d_control_flow_info *vkd3d_dxbc_compiler_push_control_flow_level(
+ struct vkd3d_dxbc_compiler *compiler)
+{
+ if (!vkd3d_array_reserve((void **)&compiler->control_flow_info, &compiler->control_flow_info_size,
+ compiler->control_flow_depth + 1, sizeof(*compiler->control_flow_info)))
+ {
+ ERR("Failed to allocate control flow info structure.\n");
+ return NULL;
+ }
+
+ return &compiler->control_flow_info[compiler->control_flow_depth++];
+}
+
+static void vkd3d_dxbc_compiler_pop_control_flow_level(struct vkd3d_dxbc_compiler *compiler)
+{
+ struct vkd3d_control_flow_info *cf_info;
+
+ assert(compiler->control_flow_depth);
+
+ cf_info = &compiler->control_flow_info[--compiler->control_flow_depth];
+ memset(cf_info, 0, sizeof(*cf_info));
+}
+
+static struct vkd3d_control_flow_info *vkd3d_dxbc_compiler_find_innermost_loop(
+ struct vkd3d_dxbc_compiler *compiler)
+{
+ int depth;
+
+ for (depth = compiler->control_flow_depth - 1; depth >= 0; --depth)
+ {
+ if (compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP)
+ return &compiler->control_flow_info[depth];
+ }
+
+ return NULL;
+}
+
+static struct vkd3d_control_flow_info *vkd3d_dxbc_compiler_find_innermost_breakable_cf_construct(
+ struct vkd3d_dxbc_compiler *compiler)
+{
+ int depth;
+
+ for (depth = compiler->control_flow_depth - 1; depth >= 0; --depth)
+ {
+ if (compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP
+ || compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_SWITCH)
+ return &compiler->control_flow_info[depth];
+ }
+
+ return NULL;
+}
+
+static int vkd3d_dxbc_compiler_emit_control_flow_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t loop_header_block_id, loop_body_block_id, continue_block_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t merge_block_id, val_id, condition_id, true_label;
+ struct vkd3d_control_flow_info *cf_info;
+
+ cf_info = compiler->control_flow_depth
+ ? &compiler->control_flow_info[compiler->control_flow_depth - 1] : NULL;
+
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_IF:
+ if (!(cf_info = vkd3d_dxbc_compiler_push_control_flow_level(compiler)))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
+ condition_id = vkd3d_dxbc_compiler_emit_int_to_bool(compiler, instruction->flags, 1, val_id);
+
+ true_label = vkd3d_spirv_alloc_id(builder);
+ merge_block_id = vkd3d_spirv_alloc_id(builder);
+ vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone);
+ cf_info->u.if_.stream_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
+ vkd3d_spirv_build_op_branch_conditional(builder, condition_id, true_label, merge_block_id);
+
+ vkd3d_spirv_build_op_label(builder, true_label);
+
+ cf_info->u.if_.id = compiler->branch_id;
+ cf_info->u.if_.merge_block_id = merge_block_id;
+ cf_info->u.if_.else_block_id = 0;
+ cf_info->inside_block = true;
+ cf_info->current_block = VKD3D_BLOCK_IF;
+
+ vkd3d_spirv_build_op_name(builder, merge_block_id, "branch%u_merge", compiler->branch_id);
+ vkd3d_spirv_build_op_name(builder, true_label, "branch%u_true", compiler->branch_id);
+ ++compiler->branch_id;
+ break;
+
+ case VKD3DSIH_ELSE:
+ assert(compiler->control_flow_depth);
+ assert(cf_info->current_block == VKD3D_BLOCK_IF);
+
+ if (cf_info->inside_block)
+ vkd3d_spirv_build_op_branch(builder, cf_info->u.if_.merge_block_id);
+
+ cf_info->u.if_.else_block_id = vkd3d_spirv_alloc_id(builder);
+ vkd3d_spirv_as_op_branch_conditional(&builder->function_stream,
+ cf_info->u.if_.stream_location)->false_label = cf_info->u.if_.else_block_id;
+ vkd3d_spirv_build_op_name(builder,
+ cf_info->u.if_.else_block_id, "branch%u_false", cf_info->u.if_.id);
+ vkd3d_spirv_build_op_label(builder, cf_info->u.if_.else_block_id);
+ cf_info->inside_block = true;
+ break;
+
+ case VKD3DSIH_ENDIF:
+ assert(compiler->control_flow_depth);
+ assert(cf_info->current_block == VKD3D_BLOCK_IF);
+
+ if (cf_info->inside_block)
+ vkd3d_spirv_build_op_branch(builder, cf_info->u.if_.merge_block_id);
+
+ vkd3d_spirv_build_op_label(builder, cf_info->u.if_.merge_block_id);
+
+ vkd3d_dxbc_compiler_pop_control_flow_level(compiler);
+ break;
+
+ case VKD3DSIH_LOOP:
+ if (!(cf_info = vkd3d_dxbc_compiler_push_control_flow_level(compiler)))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ loop_header_block_id = vkd3d_spirv_alloc_id(builder);
+ loop_body_block_id = vkd3d_spirv_alloc_id(builder);
+ continue_block_id = vkd3d_spirv_alloc_id(builder);
+ merge_block_id = vkd3d_spirv_alloc_id(builder);
+
+ vkd3d_spirv_build_op_branch(builder, loop_header_block_id);
+ vkd3d_spirv_build_op_label(builder, loop_header_block_id);
+ vkd3d_spirv_build_op_loop_merge(builder, merge_block_id, continue_block_id, SpvLoopControlMaskNone);
+ vkd3d_spirv_build_op_branch(builder, loop_body_block_id);
+
+ vkd3d_spirv_build_op_label(builder, loop_body_block_id);
+
+ cf_info->u.loop.header_block_id = loop_header_block_id;
+ cf_info->u.loop.continue_block_id = continue_block_id;
+ cf_info->u.loop.merge_block_id = merge_block_id;
+ cf_info->current_block = VKD3D_BLOCK_LOOP;
+
+ vkd3d_spirv_build_op_name(builder, loop_header_block_id, "loop%u_header", compiler->loop_id);
+ vkd3d_spirv_build_op_name(builder, loop_body_block_id, "loop%u_body", compiler->loop_id);
+ vkd3d_spirv_build_op_name(builder, continue_block_id, "loop%u_continue", compiler->loop_id);
+ vkd3d_spirv_build_op_name(builder, merge_block_id, "loop%u_merge", compiler->loop_id);
+ ++compiler->loop_id;
+ break;
+
+ case VKD3DSIH_ENDLOOP:
+ assert(compiler->control_flow_depth);
+ assert(cf_info->current_block == VKD3D_BLOCK_LOOP);
+
+ vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.continue_block_id);
+
+ vkd3d_spirv_build_op_label(builder, cf_info->u.loop.continue_block_id);
+ vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.header_block_id);
+ vkd3d_spirv_build_op_label(builder, cf_info->u.loop.merge_block_id);
+
+ vkd3d_dxbc_compiler_pop_control_flow_level(compiler);
+ break;
+
+ case VKD3DSIH_SWITCH:
+ if (!(cf_info = vkd3d_dxbc_compiler_push_control_flow_level(compiler)))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ merge_block_id = vkd3d_spirv_alloc_id(builder);
+
+ assert(src->reg.data_type == VKD3D_DATA_INT);
+ val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
+
+ vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone);
+
+ cf_info->u.switch_.id = compiler->switch_id;
+ cf_info->u.switch_.merge_block_id = merge_block_id;
+ cf_info->u.switch_.stream_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
+ cf_info->u.switch_.selector_id = val_id;
+ cf_info->u.switch_.case_blocks = NULL;
+ cf_info->u.switch_.case_blocks_size = 0;
+ cf_info->u.switch_.case_block_count = 0;
+ cf_info->u.switch_.default_block_id = 0;
+ cf_info->inside_block = false;
+ cf_info->current_block = VKD3D_BLOCK_SWITCH;
+
+ vkd3d_spirv_build_op_name(builder, merge_block_id, "switch%u_merge", compiler->switch_id);
+
+ ++compiler->switch_id;
+
+ if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size,
+ 10, sizeof(*cf_info->u.switch_.case_blocks)))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ break;
+
+ case VKD3DSIH_ENDSWITCH:
+ assert(compiler->control_flow_depth);
+ assert(cf_info->current_block == VKD3D_BLOCK_SWITCH);
+ assert(!cf_info->inside_block);
+
+ if (!cf_info->u.switch_.default_block_id)
+ cf_info->u.switch_.default_block_id = cf_info->u.switch_.merge_block_id;
+
+ vkd3d_spirv_build_op_label(builder, cf_info->u.switch_.merge_block_id);
+
+ /* The OpSwitch instruction is inserted when the endswitch
+ * instruction is processed because we do not know the number
+ * of case statments in advance.*/
+ vkd3d_spirv_begin_function_stream_insertion(builder, cf_info->u.switch_.stream_location);
+ vkd3d_spirv_build_op_switch(builder, cf_info->u.switch_.selector_id,
+ cf_info->u.switch_.default_block_id, cf_info->u.switch_.case_blocks,
+ cf_info->u.switch_.case_block_count);
+ vkd3d_spirv_end_function_stream_insertion(builder);
+
+ vkd3d_free(cf_info->u.switch_.case_blocks);
+ vkd3d_dxbc_compiler_pop_control_flow_level(compiler);
+ break;
+
+ case VKD3DSIH_CASE:
+ {
+ uint32_t label_id, value;
+
+ assert(compiler->control_flow_depth);
+ assert(cf_info->current_block == VKD3D_BLOCK_SWITCH);
+
+ assert(src->swizzle == VKD3D_SHADER_NO_SWIZZLE && src->reg.type == VKD3DSPR_IMMCONST);
+ value = *src->reg.u.immconst_uint;
+
+ if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size,
+ 2 * (cf_info->u.switch_.case_block_count + 1), sizeof(*cf_info->u.switch_.case_blocks)))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ label_id = vkd3d_spirv_alloc_id(builder);
+ if (cf_info->inside_block) /* fall-through */
+ vkd3d_spirv_build_op_branch(builder, label_id);
+
+ cf_info->u.switch_.case_blocks[2 * cf_info->u.switch_.case_block_count + 0] = value;
+ cf_info->u.switch_.case_blocks[2 * cf_info->u.switch_.case_block_count + 1] = label_id;
+ ++cf_info->u.switch_.case_block_count;
+
+ vkd3d_spirv_build_op_label(builder, label_id);
+ cf_info->inside_block = true;
+ vkd3d_spirv_build_op_name(builder, label_id, "switch%u_case%u", cf_info->u.switch_.id, value);
+ break;
+ }
+
+ case VKD3DSIH_DEFAULT:
+ assert(compiler->control_flow_depth);
+ assert(cf_info->current_block == VKD3D_BLOCK_SWITCH);
+ assert(!cf_info->u.switch_.default_block_id);
+
+ cf_info->u.switch_.default_block_id = vkd3d_spirv_alloc_id(builder);
+ if (cf_info->inside_block) /* fall-through */
+ vkd3d_spirv_build_op_branch(builder, cf_info->u.switch_.default_block_id);
+
+ vkd3d_spirv_build_op_label(builder, cf_info->u.switch_.default_block_id);
+ vkd3d_spirv_build_op_name(builder, cf_info->u.switch_.default_block_id,
+ "switch%u_default", cf_info->u.switch_.id);
+ cf_info->inside_block = true;
+ break;
+
+ case VKD3DSIH_BREAK:
+ {
+ struct vkd3d_control_flow_info *breakable_cf_info;
+
+ assert(compiler->control_flow_depth);
+
+ if (!(breakable_cf_info = vkd3d_dxbc_compiler_find_innermost_breakable_cf_construct(compiler)))
+ {
+ FIXME("Unhandled break instruction.\n");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ if (breakable_cf_info->current_block == VKD3D_BLOCK_LOOP)
+ {
+ vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.loop.merge_block_id);
+ }
+ else if (breakable_cf_info->current_block == VKD3D_BLOCK_SWITCH)
+ {
+ assert(breakable_cf_info->inside_block);
+ vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.switch_.merge_block_id);
+ }
+
+ cf_info->inside_block = false;
+ break;
+ }
+
+ case VKD3DSIH_BREAKP:
+ {
+ struct vkd3d_control_flow_info *loop_cf_info;
+
+ assert(compiler->control_flow_depth);
+
+ if (!(loop_cf_info = vkd3d_dxbc_compiler_find_innermost_loop(compiler)))
+ {
+ ERR("Invalid 'breakc' instruction outside loop.\n");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ merge_block_id = vkd3d_dxbc_compiler_emit_conditional_branch(compiler,
+ instruction, loop_cf_info->u.loop.merge_block_id);
+ vkd3d_spirv_build_op_label(builder, merge_block_id);
+ break;
+ }
+
+ case VKD3DSIH_CONTINUE:
+ {
+ struct vkd3d_control_flow_info *loop_cf_info;
+
+ assert(compiler->control_flow_depth);
+
+ if (!(loop_cf_info = vkd3d_dxbc_compiler_find_innermost_loop(compiler)))
+ {
+ ERR("Invalid 'continue' instruction outside loop.\n");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ vkd3d_spirv_build_op_branch(builder, loop_cf_info->u.loop.continue_block_id);
+
+ cf_info->inside_block = false;
+ break;
+ }
+
+ case VKD3DSIH_CONTINUEP:
+ {
+ struct vkd3d_control_flow_info *loop_cf_info;
+
+ if (!(loop_cf_info = vkd3d_dxbc_compiler_find_innermost_loop(compiler)))
+ {
+ ERR("Invalid 'continuec' instruction outside loop.\n");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ merge_block_id = vkd3d_dxbc_compiler_emit_conditional_branch(compiler,
+ instruction, loop_cf_info->u.loop.continue_block_id);
+ vkd3d_spirv_build_op_label(builder, merge_block_id);
+ break;
+ }
+
+ case VKD3DSIH_RET:
+ vkd3d_dxbc_compiler_emit_return(compiler, instruction);
+
+ if (cf_info)
+ cf_info->inside_block = false;
+ break;
+
+ case VKD3DSIH_RETP:
+ vkd3d_dxbc_compiler_emit_retc(compiler, instruction);
+ break;
+
+ case VKD3DSIH_TEXKILL:
+ vkd3d_dxbc_compiler_emit_kill(compiler, instruction);
+ break;
+
+ default:
+ ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ break;
+ }
+
+ return VKD3D_OK;
+}
+
+static void vkd3d_dxbc_compiler_emit_deriv_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct instruction_info *info;
+ uint32_t type_id, src_id, val_id;
+ unsigned int i;
+
+ static const struct instruction_info
+ {
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+ SpvOp op;
+ bool needs_derivative_control;
+ }
+ deriv_instructions[] =
+ {
+ {VKD3DSIH_DSX, SpvOpDPdx},
+ {VKD3DSIH_DSX_COARSE, SpvOpDPdxCoarse, true},
+ {VKD3DSIH_DSX_FINE, SpvOpDPdxFine, true},
+ {VKD3DSIH_DSY, SpvOpDPdy},
+ {VKD3DSIH_DSY_COARSE, SpvOpDPdyCoarse, true},
+ {VKD3DSIH_DSY_FINE, SpvOpDPdyFine, true},
+ };
+
+ info = NULL;
+ for (i = 0; i < ARRAY_SIZE(deriv_instructions); ++i)
+ {
+ if (deriv_instructions[i].handler_idx == instruction->handler_idx)
+ {
+ info = &deriv_instructions[i];
+ break;
+ }
+ }
+ if (!info)
+ {
+ ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ return;
+ }
+
+ if (info->needs_derivative_control)
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityDerivativeControl);
+
+ assert(instruction->dst_count == 1);
+ assert(instruction->src_count == 1);
+
+ type_id = vkd3d_dxbc_compiler_get_type_id_for_dst(compiler, dst);
+ src_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src, dst->write_mask);
+ val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, info->op, type_id, src_id);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+struct vkd3d_shader_image
+{
+ uint32_t id;
+ uint32_t image_id;
+ uint32_t sampled_image_id;
+
+ enum vkd3d_shader_component_type sampled_type;
+ uint32_t image_type_id;
+ const struct vkd3d_spirv_resource_type *resource_type_info;
+ unsigned int structure_stride;
+ bool raw;
+};
+
+#define VKD3D_IMAGE_FLAG_NONE 0x0
+#define VKD3D_IMAGE_FLAG_DEPTH 0x1
+#define VKD3D_IMAGE_FLAG_NO_LOAD 0x2
+#define VKD3D_IMAGE_FLAG_SAMPLED 0x4
+
+static const struct vkd3d_symbol *vkd3d_dxbc_compiler_find_resource(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *resource_reg)
+{
+ struct vkd3d_symbol resource_key;
+ struct rb_entry *entry;
+
+ vkd3d_symbol_make_resource(&resource_key, resource_reg);
+ entry = rb_get(&compiler->symbol_table, &resource_key);
+ assert(entry);
+ return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
+}
+
+static const struct vkd3d_symbol *vkd3d_dxbc_compiler_find_combined_sampler(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *resource_reg, const struct vkd3d_shader_register *sampler_reg)
+{
+ const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface;
+ unsigned int sampler_space, sampler_index;
+ struct vkd3d_symbol key;
+ struct rb_entry *entry;
+
+ if (!shader_interface->combined_sampler_count)
+ return NULL;
+
+ if (sampler_reg)
+ {
+ const struct vkd3d_symbol *sampler_symbol;
+
+ vkd3d_symbol_make_sampler(&key, sampler_reg);
+ if (!(entry = rb_get(&compiler->symbol_table, &key)))
+ return NULL;
+ sampler_symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
+ sampler_space = sampler_symbol->info.sampler.register_space;
+ sampler_index = sampler_symbol->info.sampler.register_index;
+ }
+ else
+ {
+ sampler_space = 0;
+ sampler_index = VKD3D_SHADER_DUMMY_SAMPLER_INDEX;
+ }
+
+ vkd3d_symbol_make_combined_sampler(&key, resource_reg, sampler_space, sampler_index);
+ if ((entry = rb_get(&compiler->symbol_table, &key)))
+ return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
+ return NULL;
+}
+
+static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compiler,
+ struct vkd3d_shader_image *image, const struct vkd3d_shader_register *resource_reg,
+ const struct vkd3d_shader_register *sampler_reg, unsigned int flags)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t sampler_var_id, sampler_id, sampled_image_type_id;
+ const struct vkd3d_symbol *symbol = NULL;
+ bool load, sampled, depth_comparison;
+
+ load = !(flags & VKD3D_IMAGE_FLAG_NO_LOAD);
+ sampled = flags & VKD3D_IMAGE_FLAG_SAMPLED;
+ depth_comparison = flags & VKD3D_IMAGE_FLAG_DEPTH;
+
+ if (resource_reg->type == VKD3DSPR_RESOURCE)
+ symbol = vkd3d_dxbc_compiler_find_combined_sampler(compiler, resource_reg, sampler_reg);
+ if (!symbol)
+ symbol = vkd3d_dxbc_compiler_find_resource(compiler, resource_reg);
+
+ image->id = symbol->id;
+ image->sampled_type = symbol->info.resource.sampled_type;
+ image->image_type_id = symbol->info.resource.type_id;
+ image->resource_type_info = symbol->info.resource.resource_type_info;
+ image->structure_stride = symbol->info.resource.structure_stride;
+ image->raw = symbol->info.resource.raw;
+
+ if (symbol->type == VKD3D_SYMBOL_COMBINED_SAMPLER)
+ {
+ sampled_image_type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image->image_type_id);
+ image->sampled_image_id = vkd3d_spirv_build_op_load(builder,
+ sampled_image_type_id, image->id, SpvMemoryAccessMaskNone);
+ image->image_id = !sampled ? vkd3d_spirv_build_op_image(builder,
+ image->image_type_id, image->sampled_image_id) : 0;
+ return;
+ }
+
+ image->image_id = load ? vkd3d_spirv_build_op_load(builder,
+ image->image_type_id, image->id, SpvMemoryAccessMaskNone) : 0;
+
+ image->image_type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, resource_reg,
+ symbol->info.resource.register_space, symbol->info.resource.register_index, image->resource_type_info,
+ image->sampled_type, image->structure_stride || image->raw, depth_comparison);
+
+ if (sampled)
+ {
+ assert(image->image_id);
+ assert(sampler_reg);
+
+ sampler_var_id = vkd3d_dxbc_compiler_get_register_id(compiler, sampler_reg);
+
+ sampler_id = vkd3d_spirv_build_op_load(builder,
+ vkd3d_spirv_get_op_type_sampler(builder), sampler_var_id, SpvMemoryAccessMaskNone);
+ sampled_image_type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image->image_type_id);
+ image->sampled_image_id = vkd3d_spirv_build_op_sampled_image(builder,
+ sampled_image_type_id, image->image_id, sampler_id);
+ }
+ else
+ {
+ image->sampled_image_id = 0;
+ }
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_texel_offset(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction,
+ const struct vkd3d_spirv_resource_type *resource_type_info)
+{
+ const struct vkd3d_shader_texel_offset *offset = &instruction->texel_offset;
+ unsigned int component_count = resource_type_info->offset_component_count;
+ int32_t data[4] = {offset->u, offset->v, offset->w, 0};
+ return vkd3d_dxbc_compiler_get_constant(compiler,
+ VKD3D_SHADER_COMPONENT_INT, component_count, (const uint32_t *)data);
+}
+
+static void vkd3d_dxbc_compiler_emit_ld(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t type_id, coordinate_id, val_id;
+ SpvImageOperandsMask operands_mask = 0;
+ unsigned int image_operand_count = 0;
+ struct vkd3d_shader_image image;
+ uint32_t image_operands[2];
+ DWORD coordinate_mask;
+ bool multisample;
+
+ multisample = instruction->handler_idx == VKD3DSIH_LD2DMS;
+
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+
+ type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
+ coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
+ if (image.resource_type_info->resource_type != VKD3D_SHADER_RESOURCE_BUFFER && !multisample)
+ {
+ operands_mask |= SpvImageOperandsLodMask;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
+ &src[0], VKD3DSP_WRITEMASK_3);
+ }
+ if (vkd3d_shader_instruction_has_texel_offset(instruction))
+ {
+ operands_mask |= SpvImageOperandsConstOffsetMask;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_texel_offset(compiler,
+ instruction, image.resource_type_info);
+ }
+ if (multisample)
+ {
+ operands_mask |= SpvImageOperandsSampleMask;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
+ &src[2], VKD3DSP_WRITEMASK_0);
+ }
+ assert(image_operand_count <= ARRAY_SIZE(image_operands));
+ val_id = vkd3d_spirv_build_op_image_fetch(builder, type_id,
+ image.image_id, coordinate_id, operands_mask, image_operands, image_operand_count);
+
+ vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
+ dst, val_id, image.sampled_type, src[1].swizzle);
+}
+
+static void vkd3d_dxbc_compiler_emit_lod(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_shader_src_param *resource, *sampler;
+ uint32_t type_id, coordinate_id, val_id;
+ struct vkd3d_shader_image image;
+
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery);
+
+ resource = &src[1];
+ sampler = &src[2];
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image,
+ &resource->reg, &sampler->reg, VKD3D_IMAGE_FLAG_SAMPLED);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2);
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL);
+ val_id = vkd3d_spirv_build_op_image_query_lod(builder,
+ type_id, image.sampled_image_id, coordinate_id);
+
+ vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
+ dst, val_id, image.sampled_type, resource->swizzle);
+}
+
+static void vkd3d_dxbc_compiler_emit_sample(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_shader_src_param *resource, *sampler;
+ uint32_t sampled_type_id, coordinate_id, val_id;
+ SpvImageOperandsMask operands_mask = 0;
+ unsigned int image_operand_count = 0;
+ struct vkd3d_shader_image image;
+ uint32_t image_operands[3];
+ DWORD coordinate_mask;
+ SpvOp op;
+
+ resource = &src[1];
+ sampler = &src[2];
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image,
+ &resource->reg, &sampler->reg, VKD3D_IMAGE_FLAG_SAMPLED);
+
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_SAMPLE:
+ op = SpvOpImageSampleImplicitLod;
+ break;
+ case VKD3DSIH_SAMPLE_B:
+ op = SpvOpImageSampleImplicitLod;
+ operands_mask |= SpvImageOperandsBiasMask;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
+ &src[3], VKD3DSP_WRITEMASK_0);
+ break;
+ case VKD3DSIH_SAMPLE_GRAD:
+ op = SpvOpImageSampleExplicitLod;
+ operands_mask |= SpvImageOperandsGradMask;
+ coordinate_mask = (1u << image.resource_type_info->offset_component_count) - 1;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
+ &src[3], coordinate_mask);
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
+ &src[4], coordinate_mask);
+ break;
+ case VKD3DSIH_SAMPLE_LOD:
+ op = SpvOpImageSampleExplicitLod;
+ operands_mask |= SpvImageOperandsLodMask;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
+ &src[3], VKD3DSP_WRITEMASK_0);
+ break;
+ default:
+ ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ return;
+ }
+
+ if (vkd3d_shader_instruction_has_texel_offset(instruction))
+ {
+ operands_mask |= SpvImageOperandsConstOffsetMask;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_texel_offset(compiler,
+ instruction, image.resource_type_info);
+ }
+
+ sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL);
+ assert(image_operand_count <= ARRAY_SIZE(image_operands));
+ val_id = vkd3d_spirv_build_op_image_sample(builder, op, sampled_type_id,
+ image.sampled_image_id, coordinate_id, operands_mask, image_operands, image_operand_count);
+
+ vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
+ dst, val_id, image.sampled_type, resource->swizzle);
+}
+
+static void vkd3d_dxbc_compiler_emit_sample_c(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t sampled_type_id, coordinate_id, dref_id, val_id, type_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ SpvImageOperandsMask operands_mask = 0;
+ unsigned int image_operand_count = 0;
+ struct vkd3d_shader_image image;
+ uint32_t image_operands[1];
+ SpvOp op;
+
+ if (vkd3d_shader_instruction_has_texel_offset(instruction))
+ FIXME("Texel offset not supported.\n");
+
+ if (instruction->handler_idx == VKD3DSIH_SAMPLE_C_LZ)
+ {
+ op = SpvOpImageSampleDrefExplicitLod;
+ operands_mask |= SpvImageOperandsLodMask;
+ image_operands[image_operand_count++]
+ = vkd3d_dxbc_compiler_get_constant_float(compiler, 0.0f);
+ }
+ else
+ {
+ op = SpvOpImageSampleDrefImplicitLod;
+ }
+
+ vkd3d_dxbc_compiler_prepare_image(compiler,
+ &image, &src[1].reg, &src[2].reg, VKD3D_IMAGE_FLAG_SAMPLED | VKD3D_IMAGE_FLAG_DEPTH);
+ sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, 1);
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL);
+ dref_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[3], VKD3DSP_WRITEMASK_0);
+ /* XXX: Nvidia is broken and expects that the D_ref is packed together with coordinates. */
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+ coordinate_id = vkd3d_spirv_build_op_composite_insert1(builder,
+ type_id, dref_id, coordinate_id, image.resource_type_info->coordinate_component_count);
+ val_id = vkd3d_spirv_build_op_image_sample_dref(builder, op, sampled_type_id,
+ image.sampled_image_id, coordinate_id, dref_id, operands_mask,
+ image_operands, image_operand_count);
+
+ vkd3d_dxbc_compiler_emit_store_dst_scalar(compiler,
+ dst, val_id, image.sampled_type, src[1].swizzle);
+}
+
+static void vkd3d_dxbc_compiler_emit_gather4(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_src_param *addr, *offset, *resource, *sampler;
+ uint32_t sampled_type_id, coordinate_id, component_id, dref_id, val_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ unsigned int image_flags = VKD3D_IMAGE_FLAG_SAMPLED;
+ SpvImageOperandsMask operands_mask = 0;
+ unsigned int image_operand_count = 0;
+ struct vkd3d_shader_image image;
+ unsigned int component_idx;
+ uint32_t image_operands[1];
+ DWORD coordinate_mask;
+ bool extended_offset;
+
+ if (instruction->handler_idx == VKD3DSIH_GATHER4_C
+ || instruction->handler_idx == VKD3DSIH_GATHER4_PO_C)
+ image_flags |= VKD3D_IMAGE_FLAG_DEPTH;
+
+ extended_offset = instruction->handler_idx == VKD3DSIH_GATHER4_PO
+ || instruction->handler_idx == VKD3DSIH_GATHER4_PO_C;
+
+ addr = &src[0];
+ offset = extended_offset ? &src[1] : NULL;
+ resource = &src[1 + extended_offset];
+ sampler = &src[2 + extended_offset];
+
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image,
+ &resource->reg, &sampler->reg, image_flags);
+
+ if (offset)
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityImageGatherExtended);
+ operands_mask |= SpvImageOperandsOffsetMask;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler,
+ offset, (1u << image.resource_type_info->offset_component_count) - 1);
+ }
+ else if (vkd3d_shader_instruction_has_texel_offset(instruction))
+ {
+ operands_mask |= SpvImageOperandsConstOffsetMask;
+ image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_texel_offset(compiler,
+ instruction, image.resource_type_info);
+ }
+
+ sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
+ coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, addr, coordinate_mask);
+ if (image_flags & VKD3D_IMAGE_FLAG_DEPTH)
+ {
+ dref_id = vkd3d_dxbc_compiler_emit_load_src(compiler,
+ &src[3 + extended_offset], VKD3DSP_WRITEMASK_0);
+ val_id = vkd3d_spirv_build_op_image_dref_gather(builder, sampled_type_id,
+ image.sampled_image_id, coordinate_id, dref_id,
+ operands_mask, image_operands, image_operand_count);
+ }
+ else
+ {
+ component_idx = vkd3d_swizzle_get_component(sampler->swizzle, 0);
+ /* Nvidia driver requires signed integer type. */
+ component_id = vkd3d_dxbc_compiler_get_constant(compiler,
+ VKD3D_SHADER_COMPONENT_INT, 1, &component_idx);
+ val_id = vkd3d_spirv_build_op_image_gather(builder, sampled_type_id,
+ image.sampled_image_id, coordinate_id, component_id,
+ operands_mask, image_operands, image_operand_count);
+ }
+
+ vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
+ dst, val_id, image.sampled_type, resource->swizzle);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_raw_structured_addressing(
+ struct vkd3d_dxbc_compiler *compiler, uint32_t type_id, unsigned int stride,
+ const struct vkd3d_shader_src_param *src0, DWORD src0_mask,
+ const struct vkd3d_shader_src_param *src1, DWORD src1_mask)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_src_param *offset;
+ uint32_t structure_id = 0, offset_id;
+ DWORD offset_write_mask;
+
+ if (stride)
+ {
+ structure_id = vkd3d_dxbc_compiler_emit_load_src(compiler, src0, src0_mask);
+ structure_id = vkd3d_spirv_build_op_imul(builder, type_id,
+ structure_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, stride));
+ }
+ offset = stride ? src1 : src0;
+ offset_write_mask = stride ? src1_mask : src0_mask;
+
+ offset_id = vkd3d_dxbc_compiler_emit_load_src(compiler, offset, offset_write_mask);
+ offset_id = vkd3d_spirv_build_op_shift_right_logical(builder, type_id,
+ offset_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 2));
+
+ if (structure_id)
+ return vkd3d_spirv_build_op_iadd(builder, type_id, structure_id, offset_id);
+ else
+ return offset_id;
+}
+
+static void vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t coordinate_id, type_id, val_id, texel_type_id, ptr_type_id, ptr_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_shader_src_param *resource;
+ const struct vkd3d_symbol *resource_symbol;
+ uint32_t base_coordinate_id, component_idx;
+ uint32_t constituents[VKD3D_VEC4_SIZE];
+ struct vkd3d_shader_image image;
+ uint32_t indices[2];
+ unsigned int i, j;
+ SpvOp op;
+
+ resource = &src[instruction->src_count - 1];
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &resource->reg);
+
+ if (resource->reg.type == VKD3DSPR_UAV
+ && vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ texel_type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, texel_type_id);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, resource_symbol->info.resource.structure_stride,
+ &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+
+ assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
+ for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
+
+ component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+ indices[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ indices[1] = coordinate_id;
+
+ ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+ constituents[j++] = vkd3d_spirv_build_op_load(builder, texel_type_id, ptr_id, SpvMemoryAccessMaskNone);
+ }
+ }
+ else
+ {
+ if (resource->reg.type == VKD3DSPR_RESOURCE)
+ op = SpvOpImageFetch;
+ else
+ op = SpvOpImageRead;
+
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+
+ texel_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
+ assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
+ for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
+
+ component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+
+ val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ op, texel_type_id, image.image_id, coordinate_id);
+ constituents[j++] = vkd3d_spirv_build_op_composite_extract1(builder,
+ type_id, val_id, 0);
+ }
+ }
+ assert(dst->reg.data_type == VKD3D_DATA_UINT);
+ vkd3d_dxbc_compiler_emit_store_dst_components(compiler, dst, VKD3D_SHADER_COMPONENT_UINT, constituents);
+}
+
+static void vkd3d_dxbc_compiler_emit_ld_tgsm(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t coordinate_id, type_id, ptr_type_id, ptr_id;
+ const struct vkd3d_shader_src_param *resource;
+ struct vkd3d_shader_register_info reg_info;
+ uint32_t base_coordinate_id, component_idx;
+ uint32_t constituents[VKD3D_VEC4_SIZE];
+ unsigned int i, j;
+
+ resource = &src[instruction->src_count - 1];
+ if (!vkd3d_dxbc_compiler_get_register_info(compiler, &resource->reg, ®_info))
+ return;
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+
+ assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
+ for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
+
+ component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+
+ ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, reg_info.id, coordinate_id);
+ constituents[j++] = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone);
+ }
+ assert(dst->reg.data_type == VKD3D_DATA_UINT);
+ vkd3d_dxbc_compiler_emit_store_dst_components(compiler, dst, VKD3D_SHADER_COMPONENT_UINT, constituents);
+}
+
+static void vkd3d_dxbc_compiler_emit_ld_raw_structured(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ enum vkd3d_shader_register_type reg_type = instruction->src[instruction->src_count - 1].reg.type;
+ switch (reg_type)
+ {
+ case VKD3DSPR_RESOURCE:
+ case VKD3DSPR_UAV:
+ vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(compiler, instruction);
+ break;
+ case VKD3DSPR_GROUPSHAREDMEM:
+ vkd3d_dxbc_compiler_emit_ld_tgsm(compiler, instruction);
+ break;
+ default:
+ ERR("Unexpected register type %#x.\n", reg_type);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_store_uav_raw_structured(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t coordinate_id, type_id, val_id, data_id, ptr_type_id, ptr_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_symbol *resource_symbol;
+ uint32_t base_coordinate_id, component_idx;
+ const struct vkd3d_shader_src_param *data;
+ struct vkd3d_shader_image image;
+ unsigned int component_count;
+ uint32_t indices[2];
+
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &dst->reg);
+
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, resource_symbol->info.resource.structure_stride,
+ &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+
+ data = &src[instruction->src_count - 1];
+ assert(data->reg.data_type == VKD3D_DATA_UINT);
+ val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, data, dst->write_mask);
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ for (component_idx = 0; component_idx < component_count; ++component_idx)
+ {
+ data_id = component_count > 1 ?
+ vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx) : val_id;
+
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+ indices[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ indices[1] = coordinate_id;
+
+ ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+ vkd3d_spirv_build_op_store(builder, ptr_id, data_id, SpvMemoryAccessMaskNone);
+ }
+ }
+ else
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ assert((instruction->handler_idx == VKD3DSIH_STORE_STRUCTURED) != !image.structure_stride);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+
+ data = &src[instruction->src_count - 1];
+ assert(data->reg.data_type == VKD3D_DATA_UINT);
+ val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, data, dst->write_mask);
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ for (component_idx = 0; component_idx < component_count; ++component_idx)
+ {
+ /* Mesa Vulkan drivers require the texel parameter to be a vector. */
+ data_id = vkd3d_dxbc_compiler_emit_construct_vector(compiler, VKD3D_SHADER_COMPONENT_UINT,
+ VKD3D_VEC4_SIZE, val_id, component_idx, component_count);
+
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+
+ vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id,
+ data_id, SpvImageOperandsMaskNone, NULL, 0);
+ }
+ }
+
+}
+
+static void vkd3d_dxbc_compiler_emit_store_tgsm(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t coordinate_id, type_id, val_id, ptr_type_id, ptr_id, data_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t base_coordinate_id, component_idx;
+ const struct vkd3d_shader_src_param *data;
+ struct vkd3d_shader_register_info reg_info;
+ unsigned int component_count;
+
+ if (!vkd3d_dxbc_compiler_get_register_info(compiler, &dst->reg, ®_info))
+ return;
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id);
+ assert((instruction->handler_idx == VKD3DSIH_STORE_STRUCTURED) != !reg_info.structure_stride);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+
+ data = &src[instruction->src_count - 1];
+ assert(data->reg.data_type == VKD3D_DATA_UINT);
+ val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, data, dst->write_mask);
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ for (component_idx = 0; component_idx < component_count; ++component_idx)
+ {
+ data_id = component_count > 1 ?
+ vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx) : val_id;
+
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+
+ ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, reg_info.id, coordinate_id);
+ vkd3d_spirv_build_op_store(builder, ptr_id, data_id, SpvMemoryAccessMaskNone);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_store_raw_structured(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ enum vkd3d_shader_register_type reg_type = instruction->dst[0].reg.type;
+ switch (reg_type)
+ {
+ case VKD3DSPR_UAV:
+ vkd3d_dxbc_compiler_emit_store_uav_raw_structured(compiler, instruction);
+ break;
+ case VKD3DSPR_GROUPSHAREDMEM:
+ vkd3d_dxbc_compiler_emit_store_tgsm(compiler, instruction);
+ break;
+ default:
+ ERR("Unexpected register type %#x.\n", reg_type);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_ld_uav_typed(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t coordinate_id, type_id, val_id, ptr_type_id, ptr_id;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_symbol *resource_symbol;
+ struct vkd3d_shader_image image;
+ DWORD coordinate_mask;
+ uint32_t indices[2];
+
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &src[1].reg);
+
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0);
+ indices[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ indices[1] = coordinate_id;
+
+ ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+ val_id = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone);
+
+ vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler, dst, val_id,
+ resource_symbol->info.resource.sampled_type, src[1].swizzle);
+ }
+ else
+ {
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
+ coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
+
+ val_id = vkd3d_spirv_build_op_image_read(builder, type_id,
+ image.image_id, coordinate_id, SpvImageOperandsMaskNone, NULL, 0);
+
+ vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
+ dst, val_id, image.sampled_type, src[1].swizzle);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_store_uav_typed(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ uint32_t coordinate_id, texel_id, type_id, val_id, ptr_type_id, ptr_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_symbol *resource_symbol;
+ struct vkd3d_shader_image image;
+ DWORD coordinate_mask;
+ uint32_t indices[2];
+
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &dst->reg);
+
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0);
+ indices[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ indices[1] = coordinate_id;
+
+ val_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1],
+ VKD3DSP_WRITEMASK_0, resource_symbol->info.resource.sampled_type);
+ ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+ vkd3d_spirv_build_op_store(builder, ptr_id, val_id, SpvMemoryAccessMaskNone);
+ }
+ else
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityStorageImageWriteWithoutFormat);
+
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
+ texel_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1], dst->write_mask, image.sampled_type);
+
+ vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id, texel_id,
+ SpvImageOperandsMaskNone, NULL, 0);
+ }
+}
+
+static void vkd3d_dxbc_compiler_emit_uav_counter_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ unsigned int memory_semantics = SpvMemorySemanticsMaskNone;
+ uint32_t ptr_type_id, type_id, counter_id, result_id;
+ uint32_t coordinate_id, sample_id, pointer_id;
+ const struct vkd3d_symbol *resource_symbol;
+ uint32_t operands[3];
+ SpvOp op;
+
+ op = instruction->handler_idx == VKD3DSIH_IMM_ATOMIC_ALLOC
+ ? SpvOpAtomicIIncrement : SpvOpAtomicIDecrement;
+
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &src->reg);
+ counter_id = resource_symbol->info.resource.uav_counter_id;
+ assert(counter_id);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ if (vkd3d_dxbc_compiler_is_opengl_target(compiler))
+ {
+ pointer_id = counter_id;
+ memory_semantics |= SpvMemorySemanticsAtomicCounterMemoryMask;
+ }
+ else if (compiler->ssbo_uavs)
+ {
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+ coordinate_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ operands[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ operands[1] = coordinate_id;
+ pointer_id = vkd3d_spirv_build_op_access_chain(builder,
+ ptr_type_id, counter_id, operands, 2);
+ }
+ else
+ {
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassImage, type_id);
+ coordinate_id = sample_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder,
+ ptr_type_id, counter_id, coordinate_id, sample_id);
+ }
+
+ operands[0] = pointer_id;
+ operands[1] = vkd3d_dxbc_compiler_get_constant_uint(compiler, SpvScopeDevice);
+ operands[2] = vkd3d_dxbc_compiler_get_constant_uint(compiler, memory_semantics);
+ result_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream,
+ op, type_id, operands, ARRAY_SIZE(operands));
+ if (op == SpvOpAtomicIDecrement)
+ {
+ /* SpvOpAtomicIDecrement returns the original value. */
+ result_id = vkd3d_spirv_build_op_isub(builder, type_id, result_id,
+ vkd3d_dxbc_compiler_get_constant_uint(compiler, 1));
+ }
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, result_id);
+}
+
+static SpvOp vkd3d_dxbc_compiler_map_atomic_instruction(const struct vkd3d_shader_instruction *instruction)
+{
+ static const struct
+ {
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+ SpvOp spirv_op;
+ }
+ atomic_ops[] =
+ {
+ {VKD3DSIH_ATOMIC_AND, SpvOpAtomicAnd},
+ {VKD3DSIH_ATOMIC_CMP_STORE, SpvOpAtomicCompareExchange},
+ {VKD3DSIH_ATOMIC_IADD, SpvOpAtomicIAdd},
+ {VKD3DSIH_ATOMIC_IMAX, SpvOpAtomicSMax},
+ {VKD3DSIH_ATOMIC_IMIN, SpvOpAtomicSMin},
+ {VKD3DSIH_ATOMIC_OR, SpvOpAtomicOr},
+ {VKD3DSIH_ATOMIC_UMAX, SpvOpAtomicUMax},
+ {VKD3DSIH_ATOMIC_UMIN, SpvOpAtomicUMin},
+ {VKD3DSIH_ATOMIC_XOR, SpvOpAtomicXor},
+ {VKD3DSIH_IMM_ATOMIC_AND, SpvOpAtomicAnd},
+ {VKD3DSIH_IMM_ATOMIC_CMP_EXCH, SpvOpAtomicCompareExchange},
+ {VKD3DSIH_IMM_ATOMIC_EXCH, SpvOpAtomicExchange},
+ {VKD3DSIH_IMM_ATOMIC_IADD, SpvOpAtomicIAdd},
+ {VKD3DSIH_IMM_ATOMIC_IMAX, SpvOpAtomicSMax},
+ {VKD3DSIH_IMM_ATOMIC_IMIN, SpvOpAtomicSMin},
+ {VKD3DSIH_IMM_ATOMIC_OR, SpvOpAtomicOr},
+ {VKD3DSIH_IMM_ATOMIC_UMAX, SpvOpAtomicUMax},
+ {VKD3DSIH_IMM_ATOMIC_UMIN, SpvOpAtomicUMin},
+ {VKD3DSIH_IMM_ATOMIC_XOR, SpvOpAtomicXor},
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(atomic_ops); ++i)
+ {
+ if (atomic_ops[i].handler_idx == instruction->handler_idx)
+ return atomic_ops[i].spirv_op;
+ }
+
+ return SpvOpMax;
+}
+
+static bool is_imm_atomic_instruction(enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx)
+{
+ return VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR;
+}
+
+static void vkd3d_dxbc_compiler_emit_atomic_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_symbol *resource_symbol = NULL;
+ uint32_t ptr_type_id, type_id, val_id, result_id;
+ enum vkd3d_shader_component_type component_type;
+ const struct vkd3d_shader_dst_param *resource;
+ uint32_t coordinate_id, sample_id, pointer_id;
+ struct vkd3d_shader_register_info reg_info;
+ struct vkd3d_shader_image image;
+ unsigned int structure_stride;
+ DWORD coordinate_mask;
+ uint32_t operands[6];
+ unsigned int i = 0;
+ SpvScope scope;
+ bool raw;
+ SpvOp op;
+
+ resource = is_imm_atomic_instruction(instruction->handler_idx) ? &dst[1] : &dst[0];
+
+ op = vkd3d_dxbc_compiler_map_atomic_instruction(instruction);
+ if (op == SpvOpMax)
+ {
+ ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ return;
+ }
+
+ if (resource->reg.type == VKD3DSPR_GROUPSHAREDMEM)
+ {
+ scope = SpvScopeWorkgroup;
+ coordinate_mask = 1u;
+ if (!vkd3d_dxbc_compiler_get_register_info(compiler, &resource->reg, ®_info))
+ return;
+ structure_stride = reg_info.structure_stride;
+ raw = !structure_stride;
+ }
+ else
+ {
+ scope = SpvScopeDevice;
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &resource->reg);
+
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ coordinate_mask = VKD3DSP_WRITEMASK_0;
+ structure_stride = resource_symbol->info.resource.structure_stride;
+ raw = resource_symbol->info.resource.raw;
+ }
+ else
+ {
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NO_LOAD);
+ coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
+ structure_stride = image.structure_stride;
+ raw = image.raw;
+ }
+ }
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ if (structure_stride || raw)
+ {
+ assert(!raw != !structure_stride);
+ coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, structure_stride, &src[0], VKD3DSP_WRITEMASK_0,
+ &src[0], VKD3DSP_WRITEMASK_1);
+ }
+ else
+ {
+ assert(resource->reg.type != VKD3DSPR_GROUPSHAREDMEM);
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
+ }
+
+ if (resource->reg.type == VKD3DSPR_GROUPSHAREDMEM)
+ {
+ component_type = VKD3D_SHADER_COMPONENT_UINT;
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id);
+ pointer_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, reg_info.id, coordinate_id);
+ }
+ else
+ {
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ component_type = resource_symbol->info.resource.sampled_type;
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+ operands[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ operands[1] = coordinate_id;
+ pointer_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, operands, 2);
+ }
+ else
+ {
+ component_type = image.sampled_type;
+ type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassImage, type_id);
+ sample_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder,
+ ptr_type_id, image.id, coordinate_id, sample_id);
+ }
+ }
+
+ val_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, component_type);
+
+ operands[i++] = pointer_id;
+ operands[i++] = vkd3d_dxbc_compiler_get_constant_uint(compiler, scope);
+ operands[i++] = vkd3d_dxbc_compiler_get_constant_uint(compiler, SpvMemorySemanticsMaskNone);
+ if (instruction->src_count >= 3)
+ {
+ operands[i++] = vkd3d_dxbc_compiler_get_constant_uint(compiler, SpvMemorySemanticsMaskNone);
+ operands[i++] = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[2], VKD3DSP_WRITEMASK_0, component_type);
+ }
+ operands[i++] = val_id;
+ result_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream,
+ op, type_id, operands, i);
+
+ if (is_imm_atomic_instruction(instruction->handler_idx))
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, result_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_bufinfo(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_symbol *resource_symbol;
+ uint32_t type_id, val_id, stride_id;
+ struct vkd3d_shader_image image;
+ uint32_t constituents[2];
+ unsigned int write_mask;
+
+ if (compiler->ssbo_uavs && src->reg.type == VKD3DSPR_UAV)
+ {
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &src->reg);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ val_id = vkd3d_spirv_build_op_array_length(builder, type_id, resource_symbol->id, 0);
+ write_mask = VKD3DSP_WRITEMASK_0;
+ }
+ else
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery);
+
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id);
+ write_mask = VKD3DSP_WRITEMASK_0;
+ }
+
+ if (image.structure_stride)
+ {
+ stride_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, image.structure_stride);
+ constituents[0] = vkd3d_spirv_build_op_udiv(builder, type_id, val_id, stride_id);
+ constituents[1] = stride_id;
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, ARRAY_SIZE(constituents));
+ val_id = vkd3d_spirv_build_op_composite_construct(builder,
+ type_id, constituents, ARRAY_SIZE(constituents));
+ write_mask |= VKD3DSP_WRITEMASK_1;
+ }
+ else if (image.raw)
+ {
+ val_id = vkd3d_spirv_build_op_shift_left_logical(builder, type_id,
+ val_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 2));
+ }
+
+ val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, val_id, write_mask,
+ VKD3D_SHADER_COMPONENT_UINT, src->swizzle, dst->write_mask);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static void vkd3d_dxbc_compiler_emit_resinfo(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t type_id, lod_id, val_id, miplevel_count_id;
+ uint32_t constituents[VKD3D_VEC4_SIZE];
+ unsigned int i, size_component_count;
+ struct vkd3d_shader_image image;
+ bool supports_mipmaps;
+
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery);
+
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ size_component_count = image.resource_type_info->coordinate_component_count;
+ if (image.resource_type_info->dim == SpvDimCube)
+ --size_component_count;
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, size_component_count);
+
+ supports_mipmaps = src[1].reg.type != VKD3DSPR_UAV && !image.resource_type_info->ms;
+ if (supports_mipmaps)
+ {
+ lod_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0);
+ val_id = vkd3d_spirv_build_op_image_query_size_lod(builder, type_id, image.image_id, lod_id);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ miplevel_count_id = vkd3d_spirv_build_op_image_query_levels(builder, type_id, image.image_id);
+ }
+ else
+ {
+ val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id);
+ /* For UAVs the returned miplevel count is always 1. */
+ miplevel_count_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 1);
+ }
+
+ constituents[0] = val_id;
+ for (i = 0; i < 3 - size_component_count; ++i)
+ constituents[i + 1] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ constituents[i + 1] = miplevel_count_id;
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE);
+ val_id = vkd3d_spirv_build_op_composite_construct(builder,
+ type_id, constituents, i + 2);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+ if (instruction->flags == VKD3DSI_RESINFO_UINT)
+ {
+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
+ }
+ else
+ {
+ if (instruction->flags)
+ FIXME("Unhandled flags %#x.\n", instruction->flags);
+ val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id);
+ }
+ val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, val_id, VKD3DSP_WRITEMASK_ALL,
+ VKD3D_SHADER_COMPONENT_FLOAT, src[1].swizzle, dst->write_mask);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+static uint32_t vkd3d_dxbc_compiler_emit_query_sample_count(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_src_param *src)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ struct vkd3d_shader_image image;
+ uint32_t type_id, val_id;
+
+ if (src->reg.type == VKD3DSPR_RASTERIZER)
+ {
+ val_id = vkd3d_dxbc_compiler_emit_uint_shader_parameter(compiler,
+ VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT);
+ }
+ else
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery);
+
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ val_id = vkd3d_spirv_build_op_image_query_samples(builder, type_id, image.image_id);
+ }
+
+ return val_id;
+}
+
+static void vkd3d_dxbc_compiler_emit_sample_info(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t constituents[VKD3D_VEC4_SIZE];
+ uint32_t type_id, val_id;
+ unsigned int i;
+
+ val_id = vkd3d_dxbc_compiler_emit_query_sample_count(compiler, src);
+
+ constituents[0] = val_id;
+ for (i = 1; i < VKD3D_VEC4_SIZE; ++i)
+ constituents[i] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE);
+ val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, VKD3D_VEC4_SIZE);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
+ if (instruction->flags == VKD3DSI_SAMPLE_INFO_UINT)
+ {
+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
+ }
+ else
+ {
+ if (instruction->flags)
+ FIXME("Unhandled flags %#x.\n", instruction->flags);
+ val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id);
+ }
+
+ val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, val_id, VKD3DSP_WRITEMASK_ALL,
+ VKD3D_SHADER_COMPONENT_FLOAT, src->swizzle, dst->write_mask);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+/* XXX: This is correct only when standard sample positions are used. */
+static void vkd3d_dxbc_compiler_emit_sample_position(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ /* Standard sample locations from the Vulkan spec. */
+ static const float standard_sample_positions[][2] =
+ {
+ /* 1 sample */
+ { 0.0 / 16.0, 0.0 / 16.0},
+ /* 2 samples */
+ { 4.0 / 16.0, 4.0 / 16.0},
+ {-4.0 / 16.0, -4.0 / 16.0},
+ /* 4 samples */
+ {-2.0 / 16.0, -6.0 / 16.0},
+ { 6.0 / 16.0, -2.0 / 16.0},
+ {-6.0 / 16.0, 2.0 / 16.0},
+ { 2.0 / 16.0, 6.0 / 16.0},
+ /* 8 samples */
+ { 1.0 / 16.0, -3.0 / 16.0},
+ {-1.0 / 16.0, 3.0 / 16.0},
+ { 5.0 / 16.0, 1.0 / 16.0},
+ {-3.0 / 16.0, -5.0 / 16.0},
+ {-5.0 / 16.0, 5.0 / 16.0},
+ {-7.0 / 16.0, -1.0 / 16.0},
+ { 3.0 / 16.0, 7.0 / 16.0},
+ { 7.0 / 16.0, -7.0 / 16.0},
+ /* 16 samples */
+ { 1.0 / 16.0, 1.0 / 16.0},
+ {-1.0 / 16.0, -3.0 / 16.0},
+ {-3.0 / 16.0, 2.0 / 16.0},
+ { 4.0 / 16.0, -1.0 / 16.0},
+ {-5.0 / 16.0, -2.0 / 16.0},
+ { 2.0 / 16.0, 5.0 / 16.0},
+ { 5.0 / 16.0, 3.0 / 16.0},
+ { 3.0 / 16.0, -5.0 / 16.0},
+ {-2.0 / 16.0, 6.0 / 16.0},
+ { 0.0 / 16.0, -7.0 / 16.0},
+ {-4.0 / 16.0, -6.0 / 16.0},
+ {-6.0 / 16.0, 4.0 / 16.0},
+ {-8.0 / 16.0, 0.0 / 16.0},
+ { 7.0 / 16.0, -4.0 / 16.0},
+ { 6.0 / 16.0, 7.0 / 16.0},
+ {-7.0 / 16.0, -8.0 / 16.0},
+ };
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t constituents[ARRAY_SIZE(standard_sample_positions)];
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ uint32_t array_type_id, length_id, index_id, id;
+ uint32_t sample_count_id, sample_index_id;
+ uint32_t type_id, bool_id, ptr_type_id;
+ unsigned int i;
+
+ sample_count_id = vkd3d_dxbc_compiler_emit_query_sample_count(compiler, &instruction->src[0]);
+ sample_index_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &instruction->src[1], VKD3DSP_WRITEMASK_0);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ index_id = vkd3d_spirv_build_op_iadd(builder, type_id, sample_count_id, sample_index_id);
+ index_id = vkd3d_spirv_build_op_isub(builder,
+ type_id, index_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 1));
+
+ /* Validate sample index. */
+ bool_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, 1);
+ id = vkd3d_spirv_build_op_logical_and(builder, bool_id,
+ vkd3d_spirv_build_op_uless_than(builder, bool_id, sample_index_id, sample_count_id),
+ vkd3d_spirv_build_op_uless_than_equal(builder,
+ bool_id, sample_index_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 16)));
+ index_id = vkd3d_spirv_build_op_select(builder, type_id,
+ id, index_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 0));
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2);
+ if (!(id = compiler->sample_positions_id))
+ {
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, ARRAY_SIZE(standard_sample_positions));
+ array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id);
+
+ for (i = 0; i < ARRAY_SIZE(standard_sample_positions); ++ i)
+ {
+ constituents[i] = vkd3d_dxbc_compiler_get_constant(compiler,
+ VKD3D_SHADER_COMPONENT_FLOAT, 2, (const uint32_t *)standard_sample_positions[i]);
+ }
+
+ id = vkd3d_spirv_build_op_constant_composite(builder, array_type_id, constituents, ARRAY_SIZE(constituents));
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, array_type_id);
+ id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, SpvStorageClassPrivate, id);
+ vkd3d_spirv_build_op_name(builder, id, "sample_pos");
+ compiler->sample_positions_id = id;
+ }
+
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
+ id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, id, index_id);
+ id = vkd3d_spirv_build_op_load(builder, type_id, id, SpvMemoryAccessMaskNone);
+
+ id = vkd3d_dxbc_compiler_emit_swizzle(compiler, id, VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1,
+ VKD3D_SHADER_COMPONENT_FLOAT, instruction->src[0].swizzle, dst->write_mask);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, id);
+}
+
+static void vkd3d_dxbc_compiler_emit_eval_attrib(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_shader_register *input = &src[0].reg;
+ uint32_t instr_set_id, type_id, val_id, src_ids[2];
+ struct vkd3d_shader_register_info register_info;
+ unsigned int src_count = 0;
+ enum GLSLstd450 op;
+
+ if (!vkd3d_dxbc_compiler_get_register_info(compiler, input, ®ister_info))
+ return;
+
+ if (register_info.storage_class != SpvStorageClassInput)
+ {
+ FIXME("Not supported for storage class %#x.\n", register_info.storage_class);
+ return;
+ }
+
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityInterpolationFunction);
+
+ src_ids[src_count++] = register_info.id;
+
+ if (instruction->handler_idx == VKD3DSIH_EVAL_CENTROID)
+ {
+ op = GLSLstd450InterpolateAtCentroid;
+ }
+ else
+ {
+ assert(instruction->handler_idx == VKD3DSIH_EVAL_SAMPLE_INDEX);
+ op = GLSLstd450InterpolateAtSample;
+ src_ids[src_count++] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0);
+ }
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT,
+ vkd3d_write_mask_component_count(register_info.write_mask));
+
+ instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
+ val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, op, src_ids, src_count);
+
+ val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, val_id, register_info.write_mask,
+ VKD3D_SHADER_COMPONENT_FLOAT, src[0].swizzle, dst->write_mask);
+
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
+/* From the Vulkan spec:
+ *
+ * "Scope for execution must be limited to: * Workgroup * Subgroup"
+ *
+ * "Scope for memory must be limited to: * Device * Workgroup * Invocation"
+ */
+static void vkd3d_dxbc_compiler_emit_sync(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ unsigned int memory_semantics = SpvMemorySemanticsAcquireReleaseMask;
+ unsigned int flags = instruction->flags;
+ SpvScope execution_scope = SpvScopeMax;
+ SpvScope memory_scope = SpvScopeDevice;
+
+ if (flags & VKD3DSSF_GROUP_SHARED_MEMORY)
+ {
+ memory_scope = SpvScopeWorkgroup;
+ memory_semantics |= SpvMemorySemanticsWorkgroupMemoryMask;
+ flags &= ~VKD3DSSF_GROUP_SHARED_MEMORY;
+ }
+
+ if (flags & VKD3DSSF_THREAD_GROUP)
+ {
+ execution_scope = SpvScopeWorkgroup;
+ flags &= ~VKD3DSSF_THREAD_GROUP;
+ }
+
+ if (flags)
+ {
+ FIXME("Unhandled sync flags %#x.\n", flags);
+ memory_scope = SpvScopeDevice;
+ execution_scope = SpvScopeWorkgroup;
+ memory_semantics |= SpvMemorySemanticsUniformMemoryMask
+ | SpvMemorySemanticsSubgroupMemoryMask
+ | SpvMemorySemanticsWorkgroupMemoryMask
+ | SpvMemorySemanticsCrossWorkgroupMemoryMask
+ | SpvMemorySemanticsAtomicCounterMemoryMask
+ | SpvMemorySemanticsImageMemoryMask;
+ }
+
+ vkd3d_dxbc_compiler_emit_barrier(compiler, execution_scope, memory_scope, memory_semantics);
+}
+
+static void vkd3d_dxbc_compiler_emit_emit_stream(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int stream_idx;
+
+ if (instruction->handler_idx == VKD3DSIH_EMIT_STREAM)
+ stream_idx = instruction->src[0].reg.idx[0].offset;
+ else
+ stream_idx = 0;
+
+ if (stream_idx)
+ {
+ FIXME("Multiple streams are not supported yet.\n");
+ return;
+ }
+
+ vkd3d_dxbc_compiler_emit_shader_epilogue_invocation(compiler);
+ vkd3d_spirv_build_op_emit_vertex(builder);
+}
+
+static void vkd3d_dxbc_compiler_emit_cut_stream(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int stream_idx;
+
+ if (instruction->handler_idx == VKD3DSIH_CUT_STREAM)
+ stream_idx = instruction->src[0].reg.idx[0].offset;
+ else
+ stream_idx = 0;
+
+ if (stream_idx)
+ {
+ FIXME("Multiple streams are not supported yet.\n");
+ return;
+ }
+
+ vkd3d_spirv_build_op_end_primitive(builder);
+}
+
+/* This function is called after declarations are processed. */
+static void vkd3d_dxbc_compiler_emit_main_prolog(struct vkd3d_dxbc_compiler *compiler)
+{
+ vkd3d_dxbc_compiler_emit_push_constant_buffers(compiler);
+
+ if (compiler->xfb_info && compiler->xfb_info->element_count
+ && compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY)
+ vkd3d_dxbc_compiler_emit_point_size(compiler);
+}
+
+static bool is_dcl_instruction(enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx)
+{
+ return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT)
+ || handler_idx == VKD3DSIH_HS_DECLS;
+}
+
+int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ int ret = VKD3D_OK;
+
+ if (!is_dcl_instruction(instruction->handler_idx) && !compiler->after_declarations_section)
+ {
+ compiler->after_declarations_section = true;
+ vkd3d_dxbc_compiler_emit_main_prolog(compiler);
+ }
+
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_DCL_GLOBAL_FLAGS:
+ vkd3d_dxbc_compiler_emit_dcl_global_flags(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_TEMPS:
+ vkd3d_dxbc_compiler_emit_dcl_temps(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_INDEXABLE_TEMP:
+ vkd3d_dxbc_compiler_emit_dcl_indexable_temp(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_CONSTANT_BUFFER:
+ vkd3d_dxbc_compiler_emit_dcl_constant_buffer(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER:
+ vkd3d_dxbc_compiler_emit_dcl_immediate_constant_buffer(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_SAMPLER:
+ vkd3d_dxbc_compiler_emit_dcl_sampler(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL:
+ case VKD3DSIH_DCL_UAV_TYPED:
+ vkd3d_dxbc_compiler_emit_dcl_resource(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_RESOURCE_RAW:
+ case VKD3DSIH_DCL_UAV_RAW:
+ vkd3d_dxbc_compiler_emit_dcl_resource_raw(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
+ case VKD3DSIH_DCL_UAV_STRUCTURED:
+ vkd3d_dxbc_compiler_emit_dcl_resource_structured(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_TGSM_RAW:
+ vkd3d_dxbc_compiler_emit_dcl_tgsm_raw(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_TGSM_STRUCTURED:
+ vkd3d_dxbc_compiler_emit_dcl_tgsm_structured(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_INPUT:
+ vkd3d_dxbc_compiler_emit_dcl_input(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_INPUT_PS:
+ vkd3d_dxbc_compiler_emit_dcl_input_ps(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_INPUT_PS_SGV:
+ case VKD3DSIH_DCL_INPUT_PS_SIV:
+ vkd3d_dxbc_compiler_emit_dcl_input_ps_sysval(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_INPUT_SGV:
+ case VKD3DSIH_DCL_INPUT_SIV:
+ vkd3d_dxbc_compiler_emit_dcl_input_sysval(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_OUTPUT:
+ vkd3d_dxbc_compiler_emit_dcl_output(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_OUTPUT_SIV:
+ vkd3d_dxbc_compiler_emit_dcl_output_siv(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_INDEX_RANGE:
+ vkd3d_dxbc_compiler_emit_dcl_index_range(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_STREAM:
+ vkd3d_dxbc_compiler_emit_dcl_stream(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_VERTICES_OUT:
+ vkd3d_dxbc_compiler_emit_output_vertex_count(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_INPUT_PRIMITIVE:
+ vkd3d_dxbc_compiler_emit_dcl_input_primitive(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_OUTPUT_TOPOLOGY:
+ vkd3d_dxbc_compiler_emit_dcl_output_topology(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_GS_INSTANCES:
+ vkd3d_dxbc_compiler_emit_dcl_gs_instances(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
+ compiler->input_control_point_count = instruction->declaration.count;
+ break;
+ case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT:
+ compiler->output_control_point_count = instruction->declaration.count;
+ vkd3d_dxbc_compiler_emit_output_vertex_count(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_TESSELLATOR_DOMAIN:
+ vkd3d_dxbc_compiler_emit_dcl_tessellator_domain(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE:
+ vkd3d_dxbc_compiler_emit_tessellator_output_primitive(compiler,
+ instruction->declaration.tessellator_output_primitive);
+ break;
+ case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING:
+ vkd3d_dxbc_compiler_emit_tessellator_partitioning(compiler,
+ instruction->declaration.tessellator_partitioning);
+ break;
+ case VKD3DSIH_DCL_THREAD_GROUP:
+ vkd3d_dxbc_compiler_emit_dcl_thread_group(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT:
+ case VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT:
+ ret = vkd3d_dxbc_compiler_emit_shader_phase_instance_count(compiler, instruction);
+ break;
+ case VKD3DSIH_HS_CONTROL_POINT_PHASE:
+ case VKD3DSIH_HS_FORK_PHASE:
+ case VKD3DSIH_HS_JOIN_PHASE:
+ vkd3d_dxbc_compiler_enter_shader_phase(compiler, instruction);
+ break;
+ case VKD3DSIH_MOV:
+ vkd3d_dxbc_compiler_emit_mov(compiler, instruction);
+ break;
+ case VKD3DSIH_MOVC:
+ vkd3d_dxbc_compiler_emit_movc(compiler, instruction);
+ break;
+ case VKD3DSIH_SWAPC:
+ vkd3d_dxbc_compiler_emit_swapc(compiler, instruction);
+ break;
+ case VKD3DSIH_ADD:
+ case VKD3DSIH_AND:
+ case VKD3DSIH_BFREV:
+ case VKD3DSIH_COUNTBITS:
+ case VKD3DSIH_DIV:
+ case VKD3DSIH_FTOI:
+ case VKD3DSIH_FTOU:
+ case VKD3DSIH_IADD:
+ case VKD3DSIH_INEG:
+ case VKD3DSIH_ISHL:
+ case VKD3DSIH_ISHR:
+ case VKD3DSIH_ITOF:
+ case VKD3DSIH_MUL:
+ case VKD3DSIH_NOT:
+ case VKD3DSIH_OR:
+ case VKD3DSIH_USHR:
+ case VKD3DSIH_UTOF:
+ case VKD3DSIH_XOR:
+ vkd3d_dxbc_compiler_emit_alu_instruction(compiler, instruction);
+ break;
+ case VKD3DSIH_EXP:
+ case VKD3DSIH_FIRSTBIT_HI:
+ case VKD3DSIH_FIRSTBIT_LO:
+ case VKD3DSIH_FIRSTBIT_SHI:
+ case VKD3DSIH_FRC:
+ case VKD3DSIH_IMAX:
+ case VKD3DSIH_IMIN:
+ case VKD3DSIH_LOG:
+ case VKD3DSIH_MAD:
+ case VKD3DSIH_MAX:
+ case VKD3DSIH_MIN:
+ case VKD3DSIH_ROUND_NE:
+ case VKD3DSIH_ROUND_NI:
+ case VKD3DSIH_ROUND_PI:
+ case VKD3DSIH_ROUND_Z:
+ case VKD3DSIH_RSQ:
+ case VKD3DSIH_SQRT:
+ case VKD3DSIH_UMAX:
+ case VKD3DSIH_UMIN:
+ vkd3d_dxbc_compiler_emit_ext_glsl_instruction(compiler, instruction);
+ break;
+ case VKD3DSIH_DP4:
+ case VKD3DSIH_DP3:
+ case VKD3DSIH_DP2:
+ vkd3d_dxbc_compiler_emit_dot(compiler, instruction);
+ break;
+ case VKD3DSIH_RCP:
+ vkd3d_dxbc_compiler_emit_rcp(compiler, instruction);
+ break;
+ case VKD3DSIH_SINCOS:
+ vkd3d_dxbc_compiler_emit_sincos(compiler, instruction);
+ break;
+ case VKD3DSIH_IMUL:
+ vkd3d_dxbc_compiler_emit_imul(compiler, instruction);
+ break;
+ case VKD3DSIH_IMAD:
+ vkd3d_dxbc_compiler_emit_imad(compiler, instruction);
+ break;
+ case VKD3DSIH_UDIV:
+ vkd3d_dxbc_compiler_emit_udiv(compiler, instruction);
+ break;
+ case VKD3DSIH_EQ:
+ case VKD3DSIH_GE:
+ case VKD3DSIH_IEQ:
+ case VKD3DSIH_IGE:
+ case VKD3DSIH_ILT:
+ case VKD3DSIH_INE:
+ case VKD3DSIH_LT:
+ case VKD3DSIH_NE:
+ case VKD3DSIH_UGE:
+ case VKD3DSIH_ULT:
+ vkd3d_dxbc_compiler_emit_comparison_instruction(compiler, instruction);
+ break;
+ case VKD3DSIH_BFI:
+ case VKD3DSIH_IBFE:
+ case VKD3DSIH_UBFE:
+ vkd3d_dxbc_compiler_emit_bitfield_instruction(compiler, instruction);
+ break;
+ case VKD3DSIH_F16TOF32:
+ vkd3d_dxbc_compiler_emit_f16tof32(compiler, instruction);
+ break;
+ case VKD3DSIH_F32TOF16:
+ vkd3d_dxbc_compiler_emit_f32tof16(compiler, instruction);
+ break;
+ case VKD3DSIH_BREAK:
+ case VKD3DSIH_BREAKP:
+ case VKD3DSIH_CASE:
+ case VKD3DSIH_CONTINUE:
+ case VKD3DSIH_CONTINUEP:
+ case VKD3DSIH_DEFAULT:
+ case VKD3DSIH_ELSE:
+ case VKD3DSIH_ENDIF:
+ case VKD3DSIH_ENDLOOP:
+ case VKD3DSIH_ENDSWITCH:
+ case VKD3DSIH_IF:
+ case VKD3DSIH_LOOP:
+ case VKD3DSIH_RET:
+ case VKD3DSIH_RETP:
+ case VKD3DSIH_SWITCH:
+ case VKD3DSIH_TEXKILL:
+ ret = vkd3d_dxbc_compiler_emit_control_flow_instruction(compiler, instruction);
+ break;
+ case VKD3DSIH_DSX:
+ case VKD3DSIH_DSX_COARSE:
+ case VKD3DSIH_DSX_FINE:
+ case VKD3DSIH_DSY:
+ case VKD3DSIH_DSY_COARSE:
+ case VKD3DSIH_DSY_FINE:
+ vkd3d_dxbc_compiler_emit_deriv_instruction(compiler, instruction);
+ break;
+ case VKD3DSIH_LD2DMS:
+ case VKD3DSIH_LD:
+ vkd3d_dxbc_compiler_emit_ld(compiler, instruction);
+ break;
+ case VKD3DSIH_LOD:
+ vkd3d_dxbc_compiler_emit_lod(compiler, instruction);
+ break;
+ case VKD3DSIH_SAMPLE:
+ case VKD3DSIH_SAMPLE_B:
+ case VKD3DSIH_SAMPLE_GRAD:
+ case VKD3DSIH_SAMPLE_LOD:
+ vkd3d_dxbc_compiler_emit_sample(compiler, instruction);
+ break;
+ case VKD3DSIH_SAMPLE_C:
+ case VKD3DSIH_SAMPLE_C_LZ:
+ vkd3d_dxbc_compiler_emit_sample_c(compiler, instruction);
+ break;
+ case VKD3DSIH_GATHER4:
+ case VKD3DSIH_GATHER4_C:
+ case VKD3DSIH_GATHER4_PO:
+ case VKD3DSIH_GATHER4_PO_C:
+ vkd3d_dxbc_compiler_emit_gather4(compiler, instruction);
+ break;
+ case VKD3DSIH_LD_RAW:
+ case VKD3DSIH_LD_STRUCTURED:
+ vkd3d_dxbc_compiler_emit_ld_raw_structured(compiler, instruction);
+ break;
+ case VKD3DSIH_STORE_RAW:
+ case VKD3DSIH_STORE_STRUCTURED:
+ vkd3d_dxbc_compiler_emit_store_raw_structured(compiler, instruction);
+ break;
+ case VKD3DSIH_LD_UAV_TYPED:
+ vkd3d_dxbc_compiler_emit_ld_uav_typed(compiler, instruction);
+ break;
+ case VKD3DSIH_STORE_UAV_TYPED:
+ vkd3d_dxbc_compiler_emit_store_uav_typed(compiler, instruction);
+ break;
+ case VKD3DSIH_IMM_ATOMIC_ALLOC:
+ case VKD3DSIH_IMM_ATOMIC_CONSUME:
+ vkd3d_dxbc_compiler_emit_uav_counter_instruction(compiler, instruction);
+ break;
+ case VKD3DSIH_ATOMIC_AND:
+ case VKD3DSIH_ATOMIC_CMP_STORE:
+ case VKD3DSIH_ATOMIC_IADD:
+ case VKD3DSIH_ATOMIC_IMAX:
+ case VKD3DSIH_ATOMIC_IMIN:
+ case VKD3DSIH_ATOMIC_OR:
+ case VKD3DSIH_ATOMIC_UMAX:
+ case VKD3DSIH_ATOMIC_UMIN:
+ case VKD3DSIH_ATOMIC_XOR:
+ case VKD3DSIH_IMM_ATOMIC_AND:
+ case VKD3DSIH_IMM_ATOMIC_CMP_EXCH:
+ case VKD3DSIH_IMM_ATOMIC_EXCH:
+ case VKD3DSIH_IMM_ATOMIC_IADD:
+ case VKD3DSIH_IMM_ATOMIC_IMAX:
+ case VKD3DSIH_IMM_ATOMIC_IMIN:
+ case VKD3DSIH_IMM_ATOMIC_OR:
+ case VKD3DSIH_IMM_ATOMIC_UMAX:
+ case VKD3DSIH_IMM_ATOMIC_UMIN:
+ case VKD3DSIH_IMM_ATOMIC_XOR:
+ vkd3d_dxbc_compiler_emit_atomic_instruction(compiler, instruction);
+ break;
+ case VKD3DSIH_BUFINFO:
+ vkd3d_dxbc_compiler_emit_bufinfo(compiler, instruction);
+ break;
+ case VKD3DSIH_RESINFO:
+ vkd3d_dxbc_compiler_emit_resinfo(compiler, instruction);
+ break;
+ case VKD3DSIH_SAMPLE_INFO:
+ vkd3d_dxbc_compiler_emit_sample_info(compiler, instruction);
+ break;
+ case VKD3DSIH_SAMPLE_POS:
+ vkd3d_dxbc_compiler_emit_sample_position(compiler, instruction);
+ break;
+ case VKD3DSIH_EVAL_CENTROID:
+ case VKD3DSIH_EVAL_SAMPLE_INDEX:
+ vkd3d_dxbc_compiler_emit_eval_attrib(compiler, instruction);
+ break;
+ case VKD3DSIH_SYNC:
+ vkd3d_dxbc_compiler_emit_sync(compiler, instruction);
+ break;
+ case VKD3DSIH_EMIT:
+ case VKD3DSIH_EMIT_STREAM:
+ vkd3d_dxbc_compiler_emit_emit_stream(compiler, instruction);
+ break;
+ case VKD3DSIH_CUT:
+ case VKD3DSIH_CUT_STREAM:
+ vkd3d_dxbc_compiler_emit_cut_stream(compiler, instruction);
+ break;
+ case VKD3DSIH_DCL_HS_MAX_TESSFACTOR:
+ case VKD3DSIH_HS_DECLS:
+ case VKD3DSIH_NOP:
+ /* nothing to do */
+ break;
+ default:
+ FIXME("Unhandled instruction %#x.\n", instruction->handler_idx);
+ }
+
+ return ret;
+}
+
+int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *spirv)
+{
+ const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
+ const struct vkd3d_shader_spirv_domain_shader_target_info *ds_info;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_phase *phase;
+
+ if ((phase = vkd3d_dxbc_compiler_get_current_shader_phase(compiler)))
+ vkd3d_dxbc_compiler_leave_shader_phase(compiler, phase);
+ else
+ vkd3d_spirv_build_op_function_end(builder);
+
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL)
+ vkd3d_dxbc_compiler_emit_hull_shader_main(compiler);
+
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN)
+ {
+ if (info && (ds_info = vkd3d_find_struct(compile_info->next, SPIRV_DOMAIN_SHADER_TARGET_INFO)))
+ {
+ vkd3d_dxbc_compiler_emit_tessellator_output_primitive(compiler, ds_info->output_primitive);
+ vkd3d_dxbc_compiler_emit_tessellator_partitioning(compiler, ds_info->partitioning);
+ }
+ else if (vkd3d_dxbc_compiler_is_opengl_target(compiler))
+ {
+ ERR("vkd3d_shader_spirv_domain_shader_target_info is required for "
+ "OpenGL tessellation evaluation shader.\n");
+ }
+ }
+
+ if (compiler->epilogue_function_id)
+ {
+ vkd3d_spirv_build_op_name(builder, compiler->epilogue_function_id, "epilogue");
+ vkd3d_dxbc_compiler_emit_shader_epilogue_function(compiler);
+ }
+
+ if (compiler->strip_debug)
+ vkd3d_spirv_stream_clear(&builder->debug_stream);
+
+ if (!vkd3d_spirv_compile_module(builder, spirv, vkd3d_dxbc_compiler_get_entry_point_name(compiler)))
+ return VKD3D_ERROR;
+
+ if (TRACE_ON())
+ {
+ enum vkd3d_shader_spirv_environment environment = vkd3d_dxbc_compiler_get_target_environment(compiler);
+ vkd3d_spirv_dump(spirv, environment);
+ vkd3d_spirv_validate(spirv, environment);
+ }
+
+ if (compiler->failed)
+ return VKD3D_ERROR_INVALID_SHADER;
+
+ if (compile_info->target_type == VKD3D_SHADER_TARGET_SPIRV_TEXT)
+ {
+ struct vkd3d_shader_code text;
+ enum vkd3d_shader_spirv_environment environment = vkd3d_dxbc_compiler_get_target_environment(compiler);
+ if (vkd3d_spirv_binary_to_text(spirv, environment,
+ get_binary_to_text_options(compiler->formatting), &text) != VKD3D_OK)
+ return VKD3D_ERROR;
+ *spirv = text;
+ }
+
+ return VKD3D_OK;
+}
+
+void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler)
+{
+ vkd3d_free(compiler->control_flow_info);
+
+ vkd3d_free(compiler->output_info);
+
+ vkd3d_free(compiler->push_constants);
+
+ vkd3d_spirv_builder_free(&compiler->spirv_builder);
+
+ rb_destroy(&compiler->symbol_table, vkd3d_symbol_free, NULL);
+
+ vkd3d_free(compiler->shader_phases);
+ vkd3d_free(compiler->spec_constants);
+
+ vkd3d_free(compiler);
+}
diff --git a/dlls/vkd3d/libs/vkd3d-shader/trace.c b/dlls/vkd3d/libs/vkd3d-shader/trace.c
new file mode 100644
index 00000000000..d7495ee93c8
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-shader/trace.c
@@ -0,0 +1,1602 @@
+/*
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2004 Christian Costa
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006 Ivan Gyurdiev
+ * Copyright 2007-2008, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2009-2011 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_shader_private.h"
+
+#include <stdio.h>
+
+static const char * const shader_opcode_names[] =
+{
+ /* VKD3DSIH_ABS */ "abs",
+ /* VKD3DSIH_ADD */ "add",
+ /* VKD3DSIH_AND */ "and",
+ /* VKD3DSIH_ATOMIC_AND */ "atomic_and",
+ /* VKD3DSIH_ATOMIC_CMP_STORE */ "atomic_cmp_store",
+ /* VKD3DSIH_ATOMIC_IADD */ "atomic_iadd",
+ /* VKD3DSIH_ATOMIC_IMAX */ "atomic_imax",
+ /* VKD3DSIH_ATOMIC_IMIN */ "atomic_imin",
+ /* VKD3DSIH_ATOMIC_OR */ "atomic_or",
+ /* VKD3DSIH_ATOMIC_UMAX */ "atomic_umax",
+ /* VKD3DSIH_ATOMIC_UMIN */ "atomic_umin",
+ /* VKD3DSIH_ATOMIC_XOR */ "atomic_xor",
+ /* VKD3DSIH_BEM */ "bem",
+ /* VKD3DSIH_BFI */ "bfi",
+ /* VKD3DSIH_BFREV */ "bfrev",
+ /* VKD3DSIH_BREAK */ "break",
+ /* VKD3DSIH_BREAKC */ "breakc",
+ /* VKD3DSIH_BREAKP */ "breakp",
+ /* VKD3DSIH_BUFINFO */ "bufinfo",
+ /* VKD3DSIH_CALL */ "call",
+ /* VKD3DSIH_CALLNZ */ "callnz",
+ /* VKD3DSIH_CASE */ "case",
+ /* VKD3DSIH_CMP */ "cmp",
+ /* VKD3DSIH_CND */ "cnd",
+ /* VKD3DSIH_CONTINUE */ "continue",
+ /* VKD3DSIH_CONTINUEP */ "continuec",
+ /* VKD3DSIH_COUNTBITS */ "countbits",
+ /* VKD3DSIH_CRS */ "crs",
+ /* VKD3DSIH_CUT */ "cut",
+ /* VKD3DSIH_CUT_STREAM */ "cut_stream",
+ /* VKD3DSIH_DCL */ "dcl",
+ /* VKD3DSIH_DCL_CONSTANT_BUFFER */ "dcl_constantBuffer",
+ /* VKD3DSIH_DCL_FUNCTION_BODY */ "dcl_function_body",
+ /* VKD3DSIH_DCL_FUNCTION_TABLE */ "dcl_function_table",
+ /* VKD3DSIH_DCL_GLOBAL_FLAGS */ "dcl_globalFlags",
+ /* VKD3DSIH_DCL_GS_INSTANCES */ "dcl_gs_instances",
+ /* VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT */ "dcl_hs_fork_phase_instance_count",
+ /* VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ "dcl_hs_join_phase_instance_count",
+ /* VKD3DSIH_DCL_HS_MAX_TESSFACTOR */ "dcl_hs_max_tessfactor",
+ /* VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER */ "dcl_immediateConstantBuffer",
+ /* VKD3DSIH_DCL_INDEX_RANGE */ "dcl_index_range",
+ /* VKD3DSIH_DCL_INDEXABLE_TEMP */ "dcl_indexableTemp",
+ /* VKD3DSIH_DCL_INPUT */ "dcl_input",
+ /* VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT */ "dcl_input_control_point_count",
+ /* VKD3DSIH_DCL_INPUT_PRIMITIVE */ "dcl_inputPrimitive",
+ /* VKD3DSIH_DCL_INPUT_PS */ "dcl_input_ps",
+ /* VKD3DSIH_DCL_INPUT_PS_SGV */ "dcl_input_ps_sgv",
+ /* VKD3DSIH_DCL_INPUT_PS_SIV */ "dcl_input_ps_siv",
+ /* VKD3DSIH_DCL_INPUT_SGV */ "dcl_input_sgv",
+ /* VKD3DSIH_DCL_INPUT_SIV */ "dcl_input_siv",
+ /* VKD3DSIH_DCL_INTERFACE */ "dcl_interface",
+ /* VKD3DSIH_DCL_OUTPUT */ "dcl_output",
+ /* VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT */ "dcl_output_control_point_count",
+ /* VKD3DSIH_DCL_OUTPUT_SIV */ "dcl_output_siv",
+ /* VKD3DSIH_DCL_OUTPUT_TOPOLOGY */ "dcl_outputTopology",
+ /* VKD3DSIH_DCL_RESOURCE_RAW */ "dcl_resource_raw",
+ /* VKD3DSIH_DCL_RESOURCE_STRUCTURED */ "dcl_resource_structured",
+ /* VKD3DSIH_DCL_SAMPLER */ "dcl_sampler",
+ /* VKD3DSIH_DCL_STREAM */ "dcl_stream",
+ /* VKD3DSIH_DCL_TEMPS */ "dcl_temps",
+ /* VKD3DSIH_DCL_TESSELLATOR_DOMAIN */ "dcl_tessellator_domain",
+ /* VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE */ "dcl_tessellator_output_primitive",
+ /* VKD3DSIH_DCL_TESSELLATOR_PARTITIONING */ "dcl_tessellator_partitioning",
+ /* VKD3DSIH_DCL_TGSM_RAW */ "dcl_tgsm_raw",
+ /* VKD3DSIH_DCL_TGSM_STRUCTURED */ "dcl_tgsm_structured",
+ /* VKD3DSIH_DCL_THREAD_GROUP */ "dcl_thread_group",
+ /* VKD3DSIH_DCL_UAV_RAW */ "dcl_uav_raw",
+ /* VKD3DSIH_DCL_UAV_STRUCTURED */ "dcl_uav_structured",
+ /* VKD3DSIH_DCL_UAV_TYPED */ "dcl_uav_typed",
+ /* VKD3DSIH_DCL_VERTICES_OUT */ "dcl_maxOutputVertexCount",
+ /* VKD3DSIH_DEF */ "def",
+ /* VKD3DSIH_DEFAULT */ "default",
+ /* VKD3DSIH_DEFB */ "defb",
+ /* VKD3DSIH_DEFI */ "defi",
+ /* VKD3DSIH_DIV */ "div",
+ /* VKD3DSIH_DP2 */ "dp2",
+ /* VKD3DSIH_DP2ADD */ "dp2add",
+ /* VKD3DSIH_DP3 */ "dp3",
+ /* VKD3DSIH_DP4 */ "dp4",
+ /* VKD3DSIH_DST */ "dst",
+ /* VKD3DSIH_DSX */ "dsx",
+ /* VKD3DSIH_DSX_COARSE */ "deriv_rtx_coarse",
+ /* VKD3DSIH_DSX_FINE */ "deriv_rtx_fine",
+ /* VKD3DSIH_DSY */ "dsy",
+ /* VKD3DSIH_DSY_COARSE */ "deriv_rty_coarse",
+ /* VKD3DSIH_DSY_FINE */ "deriv_rty_fine",
+ /* VKD3DSIH_ELSE */ "else",
+ /* VKD3DSIH_EMIT */ "emit",
+ /* VKD3DSIH_EMIT_STREAM */ "emit_stream",
+ /* VKD3DSIH_ENDIF */ "endif",
+ /* VKD3DSIH_ENDLOOP */ "endloop",
+ /* VKD3DSIH_ENDREP */ "endrep",
+ /* VKD3DSIH_ENDSWITCH */ "endswitch",
+ /* VKD3DSIH_EQ */ "eq",
+ /* VKD3DSIH_EVAL_CENTROID */ "eval_centroid",
+ /* VKD3DSIH_EVAL_SAMPLE_INDEX */ "eval_sample_index",
+ /* VKD3DSIH_EXP */ "exp",
+ /* VKD3DSIH_EXPP */ "expp",
+ /* VKD3DSIH_F16TOF32 */ "f16tof32",
+ /* VKD3DSIH_F32TOF16 */ "f32tof16",
+ /* VKD3DSIH_FCALL */ "fcall",
+ /* VKD3DSIH_FIRSTBIT_HI */ "firstbit_hi",
+ /* VKD3DSIH_FIRSTBIT_LO */ "firstbit_lo",
+ /* VKD3DSIH_FIRSTBIT_SHI */ "firstbit_shi",
+ /* VKD3DSIH_FRC */ "frc",
+ /* VKD3DSIH_FTOI */ "ftoi",
+ /* VKD3DSIH_FTOU */ "ftou",
+ /* VKD3DSIH_GATHER4 */ "gather4",
+ /* VKD3DSIH_GATHER4_C */ "gather4_c",
+ /* VKD3DSIH_GATHER4_PO */ "gather4_po",
+ /* VKD3DSIH_GATHER4_PO_C */ "gather4_po_c",
+ /* VKD3DSIH_GE */ "ge",
+ /* VKD3DSIH_HS_CONTROL_POINT_PHASE */ "hs_control_point_phase",
+ /* VKD3DSIH_HS_DECLS */ "hs_decls",
+ /* VKD3DSIH_HS_FORK_PHASE */ "hs_fork_phase",
+ /* VKD3DSIH_HS_JOIN_PHASE */ "hs_join_phase",
+ /* VKD3DSIH_IADD */ "iadd",
+ /* VKD3DSIH_IBFE */ "ibfe",
+ /* VKD3DSIH_IEQ */ "ieq",
+ /* VKD3DSIH_IF */ "if",
+ /* VKD3DSIH_IFC */ "ifc",
+ /* VKD3DSIH_IGE */ "ige",
+ /* VKD3DSIH_ILT */ "ilt",
+ /* VKD3DSIH_IMAD */ "imad",
+ /* VKD3DSIH_IMAX */ "imax",
+ /* VKD3DSIH_IMIN */ "imin",
+ /* VKD3DSIH_IMM_ATOMIC_ALLOC */ "imm_atomic_alloc",
+ /* VKD3DSIH_IMM_ATOMIC_AND */ "imm_atomic_and",
+ /* VKD3DSIH_IMM_ATOMIC_CMP_EXCH */ "imm_atomic_cmp_exch",
+ /* VKD3DSIH_IMM_ATOMIC_CONSUME */ "imm_atomic_consume",
+ /* VKD3DSIH_IMM_ATOMIC_EXCH */ "imm_atomic_exch",
+ /* VKD3DSIH_IMM_ATOMIC_IADD */ "imm_atomic_iadd",
+ /* VKD3DSIH_IMM_ATOMIC_IMAX */ "imm_atomic_imax",
+ /* VKD3DSIH_IMM_ATOMIC_IMIN */ "imm_atomic_imin",
+ /* VKD3DSIH_IMM_ATOMIC_OR */ "imm_atomic_or",
+ /* VKD3DSIH_IMM_ATOMIC_UMAX */ "imm_atomic_umax",
+ /* VKD3DSIH_IMM_ATOMIC_UMIN */ "imm_atomic_umin",
+ /* VKD3DSIH_IMM_ATOMIC_XOR */ "imm_atomic_xor",
+ /* VKD3DSIH_IMUL */ "imul",
+ /* VKD3DSIH_INE */ "ine",
+ /* VKD3DSIH_INEG */ "ineg",
+ /* VKD3DSIH_ISHL */ "ishl",
+ /* VKD3DSIH_ISHR */ "ishr",
+ /* VKD3DSIH_ITOF */ "itof",
+ /* VKD3DSIH_LABEL */ "label",
+ /* VKD3DSIH_LD */ "ld",
+ /* VKD3DSIH_LD2DMS */ "ld2dms",
+ /* VKD3DSIH_LD_RAW */ "ld_raw",
+ /* VKD3DSIH_LD_STRUCTURED */ "ld_structured",
+ /* VKD3DSIH_LD_UAV_TYPED */ "ld_uav_typed",
+ /* VKD3DSIH_LIT */ "lit",
+ /* VKD3DSIH_LOD */ "lod",
+ /* VKD3DSIH_LOG */ "log",
+ /* VKD3DSIH_LOGP */ "logp",
+ /* VKD3DSIH_LOOP */ "loop",
+ /* VKD3DSIH_LRP */ "lrp",
+ /* VKD3DSIH_LT */ "lt",
+ /* VKD3DSIH_M3x2 */ "m3x2",
+ /* VKD3DSIH_M3x3 */ "m3x3",
+ /* VKD3DSIH_M3x4 */ "m3x4",
+ /* VKD3DSIH_M4x3 */ "m4x3",
+ /* VKD3DSIH_M4x4 */ "m4x4",
+ /* VKD3DSIH_MAD */ "mad",
+ /* VKD3DSIH_MAX */ "max",
+ /* VKD3DSIH_MIN */ "min",
+ /* VKD3DSIH_MOV */ "mov",
+ /* VKD3DSIH_MOVA */ "mova",
+ /* VKD3DSIH_MOVC */ "movc",
+ /* VKD3DSIH_MUL */ "mul",
+ /* VKD3DSIH_NE */ "ne",
+ /* VKD3DSIH_NOP */ "nop",
+ /* VKD3DSIH_NOT */ "not",
+ /* VKD3DSIH_NRM */ "nrm",
+ /* VKD3DSIH_OR */ "or",
+ /* VKD3DSIH_PHASE */ "phase",
+ /* VKD3DSIH_POW */ "pow",
+ /* VKD3DSIH_RCP */ "rcp",
+ /* VKD3DSIH_REP */ "rep",
+ /* VKD3DSIH_RESINFO */ "resinfo",
+ /* VKD3DSIH_RET */ "ret",
+ /* VKD3DSIH_RETP */ "retp",
+ /* VKD3DSIH_ROUND_NE */ "round_ne",
+ /* VKD3DSIH_ROUND_NI */ "round_ni",
+ /* VKD3DSIH_ROUND_PI */ "round_pi",
+ /* VKD3DSIH_ROUND_Z */ "round_z",
+ /* VKD3DSIH_RSQ */ "rsq",
+ /* VKD3DSIH_SAMPLE */ "sample",
+ /* VKD3DSIH_SAMPLE_B */ "sample_b",
+ /* VKD3DSIH_SAMPLE_C */ "sample_c",
+ /* VKD3DSIH_SAMPLE_C_LZ */ "sample_c_lz",
+ /* VKD3DSIH_SAMPLE_GRAD */ "sample_d",
+ /* VKD3DSIH_SAMPLE_INFO */ "sample_info",
+ /* VKD3DSIH_SAMPLE_LOD */ "sample_l",
+ /* VKD3DSIH_SAMPLE_POS */ "sample_pos",
+ /* VKD3DSIH_SETP */ "setp",
+ /* VKD3DSIH_SGE */ "sge",
+ /* VKD3DSIH_SGN */ "sgn",
+ /* VKD3DSIH_SINCOS */ "sincos",
+ /* VKD3DSIH_SLT */ "slt",
+ /* VKD3DSIH_SQRT */ "sqrt",
+ /* VKD3DSIH_STORE_RAW */ "store_raw",
+ /* VKD3DSIH_STORE_STRUCTURED */ "store_structured",
+ /* VKD3DSIH_STORE_UAV_TYPED */ "store_uav_typed",
+ /* VKD3DSIH_SUB */ "sub",
+ /* VKD3DSIH_SWAPC */ "swapc",
+ /* VKD3DSIH_SWITCH */ "switch",
+ /* VKD3DSIH_SYNC */ "sync",
+ /* VKD3DSIH_TEX */ "texld",
+ /* VKD3DSIH_TEXBEM */ "texbem",
+ /* VKD3DSIH_TEXBEML */ "texbeml",
+ /* VKD3DSIH_TEXCOORD */ "texcrd",
+ /* VKD3DSIH_TEXDEPTH */ "texdepth",
+ /* VKD3DSIH_TEXDP3 */ "texdp3",
+ /* VKD3DSIH_TEXDP3TEX */ "texdp3tex",
+ /* VKD3DSIH_TEXKILL */ "texkill",
+ /* VKD3DSIH_TEXLDD */ "texldd",
+ /* VKD3DSIH_TEXLDL */ "texldl",
+ /* VKD3DSIH_TEXM3x2DEPTH */ "texm3x2depth",
+ /* VKD3DSIH_TEXM3x2PAD */ "texm3x2pad",
+ /* VKD3DSIH_TEXM3x2TEX */ "texm3x2tex",
+ /* VKD3DSIH_TEXM3x3 */ "texm3x3",
+ /* VKD3DSIH_TEXM3x3DIFF */ "texm3x3diff",
+ /* VKD3DSIH_TEXM3x3PAD */ "texm3x3pad",
+ /* VKD3DSIH_TEXM3x3SPEC */ "texm3x3spec",
+ /* VKD3DSIH_TEXM3x3TEX */ "texm3x3tex",
+ /* VKD3DSIH_TEXM3x3VSPEC */ "texm3x3vspec",
+ /* VKD3DSIH_TEXREG2AR */ "texreg2ar",
+ /* VKD3DSIH_TEXREG2GB */ "texreg2gb",
+ /* VKD3DSIH_TEXREG2RGB */ "texreg2rgb",
+ /* VKD3DSIH_UBFE */ "ubfe",
+ /* VKD3DSIH_UDIV */ "udiv",
+ /* VKD3DSIH_UGE */ "uge",
+ /* VKD3DSIH_ULT */ "ult",
+ /* VKD3DSIH_UMAX */ "umax",
+ /* VKD3DSIH_UMIN */ "umin",
+ /* VKD3DSIH_UMUL */ "umul",
+ /* VKD3DSIH_USHR */ "ushr",
+ /* VKD3DSIH_UTOF */ "utof",
+ /* VKD3DSIH_XOR */ "xor",
+};
+
+static const struct
+{
+ enum vkd3d_shader_input_sysval_semantic sysval_semantic;
+ const char *sysval_name;
+}
+shader_input_sysval_semantic_names[] =
+{
+ {VKD3D_SIV_POSITION, "position"},
+ {VKD3D_SIV_CLIP_DISTANCE, "clip_distance"},
+ {VKD3D_SIV_CULL_DISTANCE, "cull_distance"},
+ {VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX, "render_target_array_index"},
+ {VKD3D_SIV_VIEWPORT_ARRAY_INDEX, "viewport_array_index"},
+ {VKD3D_SIV_VERTEX_ID, "vertex_id"},
+ {VKD3D_SIV_INSTANCE_ID, "instance_id"},
+ {VKD3D_SIV_PRIMITIVE_ID, "primitive_id"},
+ {VKD3D_SIV_IS_FRONT_FACE, "is_front_face"},
+ {VKD3D_SIV_SAMPLE_INDEX, "sample_index"},
+ {VKD3D_SIV_QUAD_U0_TESS_FACTOR, "finalQuadUeq0EdgeTessFactor"},
+ {VKD3D_SIV_QUAD_V0_TESS_FACTOR, "finalQuadVeq0EdgeTessFactor"},
+ {VKD3D_SIV_QUAD_U1_TESS_FACTOR, "finalQuadUeq1EdgeTessFactor"},
+ {VKD3D_SIV_QUAD_V1_TESS_FACTOR, "finalQuadVeq1EdgeTessFactor"},
+ {VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR, "finalQuadUInsideTessFactor"},
+ {VKD3D_SIV_QUAD_V_INNER_TESS_FACTOR, "finalQuadVInsideTessFactor"},
+ {VKD3D_SIV_TRIANGLE_U_TESS_FACTOR, "finalTriUeq0EdgeTessFactor"},
+ {VKD3D_SIV_TRIANGLE_V_TESS_FACTOR, "finalTriVeq0EdgeTessFactor"},
+ {VKD3D_SIV_TRIANGLE_W_TESS_FACTOR, "finalTriWeq0EdgeTessFactor"},
+ {VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR, "finalTriInsideTessFactor"},
+ {VKD3D_SIV_LINE_DETAIL_TESS_FACTOR, "finalLineDetailTessFactor"},
+ {VKD3D_SIV_LINE_DENSITY_TESS_FACTOR, "finalLineDensityTessFactor"},
+};
+
+static int shader_ver_ge(const struct vkd3d_shader_version *v, int major, int minor)
+{
+ return v->major > major || (v->major == major && v->minor >= minor);
+}
+
+static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = vkd3d_string_buffer_vprintf(buffer, format, args);
+ va_end(args);
+
+ return ret;
+}
+
+/* Convert floating point offset relative to a register file to an absolute
+ * offset for float constants. */
+static unsigned int shader_get_float_offset(enum vkd3d_shader_register_type register_type, UINT register_idx)
+{
+ switch (register_type)
+ {
+ case VKD3DSPR_CONST: return register_idx;
+ case VKD3DSPR_CONST2: return 2048 + register_idx;
+ case VKD3DSPR_CONST3: return 4096 + register_idx;
+ case VKD3DSPR_CONST4: return 6144 + register_idx;
+ default:
+ FIXME("Unsupported register type: %u.\n", register_type);
+ return register_idx;
+ }
+}
+
+static void shader_dump_global_flags(struct vkd3d_string_buffer *buffer, DWORD global_flags)
+{
+ unsigned int i;
+
+ static const struct
+ {
+ unsigned int flag;
+ const char *name;
+ }
+ global_flag_info[] =
+ {
+ {VKD3DSGF_REFACTORING_ALLOWED, "refactoringAllowed"},
+ {VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL, "forceEarlyDepthStencil"},
+ {VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS, "enableRawAndStructuredBuffers"},
+ {VKD3DSGF_ENABLE_MINIMUM_PRECISION, "enableMinimumPrecision"},
+ {VKD3DSGF_SKIP_OPTIMIZATION, "skipOptimization"},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(global_flag_info); ++i)
+ {
+ if (global_flags & global_flag_info[i].flag)
+ {
+ shader_addline(buffer, "%s", global_flag_info[i].name);
+ global_flags &= ~global_flag_info[i].flag;
+ if (global_flags)
+ shader_addline(buffer, " | ");
+ }
+ }
+
+ if (global_flags)
+ shader_addline(buffer, "unknown_flags(%#x)", global_flags);
+}
+
+static void shader_dump_sync_flags(struct vkd3d_string_buffer *buffer, DWORD sync_flags)
+{
+ if (sync_flags & VKD3DSSF_GROUP_SHARED_MEMORY)
+ {
+ shader_addline(buffer, "_g");
+ sync_flags &= ~VKD3DSSF_GROUP_SHARED_MEMORY;
+ }
+ if (sync_flags & VKD3DSSF_THREAD_GROUP)
+ {
+ shader_addline(buffer, "_t");
+ sync_flags &= ~VKD3DSSF_THREAD_GROUP;
+ }
+
+ if (sync_flags)
+ shader_addline(buffer, "_unknown_flags(%#x)", sync_flags);
+}
+
+static void shader_dump_precise_flags(struct vkd3d_string_buffer *buffer, DWORD flags)
+{
+ if (!(flags & VKD3DSI_PRECISE_XYZW))
+ return;
+
+ shader_addline(buffer, " [precise");
+ if (flags != VKD3DSI_PRECISE_XYZW)
+ {
+ shader_addline(buffer, "(%s%s%s%s)",
+ flags & VKD3DSI_PRECISE_X ? "x" : "",
+ flags & VKD3DSI_PRECISE_Y ? "y" : "",
+ flags & VKD3DSI_PRECISE_Z ? "z" : "",
+ flags & VKD3DSI_PRECISE_W ? "w" : "");
+ }
+ shader_addline(buffer, "]");
+}
+
+static void shader_dump_uav_flags(struct vkd3d_string_buffer *buffer, DWORD uav_flags)
+{
+ if (uav_flags & VKD3DSUF_GLOBALLY_COHERENT)
+ {
+ shader_addline(buffer, "_glc");
+ uav_flags &= ~VKD3DSUF_GLOBALLY_COHERENT;
+ }
+ if (uav_flags & VKD3DSUF_ORDER_PRESERVING_COUNTER)
+ {
+ shader_addline(buffer, "_opc");
+ uav_flags &= ~VKD3DSUF_ORDER_PRESERVING_COUNTER;
+ }
+
+ if (uav_flags)
+ shader_addline(buffer, "_unknown_flags(%#x)", uav_flags);
+}
+
+static void shader_dump_tessellator_domain(struct vkd3d_string_buffer *buffer,
+ enum vkd3d_tessellator_domain domain)
+{
+ shader_addline(buffer, "domain_");
+ switch (domain)
+ {
+ case VKD3D_TESSELLATOR_DOMAIN_LINE:
+ shader_addline(buffer, "isoline");
+ break;
+ case VKD3D_TESSELLATOR_DOMAIN_TRIANGLE:
+ shader_addline(buffer, "tri");
+ break;
+ case VKD3D_TESSELLATOR_DOMAIN_QUAD:
+ shader_addline(buffer, "quad");
+ break;
+ default:
+ shader_addline(buffer, "unknown_tessellator_domain(%#x)", domain);
+ break;
+ }
+}
+
+static void shader_dump_tessellator_output_primitive(struct vkd3d_string_buffer *buffer,
+ enum vkd3d_shader_tessellator_output_primitive output_primitive)
+{
+ shader_addline(buffer, "output_");
+ switch (output_primitive)
+ {
+ case VKD3D_SHADER_TESSELLATOR_OUTPUT_POINT:
+ shader_addline(buffer, "point");
+ break;
+ case VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE:
+ shader_addline(buffer, "line");
+ break;
+ case VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CW:
+ shader_addline(buffer, "triangle_cw");
+ break;
+ case VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW:
+ shader_addline(buffer, "triangle_ccw");
+ break;
+ default:
+ shader_addline(buffer, "unknown_tessellator_output_primitive(%#x)", output_primitive);
+ break;
+ }
+}
+
+static void shader_dump_tessellator_partitioning(struct vkd3d_string_buffer *buffer,
+ enum vkd3d_shader_tessellator_partitioning partitioning)
+{
+ shader_addline(buffer, "partitioning_");
+ switch (partitioning)
+ {
+ case VKD3D_SHADER_TESSELLATOR_PARTITIONING_INTEGER:
+ shader_addline(buffer, "integer");
+ break;
+ case VKD3D_SHADER_TESSELLATOR_PARTITIONING_POW2:
+ shader_addline(buffer, "pow2");
+ break;
+ case VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD:
+ shader_addline(buffer, "fractional_odd");
+ break;
+ case VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN:
+ shader_addline(buffer, "fractional_even");
+ break;
+ default:
+ shader_addline(buffer, "unknown_tessellator_partitioning(%#x)", partitioning);
+ break;
+ }
+}
+
+static void shader_dump_shader_input_sysval_semantic(struct vkd3d_string_buffer *buffer,
+ enum vkd3d_shader_input_sysval_semantic semantic)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(shader_input_sysval_semantic_names); ++i)
+ {
+ if (shader_input_sysval_semantic_names[i].sysval_semantic == semantic)
+ {
+ shader_addline(buffer, "%s", shader_input_sysval_semantic_names[i].sysval_name);
+ return;
+ }
+ }
+
+ shader_addline(buffer, "unknown_shader_input_sysval_semantic(%#x)", semantic);
+}
+
+static void shader_dump_resource_type(struct vkd3d_string_buffer *buffer, enum vkd3d_shader_resource_type type)
+{
+ static const char *const resource_type_names[] =
+ {
+ /* VKD3D_SHADER_RESOURCE_NONE */ "none",
+ /* VKD3D_SHADER_RESOURCE_BUFFER */ "buffer",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_1D */ "texture1d",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_2D */ "texture2d",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */ "texture2dms",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_3D */ "texture3d",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */ "texturecube",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */ "texture1darray",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */ "texture2darray",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */ "texture2dmsarray",
+ /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */ "texturecubearray",
+ };
+
+ if (type <= ARRAY_SIZE(resource_type_names))
+ shader_addline(buffer, "%s", resource_type_names[type]);
+ else
+ shader_addline(buffer, "unknown");
+}
+
+static void shader_dump_data_type(struct vkd3d_string_buffer *buffer, enum vkd3d_data_type type)
+{
+ static const char *const data_type_names[] =
+ {
+ /* VKD3D_DATA_FLOAT */ "float",
+ /* VKD3D_DATA_INT */ "int",
+ /* VKD3D_DATA_RESOURCE */ "resource",
+ /* VKD3D_DATA_SAMPLER */ "sampler",
+ /* VKD3D_DATA_UAV */ "uav",
+ /* VKD3D_DATA_UINT */ "uint",
+ /* VKD3D_DATA_UNORM */ "unorm",
+ /* VKD3D_DATA_SNORM */ "snorm",
+ /* VKD3D_DATA_OPAQUE */ "opaque",
+ };
+ const char *name;
+
+ if (type <= ARRAY_SIZE(data_type_names))
+ name = data_type_names[type];
+ else
+ name = "unknown";
+
+ shader_addline(buffer, "(%s,%s,%s,%s)", name, name, name, name);
+}
+
+static void shader_dump_decl_usage(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_semantic *semantic, unsigned int flags,
+ const struct vkd3d_shader_version *shader_version)
+{
+ shader_addline(buffer, "dcl");
+
+ if (semantic->resource.reg.reg.type == VKD3DSPR_SAMPLER)
+ {
+ switch (semantic->resource_type)
+ {
+ case VKD3D_SHADER_RESOURCE_TEXTURE_2D:
+ shader_addline(buffer, "_2d");
+ break;
+
+ case VKD3D_SHADER_RESOURCE_TEXTURE_3D:
+ shader_addline(buffer, "_3d");
+ break;
+
+ case VKD3D_SHADER_RESOURCE_TEXTURE_CUBE:
+ shader_addline(buffer, "_cube");
+ break;
+
+ default:
+ shader_addline(buffer, "_unknown_resource_type(%#x)", semantic->resource_type);
+ break;
+ }
+ }
+ else if (semantic->resource.reg.reg.type == VKD3DSPR_RESOURCE || semantic->resource.reg.reg.type == VKD3DSPR_UAV)
+ {
+ if (semantic->resource.reg.reg.type == VKD3DSPR_RESOURCE)
+ shader_addline(buffer, "_resource_");
+ else
+ /* non typed UAVs don't go through this code path */
+ shader_addline(buffer, "_uav_typed_");
+
+ shader_dump_resource_type(buffer, semantic->resource_type);
+ if (semantic->resource.reg.reg.type == VKD3DSPR_UAV)
+ shader_dump_uav_flags(buffer, flags);
+ shader_dump_data_type(buffer, semantic->resource_data_type);
+ }
+ else
+ {
+ /* Pixel shaders 3.0 don't have usage semantics. */
+ if (!shader_ver_ge(shader_version, 3, 0) && shader_version->type == VKD3D_SHADER_TYPE_PIXEL)
+ return;
+ else
+ shader_addline(buffer, "_");
+
+ switch (semantic->usage)
+ {
+ case VKD3D_DECL_USAGE_POSITION:
+ shader_addline(buffer, "position%u", semantic->usage_idx);
+ break;
+
+ case VKD3D_DECL_USAGE_BLEND_INDICES:
+ shader_addline(buffer, "blend");
+ break;
+
+ case VKD3D_DECL_USAGE_BLEND_WEIGHT:
+ shader_addline(buffer, "weight");
+ break;
+
+ case VKD3D_DECL_USAGE_NORMAL:
+ shader_addline(buffer, "normal%u", semantic->usage_idx);
+ break;
+
+ case VKD3D_DECL_USAGE_PSIZE:
+ shader_addline(buffer, "psize");
+ break;
+
+ case VKD3D_DECL_USAGE_COLOR:
+ if (!semantic->usage_idx)
+ shader_addline(buffer, "color");
+ else
+ shader_addline(buffer, "specular%u", (semantic->usage_idx - 1));
+ break;
+
+ case VKD3D_DECL_USAGE_TEXCOORD:
+ shader_addline(buffer, "texture%u", semantic->usage_idx);
+ break;
+
+ case VKD3D_DECL_USAGE_TANGENT:
+ shader_addline(buffer, "tangent");
+ break;
+
+ case VKD3D_DECL_USAGE_BINORMAL:
+ shader_addline(buffer, "binormal");
+ break;
+
+ case VKD3D_DECL_USAGE_TESS_FACTOR:
+ shader_addline(buffer, "tessfactor");
+ break;
+
+ case VKD3D_DECL_USAGE_POSITIONT:
+ shader_addline(buffer, "positionT%u", semantic->usage_idx);
+ break;
+
+ case VKD3D_DECL_USAGE_FOG:
+ shader_addline(buffer, "fog");
+ break;
+
+ case VKD3D_DECL_USAGE_DEPTH:
+ shader_addline(buffer, "depth");
+ break;
+
+ case VKD3D_DECL_USAGE_SAMPLE:
+ shader_addline(buffer, "sample");
+ break;
+
+ default:
+ shader_addline(buffer, "<unknown_semantic(%#x)>", semantic->usage);
+ FIXME("Unrecognised semantic usage %#x.\n", semantic->usage);
+ }
+ }
+}
+
+static void shader_dump_src_param(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_src_param *param, const struct vkd3d_shader_version *shader_version);
+
+static void shader_dump_register(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_register *reg, const struct vkd3d_shader_version *shader_version)
+{
+ static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"};
+ static const char * const misctype_reg_names[] = {"vPos", "vFace"};
+ unsigned int offset = reg->idx[0].offset;
+
+ switch (reg->type)
+ {
+ case VKD3DSPR_TEMP:
+ shader_addline(buffer, "r");
+ break;
+
+ case VKD3DSPR_INPUT:
+ shader_addline(buffer, "v");
+ break;
+
+ case VKD3DSPR_CONST:
+ case VKD3DSPR_CONST2:
+ case VKD3DSPR_CONST3:
+ case VKD3DSPR_CONST4:
+ shader_addline(buffer, "c");
+ offset = shader_get_float_offset(reg->type, offset);
+ break;
+
+ case VKD3DSPR_TEXTURE: /* vs: case VKD3DSPR_ADDR */
+ shader_addline(buffer, "%c", shader_version->type == VKD3D_SHADER_TYPE_PIXEL ? 't' : 'a');
+ break;
+
+ case VKD3DSPR_RASTOUT:
+ shader_addline(buffer, "%s", rastout_reg_names[offset]);
+ break;
+
+ case VKD3DSPR_COLOROUT:
+ shader_addline(buffer, "o");
+ if (!shader_ver_ge(shader_version, 4, 0))
+ shader_addline(buffer, "C");
+ break;
+
+ case VKD3DSPR_DEPTHOUT:
+ shader_addline(buffer, "oDepth");
+ break;
+
+ case VKD3DSPR_DEPTHOUTGE:
+ shader_addline(buffer, "oDepthGE");
+ break;
+
+ case VKD3DSPR_DEPTHOUTLE:
+ shader_addline(buffer, "oDepthLE");
+ break;
+
+ case VKD3DSPR_ATTROUT:
+ shader_addline(buffer, "oD");
+ break;
+
+ case VKD3DSPR_TEXCRDOUT:
+ /* Vertex shaders >= 3.0 use general purpose output registers
+ * (VKD3DSPR_OUTPUT), which can include an address token. */
+ if (shader_ver_ge(shader_version, 3, 0))
+ shader_addline(buffer, "o");
+ else
+ shader_addline(buffer, "oT");
+ break;
+
+ case VKD3DSPR_CONSTINT:
+ shader_addline(buffer, "i");
+ break;
+
+ case VKD3DSPR_CONSTBOOL:
+ shader_addline(buffer, "b");
+ break;
+
+ case VKD3DSPR_LABEL:
+ shader_addline(buffer, "l");
+ break;
+
+ case VKD3DSPR_LOOP:
+ shader_addline(buffer, "aL");
+ break;
+
+ case VKD3DSPR_SAMPLER:
+ shader_addline(buffer, "s");
+ break;
+
+ case VKD3DSPR_MISCTYPE:
+ if (offset > 1)
+ {
+ FIXME("Unhandled misctype register %u.\n", offset);
+ shader_addline(buffer, "<unhandled misctype %#x>", offset);
+ }
+ else
+ {
+ shader_addline(buffer, "%s", misctype_reg_names[offset]);
+ }
+ break;
+
+ case VKD3DSPR_PREDICATE:
+ shader_addline(buffer, "p");
+ break;
+
+ case VKD3DSPR_IMMCONST:
+ shader_addline(buffer, "l");
+ break;
+
+ case VKD3DSPR_CONSTBUFFER:
+ shader_addline(buffer, "cb");
+ break;
+
+ case VKD3DSPR_IMMCONSTBUFFER:
+ shader_addline(buffer, "icb");
+ break;
+
+ case VKD3DSPR_PRIMID:
+ shader_addline(buffer, "primID");
+ break;
+
+ case VKD3DSPR_NULL:
+ shader_addline(buffer, "null");
+ break;
+
+ case VKD3DSPR_RASTERIZER:
+ shader_addline(buffer, "rasterizer");
+ break;
+
+ case VKD3DSPR_RESOURCE:
+ shader_addline(buffer, "t");
+ break;
+
+ case VKD3DSPR_UAV:
+ shader_addline(buffer, "u");
+ break;
+
+ case VKD3DSPR_OUTPOINTID:
+ shader_addline(buffer, "vOutputControlPointID");
+ break;
+
+ case VKD3DSPR_FORKINSTID:
+ shader_addline(buffer, "vForkInstanceId");
+ break;
+
+ case VKD3DSPR_JOININSTID:
+ shader_addline(buffer, "vJoinInstanceId");
+ break;
+
+ case VKD3DSPR_INCONTROLPOINT:
+ shader_addline(buffer, "vicp");
+ break;
+
+ case VKD3DSPR_OUTCONTROLPOINT:
+ shader_addline(buffer, "vocp");
+ break;
+
+ case VKD3DSPR_PATCHCONST:
+ shader_addline(buffer, "vpc");
+ break;
+
+ case VKD3DSPR_TESSCOORD:
+ shader_addline(buffer, "vDomainLocation");
+ break;
+
+ case VKD3DSPR_GROUPSHAREDMEM:
+ shader_addline(buffer, "g");
+ break;
+
+ case VKD3DSPR_THREADID:
+ shader_addline(buffer, "vThreadID");
+ break;
+
+ case VKD3DSPR_THREADGROUPID:
+ shader_addline(buffer, "vThreadGroupID");
+ break;
+
+ case VKD3DSPR_LOCALTHREADID:
+ shader_addline(buffer, "vThreadIDInGroup");
+ break;
+
+ case VKD3DSPR_LOCALTHREADINDEX:
+ shader_addline(buffer, "vThreadIDInGroupFlattened");
+ break;
+
+ case VKD3DSPR_IDXTEMP:
+ shader_addline(buffer, "x");
+ break;
+
+ case VKD3DSPR_STREAM:
+ shader_addline(buffer, "m");
+ break;
+
+ case VKD3DSPR_FUNCTIONBODY:
+ shader_addline(buffer, "fb");
+ break;
+
+ case VKD3DSPR_FUNCTIONPOINTER:
+ shader_addline(buffer, "fp");
+ break;
+
+ case VKD3DSPR_COVERAGE:
+ shader_addline(buffer, "vCoverage");
+ break;
+
+ case VKD3DSPR_SAMPLEMASK:
+ shader_addline(buffer, "oMask");
+ break;
+
+ case VKD3DSPR_GSINSTID:
+ shader_addline(buffer, "vGSInstanceID");
+ break;
+
+ default:
+ shader_addline(buffer, "<unhandled_rtype(%#x)>", reg->type);
+ break;
+ }
+
+ if (reg->type == VKD3DSPR_IMMCONST)
+ {
+ shader_addline(buffer, "(");
+ switch (reg->immconst_type)
+ {
+ case VKD3D_IMMCONST_SCALAR:
+ switch (reg->data_type)
+ {
+ case VKD3D_DATA_FLOAT:
+ shader_addline(buffer, "%.8e", reg->u.immconst_float[0]);
+ break;
+ case VKD3D_DATA_INT:
+ shader_addline(buffer, "%d", reg->u.immconst_uint[0]);
+ break;
+ case VKD3D_DATA_RESOURCE:
+ case VKD3D_DATA_SAMPLER:
+ case VKD3D_DATA_UINT:
+ shader_addline(buffer, "%u", reg->u.immconst_uint[0]);
+ break;
+ default:
+ shader_addline(buffer, "<unhandled data type %#x>", reg->data_type);
+ break;
+ }
+ break;
+
+ case VKD3D_IMMCONST_VEC4:
+ switch (reg->data_type)
+ {
+ case VKD3D_DATA_FLOAT:
+ shader_addline(buffer, "%.8e, %.8e, %.8e, %.8e",
+ reg->u.immconst_float[0], reg->u.immconst_float[1],
+ reg->u.immconst_float[2], reg->u.immconst_float[3]);
+ break;
+ case VKD3D_DATA_INT:
+ shader_addline(buffer, "%d, %d, %d, %d",
+ reg->u.immconst_uint[0], reg->u.immconst_uint[1],
+ reg->u.immconst_uint[2], reg->u.immconst_uint[3]);
+ break;
+ case VKD3D_DATA_RESOURCE:
+ case VKD3D_DATA_SAMPLER:
+ case VKD3D_DATA_UINT:
+ shader_addline(buffer, "%u, %u, %u, %u",
+ reg->u.immconst_uint[0], reg->u.immconst_uint[1],
+ reg->u.immconst_uint[2], reg->u.immconst_uint[3]);
+ break;
+ default:
+ shader_addline(buffer, "<unhandled data type %#x>", reg->data_type);
+ break;
+ }
+ break;
+
+ default:
+ shader_addline(buffer, "<unhandled immconst_type %#x>", reg->immconst_type);
+ break;
+ }
+ shader_addline(buffer, ")");
+ }
+ else if (reg->type != VKD3DSPR_RASTOUT
+ && reg->type != VKD3DSPR_MISCTYPE
+ && reg->type != VKD3DSPR_NULL)
+ {
+ if (offset != ~0u)
+ {
+ bool printbrackets = reg->idx[0].rel_addr
+ || reg->type == VKD3DSPR_INCONTROLPOINT
+ || reg->type == VKD3DSPR_IMMCONSTBUFFER
+ || ((shader_version->type == VKD3D_SHADER_TYPE_GEOMETRY
+ || shader_version->type == VKD3D_SHADER_TYPE_HULL)
+ && reg->type == VKD3DSPR_INPUT);
+
+ if (printbrackets)
+ shader_addline(buffer, "[");
+ if (reg->idx[0].rel_addr)
+ {
+ shader_dump_src_param(buffer, reg->idx[0].rel_addr, shader_version);
+ shader_addline(buffer, " + ");
+ }
+ shader_addline(buffer, "%u", offset);
+ if (printbrackets)
+ shader_addline(buffer, "]");
+
+ /* For CBs in sm < 5.1 we move the buffer offset from idx[1] to idx[2]
+ * to normalise it with 5.1.
+ * Here we should ignore it if it's a CB in sm < 5.1. */
+ if (reg->idx[1].offset != ~0u &&
+ (reg->type != VKD3DSPR_CONSTBUFFER || shader_ver_ge(shader_version, 5, 1)))
+ {
+ shader_addline(buffer, "[");
+ if (reg->idx[1].rel_addr)
+ {
+ shader_dump_src_param(buffer, reg->idx[1].rel_addr, shader_version);
+ shader_addline(buffer, " + ");
+ }
+ shader_addline(buffer, "%u]", reg->idx[1].offset);
+ }
+
+ if (reg->idx[2].offset != ~0u)
+ {
+ shader_addline(buffer, "[");
+ if (reg->idx[2].rel_addr)
+ {
+ shader_dump_src_param(buffer, reg->idx[2].rel_addr, shader_version);
+ shader_addline(buffer, " + ");
+ }
+ shader_addline(buffer, "%u]", reg->idx[2].offset);
+ }
+ }
+
+ if (reg->type == VKD3DSPR_FUNCTIONPOINTER)
+ shader_addline(buffer, "[%u]", reg->u.fp_body_idx);
+ }
+}
+
+static void shader_dump_dst_param(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_dst_param *param, const struct vkd3d_shader_version *shader_version)
+{
+ DWORD write_mask = param->write_mask;
+
+ shader_dump_register(buffer, ¶m->reg, shader_version);
+
+ if (write_mask)
+ {
+ static const char write_mask_chars[] = "xyzw";
+
+ shader_addline(buffer, ".");
+ if (write_mask & VKD3DSP_WRITEMASK_0)
+ shader_addline(buffer, "%c", write_mask_chars[0]);
+ if (write_mask & VKD3DSP_WRITEMASK_1)
+ shader_addline(buffer, "%c", write_mask_chars[1]);
+ if (write_mask & VKD3DSP_WRITEMASK_2)
+ shader_addline(buffer, "%c", write_mask_chars[2]);
+ if (write_mask & VKD3DSP_WRITEMASK_3)
+ shader_addline(buffer, "%c", write_mask_chars[3]);
+ }
+}
+
+static void shader_dump_src_param(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_src_param *param, const struct vkd3d_shader_version *shader_version)
+{
+ enum vkd3d_shader_src_modifier src_modifier = param->modifiers;
+ DWORD swizzle = param->swizzle;
+
+ if (src_modifier == VKD3DSPSM_NEG
+ || src_modifier == VKD3DSPSM_BIASNEG
+ || src_modifier == VKD3DSPSM_SIGNNEG
+ || src_modifier == VKD3DSPSM_X2NEG
+ || src_modifier == VKD3DSPSM_ABSNEG)
+ shader_addline(buffer, "-");
+ else if (src_modifier == VKD3DSPSM_COMP)
+ shader_addline(buffer, "1-");
+ else if (src_modifier == VKD3DSPSM_NOT)
+ shader_addline(buffer, "!");
+
+ if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG)
+ shader_addline(buffer, "|");
+
+ shader_dump_register(buffer, ¶m->reg, shader_version);
+
+ switch (src_modifier)
+ {
+ case VKD3DSPSM_NONE: break;
+ case VKD3DSPSM_NEG: break;
+ case VKD3DSPSM_NOT: break;
+ case VKD3DSPSM_BIAS: shader_addline(buffer, "_bias"); break;
+ case VKD3DSPSM_BIASNEG: shader_addline(buffer, "_bias"); break;
+ case VKD3DSPSM_SIGN: shader_addline(buffer, "_bx2"); break;
+ case VKD3DSPSM_SIGNNEG: shader_addline(buffer, "_bx2"); break;
+ case VKD3DSPSM_COMP: break;
+ case VKD3DSPSM_X2: shader_addline(buffer, "_x2"); break;
+ case VKD3DSPSM_X2NEG: shader_addline(buffer, "_x2"); break;
+ case VKD3DSPSM_DZ: shader_addline(buffer, "_dz"); break;
+ case VKD3DSPSM_DW: shader_addline(buffer, "_dw"); break;
+ case VKD3DSPSM_ABSNEG:
+ case VKD3DSPSM_ABS: /* handled later */ break;
+ default: shader_addline(buffer, "_unknown_modifier(%#x)", src_modifier);
+ }
+
+ if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_SAMPLER)
+ {
+ static const char swizzle_chars[] = "xyzw";
+ DWORD swizzle_x = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(0)) & VKD3D_SHADER_SWIZZLE_MASK;
+ DWORD swizzle_y = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(1)) & VKD3D_SHADER_SWIZZLE_MASK;
+ DWORD swizzle_z = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(2)) & VKD3D_SHADER_SWIZZLE_MASK;
+ DWORD swizzle_w = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(3)) & VKD3D_SHADER_SWIZZLE_MASK;
+
+ if (swizzle_x == swizzle_y
+ && swizzle_x == swizzle_z
+ && swizzle_x == swizzle_w)
+ {
+ shader_addline(buffer, ".%c", swizzle_chars[swizzle_x]);
+ }
+ else
+ {
+ shader_addline(buffer, ".%c%c%c%c", swizzle_chars[swizzle_x], swizzle_chars[swizzle_y],
+ swizzle_chars[swizzle_z], swizzle_chars[swizzle_w]);
+ }
+ }
+ if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG)
+ shader_addline(buffer, "|");
+}
+
+static void shader_dump_ins_modifiers(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_dst_param *dst)
+{
+ DWORD mmask = dst->modifiers;
+
+ switch (dst->shift)
+ {
+ case 0: break;
+ case 13: shader_addline(buffer, "_d8"); break;
+ case 14: shader_addline(buffer, "_d4"); break;
+ case 15: shader_addline(buffer, "_d2"); break;
+ case 1: shader_addline(buffer, "_x2"); break;
+ case 2: shader_addline(buffer, "_x4"); break;
+ case 3: shader_addline(buffer, "_x8"); break;
+ default: shader_addline(buffer, "_unhandled_shift(%d)", dst->shift); break;
+ }
+
+ if (mmask & VKD3DSPDM_SATURATE) shader_addline(buffer, "_sat");
+ if (mmask & VKD3DSPDM_PARTIALPRECISION) shader_addline(buffer, "_pp");
+ if (mmask & VKD3DSPDM_MSAMPCENTROID) shader_addline(buffer, "_centroid");
+
+ mmask &= ~(VKD3DSPDM_SATURATE | VKD3DSPDM_PARTIALPRECISION | VKD3DSPDM_MSAMPCENTROID);
+ if (mmask) FIXME("Unrecognised modifier %#x.\n", mmask);
+}
+
+static void shader_dump_primitive_type(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_primitive_type *primitive_type)
+{
+ switch (primitive_type->type)
+ {
+ case VKD3D_PT_UNDEFINED:
+ shader_addline(buffer, "undefined");
+ break;
+ case VKD3D_PT_POINTLIST:
+ shader_addline(buffer, "pointlist");
+ break;
+ case VKD3D_PT_LINELIST:
+ shader_addline(buffer, "linelist");
+ break;
+ case VKD3D_PT_LINESTRIP:
+ shader_addline(buffer, "linestrip");
+ break;
+ case VKD3D_PT_TRIANGLELIST:
+ shader_addline(buffer, "trianglelist");
+ break;
+ case VKD3D_PT_TRIANGLESTRIP:
+ shader_addline(buffer, "trianglestrip");
+ break;
+ case VKD3D_PT_TRIANGLEFAN:
+ shader_addline(buffer, "trianglefan");
+ break;
+ case VKD3D_PT_LINELIST_ADJ:
+ shader_addline(buffer, "linelist_adj");
+ break;
+ case VKD3D_PT_LINESTRIP_ADJ:
+ shader_addline(buffer, "linestrip_adj");
+ break;
+ case VKD3D_PT_TRIANGLELIST_ADJ:
+ shader_addline(buffer, "trianglelist_adj");
+ break;
+ case VKD3D_PT_TRIANGLESTRIP_ADJ:
+ shader_addline(buffer, "trianglestrip_adj");
+ break;
+ case VKD3D_PT_PATCH:
+ shader_addline(buffer, "patch%u", primitive_type->patch_vertex_count);
+ break;
+ default:
+ shader_addline(buffer, "<unrecognized_primitive_type %#x>", primitive_type->type);
+ break;
+ }
+}
+
+static void shader_dump_interpolation_mode(struct vkd3d_string_buffer *buffer,
+ enum vkd3d_shader_interpolation_mode interpolation_mode)
+{
+ switch (interpolation_mode)
+ {
+ case VKD3DSIM_CONSTANT:
+ shader_addline(buffer, "constant");
+ break;
+ case VKD3DSIM_LINEAR:
+ shader_addline(buffer, "linear");
+ break;
+ case VKD3DSIM_LINEAR_CENTROID:
+ shader_addline(buffer, "linear centroid");
+ break;
+ case VKD3DSIM_LINEAR_NOPERSPECTIVE:
+ shader_addline(buffer, "linear noperspective");
+ break;
+ case VKD3DSIM_LINEAR_SAMPLE:
+ shader_addline(buffer, "linear sample");
+ break;
+ case VKD3DSIM_LINEAR_NOPERSPECTIVE_CENTROID:
+ shader_addline(buffer, "linear noperspective centroid");
+ break;
+ case VKD3DSIM_LINEAR_NOPERSPECTIVE_SAMPLE:
+ shader_addline(buffer, "linear noperspective sample");
+ break;
+ default:
+ shader_addline(buffer, "<unrecognized_interpolation_mode %#x>", interpolation_mode);
+ break;
+ }
+}
+
+const char *shader_get_type_prefix(enum vkd3d_shader_type type)
+{
+ switch (type)
+ {
+ case VKD3D_SHADER_TYPE_VERTEX:
+ return "vs";
+
+ case VKD3D_SHADER_TYPE_HULL:
+ return "hs";
+
+ case VKD3D_SHADER_TYPE_DOMAIN:
+ return "ds";
+
+ case VKD3D_SHADER_TYPE_GEOMETRY:
+ return "gs";
+
+ case VKD3D_SHADER_TYPE_PIXEL:
+ return "ps";
+
+ case VKD3D_SHADER_TYPE_COMPUTE:
+ return "cs";
+
+ default:
+ FIXME("Unhandled shader type %#x.\n", type);
+ return "unknown";
+ }
+}
+
+static void shader_dump_instruction_flags(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_version *shader_version)
+{
+ switch (ins->handler_idx)
+ {
+ case VKD3DSIH_BREAKP:
+ case VKD3DSIH_CONTINUEP:
+ case VKD3DSIH_IF:
+ case VKD3DSIH_RETP:
+ case VKD3DSIH_TEXKILL:
+ switch (ins->flags)
+ {
+ case VKD3D_SHADER_CONDITIONAL_OP_NZ: shader_addline(buffer, "_nz"); break;
+ case VKD3D_SHADER_CONDITIONAL_OP_Z: shader_addline(buffer, "_z"); break;
+ default: shader_addline(buffer, "_unrecognized(%#x)", ins->flags); break;
+ }
+ break;
+
+ case VKD3DSIH_IFC:
+ case VKD3DSIH_BREAKC:
+ switch (ins->flags)
+ {
+ case VKD3D_SHADER_REL_OP_GT: shader_addline(buffer, "_gt"); break;
+ case VKD3D_SHADER_REL_OP_EQ: shader_addline(buffer, "_eq"); break;
+ case VKD3D_SHADER_REL_OP_GE: shader_addline(buffer, "_ge"); break;
+ case VKD3D_SHADER_REL_OP_LT: shader_addline(buffer, "_lt"); break;
+ case VKD3D_SHADER_REL_OP_NE: shader_addline(buffer, "_ne"); break;
+ case VKD3D_SHADER_REL_OP_LE: shader_addline(buffer, "_le"); break;
+ default: shader_addline(buffer, "_(%u)", ins->flags);
+ }
+ break;
+
+ case VKD3DSIH_RESINFO:
+ switch (ins->flags)
+ {
+ case VKD3DSI_NONE: break;
+ case VKD3DSI_RESINFO_RCP_FLOAT: shader_addline(buffer, "_rcpFloat"); break;
+ case VKD3DSI_RESINFO_UINT: shader_addline(buffer, "_uint"); break;
+ default: shader_addline(buffer, "_unrecognized(%#x)", ins->flags);
+ }
+ break;
+
+ case VKD3DSIH_SAMPLE_INFO:
+ switch (ins->flags)
+ {
+ case VKD3DSI_NONE: break;
+ case VKD3DSI_SAMPLE_INFO_UINT: shader_addline(buffer, "_uint"); break;
+ default: shader_addline(buffer, "_unrecognized(%#x)", ins->flags);
+ }
+ break;
+
+ case VKD3DSIH_SYNC:
+ shader_dump_sync_flags(buffer, ins->flags);
+ break;
+
+ case VKD3DSIH_TEX:
+ if (shader_ver_ge(shader_version, 2, 0) && (ins->flags & VKD3DSI_TEXLD_PROJECT))
+ shader_addline(buffer, "p");
+ break;
+
+ default:
+ shader_dump_precise_flags(buffer, ins->flags);
+ break;
+ }
+}
+
+static void shader_dump_register_space(struct vkd3d_string_buffer *buffer,
+ unsigned int register_space, const struct vkd3d_shader_version *shader_version)
+{
+ if (shader_ver_ge(shader_version, 5, 1))
+ shader_addline(buffer, ", space=%u", register_space);
+}
+
+static void shader_dump_instruction(struct vkd3d_string_buffer *buffer,
+ const struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_version *shader_version)
+{
+ unsigned int i;
+
+ switch (ins->handler_idx)
+ {
+ case VKD3DSIH_DCL:
+ case VKD3DSIH_DCL_UAV_TYPED:
+ shader_dump_decl_usage(buffer, &ins->declaration.semantic, ins->flags, shader_version);
+ shader_dump_ins_modifiers(buffer, &ins->declaration.semantic.resource.reg);
+ shader_addline(buffer, " ");
+ shader_dump_register(buffer, &ins->declaration.semantic.resource.reg.reg, shader_version);
+ shader_dump_register_space(buffer, ins->declaration.semantic.resource.register_space, shader_version);
+ break;
+
+ case VKD3DSIH_DCL_CONSTANT_BUFFER:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_register(buffer, &ins->declaration.cb.src.reg, shader_version);
+ if (shader_ver_ge(shader_version, 5, 1))
+ shader_addline(buffer, "[%u]", ins->declaration.cb.size);
+ shader_addline(buffer, ", %s",
+ ins->flags & VKD3DSI_INDEXED_DYNAMIC ? "dynamicIndexed" : "immediateIndexed");
+ shader_dump_register_space(buffer, ins->declaration.cb.register_space, shader_version);
+ break;
+
+ case VKD3DSIH_DCL_FUNCTION_BODY:
+ shader_addline(buffer, "%s fb%u",
+ shader_opcode_names[ins->handler_idx], ins->declaration.index);
+ break;
+
+ case VKD3DSIH_DCL_FUNCTION_TABLE:
+ shader_addline(buffer, "%s ft%u = {...}",
+ shader_opcode_names[ins->handler_idx], ins->declaration.index);
+ break;
+
+ case VKD3DSIH_DCL_GLOBAL_FLAGS:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_global_flags(buffer, ins->flags);
+ break;
+
+ case VKD3DSIH_DCL_HS_MAX_TESSFACTOR:
+ shader_addline(buffer, "%s %.8e", shader_opcode_names[ins->handler_idx],
+ ins->declaration.max_tessellation_factor);
+ break;
+
+ case VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER:
+ shader_addline(buffer, "%s {\n", shader_opcode_names[ins->handler_idx]);
+ for (i = 0; i < ins->declaration.icb->vec4_count; ++i)
+ {
+ shader_addline(buffer, " {0x%08x, 0x%08x, 0x%08x, 0x%08x},\n",
+ ins->declaration.icb->data[4 * i + 0],
+ ins->declaration.icb->data[4 * i + 1],
+ ins->declaration.icb->data[4 * i + 2],
+ ins->declaration.icb->data[4 * i + 3]);
+ }
+ shader_addline(buffer, "}");
+ break;
+
+ case VKD3DSIH_DCL_INDEX_RANGE:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_dst_param(buffer, &ins->declaration.index_range.dst, shader_version);
+ shader_addline(buffer, " %u", ins->declaration.index_range.register_count);
+ break;
+
+ case VKD3DSIH_DCL_INDEXABLE_TEMP:
+ shader_addline(buffer, "%s x%u[%u], %u", shader_opcode_names[ins->handler_idx],
+ ins->declaration.indexable_temp.register_idx,
+ ins->declaration.indexable_temp.register_size,
+ ins->declaration.indexable_temp.component_count);
+ break;
+
+ case VKD3DSIH_DCL_INPUT_PS:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_interpolation_mode(buffer, ins->flags);
+ shader_addline(buffer, " ");
+ shader_dump_dst_param(buffer, &ins->declaration.dst, shader_version);
+ break;
+
+ case VKD3DSIH_DCL_INPUT_PS_SGV:
+ case VKD3DSIH_DCL_INPUT_SGV:
+ case VKD3DSIH_DCL_INPUT_SIV:
+ case VKD3DSIH_DCL_OUTPUT_SIV:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_dst_param(buffer, &ins->declaration.register_semantic.reg, shader_version);
+ shader_addline(buffer, ", ");
+ shader_dump_shader_input_sysval_semantic(buffer, ins->declaration.register_semantic.sysval_semantic);
+ break;
+
+ case VKD3DSIH_DCL_INPUT_PS_SIV:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_interpolation_mode(buffer, ins->flags);
+ shader_addline(buffer, " ");
+ shader_dump_dst_param(buffer, &ins->declaration.register_semantic.reg, shader_version);
+ shader_addline(buffer, ", ");
+ shader_dump_shader_input_sysval_semantic(buffer, ins->declaration.register_semantic.sysval_semantic);
+ break;
+
+ case VKD3DSIH_DCL_INPUT:
+ case VKD3DSIH_DCL_OUTPUT:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_dst_param(buffer, &ins->declaration.dst, shader_version);
+ break;
+
+ case VKD3DSIH_DCL_INPUT_PRIMITIVE:
+ case VKD3DSIH_DCL_OUTPUT_TOPOLOGY:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_primitive_type(buffer, &ins->declaration.primitive_type);
+ break;
+
+ case VKD3DSIH_DCL_INTERFACE:
+ shader_addline(buffer, "%s fp%u[%u][%u] = {...}",
+ shader_opcode_names[ins->handler_idx], ins->declaration.fp.index,
+ ins->declaration.fp.array_size, ins->declaration.fp.body_count);
+ break;
+
+ case VKD3DSIH_DCL_RESOURCE_RAW:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_dst_param(buffer, &ins->declaration.raw_resource.resource.reg, shader_version);
+ shader_dump_register_space(buffer, ins->declaration.raw_resource.resource.register_space, shader_version);
+ break;
+
+ case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_dst_param(buffer, &ins->declaration.structured_resource.resource.reg, shader_version);
+ shader_addline(buffer, ", %u", ins->declaration.structured_resource.byte_stride);
+ shader_dump_register_space(buffer,
+ ins->declaration.structured_resource.resource.register_space, shader_version);
+ break;
+
+ case VKD3DSIH_DCL_SAMPLER:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_register(buffer, &ins->declaration.sampler.src.reg, shader_version);
+ if (ins->flags == VKD3DSI_SAMPLER_COMPARISON_MODE)
+ shader_addline(buffer, ", comparisonMode");
+ shader_dump_register_space(buffer, ins->declaration.sampler.register_space, shader_version);
+ break;
+
+ case VKD3DSIH_DCL_TEMPS:
+ case VKD3DSIH_DCL_GS_INSTANCES:
+ case VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT:
+ case VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT:
+ case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
+ case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT:
+ case VKD3DSIH_DCL_VERTICES_OUT:
+ shader_addline(buffer, "%s %u", shader_opcode_names[ins->handler_idx], ins->declaration.count);
+ break;
+
+ case VKD3DSIH_DCL_TESSELLATOR_DOMAIN:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_tessellator_domain(buffer, ins->declaration.tessellator_domain);
+ break;
+
+ case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_tessellator_output_primitive(buffer, ins->declaration.tessellator_output_primitive);
+ break;
+
+ case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_tessellator_partitioning(buffer, ins->declaration.tessellator_partitioning);
+ break;
+
+ case VKD3DSIH_DCL_TGSM_RAW:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_dst_param(buffer, &ins->declaration.tgsm_raw.reg, shader_version);
+ shader_addline(buffer, ", %u", ins->declaration.tgsm_raw.byte_count);
+ break;
+
+ case VKD3DSIH_DCL_TGSM_STRUCTURED:
+ shader_addline(buffer, "%s ", shader_opcode_names[ins->handler_idx]);
+ shader_dump_dst_param(buffer, &ins->declaration.tgsm_structured.reg, shader_version);
+ shader_addline(buffer, ", %u, %u", ins->declaration.tgsm_structured.byte_stride,
+ ins->declaration.tgsm_structured.structure_count);
+ break;
+
+ case VKD3DSIH_DCL_THREAD_GROUP:
+ shader_addline(buffer, "%s %u, %u, %u", shader_opcode_names[ins->handler_idx],
+ ins->declaration.thread_group_size.x,
+ ins->declaration.thread_group_size.y,
+ ins->declaration.thread_group_size.z);
+ break;
+
+ case VKD3DSIH_DCL_UAV_RAW:
+ shader_addline(buffer, "%s", shader_opcode_names[ins->handler_idx]);
+ shader_dump_uav_flags(buffer, ins->flags);
+ shader_addline(buffer, " ");
+ shader_dump_dst_param(buffer, &ins->declaration.raw_resource.resource.reg, shader_version);
+ shader_dump_register_space(buffer, ins->declaration.raw_resource.resource.register_space, shader_version);
+ break;
+
+ case VKD3DSIH_DCL_UAV_STRUCTURED:
+ shader_addline(buffer, "%s", shader_opcode_names[ins->handler_idx]);
+ shader_dump_uav_flags(buffer, ins->flags);
+ shader_addline(buffer, " ");
+ shader_dump_dst_param(buffer, &ins->declaration.structured_resource.resource.reg, shader_version);
+ shader_addline(buffer, ", %u", ins->declaration.structured_resource.byte_stride);
+ shader_dump_register_space(buffer,
+ ins->declaration.structured_resource.resource.register_space, shader_version);
+ break;
+
+ case VKD3DSIH_DEF:
+ shader_addline(buffer, "def c%u = %.8e, %.8e, %.8e, %.8e",
+ shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset),
+ ins->src[0].reg.u.immconst_float[0], ins->src[0].reg.u.immconst_float[1],
+ ins->src[0].reg.u.immconst_float[2], ins->src[0].reg.u.immconst_float[3]);
+ break;
+
+ case VKD3DSIH_DEFI:
+ shader_addline(buffer, "defi i%u = %d, %d, %d, %d", ins->dst[0].reg.idx[0].offset,
+ ins->src[0].reg.u.immconst_uint[0], ins->src[0].reg.u.immconst_uint[1],
+ ins->src[0].reg.u.immconst_uint[2], ins->src[0].reg.u.immconst_uint[3]);
+ break;
+
+ case VKD3DSIH_DEFB:
+ shader_addline(buffer, "defb b%u = %s",
+ ins->dst[0].reg.idx[0].offset, ins->src[0].reg.u.immconst_uint[0] ? "true" : "false");
+ break;
+
+ default:
+ if (ins->predicate)
+ {
+ shader_addline(buffer, "(");
+ shader_dump_src_param(buffer, ins->predicate, shader_version);
+ shader_addline(buffer, ") ");
+ }
+
+ /* PixWin marks instructions with the coissue flag with a '+' */
+ if (ins->coissue)
+ shader_addline(buffer, "+");
+
+ shader_addline(buffer, "%s", shader_opcode_names[ins->handler_idx]);
+
+ shader_dump_instruction_flags(buffer, ins, shader_version);
+ if (vkd3d_shader_instruction_has_texel_offset(ins))
+ {
+ shader_addline(buffer, "(%d,%d,%d)",
+ ins->texel_offset.u, ins->texel_offset.v, ins->texel_offset.w);
+ }
+
+ if (ins->resource_type != VKD3D_SHADER_RESOURCE_NONE)
+ {
+ shader_addline(buffer, "(");
+ shader_dump_resource_type(buffer, ins->resource_type);
+ shader_addline(buffer, ")");
+ }
+
+ if (ins->resource_data_type != VKD3D_DATA_FLOAT)
+ shader_dump_data_type(buffer, ins->resource_data_type);
+
+ for (i = 0; i < ins->dst_count; ++i)
+ {
+ shader_dump_ins_modifiers(buffer, &ins->dst[i]);
+ shader_addline(buffer, !i ? " " : ", ");
+ shader_dump_dst_param(buffer, &ins->dst[i], shader_version);
+ }
+
+ /* Other source tokens */
+ for (i = ins->dst_count; i < (ins->dst_count + ins->src_count); ++i)
+ {
+ shader_addline(buffer, !i ? " " : ", ");
+ shader_dump_src_param(buffer, &ins->src[i - ins->dst_count], shader_version);
+ }
+ break;
+ }
+
+ shader_addline(buffer, "\n");
+}
+
+void vkd3d_shader_trace(void *data)
+{
+ struct vkd3d_shader_version shader_version;
+ struct vkd3d_string_buffer buffer;
+ const char *p, *q;
+ const DWORD *ptr;
+
+ if (!vkd3d_string_buffer_init(&buffer))
+ {
+ ERR("Failed to initialize string buffer.\n");
+ return;
+ }
+
+ shader_sm4_read_header(data, &ptr, &shader_version);
+ shader_addline(&buffer, "%s_%u_%u\n",
+ shader_get_type_prefix(shader_version.type), shader_version.major, shader_version.minor);
+
+ while (!shader_sm4_is_end(data, &ptr))
+ {
+ struct vkd3d_shader_instruction ins;
+
+ shader_sm4_read_instruction(data, &ptr, &ins);
+ if (ins.handler_idx == VKD3DSIH_INVALID)
+ {
+ WARN("Skipping unrecognized instruction.\n");
+ shader_addline(&buffer, "<unrecognized instruction>\n");
+ continue;
+ }
+
+ shader_dump_instruction(&buffer, &ins, &shader_version);
+ }
+
+ for (p = buffer.buffer; *p; p = q)
+ {
+ if (!(q = strstr(p, "\n")))
+ q = p + strlen(p);
+ else
+ ++q;
+ TRACE(" %.*s", (int)(q - p), p);
+ }
+
+ vkd3d_string_buffer_cleanup(&buffer);
+}
diff --git a/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader.map b/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader.map
new file mode 100644
index 00000000000..1937131b48b
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader.map
@@ -0,0 +1,21 @@
+VKD3D_1_0
+{
+global:
+ vkd3d_shader_compile;
+ vkd3d_shader_convert_root_signature;
+ vkd3d_shader_find_signature_element;
+ vkd3d_shader_free_messages;
+ vkd3d_shader_free_root_signature;
+ vkd3d_shader_free_scan_descriptor_info;
+ vkd3d_shader_free_shader_code;
+ vkd3d_shader_free_shader_signature;
+ vkd3d_shader_get_supported_source_types;
+ vkd3d_shader_get_supported_target_types;
+ vkd3d_shader_get_version;
+ vkd3d_shader_parse_input_signature;
+ vkd3d_shader_parse_root_signature;
+ vkd3d_shader_scan;
+ vkd3d_shader_serialize_root_signature;
+
+local: *;
+};
diff --git a/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
new file mode 100644
index 00000000000..16d895ff0a4
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -0,0 +1,1091 @@
+/*
+ * Copyright 2017 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_shader_private.h"
+#include "vkd3d_version.h"
+
+#include <stdio.h>
+
+VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG");
+
+static void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer)
+{
+ buffer->buffer[0] = '\0';
+ buffer->content_size = 0;
+}
+
+bool vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer)
+{
+ buffer->buffer_size = 32;
+ if (!(buffer->buffer = vkd3d_malloc(buffer->buffer_size)))
+ {
+ ERR("Failed to allocate shader buffer memory.\n");
+ return false;
+ }
+
+ vkd3d_string_buffer_clear(buffer);
+ return true;
+}
+
+void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer)
+{
+ vkd3d_free(buffer->buffer);
+}
+
+static bool vkd3d_string_buffer_resize(struct vkd3d_string_buffer *buffer, int rc)
+{
+ unsigned int new_buffer_size = buffer->buffer_size * 2;
+ char *new_buffer;
+
+ while (rc > 0 && (unsigned int)rc >= new_buffer_size - buffer->content_size)
+ new_buffer_size *= 2;
+ if (!(new_buffer = vkd3d_realloc(buffer->buffer, new_buffer_size)))
+ {
+ ERR("Failed to grow buffer.\n");
+ buffer->buffer[buffer->content_size] = '\0';
+ return false;
+ }
+ buffer->buffer = new_buffer;
+ buffer->buffer_size = new_buffer_size;
+ return true;
+}
+
+int vkd3d_string_buffer_vprintf(struct vkd3d_string_buffer *buffer, const char *format, va_list args)
+{
+ unsigned int rem;
+ va_list a;
+ int rc;
+
+ for (;;)
+ {
+ rem = buffer->buffer_size - buffer->content_size;
+ va_copy(a, args);
+ rc = vsnprintf(&buffer->buffer[buffer->content_size], rem, format, a);
+ va_end(a);
+ if (rc >= 0 && (unsigned int)rc < rem)
+ {
+ buffer->content_size += rc;
+ return 0;
+ }
+
+ if (!vkd3d_string_buffer_resize(buffer, rc))
+ return -1;
+ }
+}
+
+static int VKD3D_PRINTF_FUNC(2, 3) vkd3d_string_buffer_printf(struct vkd3d_string_buffer *buffer,
+ const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = vkd3d_string_buffer_vprintf(buffer, format, args);
+ va_end(args);
+
+ return ret;
+}
+
+static void vkd3d_string_buffer_trace_(const struct vkd3d_string_buffer *buffer, const char *function)
+{
+ const char *p, *q;
+
+ if (!TRACE_ON())
+ return;
+
+ for (p = buffer->buffer; *p; p = q)
+ {
+ if (!(q = strstr(p, "\n")))
+ q = p + strlen(p);
+ else
+ ++q;
+ vkd3d_dbg_printf(VKD3D_DBG_LEVEL_TRACE, function, "%.*s", (int)(q - p), p);
+ }
+}
+
+bool vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context,
+ enum vkd3d_shader_log_level log_level, const char *source_name)
+{
+ context->log_level = log_level;
+ context->source_name = source_name ? source_name : "<anonymous>";
+ context->line = 0;
+ context->column = 0;
+
+ return vkd3d_string_buffer_init(&context->messages);
+}
+
+void vkd3d_shader_message_context_cleanup(struct vkd3d_shader_message_context *context)
+{
+ vkd3d_string_buffer_cleanup(&context->messages);
+}
+
+void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_message_context *context,
+ const char *function)
+{
+ vkd3d_string_buffer_trace_(&context->messages, function);
+}
+
+char *vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context)
+{
+ char *messages;
+
+ if ((messages = vkd3d_malloc(context->messages.content_size + 1)))
+ memcpy(messages, context->messages.buffer, context->messages.content_size + 1);
+
+ return messages;
+}
+
+void vkd3d_shader_verror(struct vkd3d_shader_message_context *context,
+ enum vkd3d_shader_error error, const char *format, va_list args)
+{
+ if (context->log_level < VKD3D_SHADER_LOG_ERROR)
+ return;
+
+ if (context->line)
+ vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: E%04u: ",
+ context->source_name, context->line, context->column, error);
+ else
+ vkd3d_string_buffer_printf(&context->messages, "%s: E%04u: ", context->source_name, error);
+ vkd3d_string_buffer_vprintf(&context->messages, format, args);
+ vkd3d_string_buffer_printf(&context->messages, "\n");
+}
+
+void vkd3d_shader_error(struct vkd3d_shader_message_context *context,
+ enum vkd3d_shader_error error, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vkd3d_shader_verror(context, error, format, args);
+ va_end(args);
+}
+
+static void vkd3d_shader_dump_blob(const char *path, const char *prefix, const void *data, size_t size)
+{
+ static int shader_id = 0;
+ char filename[1024];
+ unsigned int id;
+ FILE *f;
+
+ id = InterlockedIncrement(&shader_id) - 1;
+
+ snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%s-%u.dxbc", path, prefix, id);
+ if ((f = fopen(filename, "wb")))
+ {
+ if (fwrite(data, 1, size, f) != size)
+ ERR("Failed to write shader to %s.\n", filename);
+ if (fclose(f))
+ ERR("Failed to close stream %s.\n", filename);
+ }
+ else
+ {
+ ERR("Failed to open %s for dumping shader.\n", filename);
+ }
+}
+
+static void vkd3d_shader_dump_shader(enum vkd3d_shader_type type, const struct vkd3d_shader_code *shader)
+{
+ static bool enabled = true;
+ const char *path;
+
+ if (!enabled)
+ return;
+
+ if (!(path = getenv("VKD3D_SHADER_DUMP_PATH")))
+ {
+ enabled = false;
+ return;
+ }
+
+ vkd3d_shader_dump_blob(path, shader_get_type_prefix(type), shader->code, shader->size);
+}
+
+struct vkd3d_shader_parser
+{
+ struct vkd3d_shader_desc shader_desc;
+ struct vkd3d_shader_version shader_version;
+ void *data;
+ const DWORD *ptr;
+};
+
+static int vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
+ const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context)
+{
+ struct vkd3d_shader_desc *shader_desc = &parser->shader_desc;
+ int ret;
+
+ if ((ret = shader_extract_from_dxbc(dxbc->code, dxbc->size, message_context, shader_desc)) < 0)
+ {
+ WARN("Failed to extract shader, vkd3d result %d.\n", ret);
+ return ret;
+ }
+
+ if (!(parser->data = shader_sm4_init(shader_desc->byte_code,
+ shader_desc->byte_code_size, &shader_desc->output_signature)))
+ {
+ WARN("Failed to initialize shader parser.\n");
+ free_shader_desc(shader_desc);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ shader_sm4_read_header(parser->data, &parser->ptr, &parser->shader_version);
+ return VKD3D_OK;
+}
+
+static void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser)
+{
+ shader_sm4_free(parser->data);
+ free_shader_desc(&parser->shader_desc);
+}
+
+static int vkd3d_shader_validate_compile_info(const struct vkd3d_shader_compile_info *compile_info)
+{
+ const enum vkd3d_shader_source_type *source_types;
+ const enum vkd3d_shader_target_type *target_types;
+ unsigned int count, i;
+
+ if (compile_info->type != VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO)
+ {
+ WARN("Invalid structure type %#x.\n", compile_info->type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ source_types = vkd3d_shader_get_supported_source_types(&count);
+ for (i = 0; i < count; ++i)
+ {
+ if (source_types[i] == compile_info->source_type)
+ break;
+ }
+ if (i == count)
+ {
+ WARN("Invalid shader source type %#x.\n", compile_info->source_type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ target_types = vkd3d_shader_get_supported_target_types(compile_info->source_type, &count);
+ for (i = 0; i < count; ++i)
+ {
+ if (target_types[i] == compile_info->target_type)
+ break;
+ }
+ if (i == count)
+ {
+ WARN("Invalid shader target type %#x.\n", compile_info->target_type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ return VKD3D_OK;
+}
+
+void vkd3d_shader_free_messages(char *messages)
+{
+ TRACE("messages %p.\n", messages);
+
+ vkd3d_free(messages);
+}
+
+int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
+ struct vkd3d_shader_code *out, char **messages)
+{
+ struct vkd3d_shader_scan_descriptor_info scan_descriptor_info;
+ struct vkd3d_shader_message_context message_context;
+ struct vkd3d_shader_instruction instruction;
+ struct vkd3d_shader_compile_info scan_info;
+ struct vkd3d_dxbc_compiler *spirv_compiler;
+ struct vkd3d_shader_parser parser;
+ int ret;
+
+ TRACE("compile_info %p, out %p, messages %p.\n", compile_info, out, messages);
+
+ if (messages)
+ *messages = NULL;
+
+ if ((ret = vkd3d_shader_validate_compile_info(compile_info)) < 0)
+ return ret;
+
+ scan_info = *compile_info;
+ scan_descriptor_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO;
+ scan_descriptor_info.next = scan_info.next;
+ scan_info.next = &scan_descriptor_info;
+
+ if ((ret = vkd3d_shader_scan(&scan_info, messages)) < 0)
+ return ret;
+ if (messages)
+ {
+ vkd3d_shader_free_messages(*messages);
+ *messages = NULL;
+ }
+
+ if (!vkd3d_shader_message_context_init(&message_context, compile_info->log_level, compile_info->source_name))
+ return VKD3D_ERROR;
+ if ((ret = vkd3d_shader_parser_init(&parser, &compile_info->source, &message_context)) < 0)
+ goto done;
+
+ vkd3d_shader_dump_shader(parser.shader_version.type, &compile_info->source);
+
+ if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser.shader_version,
+ &parser.shader_desc, compile_info, &scan_descriptor_info, &message_context)))
+ {
+ ERR("Failed to create DXBC compiler.\n");
+ vkd3d_shader_parser_destroy(&parser);
+ ret = VKD3D_ERROR;
+ goto done;
+ }
+
+ message_context.line = 2; /* Line 1 is the version token. */
+ message_context.column = 1;
+ while (!shader_sm4_is_end(parser.data, &parser.ptr))
+ {
+ shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction);
+
+ if (instruction.handler_idx == VKD3DSIH_INVALID)
+ {
+ WARN("Encountered unrecognized or invalid instruction.\n");
+ ret = VKD3D_ERROR_INVALID_SHADER;
+ break;
+ }
+
+ if ((ret = vkd3d_dxbc_compiler_handle_instruction(spirv_compiler, &instruction)) < 0)
+ break;
+ ++message_context.line;
+ }
+
+ if (ret >= 0)
+ ret = vkd3d_dxbc_compiler_generate_spirv(spirv_compiler, compile_info, out);
+
+ vkd3d_dxbc_compiler_destroy(spirv_compiler);
+ vkd3d_shader_parser_destroy(&parser);
+done:
+ vkd3d_shader_message_context_trace_messages(&message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ vkd3d_shader_message_context_cleanup(&message_context);
+ vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info);
+ return ret;
+}
+
+struct vkd3d_shader_scan_context
+{
+ struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info;
+ size_t descriptors_size;
+
+ struct vkd3d_shader_message_context message_context;
+
+ struct vkd3d_shader_cf_info
+ {
+ enum
+ {
+ VKD3D_SHADER_BLOCK_IF,
+ VKD3D_SHADER_BLOCK_LOOP,
+ VKD3D_SHADER_BLOCK_SWITCH,
+ } type;
+ bool inside_block;
+ bool has_default;
+ } *cf_info;
+ size_t cf_info_size;
+ size_t cf_info_count;
+
+ struct
+ {
+ unsigned int id;
+ unsigned int descriptor_idx;
+ } *uav_ranges;
+ size_t uav_ranges_size;
+ size_t uav_range_count;
+};
+
+static bool vkd3d_shader_scan_context_init(struct vkd3d_shader_scan_context *context,
+ struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info,
+ enum vkd3d_shader_log_level log_level, const char *source_name)
+{
+ memset(context, 0, sizeof(*context));
+ context->scan_descriptor_info = scan_descriptor_info;
+ return vkd3d_shader_message_context_init(&context->message_context, log_level, source_name);
+}
+
+static void vkd3d_shader_scan_context_cleanup(struct vkd3d_shader_scan_context *context)
+{
+ vkd3d_free(context->uav_ranges);
+ vkd3d_free(context->cf_info);
+ vkd3d_shader_message_context_cleanup(&context->message_context);
+}
+
+static struct vkd3d_shader_cf_info *vkd3d_shader_scan_get_current_cf_info(struct vkd3d_shader_scan_context *context)
+{
+ if (!context->cf_info_count)
+ return NULL;
+ return &context->cf_info[context->cf_info_count - 1];
+}
+
+static struct vkd3d_shader_cf_info *vkd3d_shader_scan_push_cf_info(struct vkd3d_shader_scan_context *context)
+{
+ struct vkd3d_shader_cf_info *cf_info;
+
+ if (!vkd3d_array_reserve((void **)&context->cf_info, &context->cf_info_size,
+ context->cf_info_count + 1, sizeof(*context->cf_info)))
+ {
+ ERR("Failed to allocate UAV range.\n");
+ return false;
+ }
+
+ cf_info = &context->cf_info[context->cf_info_count++];
+ memset(cf_info, 0, sizeof(*cf_info));
+
+ return cf_info;
+}
+
+static void vkd3d_shader_scan_pop_cf_info(struct vkd3d_shader_scan_context *context)
+{
+ assert(context->cf_info_count);
+
+ --context->cf_info_count;
+}
+
+static struct vkd3d_shader_cf_info *vkd3d_shader_scan_find_innermost_breakable_cf_info(
+ struct vkd3d_shader_scan_context *context)
+{
+ size_t count = context->cf_info_count;
+ struct vkd3d_shader_cf_info *cf_info;
+
+ while (count)
+ {
+ cf_info = &context->cf_info[--count];
+ if (cf_info->type == VKD3D_SHADER_BLOCK_LOOP
+ || cf_info->type == VKD3D_SHADER_BLOCK_SWITCH)
+ return cf_info;
+ }
+
+ return NULL;
+}
+
+static struct vkd3d_shader_cf_info *vkd3d_shader_scan_find_innermost_loop_cf_info(
+ struct vkd3d_shader_scan_context *context)
+{
+ size_t count = context->cf_info_count;
+ struct vkd3d_shader_cf_info *cf_info;
+
+ while (count)
+ {
+ cf_info = &context->cf_info[--count];
+ if (cf_info->type == VKD3D_SHADER_BLOCK_LOOP)
+ return cf_info;
+ }
+
+ return NULL;
+}
+
+static struct vkd3d_shader_descriptor_info *vkd3d_shader_scan_get_uav_descriptor_info(
+ const struct vkd3d_shader_scan_context *context, unsigned int range_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < context->uav_range_count; ++i)
+ {
+ if (context->uav_ranges[i].id == range_id)
+ return &context->scan_descriptor_info->descriptors[context->uav_ranges[i].descriptor_idx];
+ }
+
+ return NULL;
+}
+
+static bool vkd3d_shader_instruction_is_uav_read(const struct vkd3d_shader_instruction *instruction)
+{
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx;
+ return (VKD3DSIH_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_ATOMIC_XOR)
+ || (VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR)
+ || handler_idx == VKD3DSIH_LD_UAV_TYPED
+ || (handler_idx == VKD3DSIH_LD_RAW && instruction->src[1].reg.type == VKD3DSPR_UAV)
+ || (handler_idx == VKD3DSIH_LD_STRUCTURED && instruction->src[2].reg.type == VKD3DSPR_UAV);
+}
+
+static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_context *context,
+ const struct vkd3d_shader_register *reg)
+{
+ struct vkd3d_shader_descriptor_info *d;
+
+ if (!context->scan_descriptor_info)
+ return;
+
+ d = vkd3d_shader_scan_get_uav_descriptor_info(context, reg->idx[0].offset);
+ d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ;
+}
+
+static bool vkd3d_shader_instruction_is_uav_counter(const struct vkd3d_shader_instruction *instruction)
+{
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx;
+ return handler_idx == VKD3DSIH_IMM_ATOMIC_ALLOC
+ || handler_idx == VKD3DSIH_IMM_ATOMIC_CONSUME;
+}
+
+static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_context *context,
+ const struct vkd3d_shader_register *reg)
+{
+ struct vkd3d_shader_descriptor_info *d;
+
+ if (!context->scan_descriptor_info)
+ return;
+
+ d = vkd3d_shader_scan_get_uav_descriptor_info(context, reg->idx[0].offset);
+ d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER;
+}
+
+static bool vkd3d_shader_scan_add_descriptor(struct vkd3d_shader_scan_context *context,
+ enum vkd3d_shader_descriptor_type type, unsigned int register_space, unsigned int register_index,
+ enum vkd3d_shader_resource_type resource_type, enum vkd3d_shader_resource_data_type resource_data_type,
+ unsigned int flags)
+{
+ struct vkd3d_shader_scan_descriptor_info *info = context->scan_descriptor_info;
+ struct vkd3d_shader_descriptor_info *d;
+
+ if (!vkd3d_array_reserve((void **)&info->descriptors, &context->descriptors_size,
+ info->descriptor_count + 1, sizeof(*info->descriptors)))
+ {
+ ERR("Failed to allocate descriptor info.\n");
+ return false;
+ }
+
+ d = &info->descriptors[info->descriptor_count];
+ d->type = type;
+ d->register_space = register_space;
+ d->register_index = register_index;
+ d->resource_type = resource_type;
+ d->resource_data_type = resource_data_type;
+ d->flags = flags;
+ d->count = 1;
+ ++info->descriptor_count;
+
+ return true;
+}
+
+static bool vkd3d_shader_scan_add_uav_range(struct vkd3d_shader_scan_context *context,
+ unsigned int id, unsigned int descriptor_idx)
+{
+ if (!vkd3d_array_reserve((void **)&context->uav_ranges, &context->uav_ranges_size,
+ context->uav_range_count + 1, sizeof(*context->uav_ranges)))
+ {
+ ERR("Failed to allocate UAV range.\n");
+ return false;
+ }
+
+ context->uav_ranges[context->uav_range_count].id = id;
+ context->uav_ranges[context->uav_range_count].descriptor_idx = descriptor_idx;
+ ++context->uav_range_count;
+
+ return true;
+}
+
+static void vkd3d_shader_scan_constant_buffer_declaration(struct vkd3d_shader_scan_context *context,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb;
+
+ if (!context->scan_descriptor_info)
+ return;
+
+ vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, cb->register_space,
+ cb->register_index, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0);
+}
+
+static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_context *context,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_sampler *sampler = &instruction->declaration.sampler;
+ unsigned int flags;
+
+ if (!context->scan_descriptor_info)
+ return;
+
+ if (instruction->flags & VKD3DSI_SAMPLER_COMPARISON_MODE)
+ flags = VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE;
+ else
+ flags = 0;
+ vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler->register_space,
+ sampler->register_index, VKD3D_SHADER_RESOURCE_NONE, VKD3D_SHADER_RESOURCE_DATA_UINT, flags);
+}
+
+static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_context *context,
+ const struct vkd3d_shader_resource *resource, enum vkd3d_shader_resource_type resource_type,
+ enum vkd3d_shader_resource_data_type resource_data_type)
+{
+ enum vkd3d_shader_descriptor_type type;
+
+ if (!context->scan_descriptor_info)
+ return;
+
+ if (resource->reg.reg.type == VKD3DSPR_UAV)
+ type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
+ else
+ type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
+ vkd3d_shader_scan_add_descriptor(context, type, resource->register_space,
+ resource->register_index, resource_type, resource_data_type, 0);
+ if (type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV)
+ vkd3d_shader_scan_add_uav_range(context, resource->reg.reg.idx[0].offset,
+ context->scan_descriptor_info->descriptor_count - 1);
+}
+
+static void vkd3d_shader_scan_typed_resource_declaration(struct vkd3d_shader_scan_context *context,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_semantic *semantic = &instruction->declaration.semantic;
+ enum vkd3d_shader_resource_data_type resource_data_type;
+
+ switch (semantic->resource_data_type)
+ {
+ case VKD3D_DATA_UNORM:
+ resource_data_type = VKD3D_SHADER_RESOURCE_DATA_UNORM;
+ break;
+ case VKD3D_DATA_SNORM:
+ resource_data_type = VKD3D_SHADER_RESOURCE_DATA_SNORM;
+ break;
+ case VKD3D_DATA_INT:
+ resource_data_type = VKD3D_SHADER_RESOURCE_DATA_INT;
+ break;
+ case VKD3D_DATA_UINT:
+ resource_data_type = VKD3D_SHADER_RESOURCE_DATA_UINT;
+ break;
+ case VKD3D_DATA_FLOAT:
+ resource_data_type = VKD3D_SHADER_RESOURCE_DATA_FLOAT;
+ break;
+ default:
+ ERR("Invalid resource data type %#x.\n", semantic->resource_data_type);
+ resource_data_type = VKD3D_SHADER_RESOURCE_DATA_FLOAT;
+ break;
+ }
+ vkd3d_shader_scan_resource_declaration(context, &semantic->resource,
+ semantic->resource_type, resource_data_type);
+}
+
+static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *context,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_shader_cf_info *cf_info;
+ unsigned int i;
+
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_DCL_CONSTANT_BUFFER:
+ vkd3d_shader_scan_constant_buffer_declaration(context, instruction);
+ break;
+ case VKD3DSIH_DCL_SAMPLER:
+ vkd3d_shader_scan_sampler_declaration(context, instruction);
+ break;
+ case VKD3DSIH_DCL:
+ case VKD3DSIH_DCL_UAV_TYPED:
+ vkd3d_shader_scan_typed_resource_declaration(context, instruction);
+ break;
+ case VKD3DSIH_DCL_RESOURCE_RAW:
+ case VKD3DSIH_DCL_UAV_RAW:
+ vkd3d_shader_scan_resource_declaration(context, &instruction->declaration.raw_resource.resource,
+ VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT);
+ break;
+ case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
+ case VKD3DSIH_DCL_UAV_STRUCTURED:
+ vkd3d_shader_scan_resource_declaration(context, &instruction->declaration.structured_resource.resource,
+ VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT);
+ break;
+ case VKD3DSIH_IF:
+ cf_info = vkd3d_shader_scan_push_cf_info(context);
+ cf_info->type = VKD3D_SHADER_BLOCK_IF;
+ cf_info->inside_block = true;
+ break;
+ case VKD3DSIH_ELSE:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_IF)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘else’ instruction without corresponding ‘if’ block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = true;
+ break;
+ case VKD3DSIH_ENDIF:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_IF)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘endif’ instruction without corresponding ‘if’ block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ vkd3d_shader_scan_pop_cf_info(context);
+ break;
+ case VKD3DSIH_LOOP:
+ cf_info = vkd3d_shader_scan_push_cf_info(context);
+ cf_info->type = VKD3D_SHADER_BLOCK_LOOP;
+ break;
+ case VKD3DSIH_ENDLOOP:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_LOOP)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘endloop’ instruction without corresponding ‘loop’ block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ vkd3d_shader_scan_pop_cf_info(context);
+ break;
+ case VKD3DSIH_SWITCH:
+ cf_info = vkd3d_shader_scan_push_cf_info(context);
+ cf_info->type = VKD3D_SHADER_BLOCK_SWITCH;
+ break;
+ case VKD3DSIH_ENDSWITCH:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context))
+ || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH || cf_info->inside_block)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘endswitch’ instruction without corresponding ‘switch’ block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ vkd3d_shader_scan_pop_cf_info(context);
+ break;
+ case VKD3DSIH_CASE:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context))
+ || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘case’ instruction outside switch block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = true;
+ break;
+ case VKD3DSIH_DEFAULT:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context))
+ || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘default’ instruction outside switch block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ if (cf_info->has_default)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered duplicate ‘default’ instruction inside the current switch block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = true;
+ cf_info->has_default = true;
+ break;
+ case VKD3DSIH_BREAK:
+ if (!(cf_info = vkd3d_shader_scan_find_innermost_breakable_cf_info(context)))
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘break’ instruction outside breakable block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = false;
+ break;
+ case VKD3DSIH_BREAKP:
+ if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context)))
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘breakp’ instruction outside loop.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ break;
+ case VKD3DSIH_CONTINUE:
+ if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context)))
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘continue’ instruction outside loop.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = false;
+ break;
+ case VKD3DSIH_CONTINUEP:
+ if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context)))
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘continue’ instruction outside loop.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ break;
+ case VKD3DSIH_RET:
+ if (context->cf_info_count)
+ context->cf_info[context->cf_info_count - 1].inside_block = false;
+ break;
+ default:
+ break;
+ }
+
+ if (vkd3d_shader_instruction_is_uav_read(instruction))
+ {
+ for (i = 0; i < instruction->dst_count; ++i)
+ {
+ if (instruction->dst[i].reg.type == VKD3DSPR_UAV)
+ vkd3d_shader_scan_record_uav_read(context, &instruction->dst[i].reg);
+ }
+ for (i = 0; i < instruction->src_count; ++i)
+ {
+ if (instruction->src[i].reg.type == VKD3DSPR_UAV)
+ vkd3d_shader_scan_record_uav_read(context, &instruction->src[i].reg);
+ }
+ }
+
+ if (vkd3d_shader_instruction_is_uav_counter(instruction))
+ vkd3d_shader_scan_record_uav_counter(context, &instruction->src[0].reg);
+
+ return VKD3D_OK;
+}
+
+int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char **messages)
+{
+ struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info;
+ struct vkd3d_shader_message_context *message_context;
+ struct vkd3d_shader_instruction instruction;
+ struct vkd3d_shader_scan_context context;
+ struct vkd3d_shader_parser parser;
+ int ret;
+
+ TRACE("compile_info %p, messages %p.\n", compile_info, messages);
+
+ if (messages)
+ *messages = NULL;
+
+ if ((ret = vkd3d_shader_validate_compile_info(compile_info)) < 0)
+ return ret;
+
+ if ((scan_descriptor_info = vkd3d_find_struct(compile_info->next, SCAN_DESCRIPTOR_INFO)))
+ {
+ scan_descriptor_info->descriptors = NULL;
+ scan_descriptor_info->descriptor_count = 0;
+ }
+
+ if (!vkd3d_shader_scan_context_init(&context, scan_descriptor_info,
+ compile_info->log_level, compile_info->source_name))
+ return VKD3D_ERROR;
+ message_context = &context.message_context;
+
+ if ((ret = vkd3d_shader_parser_init(&parser, &compile_info->source, message_context)) < 0)
+ {
+ vkd3d_shader_message_context_trace_messages(message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ vkd3d_shader_scan_context_cleanup(&context);
+ return ret;
+ }
+
+ if (TRACE_ON())
+ vkd3d_shader_trace(parser.data);
+
+ message_context->line = 2; /* Line 1 is the version token. */
+ message_context->column = 1;
+ while (!shader_sm4_is_end(parser.data, &parser.ptr))
+ {
+ shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction);
+
+ if (instruction.handler_idx == VKD3DSIH_INVALID)
+ {
+ WARN("Encountered unrecognized or invalid instruction.\n");
+ if (scan_descriptor_info)
+ vkd3d_shader_free_scan_descriptor_info(scan_descriptor_info);
+ ret = VKD3D_ERROR_INVALID_SHADER;
+ goto done;
+ }
+
+ if ((ret = vkd3d_shader_scan_instruction(&context, &instruction)) < 0)
+ {
+ if (scan_descriptor_info)
+ vkd3d_shader_free_scan_descriptor_info(scan_descriptor_info);
+ goto done;
+ }
+ ++message_context->line;
+ }
+
+ ret = VKD3D_OK;
+
+done:
+ vkd3d_shader_message_context_trace_messages(message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ vkd3d_shader_scan_context_cleanup(&context);
+ vkd3d_shader_parser_destroy(&parser);
+ return ret;
+}
+
+void vkd3d_shader_free_scan_descriptor_info(struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info)
+{
+ TRACE("scan_descriptor_info %p.\n", scan_descriptor_info);
+
+ vkd3d_free(scan_descriptor_info->descriptors);
+}
+
+void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *shader_code)
+{
+ TRACE("shader_code %p.\n", shader_code);
+
+ vkd3d_free((void *)shader_code->code);
+}
+
+static void vkd3d_shader_free_root_signature_v_1_0(struct vkd3d_shader_root_signature_desc *root_signature)
+{
+ unsigned int i;
+
+ for (i = 0; i < root_signature->parameter_count; ++i)
+ {
+ const struct vkd3d_shader_root_parameter *parameter = &root_signature->parameters[i];
+
+ if (parameter->parameter_type == VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
+ vkd3d_free((void *)parameter->u.descriptor_table.descriptor_ranges);
+ }
+ vkd3d_free((void *)root_signature->parameters);
+ vkd3d_free((void *)root_signature->static_samplers);
+
+ memset(root_signature, 0, sizeof(*root_signature));
+}
+
+static void vkd3d_shader_free_root_signature_v_1_1(struct vkd3d_shader_root_signature_desc1 *root_signature)
+{
+ unsigned int i;
+
+ for (i = 0; i < root_signature->parameter_count; ++i)
+ {
+ const struct vkd3d_shader_root_parameter1 *parameter = &root_signature->parameters[i];
+
+ if (parameter->parameter_type == VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
+ vkd3d_free((void *)parameter->u.descriptor_table.descriptor_ranges);
+ }
+ vkd3d_free((void *)root_signature->parameters);
+ vkd3d_free((void *)root_signature->static_samplers);
+
+ memset(root_signature, 0, sizeof(*root_signature));
+}
+
+void vkd3d_shader_free_root_signature(struct vkd3d_shader_versioned_root_signature_desc *desc)
+{
+ TRACE("desc %p.\n", desc);
+
+ if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ {
+ vkd3d_shader_free_root_signature_v_1_0(&desc->u.v_1_0);
+ }
+ else if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1)
+ {
+ vkd3d_shader_free_root_signature_v_1_1(&desc->u.v_1_1);
+ }
+ else if (desc->version)
+ {
+ FIXME("Unknown version %#x.\n", desc->version);
+ return;
+ }
+
+ desc->version = 0;
+}
+
+int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
+ struct vkd3d_shader_signature *signature, char **messages)
+{
+ struct vkd3d_shader_message_context message_context;
+ int ret;
+
+ TRACE("dxbc {%p, %zu}, signature %p, messages %p.\n", dxbc->code, dxbc->size, signature, messages);
+
+ if (messages)
+ *messages = NULL;
+ if (!vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO, NULL))
+ return VKD3D_ERROR;
+
+ ret = shader_parse_input_signature(dxbc->code, dxbc->size, &message_context, signature);
+ vkd3d_shader_message_context_trace_messages(&message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+
+ vkd3d_shader_message_context_cleanup(&message_context);
+
+ return ret;
+}
+
+struct vkd3d_shader_signature_element *vkd3d_shader_find_signature_element(
+ const struct vkd3d_shader_signature *signature, const char *semantic_name,
+ unsigned int semantic_index, unsigned int stream_index)
+{
+ struct vkd3d_shader_signature_element *e;
+ unsigned int i;
+
+ TRACE("signature %p, semantic_name %s, semantic_index %u, stream_index %u.\n",
+ signature, debugstr_a(semantic_name), semantic_index, stream_index);
+
+ e = signature->elements;
+ for (i = 0; i < signature->element_count; ++i)
+ {
+ if (!ascii_strcasecmp(e[i].semantic_name, semantic_name)
+ && e[i].semantic_index == semantic_index
+ && e[i].stream_index == stream_index)
+ return &e[i];
+ }
+
+ return NULL;
+}
+
+void vkd3d_shader_free_shader_signature(struct vkd3d_shader_signature *signature)
+{
+ TRACE("signature %p.\n", signature);
+
+ vkd3d_free(signature->elements);
+ signature->elements = NULL;
+}
+
+const char *vkd3d_shader_get_version(unsigned int *major, unsigned int *minor)
+{
+ int x, y;
+
+ TRACE("major %p, minor %p.\n", major, minor);
+
+ if (major || minor)
+ {
+ vkd3d_parse_version(PACKAGE_VERSION, &x, &y);
+ if (major)
+ *major = x;
+ if (minor)
+ *minor = y;
+ }
+
+ return "vkd3d-shader " PACKAGE_VERSION VKD3D_VCS_ID;
+}
+
+const enum vkd3d_shader_source_type *vkd3d_shader_get_supported_source_types(unsigned int *count)
+{
+ static const enum vkd3d_shader_source_type types[] =
+ {
+ VKD3D_SHADER_SOURCE_DXBC_TPF,
+ };
+
+ TRACE("count %p.\n", count);
+
+ *count = ARRAY_SIZE(types);
+ return types;
+}
+
+const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
+ enum vkd3d_shader_source_type source_type, unsigned int *count)
+{
+ static const enum vkd3d_shader_target_type dxbc_tpf_types[] =
+ {
+ VKD3D_SHADER_TARGET_SPIRV_BINARY,
+#ifdef HAVE_SPIRV_TOOLS
+ VKD3D_SHADER_TARGET_SPIRV_TEXT,
+#endif
+ };
+
+ TRACE("source_type %#x, count %p.\n", source_type, count);
+
+ switch (source_type)
+ {
+ case VKD3D_SHADER_SOURCE_DXBC_TPF:
+ *count = ARRAY_SIZE(dxbc_tpf_types);
+ return dxbc_tpf_types;
+
+ default:
+ *count = 0;
+ return NULL;
+ }
+}
diff --git a/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
new file mode 100644
index 00000000000..00b2441e559
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -0,0 +1,989 @@
+/*
+ * Copyright 2017 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2002-2003 The wine-d3d team
+ * Copyright 2002-2003 2004 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ * Copyright 2005 Oliver Stieber
+ * Copyright 2006 Stefan Dösinger
+ * Copyright 2006-2011, 2013 Stefan Dösinger for CodeWeavers
+ * Copyright 2007 Henri Verbeet
+ * Copyright 2008-2009 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_SHADER_PRIVATE_H
+#define __VKD3D_SHADER_PRIVATE_H
+
+#define NONAMELESSUNION
+#include "vkd3d_common.h"
+#include "vkd3d_memory.h"
+#include "vkd3d_shader.h"
+#include "list.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <string.h>
+
+#define VKD3D_VEC4_SIZE 4
+
+enum vkd3d_shader_error
+{
+ VKD3D_SHADER_ERROR_DXBC_INVALID_SIZE = 1,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_MAGIC = 2,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM = 3,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_VERSION = 4,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET = 5,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE = 6,
+
+ VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
+
+ VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000,
+ VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001,
+ VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING = 2002,
+
+ VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY = 3000,
+ VKD3D_SHADER_ERROR_RS_INVALID_VERSION = 3001,
+ VKD3D_SHADER_ERROR_RS_INVALID_ROOT_PARAMETER_TYPE = 3002,
+ VKD3D_SHADER_ERROR_RS_INVALID_DESCRIPTOR_RANGE_TYPE = 3003,
+ VKD3D_SHADER_ERROR_RS_MIXED_DESCRIPTOR_RANGE_TYPES = 3004,
+};
+
+enum VKD3D_SHADER_INSTRUCTION_HANDLER
+{
+ VKD3DSIH_ABS,
+ VKD3DSIH_ADD,
+ VKD3DSIH_AND,
+ VKD3DSIH_ATOMIC_AND,
+ VKD3DSIH_ATOMIC_CMP_STORE,
+ VKD3DSIH_ATOMIC_IADD,
+ VKD3DSIH_ATOMIC_IMAX,
+ VKD3DSIH_ATOMIC_IMIN,
+ VKD3DSIH_ATOMIC_OR,
+ VKD3DSIH_ATOMIC_UMAX,
+ VKD3DSIH_ATOMIC_UMIN,
+ VKD3DSIH_ATOMIC_XOR,
+ VKD3DSIH_BEM,
+ VKD3DSIH_BFI,
+ VKD3DSIH_BFREV,
+ VKD3DSIH_BREAK,
+ VKD3DSIH_BREAKC,
+ VKD3DSIH_BREAKP,
+ VKD3DSIH_BUFINFO,
+ VKD3DSIH_CALL,
+ VKD3DSIH_CALLNZ,
+ VKD3DSIH_CASE,
+ VKD3DSIH_CMP,
+ VKD3DSIH_CND,
+ VKD3DSIH_CONTINUE,
+ VKD3DSIH_CONTINUEP,
+ VKD3DSIH_COUNTBITS,
+ VKD3DSIH_CRS,
+ VKD3DSIH_CUT,
+ VKD3DSIH_CUT_STREAM,
+ VKD3DSIH_DCL,
+ VKD3DSIH_DCL_CONSTANT_BUFFER,
+ VKD3DSIH_DCL_FUNCTION_BODY,
+ VKD3DSIH_DCL_FUNCTION_TABLE,
+ VKD3DSIH_DCL_GLOBAL_FLAGS,
+ VKD3DSIH_DCL_GS_INSTANCES,
+ VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT,
+ VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT,
+ VKD3DSIH_DCL_HS_MAX_TESSFACTOR,
+ VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER,
+ VKD3DSIH_DCL_INDEX_RANGE,
+ VKD3DSIH_DCL_INDEXABLE_TEMP,
+ VKD3DSIH_DCL_INPUT,
+ VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT,
+ VKD3DSIH_DCL_INPUT_PRIMITIVE,
+ VKD3DSIH_DCL_INPUT_PS,
+ VKD3DSIH_DCL_INPUT_PS_SGV,
+ VKD3DSIH_DCL_INPUT_PS_SIV,
+ VKD3DSIH_DCL_INPUT_SGV,
+ VKD3DSIH_DCL_INPUT_SIV,
+ VKD3DSIH_DCL_INTERFACE,
+ VKD3DSIH_DCL_OUTPUT,
+ VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT,
+ VKD3DSIH_DCL_OUTPUT_SIV,
+ VKD3DSIH_DCL_OUTPUT_TOPOLOGY,
+ VKD3DSIH_DCL_RESOURCE_RAW,
+ VKD3DSIH_DCL_RESOURCE_STRUCTURED,
+ VKD3DSIH_DCL_SAMPLER,
+ VKD3DSIH_DCL_STREAM,
+ VKD3DSIH_DCL_TEMPS,
+ VKD3DSIH_DCL_TESSELLATOR_DOMAIN,
+ VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE,
+ VKD3DSIH_DCL_TESSELLATOR_PARTITIONING,
+ VKD3DSIH_DCL_TGSM_RAW,
+ VKD3DSIH_DCL_TGSM_STRUCTURED,
+ VKD3DSIH_DCL_THREAD_GROUP,
+ VKD3DSIH_DCL_UAV_RAW,
+ VKD3DSIH_DCL_UAV_STRUCTURED,
+ VKD3DSIH_DCL_UAV_TYPED,
+ VKD3DSIH_DCL_VERTICES_OUT,
+ VKD3DSIH_DEF,
+ VKD3DSIH_DEFAULT,
+ VKD3DSIH_DEFB,
+ VKD3DSIH_DEFI,
+ VKD3DSIH_DIV,
+ VKD3DSIH_DP2,
+ VKD3DSIH_DP2ADD,
+ VKD3DSIH_DP3,
+ VKD3DSIH_DP4,
+ VKD3DSIH_DST,
+ VKD3DSIH_DSX,
+ VKD3DSIH_DSX_COARSE,
+ VKD3DSIH_DSX_FINE,
+ VKD3DSIH_DSY,
+ VKD3DSIH_DSY_COARSE,
+ VKD3DSIH_DSY_FINE,
+ VKD3DSIH_ELSE,
+ VKD3DSIH_EMIT,
+ VKD3DSIH_EMIT_STREAM,
+ VKD3DSIH_ENDIF,
+ VKD3DSIH_ENDLOOP,
+ VKD3DSIH_ENDREP,
+ VKD3DSIH_ENDSWITCH,
+ VKD3DSIH_EQ,
+ VKD3DSIH_EVAL_CENTROID,
+ VKD3DSIH_EVAL_SAMPLE_INDEX,
+ VKD3DSIH_EXP,
+ VKD3DSIH_EXPP,
+ VKD3DSIH_F16TOF32,
+ VKD3DSIH_F32TOF16,
+ VKD3DSIH_FCALL,
+ VKD3DSIH_FIRSTBIT_HI,
+ VKD3DSIH_FIRSTBIT_LO,
+ VKD3DSIH_FIRSTBIT_SHI,
+ VKD3DSIH_FRC,
+ VKD3DSIH_FTOI,
+ VKD3DSIH_FTOU,
+ VKD3DSIH_GATHER4,
+ VKD3DSIH_GATHER4_C,
+ VKD3DSIH_GATHER4_PO,
+ VKD3DSIH_GATHER4_PO_C,
+ VKD3DSIH_GE,
+ VKD3DSIH_HS_CONTROL_POINT_PHASE,
+ VKD3DSIH_HS_DECLS,
+ VKD3DSIH_HS_FORK_PHASE,
+ VKD3DSIH_HS_JOIN_PHASE,
+ VKD3DSIH_IADD,
+ VKD3DSIH_IBFE,
+ VKD3DSIH_IEQ,
+ VKD3DSIH_IF,
+ VKD3DSIH_IFC,
+ VKD3DSIH_IGE,
+ VKD3DSIH_ILT,
+ VKD3DSIH_IMAD,
+ VKD3DSIH_IMAX,
+ VKD3DSIH_IMIN,
+ VKD3DSIH_IMM_ATOMIC_ALLOC,
+ VKD3DSIH_IMM_ATOMIC_AND,
+ VKD3DSIH_IMM_ATOMIC_CMP_EXCH,
+ VKD3DSIH_IMM_ATOMIC_CONSUME,
+ VKD3DSIH_IMM_ATOMIC_EXCH,
+ VKD3DSIH_IMM_ATOMIC_IADD,
+ VKD3DSIH_IMM_ATOMIC_IMAX,
+ VKD3DSIH_IMM_ATOMIC_IMIN,
+ VKD3DSIH_IMM_ATOMIC_OR,
+ VKD3DSIH_IMM_ATOMIC_UMAX,
+ VKD3DSIH_IMM_ATOMIC_UMIN,
+ VKD3DSIH_IMM_ATOMIC_XOR,
+ VKD3DSIH_IMUL,
+ VKD3DSIH_INE,
+ VKD3DSIH_INEG,
+ VKD3DSIH_ISHL,
+ VKD3DSIH_ISHR,
+ VKD3DSIH_ITOF,
+ VKD3DSIH_LABEL,
+ VKD3DSIH_LD,
+ VKD3DSIH_LD2DMS,
+ VKD3DSIH_LD_RAW,
+ VKD3DSIH_LD_STRUCTURED,
+ VKD3DSIH_LD_UAV_TYPED,
+ VKD3DSIH_LIT,
+ VKD3DSIH_LOD,
+ VKD3DSIH_LOG,
+ VKD3DSIH_LOGP,
+ VKD3DSIH_LOOP,
+ VKD3DSIH_LRP,
+ VKD3DSIH_LT,
+ VKD3DSIH_M3x2,
+ VKD3DSIH_M3x3,
+ VKD3DSIH_M3x4,
+ VKD3DSIH_M4x3,
+ VKD3DSIH_M4x4,
+ VKD3DSIH_MAD,
+ VKD3DSIH_MAX,
+ VKD3DSIH_MIN,
+ VKD3DSIH_MOV,
+ VKD3DSIH_MOVA,
+ VKD3DSIH_MOVC,
+ VKD3DSIH_MUL,
+ VKD3DSIH_NE,
+ VKD3DSIH_NOP,
+ VKD3DSIH_NOT,
+ VKD3DSIH_NRM,
+ VKD3DSIH_OR,
+ VKD3DSIH_PHASE,
+ VKD3DSIH_POW,
+ VKD3DSIH_RCP,
+ VKD3DSIH_REP,
+ VKD3DSIH_RESINFO,
+ VKD3DSIH_RET,
+ VKD3DSIH_RETP,
+ VKD3DSIH_ROUND_NE,
+ VKD3DSIH_ROUND_NI,
+ VKD3DSIH_ROUND_PI,
+ VKD3DSIH_ROUND_Z,
+ VKD3DSIH_RSQ,
+ VKD3DSIH_SAMPLE,
+ VKD3DSIH_SAMPLE_B,
+ VKD3DSIH_SAMPLE_C,
+ VKD3DSIH_SAMPLE_C_LZ,
+ VKD3DSIH_SAMPLE_GRAD,
+ VKD3DSIH_SAMPLE_INFO,
+ VKD3DSIH_SAMPLE_LOD,
+ VKD3DSIH_SAMPLE_POS,
+ VKD3DSIH_SETP,
+ VKD3DSIH_SGE,
+ VKD3DSIH_SGN,
+ VKD3DSIH_SINCOS,
+ VKD3DSIH_SLT,
+ VKD3DSIH_SQRT,
+ VKD3DSIH_STORE_RAW,
+ VKD3DSIH_STORE_STRUCTURED,
+ VKD3DSIH_STORE_UAV_TYPED,
+ VKD3DSIH_SUB,
+ VKD3DSIH_SWAPC,
+ VKD3DSIH_SWITCH,
+ VKD3DSIH_SYNC,
+ VKD3DSIH_TEX,
+ VKD3DSIH_TEXBEM,
+ VKD3DSIH_TEXBEML,
+ VKD3DSIH_TEXCOORD,
+ VKD3DSIH_TEXDEPTH,
+ VKD3DSIH_TEXDP3,
+ VKD3DSIH_TEXDP3TEX,
+ VKD3DSIH_TEXKILL,
+ VKD3DSIH_TEXLDD,
+ VKD3DSIH_TEXLDL,
+ VKD3DSIH_TEXM3x2DEPTH,
+ VKD3DSIH_TEXM3x2PAD,
+ VKD3DSIH_TEXM3x2TEX,
+ VKD3DSIH_TEXM3x3,
+ VKD3DSIH_TEXM3x3DIFF,
+ VKD3DSIH_TEXM3x3PAD,
+ VKD3DSIH_TEXM3x3SPEC,
+ VKD3DSIH_TEXM3x3TEX,
+ VKD3DSIH_TEXM3x3VSPEC,
+ VKD3DSIH_TEXREG2AR,
+ VKD3DSIH_TEXREG2GB,
+ VKD3DSIH_TEXREG2RGB,
+ VKD3DSIH_UBFE,
+ VKD3DSIH_UDIV,
+ VKD3DSIH_UGE,
+ VKD3DSIH_ULT,
+ VKD3DSIH_UMAX,
+ VKD3DSIH_UMIN,
+ VKD3DSIH_UMUL,
+ VKD3DSIH_USHR,
+ VKD3DSIH_UTOF,
+ VKD3DSIH_XOR,
+
+ VKD3DSIH_INVALID,
+};
+
+enum vkd3d_shader_register_type
+{
+ VKD3DSPR_TEMP = 0,
+ VKD3DSPR_INPUT = 1,
+ VKD3DSPR_CONST = 2,
+ VKD3DSPR_ADDR = 3,
+ VKD3DSPR_TEXTURE = 3,
+ VKD3DSPR_RASTOUT = 4,
+ VKD3DSPR_ATTROUT = 5,
+ VKD3DSPR_TEXCRDOUT = 6,
+ VKD3DSPR_OUTPUT = 6,
+ VKD3DSPR_CONSTINT = 7,
+ VKD3DSPR_COLOROUT = 8,
+ VKD3DSPR_DEPTHOUT = 9,
+ VKD3DSPR_SAMPLER = 10,
+ VKD3DSPR_CONST2 = 11,
+ VKD3DSPR_CONST3 = 12,
+ VKD3DSPR_CONST4 = 13,
+ VKD3DSPR_CONSTBOOL = 14,
+ VKD3DSPR_LOOP = 15,
+ VKD3DSPR_TEMPFLOAT16 = 16,
+ VKD3DSPR_MISCTYPE = 17,
+ VKD3DSPR_LABEL = 18,
+ VKD3DSPR_PREDICATE = 19,
+ VKD3DSPR_IMMCONST,
+ VKD3DSPR_CONSTBUFFER,
+ VKD3DSPR_IMMCONSTBUFFER,
+ VKD3DSPR_PRIMID,
+ VKD3DSPR_NULL,
+ VKD3DSPR_RESOURCE,
+ VKD3DSPR_UAV,
+ VKD3DSPR_OUTPOINTID,
+ VKD3DSPR_FORKINSTID,
+ VKD3DSPR_JOININSTID,
+ VKD3DSPR_INCONTROLPOINT,
+ VKD3DSPR_OUTCONTROLPOINT,
+ VKD3DSPR_PATCHCONST,
+ VKD3DSPR_TESSCOORD,
+ VKD3DSPR_GROUPSHAREDMEM,
+ VKD3DSPR_THREADID,
+ VKD3DSPR_THREADGROUPID,
+ VKD3DSPR_LOCALTHREADID,
+ VKD3DSPR_LOCALTHREADINDEX,
+ VKD3DSPR_IDXTEMP,
+ VKD3DSPR_STREAM,
+ VKD3DSPR_FUNCTIONBODY,
+ VKD3DSPR_FUNCTIONPOINTER,
+ VKD3DSPR_COVERAGE,
+ VKD3DSPR_SAMPLEMASK,
+ VKD3DSPR_GSINSTID,
+ VKD3DSPR_DEPTHOUTGE,
+ VKD3DSPR_DEPTHOUTLE,
+ VKD3DSPR_RASTERIZER,
+
+ VKD3DSPR_INVALID = ~0u,
+};
+
+enum vkd3d_data_type
+{
+ VKD3D_DATA_FLOAT,
+ VKD3D_DATA_INT,
+ VKD3D_DATA_RESOURCE,
+ VKD3D_DATA_SAMPLER,
+ VKD3D_DATA_UAV,
+ VKD3D_DATA_UINT,
+ VKD3D_DATA_UNORM,
+ VKD3D_DATA_SNORM,
+ VKD3D_DATA_OPAQUE,
+};
+
+enum vkd3d_immconst_type
+{
+ VKD3D_IMMCONST_SCALAR,
+ VKD3D_IMMCONST_VEC4,
+};
+
+enum vkd3d_shader_src_modifier
+{
+ VKD3DSPSM_NONE = 0,
+ VKD3DSPSM_NEG = 1,
+ VKD3DSPSM_BIAS = 2,
+ VKD3DSPSM_BIASNEG = 3,
+ VKD3DSPSM_SIGN = 4,
+ VKD3DSPSM_SIGNNEG = 5,
+ VKD3DSPSM_COMP = 6,
+ VKD3DSPSM_X2 = 7,
+ VKD3DSPSM_X2NEG = 8,
+ VKD3DSPSM_DZ = 9,
+ VKD3DSPSM_DW = 10,
+ VKD3DSPSM_ABS = 11,
+ VKD3DSPSM_ABSNEG = 12,
+ VKD3DSPSM_NOT = 13,
+};
+
+#define VKD3DSP_WRITEMASK_0 0x1u /* .x r */
+#define VKD3DSP_WRITEMASK_1 0x2u /* .y g */
+#define VKD3DSP_WRITEMASK_2 0x4u /* .z b */
+#define VKD3DSP_WRITEMASK_3 0x8u /* .w a */
+#define VKD3DSP_WRITEMASK_ALL 0xfu /* all */
+
+enum vkd3d_shader_dst_modifier
+{
+ VKD3DSPDM_NONE = 0,
+ VKD3DSPDM_SATURATE = 1,
+ VKD3DSPDM_PARTIALPRECISION = 2,
+ VKD3DSPDM_MSAMPCENTROID = 4,
+};
+
+enum vkd3d_shader_interpolation_mode
+{
+ VKD3DSIM_NONE = 0,
+ VKD3DSIM_CONSTANT = 1,
+ VKD3DSIM_LINEAR = 2,
+ VKD3DSIM_LINEAR_CENTROID = 3,
+ VKD3DSIM_LINEAR_NOPERSPECTIVE = 4,
+ VKD3DSIM_LINEAR_NOPERSPECTIVE_CENTROID = 5,
+ VKD3DSIM_LINEAR_SAMPLE = 6,
+ VKD3DSIM_LINEAR_NOPERSPECTIVE_SAMPLE = 7,
+};
+
+enum vkd3d_shader_global_flags
+{
+ VKD3DSGF_REFACTORING_ALLOWED = 0x01,
+ VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL = 0x04,
+ VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS = 0x08,
+ VKD3DSGF_SKIP_OPTIMIZATION = 0x10,
+ VKD3DSGF_ENABLE_MINIMUM_PRECISION = 0x20
+};
+
+enum vkd3d_shader_sync_flags
+{
+ VKD3DSSF_THREAD_GROUP = 0x1,
+ VKD3DSSF_GROUP_SHARED_MEMORY = 0x2,
+};
+
+enum vkd3d_shader_uav_flags
+{
+ VKD3DSUF_GLOBALLY_COHERENT = 0x2,
+ VKD3DSUF_ORDER_PRESERVING_COUNTER = 0x100,
+};
+
+enum vkd3d_tessellator_domain
+{
+ VKD3D_TESSELLATOR_DOMAIN_LINE = 1,
+ VKD3D_TESSELLATOR_DOMAIN_TRIANGLE = 2,
+ VKD3D_TESSELLATOR_DOMAIN_QUAD = 3,
+};
+
+#define VKD3DSI_NONE 0x0
+#define VKD3DSI_TEXLD_PROJECT 0x1
+#define VKD3DSI_INDEXED_DYNAMIC 0x4
+#define VKD3DSI_RESINFO_RCP_FLOAT 0x1
+#define VKD3DSI_RESINFO_UINT 0x2
+#define VKD3DSI_SAMPLE_INFO_UINT 0x1
+#define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1
+
+#define VKD3DSI_PRECISE_X 0x100
+#define VKD3DSI_PRECISE_Y 0x200
+#define VKD3DSI_PRECISE_Z 0x400
+#define VKD3DSI_PRECISE_W 0x800
+#define VKD3DSI_PRECISE_XYZW (VKD3DSI_PRECISE_X | VKD3DSI_PRECISE_Y \
+ | VKD3DSI_PRECISE_Z | VKD3DSI_PRECISE_W)
+#define VKD3DSI_PRECISE_SHIFT 8
+
+enum vkd3d_shader_rel_op
+{
+ VKD3D_SHADER_REL_OP_GT = 1,
+ VKD3D_SHADER_REL_OP_EQ = 2,
+ VKD3D_SHADER_REL_OP_GE = 3,
+ VKD3D_SHADER_REL_OP_LT = 4,
+ VKD3D_SHADER_REL_OP_NE = 5,
+ VKD3D_SHADER_REL_OP_LE = 6,
+};
+
+enum vkd3d_shader_conditional_op
+{
+ VKD3D_SHADER_CONDITIONAL_OP_NZ = 0,
+ VKD3D_SHADER_CONDITIONAL_OP_Z = 1
+};
+
+#define VKD3D_SM1_VS 0xfffeu
+#define VKD3D_SM1_PS 0xffffu
+#define VKD3D_SM4_PS 0x0000u
+#define VKD3D_SM4_VS 0x0001u
+#define VKD3D_SM4_GS 0x0002u
+#define VKD3D_SM5_HS 0x0003u
+#define VKD3D_SM5_DS 0x0004u
+#define VKD3D_SM5_CS 0x0005u
+
+/* Shader version tokens, and shader end tokens */
+#define VKD3DPS_VERSION(major, minor) ((VKD3D_SM1_PS << 16) | ((major) << 8) | (minor))
+#define VKD3DVS_VERSION(major, minor) ((VKD3D_SM1_VS << 16) | ((major) << 8) | (minor))
+
+#define MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE 4096
+#define MAX_REG_OUTPUT 32
+
+enum vkd3d_shader_type
+{
+ VKD3D_SHADER_TYPE_PIXEL,
+ VKD3D_SHADER_TYPE_VERTEX,
+ VKD3D_SHADER_TYPE_GEOMETRY,
+ VKD3D_SHADER_TYPE_HULL,
+ VKD3D_SHADER_TYPE_DOMAIN,
+ VKD3D_SHADER_TYPE_GRAPHICS_COUNT,
+
+ VKD3D_SHADER_TYPE_COMPUTE = VKD3D_SHADER_TYPE_GRAPHICS_COUNT,
+ VKD3D_SHADER_TYPE_COUNT,
+};
+
+struct vkd3d_shader_version
+{
+ enum vkd3d_shader_type type;
+ uint8_t major;
+ uint8_t minor;
+};
+
+struct vkd3d_shader_immediate_constant_buffer
+{
+ unsigned int vec4_count;
+ DWORD data[MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE];
+};
+
+struct vkd3d_shader_indexable_temp
+{
+ struct list entry;
+ unsigned int register_idx;
+ unsigned int register_size;
+ unsigned int component_count;
+};
+
+struct vkd3d_shader_register_index
+{
+ const struct vkd3d_shader_src_param *rel_addr;
+ unsigned int offset;
+};
+
+struct vkd3d_shader_register
+{
+ enum vkd3d_shader_register_type type;
+ enum vkd3d_data_type data_type;
+ struct vkd3d_shader_register_index idx[3];
+ enum vkd3d_immconst_type immconst_type;
+ union
+ {
+ DWORD immconst_uint[VKD3D_VEC4_SIZE];
+ float immconst_float[VKD3D_VEC4_SIZE];
+ unsigned fp_body_idx;
+ } u;
+};
+
+struct vkd3d_shader_dst_param
+{
+ struct vkd3d_shader_register reg;
+ DWORD write_mask;
+ DWORD modifiers;
+ DWORD shift;
+};
+
+struct vkd3d_shader_src_param
+{
+ struct vkd3d_shader_register reg;
+ DWORD swizzle;
+ enum vkd3d_shader_src_modifier modifiers;
+};
+
+struct vkd3d_shader_index_range
+{
+ struct vkd3d_shader_dst_param dst;
+ unsigned int register_count;
+};
+
+struct vkd3d_shader_resource
+{
+ struct vkd3d_shader_dst_param reg;
+ unsigned int register_space;
+ unsigned int register_index;
+};
+
+enum vkd3d_decl_usage
+{
+ VKD3D_DECL_USAGE_POSITION = 0,
+ VKD3D_DECL_USAGE_BLEND_WEIGHT = 1,
+ VKD3D_DECL_USAGE_BLEND_INDICES = 2,
+ VKD3D_DECL_USAGE_NORMAL = 3,
+ VKD3D_DECL_USAGE_PSIZE = 4,
+ VKD3D_DECL_USAGE_TEXCOORD = 5,
+ VKD3D_DECL_USAGE_TANGENT = 6,
+ VKD3D_DECL_USAGE_BINORMAL = 7,
+ VKD3D_DECL_USAGE_TESS_FACTOR = 8,
+ VKD3D_DECL_USAGE_POSITIONT = 9,
+ VKD3D_DECL_USAGE_COLOR = 10,
+ VKD3D_DECL_USAGE_FOG = 11,
+ VKD3D_DECL_USAGE_DEPTH = 12,
+ VKD3D_DECL_USAGE_SAMPLE = 13
+};
+
+struct vkd3d_shader_semantic
+{
+ enum vkd3d_decl_usage usage;
+ unsigned int usage_idx;
+ enum vkd3d_shader_resource_type resource_type;
+ enum vkd3d_data_type resource_data_type;
+ struct vkd3d_shader_resource resource;
+};
+
+enum vkd3d_shader_input_sysval_semantic
+{
+ VKD3D_SIV_NONE = 0,
+ VKD3D_SIV_POSITION = 1,
+ VKD3D_SIV_CLIP_DISTANCE = 2,
+ VKD3D_SIV_CULL_DISTANCE = 3,
+ VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX = 4,
+ VKD3D_SIV_VIEWPORT_ARRAY_INDEX = 5,
+ VKD3D_SIV_VERTEX_ID = 6,
+ VKD3D_SIV_PRIMITIVE_ID = 7,
+ VKD3D_SIV_INSTANCE_ID = 8,
+ VKD3D_SIV_IS_FRONT_FACE = 9,
+ VKD3D_SIV_SAMPLE_INDEX = 10,
+ VKD3D_SIV_QUAD_U0_TESS_FACTOR = 11,
+ VKD3D_SIV_QUAD_V0_TESS_FACTOR = 12,
+ VKD3D_SIV_QUAD_U1_TESS_FACTOR = 13,
+ VKD3D_SIV_QUAD_V1_TESS_FACTOR = 14,
+ VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR = 15,
+ VKD3D_SIV_QUAD_V_INNER_TESS_FACTOR = 16,
+ VKD3D_SIV_TRIANGLE_U_TESS_FACTOR = 17,
+ VKD3D_SIV_TRIANGLE_V_TESS_FACTOR = 18,
+ VKD3D_SIV_TRIANGLE_W_TESS_FACTOR = 19,
+ VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR = 20,
+ VKD3D_SIV_LINE_DETAIL_TESS_FACTOR = 21,
+ VKD3D_SIV_LINE_DENSITY_TESS_FACTOR = 22,
+};
+
+struct vkd3d_shader_desc
+{
+ const DWORD *byte_code;
+ size_t byte_code_size;
+ struct vkd3d_shader_signature input_signature;
+ struct vkd3d_shader_signature output_signature;
+ struct vkd3d_shader_signature patch_constant_signature;
+};
+
+struct vkd3d_shader_register_semantic
+{
+ struct vkd3d_shader_dst_param reg;
+ enum vkd3d_shader_input_sysval_semantic sysval_semantic;
+};
+
+struct vkd3d_shader_sampler
+{
+ struct vkd3d_shader_src_param src;
+ unsigned int register_space, register_index;
+};
+
+struct vkd3d_shader_constant_buffer
+{
+ struct vkd3d_shader_src_param src;
+ unsigned int size;
+ unsigned int register_space, register_index;
+};
+
+struct vkd3d_shader_structured_resource
+{
+ struct vkd3d_shader_resource resource;
+ unsigned int byte_stride;
+};
+
+struct vkd3d_shader_raw_resource
+{
+ struct vkd3d_shader_resource resource;
+};
+
+struct vkd3d_shader_tgsm
+{
+ unsigned int size;
+ unsigned int stride;
+};
+
+struct vkd3d_shader_tgsm_raw
+{
+ struct vkd3d_shader_dst_param reg;
+ unsigned int byte_count;
+};
+
+struct vkd3d_shader_tgsm_structured
+{
+ struct vkd3d_shader_dst_param reg;
+ unsigned int byte_stride;
+ unsigned int structure_count;
+};
+
+struct vkd3d_shader_thread_group_size
+{
+ unsigned int x, y, z;
+};
+
+struct vkd3d_shader_function_table_pointer
+{
+ unsigned int index;
+ unsigned int array_size;
+ unsigned int body_count;
+ unsigned int table_count;
+};
+
+struct vkd3d_shader_texel_offset
+{
+ signed char u, v, w;
+};
+
+enum vkd3d_primitive_type
+{
+ VKD3D_PT_UNDEFINED = 0,
+ VKD3D_PT_POINTLIST = 1,
+ VKD3D_PT_LINELIST = 2,
+ VKD3D_PT_LINESTRIP = 3,
+ VKD3D_PT_TRIANGLELIST = 4,
+ VKD3D_PT_TRIANGLESTRIP = 5,
+ VKD3D_PT_TRIANGLEFAN = 6,
+ VKD3D_PT_LINELIST_ADJ = 10,
+ VKD3D_PT_LINESTRIP_ADJ = 11,
+ VKD3D_PT_TRIANGLELIST_ADJ = 12,
+ VKD3D_PT_TRIANGLESTRIP_ADJ = 13,
+ VKD3D_PT_PATCH = 14,
+};
+
+struct vkd3d_shader_primitive_type
+{
+ enum vkd3d_primitive_type type;
+ unsigned int patch_vertex_count;
+};
+
+struct vkd3d_shader_instruction
+{
+ enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx;
+ DWORD flags;
+ unsigned int dst_count;
+ unsigned int src_count;
+ const struct vkd3d_shader_dst_param *dst;
+ const struct vkd3d_shader_src_param *src;
+ struct vkd3d_shader_texel_offset texel_offset;
+ enum vkd3d_shader_resource_type resource_type;
+ enum vkd3d_data_type resource_data_type;
+ bool coissue;
+ const struct vkd3d_shader_src_param *predicate;
+ union
+ {
+ struct vkd3d_shader_semantic semantic;
+ struct vkd3d_shader_register_semantic register_semantic;
+ struct vkd3d_shader_primitive_type primitive_type;
+ struct vkd3d_shader_dst_param dst;
+ struct vkd3d_shader_constant_buffer cb;
+ struct vkd3d_shader_sampler sampler;
+ unsigned int count;
+ unsigned int index;
+ const struct vkd3d_shader_immediate_constant_buffer *icb;
+ struct vkd3d_shader_raw_resource raw_resource;
+ struct vkd3d_shader_structured_resource structured_resource;
+ struct vkd3d_shader_tgsm_raw tgsm_raw;
+ struct vkd3d_shader_tgsm_structured tgsm_structured;
+ struct vkd3d_shader_thread_group_size thread_group_size;
+ enum vkd3d_tessellator_domain tessellator_domain;
+ enum vkd3d_shader_tessellator_output_primitive tessellator_output_primitive;
+ enum vkd3d_shader_tessellator_partitioning tessellator_partitioning;
+ float max_tessellation_factor;
+ struct vkd3d_shader_index_range index_range;
+ struct vkd3d_shader_indexable_temp indexable_temp;
+ struct vkd3d_shader_function_table_pointer fp;
+ } declaration;
+};
+
+static inline bool vkd3d_shader_instruction_has_texel_offset(const struct vkd3d_shader_instruction *ins)
+{
+ return ins->texel_offset.u || ins->texel_offset.v || ins->texel_offset.w;
+}
+
+static inline bool vkd3d_shader_register_is_input(const struct vkd3d_shader_register *reg)
+{
+ return reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT;
+}
+
+static inline bool vkd3d_shader_register_is_output(const struct vkd3d_shader_register *reg)
+{
+ return reg->type == VKD3DSPR_OUTPUT || reg->type == VKD3DSPR_COLOROUT;
+}
+
+void vkd3d_shader_trace(void *data) DECLSPEC_HIDDEN;
+
+const char *shader_get_type_prefix(enum vkd3d_shader_type type) DECLSPEC_HIDDEN;
+
+void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
+ const struct vkd3d_shader_signature *output_signature) DECLSPEC_HIDDEN;
+void shader_sm4_free(void *data) DECLSPEC_HIDDEN;
+void shader_sm4_read_header(void *data, const DWORD **ptr,
+ struct vkd3d_shader_version *shader_version) DECLSPEC_HIDDEN;
+void shader_sm4_read_instruction(void *data, const DWORD **ptr,
+ struct vkd3d_shader_instruction *ins) DECLSPEC_HIDDEN;
+bool shader_sm4_is_end(void *data, const DWORD **ptr) DECLSPEC_HIDDEN;
+
+struct vkd3d_string_buffer
+{
+ char *buffer;
+ unsigned int buffer_size;
+ unsigned int content_size;
+};
+
+void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer) DECLSPEC_HIDDEN;
+bool vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer) DECLSPEC_HIDDEN;
+int vkd3d_string_buffer_vprintf(struct vkd3d_string_buffer *buffer, const char *format, va_list args) DECLSPEC_HIDDEN;
+
+struct vkd3d_shader_message_context
+{
+ enum vkd3d_shader_log_level log_level;
+ const char *source_name;
+ unsigned int line, column;
+ struct vkd3d_string_buffer messages;
+};
+
+void vkd3d_shader_message_context_cleanup(struct vkd3d_shader_message_context *context) DECLSPEC_HIDDEN;
+char *vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context) DECLSPEC_HIDDEN;
+bool vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context,
+ enum vkd3d_shader_log_level log_level, const char *source_name) DECLSPEC_HIDDEN;
+void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_message_context *context,
+ const char *function) DECLSPEC_HIDDEN;
+#define vkd3d_shader_message_context_trace_messages(context) \
+ vkd3d_shader_message_context_trace_messages_(context, __FUNCTION__)
+void vkd3d_shader_error(struct vkd3d_shader_message_context *context, enum vkd3d_shader_error error,
+ const char *format, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN;
+void vkd3d_shader_verror(struct vkd3d_shader_message_context *context,
+ enum vkd3d_shader_error error, const char *format, va_list args) DECLSPEC_HIDDEN;
+
+int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
+ struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN;
+void free_shader_desc(struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN;
+
+int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
+ struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature) DECLSPEC_HIDDEN;
+
+struct vkd3d_dxbc_compiler;
+
+struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
+ const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
+ const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info,
+ struct vkd3d_shader_message_context *message_context) DECLSPEC_HIDDEN;
+int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN;
+int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *spirv) DECLSPEC_HIDDEN;
+void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler) DECLSPEC_HIDDEN;
+
+void vkd3d_compute_dxbc_checksum(const void *dxbc, size_t size, uint32_t checksum[4]) DECLSPEC_HIDDEN;
+
+static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type(
+ enum vkd3d_data_type data_type)
+{
+ switch (data_type)
+ {
+ case VKD3D_DATA_FLOAT:
+ case VKD3D_DATA_UNORM:
+ case VKD3D_DATA_SNORM:
+ return VKD3D_SHADER_COMPONENT_FLOAT;
+ case VKD3D_DATA_UINT:
+ return VKD3D_SHADER_COMPONENT_UINT;
+ case VKD3D_DATA_INT:
+ return VKD3D_SHADER_COMPONENT_INT;
+ default:
+ FIXME("Unhandled data type %#x.\n", data_type);
+ return VKD3D_SHADER_COMPONENT_UINT;
+ }
+}
+
+static inline enum vkd3d_data_type vkd3d_data_type_from_component_type(
+ enum vkd3d_shader_component_type component_type)
+{
+ switch (component_type)
+ {
+ case VKD3D_SHADER_COMPONENT_FLOAT:
+ return VKD3D_DATA_FLOAT;
+ case VKD3D_SHADER_COMPONENT_UINT:
+ return VKD3D_DATA_UINT;
+ case VKD3D_SHADER_COMPONENT_INT:
+ return VKD3D_DATA_INT;
+ default:
+ FIXME("Unhandled component type %#x.\n", component_type);
+ return VKD3D_DATA_FLOAT;
+ }
+}
+
+static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask)
+{
+ unsigned int i;
+
+ assert(write_mask);
+ for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
+ return i;
+ }
+
+ FIXME("Invalid write mask %#x.\n", write_mask);
+ return 0;
+}
+
+static inline unsigned int vkd3d_write_mask_component_count(DWORD write_mask)
+{
+ unsigned int count = vkd3d_popcount(write_mask & VKD3DSP_WRITEMASK_ALL);
+ assert(1 <= count && count <= VKD3D_VEC4_SIZE);
+ return count;
+}
+
+static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int component_count)
+{
+ assert(component_count <= VKD3D_VEC4_SIZE);
+ return (VKD3DSP_WRITEMASK_0 << component_count) - 1;
+}
+
+static inline unsigned int vkd3d_swizzle_get_component(DWORD swizzle,
+ unsigned int idx)
+{
+ return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK;
+}
+
+static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned int write_mask)
+{
+ unsigned int i, compacted_swizzle = 0;
+
+ for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
+ {
+ compacted_swizzle <<= VKD3D_SHADER_SWIZZLE_SHIFT(1);
+ compacted_swizzle |= vkd3d_swizzle_get_component(swizzle, i);
+ }
+ }
+
+ return compacted_swizzle;
+}
+
+struct vkd3d_struct
+{
+ enum vkd3d_shader_structure_type type;
+ const void *next;
+};
+
+#define vkd3d_find_struct(c, t) vkd3d_find_struct_(c, VKD3D_SHADER_STRUCTURE_TYPE_##t)
+static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
+ enum vkd3d_shader_structure_type type)
+{
+ while (chain)
+ {
+ if (chain->type == type)
+ return (void *)chain;
+
+ chain = chain->next;
+ }
+
+ return NULL;
+}
+
+#define VKD3D_DXBC_MAX_SOURCE_COUNT 6
+#define VKD3D_DXBC_HEADER_SIZE (8 * sizeof(uint32_t))
+
+#endif /* __VKD3D_SHADER_PRIVATE_H */
diff --git a/dlls/vkd3d/libs/vkd3d-utils/libvkd3d-utils.pc.in b/dlls/vkd3d/libs/vkd3d-utils/libvkd3d-utils.pc.in
new file mode 100644
index 00000000000..31d2a89c3fc
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-utils/libvkd3d-utils.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: vkd3d-utils
+Description: The vkd3d 3D Graphics Utility Library
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}/vkd3d
+Libs: -L${libdir} -lvkd3d-utils
diff --git a/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils.map b/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils.map
new file mode 100644
index 00000000000..fb3912406cb
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils.map
@@ -0,0 +1,17 @@
+VKD3D_1_0
+{
+global:
+ D3D12CreateDevice;
+ D3D12CreateDeviceVKD3D;
+ D3D12CreateRootSignatureDeserializer;
+ D3D12CreateVersionedRootSignatureDeserializer;
+ D3D12GetDebugInterface;
+ D3D12SerializeRootSignature;
+ D3D12SerializeVersionedRootSignature;
+ vkd3d_create_event;
+ vkd3d_destroy_event;
+ vkd3d_signal_event;
+ vkd3d_wait_event;
+
+local: *;
+};
diff --git a/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c b/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c
new file mode 100644
index 00000000000..c19fe7f1fc5
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_utils_private.h"
+#undef D3D12CreateDevice
+
+VKD3D_DEBUG_ENV_NAME("VKD3D_DEBUG");
+
+HRESULT WINAPI D3D12GetDebugInterface(REFIID iid, void **debug)
+{
+ FIXME("iid %s, debug %p stub!\n", debugstr_guid(iid), debug);
+
+ return E_NOTIMPL;
+}
+
+HRESULT WINAPI D3D12CreateDeviceVKD3D(IUnknown *adapter, D3D_FEATURE_LEVEL minimum_feature_level,
+ REFIID iid, void **device, enum vkd3d_api_version api_version)
+{
+ struct vkd3d_optional_instance_extensions_info optional_extensions_info;
+ struct vkd3d_instance_create_info instance_create_info;
+ struct vkd3d_device_create_info device_create_info;
+
+ static const char * const instance_extensions[] =
+ {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+ };
+ static const char * const optional_instance_extensions[] =
+ {
+ "VK_KHR_xcb_surface",
+ "VK_MVK_macos_surface",
+ };
+ static const char * const device_extensions[] =
+ {
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ };
+ struct vkd3d_application_info application_info =
+ {
+ .type = VKD3D_STRUCTURE_TYPE_APPLICATION_INFO,
+ .api_version = api_version,
+ };
+
+ TRACE("adapter %p, minimum_feature_level %#x, iid %s, device %p, api_version %#x.\n",
+ adapter, minimum_feature_level, debugstr_guid(iid), device, api_version);
+
+ if (adapter)
+ FIXME("Ignoring adapter %p.\n", adapter);
+
+ memset(&optional_extensions_info, 0, sizeof(optional_extensions_info));
+ optional_extensions_info.type = VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO;
+ optional_extensions_info.next = &application_info;
+ optional_extensions_info.extensions = optional_instance_extensions;
+ optional_extensions_info.extension_count = ARRAY_SIZE(optional_instance_extensions);
+
+ memset(&instance_create_info, 0, sizeof(instance_create_info));
+ instance_create_info.type = VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ instance_create_info.next = &optional_extensions_info;
+ instance_create_info.pfn_signal_event = vkd3d_signal_event;
+ instance_create_info.wchar_size = sizeof(WCHAR);
+ instance_create_info.instance_extensions = instance_extensions;
+ instance_create_info.instance_extension_count = ARRAY_SIZE(instance_extensions);
+
+ memset(&device_create_info, 0, sizeof(device_create_info));
+ device_create_info.type = VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ device_create_info.next = NULL;
+ device_create_info.minimum_feature_level = minimum_feature_level;
+ device_create_info.instance_create_info = &instance_create_info;
+ device_create_info.device_extensions = device_extensions;
+ device_create_info.device_extension_count = ARRAY_SIZE(device_extensions);
+
+ return vkd3d_create_device(&device_create_info, iid, device);
+}
+
+HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter,
+ D3D_FEATURE_LEVEL minimum_feature_level, REFIID iid, void **device)
+{
+ return D3D12CreateDeviceVKD3D(adapter, minimum_feature_level, iid, device, VKD3D_API_VERSION_1_0);
+}
+
+HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size,
+ REFIID iid, void **deserializer)
+{
+ TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
+ data, data_size, debugstr_guid(iid), deserializer);
+
+ return vkd3d_create_root_signature_deserializer(data, data_size, iid, deserializer);
+}
+
+HRESULT WINAPI D3D12CreateVersionedRootSignatureDeserializer(const void *data, SIZE_T data_size,
+ REFIID iid,void **deserializer)
+{
+ TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
+ data, data_size, debugstr_guid(iid), deserializer);
+
+ return vkd3d_create_versioned_root_signature_deserializer(data, data_size, iid, deserializer);
+}
+
+HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *desc,
+ D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob)
+{
+ TRACE("desc %p, version %#x, blob %p, error_blob %p.\n", desc, version, blob, error_blob);
+
+ return vkd3d_serialize_root_signature(desc, version, blob, error_blob);
+}
+
+HRESULT WINAPI D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
+ ID3DBlob **blob, ID3DBlob **error_blob)
+{
+ TRACE("desc %p, blob %p, error_blob %p.\n", desc, blob, error_blob);
+
+ return vkd3d_serialize_versioned_root_signature(desc, blob, error_blob);
+}
+
+/* Events */
+HANDLE vkd3d_create_event(void)
+{
+ struct vkd3d_event *event;
+ int rc;
+
+ TRACE(".\n");
+
+ if (!(event = vkd3d_malloc(sizeof(*event))))
+ return NULL;
+
+ if ((rc = pthread_mutex_init(&event->mutex, NULL)))
+ {
+ ERR("Failed to initialize mutex, error %d.\n", rc);
+ vkd3d_free(event);
+ return NULL;
+ }
+ if ((rc = pthread_cond_init(&event->cond, NULL)))
+ {
+ ERR("Failed to initialize condition variable, error %d.\n", rc);
+ pthread_mutex_destroy(&event->mutex);
+ vkd3d_free(event);
+ return NULL;
+ }
+
+ event->is_signaled = false;
+
+ TRACE("Created event %p.\n", event);
+
+ return event;
+}
+
+unsigned int vkd3d_wait_event(HANDLE event, unsigned int milliseconds)
+{
+ struct vkd3d_event *impl = event;
+ int rc;
+
+ TRACE("event %p, milliseconds %u.\n", event, milliseconds);
+
+ if ((rc = pthread_mutex_lock(&impl->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return VKD3D_WAIT_FAILED;
+ }
+
+ if (impl->is_signaled || !milliseconds)
+ {
+ bool is_signaled = impl->is_signaled;
+ impl->is_signaled = false;
+ pthread_mutex_unlock(&impl->mutex);
+ return is_signaled ? VKD3D_WAIT_OBJECT_0 : VKD3D_WAIT_TIMEOUT;
+ }
+
+ if (milliseconds == VKD3D_INFINITE)
+ {
+ do
+ {
+ if ((rc = pthread_cond_wait(&impl->cond, &impl->mutex)))
+ {
+ ERR("Failed to wait on condition variable, error %d.\n", rc);
+ pthread_mutex_unlock(&impl->mutex);
+ return VKD3D_WAIT_FAILED;
+ }
+ } while (!impl->is_signaled);
+
+ impl->is_signaled = false;
+ pthread_mutex_unlock(&impl->mutex);
+ return VKD3D_WAIT_OBJECT_0;
+ }
+
+ pthread_mutex_unlock(&impl->mutex);
+ FIXME("Timed wait not implemented yet.\n");
+ return VKD3D_WAIT_FAILED;
+}
+
+HRESULT vkd3d_signal_event(HANDLE event)
+{
+ struct vkd3d_event *impl = event;
+ int rc;
+
+ TRACE("event %p.\n", event);
+
+ if ((rc = pthread_mutex_lock(&impl->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return E_FAIL;
+ }
+ impl->is_signaled = true;
+ pthread_cond_signal(&impl->cond);
+ pthread_mutex_unlock(&impl->mutex);
+
+ return S_OK;
+}
+
+void vkd3d_destroy_event(HANDLE event)
+{
+ struct vkd3d_event *impl = event;
+ int rc;
+
+ TRACE("event %p.\n", event);
+
+ if ((rc = pthread_mutex_destroy(&impl->mutex)))
+ ERR("Failed to destroy mutex, error %d.\n", rc);
+ if ((rc = pthread_cond_destroy(&impl->cond)))
+ ERR("Failed to destroy condition variable, error %d.\n", rc);
+ vkd3d_free(impl);
+}
diff --git a/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils_private.h b/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils_private.h
new file mode 100644
index 00000000000..6b5851e6bfc
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d-utils/vkd3d_utils_private.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_UTILS_PRIVATE_H
+#define __VKD3D_UTILS_PRIVATE_H
+
+#define COBJMACROS
+#define NONAMELESSUNION
+#define VK_NO_PROTOTYPES
+
+#include <pthread.h>
+#include <vkd3d.h>
+
+#include "vkd3d_memory.h"
+#include <vkd3d_utils.h>
+
+struct vkd3d_event
+{
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ BOOL is_signaled;
+};
+
+#endif /* __VKD3D_UTILS_PRIVATE_H */
diff --git a/dlls/vkd3d/libs/vkd3d/command.c b/dlls/vkd3d/libs/vkd3d/command.c
new file mode 100644
index 00000000000..e5c6791b83a
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/command.c
@@ -0,0 +1,6461 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ * Copyright 2016 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_private.h"
+
+static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkFence vk_fence);
+
+HRESULT vkd3d_queue_create(struct d3d12_device *device,
+ uint32_t family_index, const VkQueueFamilyProperties *properties, struct vkd3d_queue **queue)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_queue *object;
+ int rc;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if ((rc = pthread_mutex_init(&object->mutex, NULL)))
+ {
+ ERR("Failed to initialize mutex, error %d.\n", rc);
+ vkd3d_free(object);
+ return hresult_from_errno(rc);
+ }
+
+ object->completed_sequence_number = 0;
+ object->submitted_sequence_number = 0;
+
+ object->vk_family_index = family_index;
+ object->vk_queue_flags = properties->queueFlags;
+ object->timestamp_bits = properties->timestampValidBits;
+
+ object->semaphores = NULL;
+ object->semaphores_size = 0;
+ object->semaphore_count = 0;
+
+ memset(object->old_vk_semaphores, 0, sizeof(object->old_vk_semaphores));
+
+ VK_CALL(vkGetDeviceQueue(device->vk_device, family_index, 0, &object->vk_queue));
+
+ TRACE("Created queue %p for queue family index %u.\n", object, family_index);
+
+ *queue = object;
+
+ return S_OK;
+}
+
+void vkd3d_queue_destroy(struct vkd3d_queue *queue, struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ unsigned int i;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&queue->mutex)))
+ ERR("Failed to lock mutex, error %d.\n", rc);
+
+ for (i = 0; i < queue->semaphore_count; ++i)
+ VK_CALL(vkDestroySemaphore(device->vk_device, queue->semaphores[i].vk_semaphore, NULL));
+
+ vkd3d_free(queue->semaphores);
+
+ for (i = 0; i < ARRAY_SIZE(queue->old_vk_semaphores); ++i)
+ {
+ if (queue->old_vk_semaphores[i])
+ VK_CALL(vkDestroySemaphore(device->vk_device, queue->old_vk_semaphores[i], NULL));
+ }
+
+ if (!rc)
+ pthread_mutex_unlock(&queue->mutex);
+
+ pthread_mutex_destroy(&queue->mutex);
+ vkd3d_free(queue);
+}
+
+VkQueue vkd3d_queue_acquire(struct vkd3d_queue *queue)
+{
+ int rc;
+
+ TRACE("queue %p.\n", queue);
+
+ if ((rc = pthread_mutex_lock(&queue->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return VK_NULL_HANDLE;
+ }
+
+ assert(queue->vk_queue);
+ return queue->vk_queue;
+}
+
+void vkd3d_queue_release(struct vkd3d_queue *queue)
+{
+ TRACE("queue %p.\n", queue);
+
+ pthread_mutex_unlock(&queue->mutex);
+}
+
+static VkResult vkd3d_queue_wait_idle(struct vkd3d_queue *queue,
+ const struct vkd3d_vk_device_procs *vk_procs)
+{
+ VkQueue vk_queue;
+ VkResult vr;
+
+ if ((vk_queue = vkd3d_queue_acquire(queue)))
+ {
+ vr = VK_CALL(vkQueueWaitIdle(vk_queue));
+ vkd3d_queue_release(queue);
+
+ if (vr < 0)
+ WARN("Failed to wait for queue, vr %d.\n", vr);
+ }
+ else
+ {
+ ERR("Failed to acquire queue %p.\n", queue);
+ vr = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ return vr;
+}
+
+static void vkd3d_queue_update_sequence_number(struct vkd3d_queue *queue,
+ uint64_t sequence_number, struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ unsigned int destroyed_semaphore_count = 0;
+ uint64_t completed_sequence_number;
+ VkSemaphore vk_semaphore;
+ unsigned int i, j;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&queue->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return;
+ }
+
+ completed_sequence_number = queue->completed_sequence_number;
+ queue->completed_sequence_number = max(sequence_number, queue->completed_sequence_number);
+
+ TRACE("Queue %p sequence number %"PRIu64" -> %"PRIu64".\n",
+ queue, completed_sequence_number, queue->completed_sequence_number);
+
+ for (i = 0; i < queue->semaphore_count; ++i)
+ {
+ if (queue->semaphores[i].sequence_number > queue->completed_sequence_number)
+ break;
+
+ vk_semaphore = queue->semaphores[i].vk_semaphore;
+
+ /* Try to store the Vulkan semaphore for reuse. */
+ for (j = 0; j < ARRAY_SIZE(queue->old_vk_semaphores); ++j)
+ {
+ if (queue->old_vk_semaphores[j] == VK_NULL_HANDLE)
+ {
+ queue->old_vk_semaphores[j] = vk_semaphore;
+ vk_semaphore = VK_NULL_HANDLE;
+ break;
+ }
+ }
+
+ if (!vk_semaphore)
+ continue;
+
+ VK_CALL(vkDestroySemaphore(device->vk_device, vk_semaphore, NULL));
+ ++destroyed_semaphore_count;
+ }
+ if (i > 0)
+ {
+ queue->semaphore_count -= i;
+ memmove(queue->semaphores, &queue->semaphores[i], queue->semaphore_count * sizeof(*queue->semaphores));
+ }
+
+ if (destroyed_semaphore_count)
+ TRACE("Destroyed %u Vulkan semaphores.\n", destroyed_semaphore_count);
+
+ pthread_mutex_unlock(&queue->mutex);
+}
+
+static uint64_t vkd3d_queue_reset_sequence_number_locked(struct vkd3d_queue *queue)
+{
+ unsigned int i;
+
+ WARN("Ressetting sequence number for queue %p.\n", queue);
+
+ queue->completed_sequence_number = 0;
+ queue->submitted_sequence_number = 1;
+
+ for (i = 0; i < queue->semaphore_count; ++i)
+ queue->semaphores[i].sequence_number = queue->submitted_sequence_number;
+
+ return queue->submitted_sequence_number;
+}
+
+static VkResult vkd3d_queue_create_vk_semaphore_locked(struct vkd3d_queue *queue,
+ struct d3d12_device *device, VkSemaphore *vk_semaphore)
+{
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkSemaphoreCreateInfo semaphore_info;
+ unsigned int i;
+ VkResult vr;
+
+ *vk_semaphore = VK_NULL_HANDLE;
+
+ for (i = 0; i < ARRAY_SIZE(queue->old_vk_semaphores); ++i)
+ {
+ if ((*vk_semaphore = queue->old_vk_semaphores[i]))
+ {
+ queue->old_vk_semaphores[i] = VK_NULL_HANDLE;
+ break;
+ }
+ }
+
+ if (*vk_semaphore)
+ return VK_SUCCESS;
+
+ vk_procs = &device->vk_procs;
+
+ semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphore_info.pNext = NULL;
+ semaphore_info.flags = 0;
+ if ((vr = VK_CALL(vkCreateSemaphore(device->vk_device, &semaphore_info, NULL, vk_semaphore))) < 0)
+ {
+ WARN("Failed to create Vulkan semaphore, vr %d.\n", vr);
+ *vk_semaphore = VK_NULL_HANDLE;
+ }
+
+ return vr;
+}
+
+/* Fence worker thread */
+static HRESULT vkd3d_enqueue_gpu_fence(struct vkd3d_fence_worker *worker,
+ VkFence vk_fence, struct d3d12_fence *fence, uint64_t value,
+ struct vkd3d_queue *queue, uint64_t queue_sequence_number)
+{
+ struct vkd3d_waiting_fence *waiting_fence;
+ int rc;
+
+ TRACE("worker %p, fence %p, value %#"PRIx64".\n", worker, fence, value);
+
+ if ((rc = pthread_mutex_lock(&worker->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ if (!vkd3d_array_reserve((void **)&worker->enqueued_fences, &worker->enqueued_fences_size,
+ worker->enqueued_fence_count + 1, sizeof(*worker->enqueued_fences)))
+ {
+ ERR("Failed to add GPU fence.\n");
+ pthread_mutex_unlock(&worker->mutex);
+ return E_OUTOFMEMORY;
+ }
+
+ worker->enqueued_fences[worker->enqueued_fence_count].vk_fence = vk_fence;
+ waiting_fence = &worker->enqueued_fences[worker->enqueued_fence_count].waiting_fence;
+ waiting_fence->fence = fence;
+ waiting_fence->value = value;
+ waiting_fence->queue = queue;
+ waiting_fence->queue_sequence_number = queue_sequence_number;
+ ++worker->enqueued_fence_count;
+
+ InterlockedIncrement(&fence->pending_worker_operation_count);
+
+ pthread_cond_signal(&worker->cond);
+ pthread_mutex_unlock(&worker->mutex);
+
+ return S_OK;
+}
+
+static void vkd3d_fence_worker_remove_fence(struct vkd3d_fence_worker *worker, struct d3d12_fence *fence)
+{
+ LONG count;
+ int rc;
+
+ if (!(count = atomic_add_fetch(&fence->pending_worker_operation_count, 0)))
+ return;
+
+ WARN("Waiting for %u pending fence operations (fence %p).\n", count, fence);
+
+ if ((rc = pthread_mutex_lock(&worker->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return;
+ }
+
+ while ((count = atomic_add_fetch(&fence->pending_worker_operation_count, 0)))
+ {
+ TRACE("Still waiting for %u pending fence operations (fence %p).\n", count, fence);
+
+ worker->pending_fence_destruction = true;
+ pthread_cond_signal(&worker->cond);
+
+ pthread_cond_wait(&worker->fence_destruction_cond, &worker->mutex);
+ }
+
+ TRACE("Removed fence %p.\n", fence);
+
+ pthread_mutex_unlock(&worker->mutex);
+}
+
+static void vkd3d_fence_worker_move_enqueued_fences_locked(struct vkd3d_fence_worker *worker)
+{
+ unsigned int i;
+ size_t count;
+ bool ret;
+
+ if (!worker->enqueued_fence_count)
+ return;
+
+ count = worker->fence_count + worker->enqueued_fence_count;
+
+ ret = vkd3d_array_reserve((void **)&worker->vk_fences, &worker->vk_fences_size,
+ count, sizeof(*worker->vk_fences));
+ ret &= vkd3d_array_reserve((void **)&worker->fences, &worker->fences_size,
+ count, sizeof(*worker->fences));
+ if (!ret)
+ {
+ ERR("Failed to reserve memory.\n");
+ return;
+ }
+
+ for (i = 0; i < worker->enqueued_fence_count; ++i)
+ {
+ struct vkd3d_enqueued_fence *current = &worker->enqueued_fences[i];
+
+ worker->vk_fences[worker->fence_count] = current->vk_fence;
+ worker->fences[worker->fence_count] = current->waiting_fence;
+ ++worker->fence_count;
+ }
+ assert(worker->fence_count == count);
+ worker->enqueued_fence_count = 0;
+}
+
+static void vkd3d_wait_for_gpu_fences(struct vkd3d_fence_worker *worker)
+{
+ struct d3d12_device *device = worker->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ unsigned int i, j;
+ VkFence vk_fence;
+ HRESULT hr;
+ int vr;
+
+ if (!worker->fence_count)
+ return;
+
+ vr = VK_CALL(vkWaitForFences(device->vk_device,
+ worker->fence_count, worker->vk_fences, VK_FALSE, ~(uint64_t)0));
+ if (vr == VK_TIMEOUT)
+ return;
+ if (vr != VK_SUCCESS)
+ {
+ ERR("Failed to wait for Vulkan fences, vr %d.\n", vr);
+ return;
+ }
+
+ for (i = 0, j = 0; i < worker->fence_count; ++i)
+ {
+ vk_fence = worker->vk_fences[i];
+ if (!(vr = VK_CALL(vkGetFenceStatus(device->vk_device, vk_fence))))
+ {
+ struct vkd3d_waiting_fence *current = &worker->fences[i];
+
+ TRACE("Signaling fence %p value %#"PRIx64".\n", current->fence, current->value);
+ if (FAILED(hr = d3d12_fence_signal(current->fence, current->value, vk_fence)))
+ ERR("Failed to signal D3D12 fence, hr %#x.\n", hr);
+
+ InterlockedDecrement(¤t->fence->pending_worker_operation_count);
+
+ vkd3d_queue_update_sequence_number(current->queue, current->queue_sequence_number, device);
+ continue;
+ }
+
+ if (vr != VK_NOT_READY)
+ ERR("Failed to get Vulkan fence status, vr %d.\n", vr);
+
+ if (i != j)
+ {
+ worker->vk_fences[j] = worker->vk_fences[i];
+ worker->fences[j] = worker->fences[i];
+ }
+ ++j;
+ }
+ worker->fence_count = j;
+}
+
+static void *vkd3d_fence_worker_main(void *arg)
+{
+ struct vkd3d_fence_worker *worker = arg;
+ int rc;
+
+ vkd3d_set_thread_name("vkd3d_fence");
+
+ for (;;)
+ {
+ vkd3d_wait_for_gpu_fences(worker);
+
+ if (!worker->fence_count || atomic_add_fetch(&worker->enqueued_fence_count, 0))
+ {
+ if ((rc = pthread_mutex_lock(&worker->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ break;
+ }
+
+ if (worker->pending_fence_destruction)
+ {
+ pthread_cond_broadcast(&worker->fence_destruction_cond);
+ worker->pending_fence_destruction = false;
+ }
+
+ if (worker->enqueued_fence_count)
+ {
+ vkd3d_fence_worker_move_enqueued_fences_locked(worker);
+ }
+ else
+ {
+ if (worker->should_exit)
+ {
+ pthread_mutex_unlock(&worker->mutex);
+ break;
+ }
+
+ if ((rc = pthread_cond_wait(&worker->cond, &worker->mutex)))
+ {
+ ERR("Failed to wait on condition variable, error %d.\n", rc);
+ pthread_mutex_unlock(&worker->mutex);
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&worker->mutex);
+ }
+ }
+
+ return NULL;
+}
+
+HRESULT vkd3d_fence_worker_start(struct vkd3d_fence_worker *worker,
+ struct d3d12_device *device)
+{
+ HRESULT hr;
+ int rc;
+
+ TRACE("worker %p.\n", worker);
+
+ worker->should_exit = false;
+ worker->pending_fence_destruction = false;
+ worker->device = device;
+
+ worker->enqueued_fence_count = 0;
+ worker->enqueued_fences = NULL;
+ worker->enqueued_fences_size = 0;
+
+ worker->fence_count = 0;
+
+ worker->vk_fences = NULL;
+ worker->vk_fences_size = 0;
+ worker->fences = NULL;
+ worker->fences_size = 0;
+
+ if ((rc = pthread_mutex_init(&worker->mutex, NULL)))
+ {
+ ERR("Failed to initialize mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ if ((rc = pthread_cond_init(&worker->cond, NULL)))
+ {
+ ERR("Failed to initialize condition variable, error %d.\n", rc);
+ pthread_mutex_destroy(&worker->mutex);
+ return hresult_from_errno(rc);
+ }
+
+ if ((rc = pthread_cond_init(&worker->fence_destruction_cond, NULL)))
+ {
+ ERR("Failed to initialize condition variable, error %d.\n", rc);
+ pthread_mutex_destroy(&worker->mutex);
+ pthread_cond_destroy(&worker->cond);
+ return hresult_from_errno(rc);
+ }
+
+ if (FAILED(hr = vkd3d_create_thread(device->vkd3d_instance,
+ vkd3d_fence_worker_main, worker, &worker->thread)))
+ {
+ pthread_mutex_destroy(&worker->mutex);
+ pthread_cond_destroy(&worker->cond);
+ pthread_cond_destroy(&worker->fence_destruction_cond);
+ }
+
+ return hr;
+}
+
+HRESULT vkd3d_fence_worker_stop(struct vkd3d_fence_worker *worker,
+ struct d3d12_device *device)
+{
+ HRESULT hr;
+ int rc;
+
+ TRACE("worker %p.\n", worker);
+
+ if ((rc = pthread_mutex_lock(&worker->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ worker->should_exit = true;
+ pthread_cond_signal(&worker->cond);
+
+ pthread_mutex_unlock(&worker->mutex);
+
+ if (FAILED(hr = vkd3d_join_thread(device->vkd3d_instance, &worker->thread)))
+ return hr;
+
+ pthread_mutex_destroy(&worker->mutex);
+ pthread_cond_destroy(&worker->cond);
+ pthread_cond_destroy(&worker->fence_destruction_cond);
+
+ vkd3d_free(worker->enqueued_fences);
+ vkd3d_free(worker->vk_fences);
+ vkd3d_free(worker->fences);
+
+ return S_OK;
+}
+
+static const struct d3d12_root_parameter *root_signature_get_parameter(
+ const struct d3d12_root_signature *root_signature, unsigned int index)
+{
+ assert(index < root_signature->parameter_count);
+ return &root_signature->parameters[index];
+}
+
+static const struct d3d12_root_descriptor_table *root_signature_get_descriptor_table(
+ const struct d3d12_root_signature *root_signature, unsigned int index)
+{
+ const struct d3d12_root_parameter *p = root_signature_get_parameter(root_signature, index);
+ assert(p->parameter_type == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE);
+ return &p->u.descriptor_table;
+}
+
+static const struct d3d12_root_constant *root_signature_get_32bit_constants(
+ const struct d3d12_root_signature *root_signature, unsigned int index)
+{
+ const struct d3d12_root_parameter *p = root_signature_get_parameter(root_signature, index);
+ assert(p->parameter_type == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS);
+ return &p->u.constant;
+}
+
+static const struct d3d12_root_parameter *root_signature_get_root_descriptor(
+ const struct d3d12_root_signature *root_signature, unsigned int index)
+{
+ const struct d3d12_root_parameter *p = root_signature_get_parameter(root_signature, index);
+ assert(p->parameter_type == D3D12_ROOT_PARAMETER_TYPE_CBV
+ || p->parameter_type == D3D12_ROOT_PARAMETER_TYPE_SRV
+ || p->parameter_type == D3D12_ROOT_PARAMETER_TYPE_UAV);
+ return p;
+}
+
+/* ID3D12Fence */
+static struct d3d12_fence *impl_from_ID3D12Fence(ID3D12Fence *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_fence, ID3D12Fence_iface);
+}
+
+static VkResult d3d12_fence_create_vk_fence(struct d3d12_fence *fence, VkFence *vk_fence)
+{
+ const struct vkd3d_vk_device_procs *vk_procs;
+ struct d3d12_device *device = fence->device;
+ VkFenceCreateInfo fence_info;
+ unsigned int i;
+ VkResult vr;
+ int rc;
+
+ *vk_fence = VK_NULL_HANDLE;
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ goto create_fence;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(fence->old_vk_fences); ++i)
+ {
+ if ((*vk_fence = fence->old_vk_fences[i]))
+ {
+ fence->old_vk_fences[i] = VK_NULL_HANDLE;
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&fence->mutex);
+
+ if (*vk_fence)
+ return VK_SUCCESS;
+
+create_fence:
+ vk_procs = &device->vk_procs;
+
+ fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fence_info.pNext = NULL;
+ fence_info.flags = 0;
+ if ((vr = VK_CALL(vkCreateFence(device->vk_device, &fence_info, NULL, vk_fence))) < 0)
+ {
+ WARN("Failed to create Vulkan fence, vr %d.\n", vr);
+ *vk_fence = VK_NULL_HANDLE;
+ }
+
+ return vr;
+}
+
+static void d3d12_fence_garbage_collect_vk_semaphores_locked(struct d3d12_fence *fence,
+ bool destroy_all)
+{
+ struct d3d12_device *device = fence->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_signaled_semaphore *current, *p;
+ unsigned int semaphore_count;
+
+ semaphore_count = fence->semaphore_count;
+ if (!destroy_all && semaphore_count < VKD3D_MAX_VK_SYNC_OBJECTS)
+ return;
+
+ LIST_FOR_EACH_ENTRY_SAFE(current, p, &fence->semaphores, struct vkd3d_signaled_semaphore, entry)
+ {
+ if (!destroy_all && fence->semaphore_count < VKD3D_MAX_VK_SYNC_OBJECTS)
+ break;
+
+ /* The semaphore doesn't have a pending signal operation if the fence
+ * was signaled. */
+ if ((current->vk_fence || current->is_acquired) && !destroy_all)
+ continue;
+
+ if (current->vk_fence)
+ WARN("Destroying potentially pending semaphore.\n");
+ assert(!current->is_acquired);
+
+ VK_CALL(vkDestroySemaphore(device->vk_device, current->vk_semaphore, NULL));
+ list_remove(¤t->entry);
+ vkd3d_free(current);
+
+ --fence->semaphore_count;
+ }
+
+ if (semaphore_count != fence->semaphore_count)
+ TRACE("Destroyed %u Vulkan semaphores.\n", semaphore_count - fence->semaphore_count);
+}
+
+static void d3d12_fence_destroy_vk_objects(struct d3d12_fence *fence)
+{
+ const struct vkd3d_vk_device_procs *vk_procs;
+ struct d3d12_device *device = fence->device;
+ unsigned int i;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return;
+ }
+
+ vk_procs = &device->vk_procs;
+
+ for (i = 0; i < ARRAY_SIZE(fence->old_vk_fences); ++i)
+ {
+ if (fence->old_vk_fences[i])
+ VK_CALL(vkDestroyFence(device->vk_device, fence->old_vk_fences[i], NULL));
+ fence->old_vk_fences[i] = VK_NULL_HANDLE;
+ }
+
+ d3d12_fence_garbage_collect_vk_semaphores_locked(fence, true);
+
+ pthread_mutex_unlock(&fence->mutex);
+}
+
+static struct vkd3d_signaled_semaphore *d3d12_fence_acquire_vk_semaphore(struct d3d12_fence *fence,
+ uint64_t value, uint64_t *completed_value)
+{
+ struct vkd3d_signaled_semaphore *semaphore;
+ struct vkd3d_signaled_semaphore *current;
+ uint64_t semaphore_value;
+ int rc;
+
+ TRACE("fence %p, value %#"PRIx64".\n", fence, value);
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return VK_NULL_HANDLE;
+ }
+
+ semaphore = NULL;
+ semaphore_value = ~(uint64_t)0;
+
+ LIST_FOR_EACH_ENTRY(current, &fence->semaphores, struct vkd3d_signaled_semaphore, entry)
+ {
+ /* Prefer a semaphore with the smallest value. */
+ if (!current->is_acquired && current->value >= value && semaphore_value >= current->value)
+ {
+ semaphore = current;
+ semaphore_value = current->value;
+ }
+ if (semaphore_value == value)
+ break;
+ }
+
+ if (semaphore)
+ semaphore->is_acquired = true;
+
+ *completed_value = fence->value;
+
+ pthread_mutex_unlock(&fence->mutex);
+
+ return semaphore;
+}
+
+static void d3d12_fence_remove_vk_semaphore(struct d3d12_fence *fence, struct vkd3d_signaled_semaphore *semaphore)
+{
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return;
+ }
+
+ assert(semaphore->is_acquired);
+
+ list_remove(&semaphore->entry);
+ vkd3d_free(semaphore);
+
+ --fence->semaphore_count;
+
+ pthread_mutex_unlock(&fence->mutex);
+}
+
+static void d3d12_fence_release_vk_semaphore(struct d3d12_fence *fence, struct vkd3d_signaled_semaphore *semaphore)
+{
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return;
+ }
+
+ assert(semaphore->is_acquired);
+ semaphore->is_acquired = false;
+
+ pthread_mutex_unlock(&fence->mutex);
+}
+
+static HRESULT d3d12_fence_add_vk_semaphore(struct d3d12_fence *fence,
+ VkSemaphore vk_semaphore, VkFence vk_fence, uint64_t value)
+{
+ struct vkd3d_signaled_semaphore *semaphore;
+ HRESULT hr = S_OK;
+ int rc;
+
+ TRACE("fence %p, value %#"PRIx64".\n", fence, value);
+
+ if (!(semaphore = vkd3d_malloc(sizeof(*semaphore))))
+ {
+ ERR("Failed to add semaphore.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ vkd3d_free(semaphore);
+ return E_FAIL;
+ }
+
+ d3d12_fence_garbage_collect_vk_semaphores_locked(fence, false);
+
+ semaphore->value = value;
+ semaphore->vk_semaphore = vk_semaphore;
+ semaphore->vk_fence = vk_fence;
+ semaphore->is_acquired = false;
+
+ list_add_tail(&fence->semaphores, &semaphore->entry);
+ ++fence->semaphore_count;
+
+ pthread_mutex_unlock(&fence->mutex);
+
+ return hr;
+}
+
+static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkFence vk_fence)
+{
+ struct d3d12_device *device = fence->device;
+ struct vkd3d_signaled_semaphore *current;
+ unsigned int i, j;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ fence->value = value;
+
+ for (i = 0, j = 0; i < fence->event_count; ++i)
+ {
+ struct vkd3d_waiting_event *current = &fence->events[i];
+
+ if (current->value <= value)
+ {
+ fence->device->signal_event(current->event);
+ }
+ else
+ {
+ if (i != j)
+ fence->events[j] = *current;
+ ++j;
+ }
+ }
+ fence->event_count = j;
+
+ if (vk_fence)
+ {
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ LIST_FOR_EACH_ENTRY(current, &fence->semaphores, struct vkd3d_signaled_semaphore, entry)
+ {
+ if (current->vk_fence == vk_fence)
+ current->vk_fence = VK_NULL_HANDLE;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(fence->old_vk_fences); ++i)
+ {
+ if (fence->old_vk_fences[i] == VK_NULL_HANDLE)
+ {
+ fence->old_vk_fences[i] = vk_fence;
+ VK_CALL(vkResetFences(device->vk_device, 1, &vk_fence));
+ vk_fence = VK_NULL_HANDLE;
+ break;
+ }
+ }
+ if (vk_fence)
+ VK_CALL(vkDestroyFence(device->vk_device, vk_fence, NULL));
+ }
+
+ pthread_mutex_unlock(&fence->mutex);
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_fence_QueryInterface(ID3D12Fence *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12Fence)
+ || IsEqualGUID(riid, &IID_ID3D12Pageable)
+ || IsEqualGUID(riid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12Fence_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_fence_AddRef(ID3D12Fence *iface)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+ ULONG refcount = InterlockedIncrement(&fence->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", fence, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_fence_Release(ID3D12Fence *iface)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+ ULONG refcount = InterlockedDecrement(&fence->refcount);
+ int rc;
+
+ TRACE("%p decreasing refcount to %u.\n", fence, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = fence->device;
+
+ vkd3d_private_store_destroy(&fence->private_store);
+
+ vkd3d_fence_worker_remove_fence(&device->fence_worker, fence);
+
+ d3d12_fence_destroy_vk_objects(fence);
+
+ vkd3d_free(fence->events);
+ if ((rc = pthread_mutex_destroy(&fence->mutex)))
+ ERR("Failed to destroy mutex, error %d.\n", rc);
+ vkd3d_free(fence);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_fence_GetPrivateData(ID3D12Fence *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n",
+ iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&fence->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_fence_SetPrivateData(ID3D12Fence *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n",
+ iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&fence->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_fence_SetPrivateDataInterface(ID3D12Fence *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&fence->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_fence_SetName(ID3D12Fence *iface, const WCHAR *name)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, fence->device->wchar_size));
+
+ return name ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_fence_GetDevice(ID3D12Fence *iface, REFIID iid, void **device)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(fence->device, iid, device);
+}
+
+static UINT64 STDMETHODCALLTYPE d3d12_fence_GetCompletedValue(ID3D12Fence *iface)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+ uint64_t completed_value;
+ int rc;
+
+ TRACE("iface %p.\n", iface);
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return 0;
+ }
+ completed_value = fence->value;
+ pthread_mutex_unlock(&fence->mutex);
+ return completed_value;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence *iface,
+ UINT64 value, HANDLE event)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+ unsigned int i;
+ int rc;
+
+ TRACE("iface %p, value %#"PRIx64", event %p.\n", iface, value, event);
+
+ if ((rc = pthread_mutex_lock(&fence->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ if (value <= fence->value)
+ {
+ fence->device->signal_event(event);
+ pthread_mutex_unlock(&fence->mutex);
+ return S_OK;
+ }
+
+ for (i = 0; i < fence->event_count; ++i)
+ {
+ struct vkd3d_waiting_event *current = &fence->events[i];
+ if (current->value == value && current->event == event)
+ {
+ WARN("Event completion for (%p, %#"PRIx64") is already in the list.\n",
+ event, value);
+ pthread_mutex_unlock(&fence->mutex);
+ return S_OK;
+ }
+ }
+
+ if (!vkd3d_array_reserve((void **)&fence->events, &fence->events_size,
+ fence->event_count + 1, sizeof(*fence->events)))
+ {
+ WARN("Failed to add event.\n");
+ pthread_mutex_unlock(&fence->mutex);
+ return E_OUTOFMEMORY;
+ }
+
+ fence->events[fence->event_count].value = value;
+ fence->events[fence->event_count].event = event;
+ ++fence->event_count;
+
+ pthread_mutex_unlock(&fence->mutex);
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_fence_Signal(ID3D12Fence *iface, UINT64 value)
+{
+ struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+
+ TRACE("iface %p, value %#"PRIx64".\n", iface, value);
+
+ return d3d12_fence_signal(fence, value, VK_NULL_HANDLE);
+}
+
+static const struct ID3D12FenceVtbl d3d12_fence_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_fence_QueryInterface,
+ d3d12_fence_AddRef,
+ d3d12_fence_Release,
+ /* ID3D12Object methods */
+ d3d12_fence_GetPrivateData,
+ d3d12_fence_SetPrivateData,
+ d3d12_fence_SetPrivateDataInterface,
+ d3d12_fence_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_fence_GetDevice,
+ /* ID3D12Fence methods */
+ d3d12_fence_GetCompletedValue,
+ d3d12_fence_SetEventOnCompletion,
+ d3d12_fence_Signal,
+};
+
+static struct d3d12_fence *unsafe_impl_from_ID3D12Fence(ID3D12Fence *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_fence_vtbl);
+ return impl_from_ID3D12Fence(iface);
+}
+
+static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *device,
+ UINT64 initial_value, D3D12_FENCE_FLAGS flags)
+{
+ HRESULT hr;
+ int rc;
+
+ fence->ID3D12Fence_iface.lpVtbl = &d3d12_fence_vtbl;
+ fence->refcount = 1;
+
+ fence->value = initial_value;
+
+ if ((rc = pthread_mutex_init(&fence->mutex, NULL)))
+ {
+ ERR("Failed to initialize mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ if (flags)
+ FIXME("Ignoring flags %#x.\n", flags);
+
+ fence->events = NULL;
+ fence->events_size = 0;
+ fence->event_count = 0;
+
+ list_init(&fence->semaphores);
+ fence->semaphore_count = 0;
+
+ memset(fence->old_vk_fences, 0, sizeof(fence->old_vk_fences));
+
+ fence->pending_worker_operation_count = 0;
+
+ if (FAILED(hr = vkd3d_private_store_init(&fence->private_store)))
+ {
+ pthread_mutex_destroy(&fence->mutex);
+ return hr;
+ }
+
+ d3d12_device_add_ref(fence->device = device);
+
+ return S_OK;
+}
+
+HRESULT d3d12_fence_create(struct d3d12_device *device,
+ uint64_t initial_value, D3D12_FENCE_FLAGS flags, struct d3d12_fence **fence)
+{
+ struct d3d12_fence *object;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ d3d12_fence_init(object, device, initial_value, flags);
+
+ TRACE("Created fence %p.\n", object);
+
+ *fence = object;
+
+ return S_OK;
+}
+
+/* Command buffers */
+static void d3d12_command_list_mark_as_invalid(struct d3d12_command_list *list,
+ const char *message, ...)
+{
+ va_list args;
+
+ va_start(args, message);
+ WARN("Command list %p is invalid: \"%s\".\n", list, vkd3d_dbg_vsprintf(message, args));
+ va_end(args);
+
+ list->is_valid = false;
+}
+
+static HRESULT d3d12_command_list_begin_command_buffer(struct d3d12_command_list *list)
+{
+ struct d3d12_device *device = list->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkCommandBufferBeginInfo begin_info;
+ VkResult vr;
+
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.pNext = NULL;
+ begin_info.flags = 0;
+ begin_info.pInheritanceInfo = NULL;
+
+ if ((vr = VK_CALL(vkBeginCommandBuffer(list->vk_command_buffer, &begin_info))) < 0)
+ {
+ WARN("Failed to begin command buffer, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ list->is_recording = true;
+ list->is_valid = true;
+
+ return S_OK;
+}
+
+static HRESULT d3d12_command_allocator_allocate_command_buffer(struct d3d12_command_allocator *allocator,
+ struct d3d12_command_list *list)
+{
+ struct d3d12_device *device = allocator->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkCommandBufferAllocateInfo command_buffer_info;
+ VkResult vr;
+ HRESULT hr;
+
+ TRACE("allocator %p, list %p.\n", allocator, list);
+
+ if (allocator->current_command_list)
+ {
+ WARN("Command allocator is already in use.\n");
+ return E_INVALIDARG;
+ }
+
+ command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ command_buffer_info.pNext = NULL;
+ command_buffer_info.commandPool = allocator->vk_command_pool;
+ command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ command_buffer_info.commandBufferCount = 1;
+
+ if ((vr = VK_CALL(vkAllocateCommandBuffers(device->vk_device, &command_buffer_info,
+ &list->vk_command_buffer))) < 0)
+ {
+ WARN("Failed to allocate Vulkan command buffer, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ list->vk_queue_flags = allocator->vk_queue_flags;
+
+ if (FAILED(hr = d3d12_command_list_begin_command_buffer(list)))
+ {
+ VK_CALL(vkFreeCommandBuffers(device->vk_device, allocator->vk_command_pool,
+ 1, &list->vk_command_buffer));
+ return hr;
+ }
+
+ allocator->current_command_list = list;
+
+ return S_OK;
+}
+
+static void d3d12_command_allocator_free_command_buffer(struct d3d12_command_allocator *allocator,
+ struct d3d12_command_list *list)
+{
+ struct d3d12_device *device = allocator->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ TRACE("allocator %p, list %p.\n", allocator, list);
+
+ if (allocator->current_command_list == list)
+ allocator->current_command_list = NULL;
+
+ if (!vkd3d_array_reserve((void **)&allocator->command_buffers, &allocator->command_buffers_size,
+ allocator->command_buffer_count + 1, sizeof(*allocator->command_buffers)))
+ {
+ WARN("Failed to add command buffer.\n");
+ VK_CALL(vkFreeCommandBuffers(device->vk_device, allocator->vk_command_pool,
+ 1, &list->vk_command_buffer));
+ return;
+ }
+
+ allocator->command_buffers[allocator->command_buffer_count++] = list->vk_command_buffer;
+}
+
+static bool d3d12_command_allocator_add_render_pass(struct d3d12_command_allocator *allocator, VkRenderPass pass)
+{
+ if (!vkd3d_array_reserve((void **)&allocator->passes, &allocator->passes_size,
+ allocator->pass_count + 1, sizeof(*allocator->passes)))
+ return false;
+
+ allocator->passes[allocator->pass_count++] = pass;
+
+ return true;
+}
+
+static bool d3d12_command_allocator_add_framebuffer(struct d3d12_command_allocator *allocator,
+ VkFramebuffer framebuffer)
+{
+ if (!vkd3d_array_reserve((void **)&allocator->framebuffers, &allocator->framebuffers_size,
+ allocator->framebuffer_count + 1, sizeof(*allocator->framebuffers)))
+ return false;
+
+ allocator->framebuffers[allocator->framebuffer_count++] = framebuffer;
+
+ return true;
+}
+
+static bool d3d12_command_allocator_add_descriptor_pool(struct d3d12_command_allocator *allocator,
+ VkDescriptorPool pool)
+{
+ if (!vkd3d_array_reserve((void **)&allocator->descriptor_pools, &allocator->descriptor_pools_size,
+ allocator->descriptor_pool_count + 1, sizeof(*allocator->descriptor_pools)))
+ return false;
+
+ allocator->descriptor_pools[allocator->descriptor_pool_count++] = pool;
+
+ return true;
+}
+
+static bool d3d12_command_allocator_add_view(struct d3d12_command_allocator *allocator,
+ struct vkd3d_view *view)
+{
+ if (!vkd3d_array_reserve((void **)&allocator->views, &allocator->views_size,
+ allocator->view_count + 1, sizeof(*allocator->views)))
+ return false;
+
+ vkd3d_view_incref(view);
+ allocator->views[allocator->view_count++] = view;
+
+ return true;
+}
+
+static bool d3d12_command_allocator_add_buffer_view(struct d3d12_command_allocator *allocator,
+ VkBufferView view)
+{
+ if (!vkd3d_array_reserve((void **)&allocator->buffer_views, &allocator->buffer_views_size,
+ allocator->buffer_view_count + 1, sizeof(*allocator->buffer_views)))
+ return false;
+
+ allocator->buffer_views[allocator->buffer_view_count++] = view;
+
+ return true;
+}
+
+static bool d3d12_command_allocator_add_transfer_buffer(struct d3d12_command_allocator *allocator,
+ const struct vkd3d_buffer *buffer)
+{
+ if (!vkd3d_array_reserve((void **)&allocator->transfer_buffers, &allocator->transfer_buffers_size,
+ allocator->transfer_buffer_count + 1, sizeof(*allocator->transfer_buffers)))
+ return false;
+
+ allocator->transfer_buffers[allocator->transfer_buffer_count++] = *buffer;
+
+ return true;
+}
+
+static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool(
+ struct d3d12_command_allocator *allocator)
+{
+ static const VkDescriptorPoolSize pool_sizes[] =
+ {
+ {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
+ {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
+ {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
+ {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
+ {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
+ {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
+ };
+ struct d3d12_device *device = allocator->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct VkDescriptorPoolCreateInfo pool_desc;
+ VkDevice vk_device = device->vk_device;
+ VkDescriptorPool vk_pool;
+ VkResult vr;
+
+ if (allocator->free_descriptor_pool_count > 0)
+ {
+ vk_pool = allocator->free_descriptor_pools[allocator->free_descriptor_pool_count - 1];
+ allocator->free_descriptor_pools[allocator->free_descriptor_pool_count - 1] = VK_NULL_HANDLE;
+ --allocator->free_descriptor_pool_count;
+ }
+ else
+ {
+ pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ pool_desc.pNext = NULL;
+ pool_desc.flags = 0;
+ pool_desc.maxSets = 512;
+ pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
+ pool_desc.pPoolSizes = pool_sizes;
+ if ((vr = VK_CALL(vkCreateDescriptorPool(vk_device, &pool_desc, NULL, &vk_pool))) < 0)
+ {
+ ERR("Failed to create descriptor pool, vr %d.\n", vr);
+ return VK_NULL_HANDLE;
+ }
+ }
+
+ if (!(d3d12_command_allocator_add_descriptor_pool(allocator, vk_pool)))
+ {
+ ERR("Failed to add descriptor pool.\n");
+ VK_CALL(vkDestroyDescriptorPool(vk_device, vk_pool, NULL));
+ return VK_NULL_HANDLE;
+ }
+
+ return vk_pool;
+}
+
+static VkDescriptorSet d3d12_command_allocator_allocate_descriptor_set(
+ struct d3d12_command_allocator *allocator, VkDescriptorSetLayout vk_set_layout)
+{
+ struct d3d12_device *device = allocator->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct VkDescriptorSetAllocateInfo set_desc;
+ VkDevice vk_device = device->vk_device;
+ VkDescriptorSet vk_descriptor_set;
+ VkResult vr;
+
+ if (!allocator->vk_descriptor_pool)
+ allocator->vk_descriptor_pool = d3d12_command_allocator_allocate_descriptor_pool(allocator);
+ if (!allocator->vk_descriptor_pool)
+ return VK_NULL_HANDLE;
+
+ set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ set_desc.pNext = NULL;
+ set_desc.descriptorPool = allocator->vk_descriptor_pool;
+ set_desc.descriptorSetCount = 1;
+ set_desc.pSetLayouts = &vk_set_layout;
+ if ((vr = VK_CALL(vkAllocateDescriptorSets(vk_device, &set_desc, &vk_descriptor_set))) >= 0)
+ return vk_descriptor_set;
+
+ allocator->vk_descriptor_pool = VK_NULL_HANDLE;
+ if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY_KHR)
+ allocator->vk_descriptor_pool = d3d12_command_allocator_allocate_descriptor_pool(allocator);
+ if (!allocator->vk_descriptor_pool)
+ {
+ ERR("Failed to allocate descriptor set, vr %d.\n", vr);
+ return VK_NULL_HANDLE;
+ }
+
+ set_desc.descriptorPool = allocator->vk_descriptor_pool;
+ if ((vr = VK_CALL(vkAllocateDescriptorSets(vk_device, &set_desc, &vk_descriptor_set))) < 0)
+ {
+ FIXME("Failed to allocate descriptor set from a new pool, vr %d.\n", vr);
+ return VK_NULL_HANDLE;
+ }
+
+ return vk_descriptor_set;
+}
+
+static void d3d12_command_list_allocator_destroyed(struct d3d12_command_list *list)
+{
+ TRACE("list %p.\n", list);
+
+ list->allocator = NULL;
+ list->vk_command_buffer = VK_NULL_HANDLE;
+}
+
+static void vkd3d_buffer_destroy(struct vkd3d_buffer *buffer, struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ VK_CALL(vkFreeMemory(device->vk_device, buffer->vk_memory, NULL));
+ VK_CALL(vkDestroyBuffer(device->vk_device, buffer->vk_buffer, NULL));
+}
+
+static void d3d12_command_allocator_free_resources(struct d3d12_command_allocator *allocator,
+ bool keep_reusable_resources)
+{
+ struct d3d12_device *device = allocator->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ unsigned int i, j;
+
+ allocator->vk_descriptor_pool = VK_NULL_HANDLE;
+
+ if (keep_reusable_resources)
+ {
+ if (vkd3d_array_reserve((void **)&allocator->free_descriptor_pools,
+ &allocator->free_descriptor_pools_size,
+ allocator->free_descriptor_pool_count + allocator->descriptor_pool_count,
+ sizeof(*allocator->free_descriptor_pools)))
+ {
+ for (i = 0, j = allocator->free_descriptor_pool_count; i < allocator->descriptor_pool_count; ++i, ++j)
+ {
+ VK_CALL(vkResetDescriptorPool(device->vk_device, allocator->descriptor_pools[i], 0));
+ allocator->free_descriptor_pools[j] = allocator->descriptor_pools[i];
+ }
+ allocator->free_descriptor_pool_count += allocator->descriptor_pool_count;
+ allocator->descriptor_pool_count = 0;
+ }
+ }
+ else
+ {
+ for (i = 0; i < allocator->free_descriptor_pool_count; ++i)
+ {
+ VK_CALL(vkDestroyDescriptorPool(device->vk_device, allocator->free_descriptor_pools[i], NULL));
+ }
+ allocator->free_descriptor_pool_count = 0;
+ }
+
+ for (i = 0; i < allocator->transfer_buffer_count; ++i)
+ {
+ vkd3d_buffer_destroy(&allocator->transfer_buffers[i], device);
+ }
+ allocator->transfer_buffer_count = 0;
+
+ for (i = 0; i < allocator->buffer_view_count; ++i)
+ {
+ VK_CALL(vkDestroyBufferView(device->vk_device, allocator->buffer_views[i], NULL));
+ }
+ allocator->buffer_view_count = 0;
+
+ for (i = 0; i < allocator->view_count; ++i)
+ {
+ vkd3d_view_decref(allocator->views[i], device);
+ }
+ allocator->view_count = 0;
+
+ for (i = 0; i < allocator->descriptor_pool_count; ++i)
+ {
+ VK_CALL(vkDestroyDescriptorPool(device->vk_device, allocator->descriptor_pools[i], NULL));
+ }
+ allocator->descriptor_pool_count = 0;
+
+ for (i = 0; i < allocator->framebuffer_count; ++i)
+ {
+ VK_CALL(vkDestroyFramebuffer(device->vk_device, allocator->framebuffers[i], NULL));
+ }
+ allocator->framebuffer_count = 0;
+
+ for (i = 0; i < allocator->pass_count; ++i)
+ {
+ VK_CALL(vkDestroyRenderPass(device->vk_device, allocator->passes[i], NULL));
+ }
+ allocator->pass_count = 0;
+}
+
+/* ID3D12CommandAllocator */
+static inline struct d3d12_command_allocator *impl_from_ID3D12CommandAllocator(ID3D12CommandAllocator *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_command_allocator, ID3D12CommandAllocator_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_QueryInterface(ID3D12CommandAllocator *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12CommandAllocator)
+ || IsEqualGUID(riid, &IID_ID3D12Pageable)
+ || IsEqualGUID(riid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12CommandAllocator_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_command_allocator_AddRef(ID3D12CommandAllocator *iface)
+{
+ struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+ ULONG refcount = InterlockedIncrement(&allocator->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", allocator, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_command_allocator_Release(ID3D12CommandAllocator *iface)
+{
+ struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+ ULONG refcount = InterlockedDecrement(&allocator->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", allocator, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = allocator->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ vkd3d_private_store_destroy(&allocator->private_store);
+
+ if (allocator->current_command_list)
+ d3d12_command_list_allocator_destroyed(allocator->current_command_list);
+
+ d3d12_command_allocator_free_resources(allocator, false);
+ vkd3d_free(allocator->transfer_buffers);
+ vkd3d_free(allocator->buffer_views);
+ vkd3d_free(allocator->views);
+ vkd3d_free(allocator->descriptor_pools);
+ vkd3d_free(allocator->free_descriptor_pools);
+ vkd3d_free(allocator->framebuffers);
+ vkd3d_free(allocator->passes);
+
+ /* All command buffers are implicitly freed when a pool is destroyed. */
+ vkd3d_free(allocator->command_buffers);
+ VK_CALL(vkDestroyCommandPool(device->vk_device, allocator->vk_command_pool, NULL));
+
+ vkd3d_free(allocator);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_GetPrivateData(ID3D12CommandAllocator *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&allocator->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_SetPrivateData(ID3D12CommandAllocator *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&allocator->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_SetPrivateDataInterface(ID3D12CommandAllocator *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&allocator->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_SetName(ID3D12CommandAllocator *iface, const WCHAR *name)
+{
+ struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, allocator->device->wchar_size));
+
+ return vkd3d_set_vk_object_name(allocator->device, (uint64_t)allocator->vk_command_pool,
+ VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, name);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_GetDevice(ID3D12CommandAllocator *iface, REFIID iid, void **device)
+{
+ struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(allocator->device, iid, device);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_Reset(ID3D12CommandAllocator *iface)
+{
+ struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ struct d3d12_command_list *list;
+ struct d3d12_device *device;
+ VkResult vr;
+
+ TRACE("iface %p.\n", iface);
+
+ if ((list = allocator->current_command_list))
+ {
+ if (list->is_recording)
+ {
+ WARN("A command list using this allocator is in the recording state.\n");
+ return E_FAIL;
+ }
+
+ TRACE("Resetting command list %p.\n", list);
+ }
+
+ device = allocator->device;
+ vk_procs = &device->vk_procs;
+
+ d3d12_command_allocator_free_resources(allocator, true);
+ if (allocator->command_buffer_count)
+ {
+ VK_CALL(vkFreeCommandBuffers(device->vk_device, allocator->vk_command_pool,
+ allocator->command_buffer_count, allocator->command_buffers));
+ allocator->command_buffer_count = 0;
+ }
+
+ /* The intent here is to recycle memory, so do not use RELEASE_RESOURCES_BIT here. */
+ if ((vr = VK_CALL(vkResetCommandPool(device->vk_device, allocator->vk_command_pool, 0))))
+ {
+ WARN("Resetting command pool failed, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ return S_OK;
+}
+
+static const struct ID3D12CommandAllocatorVtbl d3d12_command_allocator_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_command_allocator_QueryInterface,
+ d3d12_command_allocator_AddRef,
+ d3d12_command_allocator_Release,
+ /* ID3D12Object methods */
+ d3d12_command_allocator_GetPrivateData,
+ d3d12_command_allocator_SetPrivateData,
+ d3d12_command_allocator_SetPrivateDataInterface,
+ d3d12_command_allocator_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_command_allocator_GetDevice,
+ /* ID3D12CommandAllocator methods */
+ d3d12_command_allocator_Reset,
+};
+
+static struct d3d12_command_allocator *unsafe_impl_from_ID3D12CommandAllocator(ID3D12CommandAllocator *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_command_allocator_vtbl);
+ return impl_from_ID3D12CommandAllocator(iface);
+}
+
+struct vkd3d_queue *d3d12_device_get_vkd3d_queue(struct d3d12_device *device,
+ D3D12_COMMAND_LIST_TYPE type)
+{
+ switch (type)
+ {
+ case D3D12_COMMAND_LIST_TYPE_DIRECT:
+ return device->direct_queue;
+ case D3D12_COMMAND_LIST_TYPE_COMPUTE:
+ return device->compute_queue;
+ case D3D12_COMMAND_LIST_TYPE_COPY:
+ return device->copy_queue;
+ default:
+ FIXME("Unhandled command list type %#x.\n", type);
+ return NULL;
+ }
+}
+
+static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allocator,
+ struct d3d12_device *device, D3D12_COMMAND_LIST_TYPE type)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkCommandPoolCreateInfo command_pool_info;
+ struct vkd3d_queue *queue;
+ VkResult vr;
+ HRESULT hr;
+
+ if (FAILED(hr = vkd3d_private_store_init(&allocator->private_store)))
+ return hr;
+
+ if (!(queue = d3d12_device_get_vkd3d_queue(device, type)))
+ queue = device->direct_queue;
+
+ allocator->ID3D12CommandAllocator_iface.lpVtbl = &d3d12_command_allocator_vtbl;
+ allocator->refcount = 1;
+
+ allocator->type = type;
+ allocator->vk_queue_flags = queue->vk_queue_flags;
+
+ command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ command_pool_info.pNext = NULL;
+ /* Do not use RESET_COMMAND_BUFFER_BIT. This allows the CommandPool to be a D3D12-style command pool.
+ * Memory is owned by the pool and CommandBuffers become lightweight handles,
+ * assuming a half-decent driver implementation. */
+ command_pool_info.flags = 0;
+ command_pool_info.queueFamilyIndex = queue->vk_family_index;
+
+ if ((vr = VK_CALL(vkCreateCommandPool(device->vk_device, &command_pool_info, NULL,
+ &allocator->vk_command_pool))) < 0)
+ {
+ WARN("Failed to create Vulkan command pool, vr %d.\n", vr);
+ vkd3d_private_store_destroy(&allocator->private_store);
+ return hresult_from_vk_result(vr);
+ }
+
+ allocator->vk_descriptor_pool = VK_NULL_HANDLE;
+
+ allocator->free_descriptor_pools = NULL;
+ allocator->free_descriptor_pools_size = 0;
+ allocator->free_descriptor_pool_count = 0;
+
+ allocator->passes = NULL;
+ allocator->passes_size = 0;
+ allocator->pass_count = 0;
+
+ allocator->framebuffers = NULL;
+ allocator->framebuffers_size = 0;
+ allocator->framebuffer_count = 0;
+
+ allocator->descriptor_pools = NULL;
+ allocator->descriptor_pools_size = 0;
+ allocator->descriptor_pool_count = 0;
+
+ allocator->views = NULL;
+ allocator->views_size = 0;
+ allocator->view_count = 0;
+
+ allocator->buffer_views = NULL;
+ allocator->buffer_views_size = 0;
+ allocator->buffer_view_count = 0;
+
+ allocator->transfer_buffers = NULL;
+ allocator->transfer_buffers_size = 0;
+ allocator->transfer_buffer_count = 0;
+
+ allocator->command_buffers = NULL;
+ allocator->command_buffers_size = 0;
+ allocator->command_buffer_count = 0;
+
+ allocator->current_command_list = NULL;
+
+ d3d12_device_add_ref(allocator->device = device);
+
+ return S_OK;
+}
+
+HRESULT d3d12_command_allocator_create(struct d3d12_device *device,
+ D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_allocator **allocator)
+{
+ struct d3d12_command_allocator *object;
+ HRESULT hr;
+
+ if (!(D3D12_COMMAND_LIST_TYPE_DIRECT <= type && type <= D3D12_COMMAND_LIST_TYPE_COPY))
+ {
+ WARN("Invalid type %#x.\n", type);
+ return E_INVALIDARG;
+ }
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_command_allocator_init(object, device, type)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created command allocator %p.\n", object);
+
+ *allocator = object;
+
+ return S_OK;
+}
+
+/* ID3D12CommandList */
+static inline struct d3d12_command_list *impl_from_ID3D12GraphicsCommandList2(ID3D12GraphicsCommandList2 *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandList2_iface);
+}
+
+static void d3d12_command_list_invalidate_current_framebuffer(struct d3d12_command_list *list)
+{
+ list->current_framebuffer = VK_NULL_HANDLE;
+}
+
+static void d3d12_command_list_invalidate_current_pipeline(struct d3d12_command_list *list)
+{
+ list->current_pipeline = VK_NULL_HANDLE;
+}
+
+static void d3d12_command_list_end_current_render_pass(struct d3d12_command_list *list)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+
+ if (list->xfb_enabled)
+ {
+ VK_CALL(vkCmdEndTransformFeedbackEXT(list->vk_command_buffer, 0, ARRAY_SIZE(list->so_counter_buffers),
+ list->so_counter_buffers, list->so_counter_buffer_offsets));
+ }
+
+ if (list->current_render_pass)
+ VK_CALL(vkCmdEndRenderPass(list->vk_command_buffer));
+
+ list->current_render_pass = VK_NULL_HANDLE;
+
+ if (list->xfb_enabled)
+ {
+ VkMemoryBarrier vk_barrier;
+
+ /* We need a barrier between pause and resume. */
+ vk_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ vk_barrier.pNext = NULL;
+ vk_barrier.srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
+ vk_barrier.dstAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT;
+ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
+ VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0,
+ 1, &vk_barrier, 0, NULL, 0, NULL));
+
+ list->xfb_enabled = false;
+ }
+}
+
+static void d3d12_command_list_invalidate_current_render_pass(struct d3d12_command_list *list)
+{
+ d3d12_command_list_end_current_render_pass(list);
+}
+
+static void d3d12_command_list_invalidate_bindings(struct d3d12_command_list *list,
+ struct d3d12_pipeline_state *state)
+{
+ if (state && state->uav_counter_count)
+ {
+ enum vkd3d_pipeline_bind_point bind_point = (enum vkd3d_pipeline_bind_point)state->vk_bind_point;
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+
+ vkd3d_array_reserve((void **)&bindings->vk_uav_counter_views, &bindings->vk_uav_counter_views_size,
+ state->uav_counter_count, sizeof(*bindings->vk_uav_counter_views));
+ bindings->uav_counters_dirty = true;
+ }
+}
+
+static void d3d12_command_list_invalidate_root_parameters(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+
+ if (!bindings->root_signature)
+ return;
+
+ bindings->descriptor_set = VK_NULL_HANDLE;
+ bindings->descriptor_table_dirty_mask = bindings->descriptor_table_active_mask & bindings->root_signature->descriptor_table_mask;
+ bindings->push_descriptor_dirty_mask = bindings->push_descriptor_active_mask & bindings->root_signature->push_descriptor_mask;
+}
+
+static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state, unsigned int stencil_state,
+ const struct d3d12_resource *resource, VkQueueFlags vk_queue_flags, const struct vkd3d_vulkan_info *vk_info,
+ VkAccessFlags *access_mask, VkPipelineStageFlags *stage_flags, VkImageLayout *image_layout)
+{
+ bool is_swapchain_image = resource && (resource->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION);
+ VkPipelineStageFlags queue_shader_stages = 0;
+
+ if (vk_queue_flags & VK_QUEUE_GRAPHICS_BIT)
+ {
+ queue_shader_stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
+ | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
+ | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
+ | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
+ | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ }
+ if (vk_queue_flags & VK_QUEUE_COMPUTE_BIT)
+ queue_shader_stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+
+ switch (state)
+ {
+ case D3D12_RESOURCE_STATE_COMMON: /* D3D12_RESOURCE_STATE_PRESENT */
+ /* The COMMON state is used for ownership transfer between
+ * DIRECT/COMPUTE and COPY queues. Additionally, a texture has to
+ * be in the COMMON state to be accessed by CPU. Moreover,
+ * resources can be implicitly promoted to other states out of the
+ * COMMON state, and the resource state can decay to the COMMON
+ * state when GPU finishes execution of a command list. */
+ if (is_swapchain_image)
+ {
+ if (resource->present_state == D3D12_RESOURCE_STATE_PRESENT)
+ {
+ *access_mask = VK_ACCESS_MEMORY_READ_BIT;
+ *stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ return true;
+ }
+ else if (resource->present_state != D3D12_RESOURCE_STATE_COMMON)
+ {
+ vk_barrier_parameters_from_d3d12_resource_state(resource->present_state, 0,
+ resource, vk_queue_flags, vk_info, access_mask, stage_flags, image_layout);
+ return true;
+ }
+ }
+
+ *access_mask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
+ *stage_flags = VK_PIPELINE_STAGE_HOST_BIT;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_GENERAL;
+ return true;
+
+ /* Handle write states. */
+ case D3D12_RESOURCE_STATE_RENDER_TARGET:
+ *access_mask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
+ | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ *stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ return true;
+
+ case D3D12_RESOURCE_STATE_UNORDERED_ACCESS:
+ *access_mask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ *stage_flags = queue_shader_stages;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_GENERAL;
+ return true;
+
+ case D3D12_RESOURCE_STATE_DEPTH_WRITE:
+ *access_mask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
+ | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ *stage_flags = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
+ | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ if (image_layout)
+ {
+ if (!stencil_state || (stencil_state & D3D12_RESOURCE_STATE_DEPTH_WRITE))
+ *image_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ else
+ *image_layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
+ }
+ return true;
+
+ case D3D12_RESOURCE_STATE_COPY_DEST:
+ case D3D12_RESOURCE_STATE_RESOLVE_DEST:
+ *access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ *stage_flags = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ return true;
+
+ case D3D12_RESOURCE_STATE_STREAM_OUT:
+ *access_mask = VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
+ | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
+ | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
+ *stage_flags = VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
+ | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
+ return true;
+
+ /* Set the Vulkan image layout for read-only states. */
+ case D3D12_RESOURCE_STATE_DEPTH_READ:
+ case D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE:
+ case D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE:
+ case D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
+ | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE:
+ *access_mask = 0;
+ *stage_flags = 0;
+ if (image_layout)
+ {
+ if (stencil_state & D3D12_RESOURCE_STATE_DEPTH_WRITE)
+ {
+ *image_layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
+ *access_mask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ }
+ else
+ {
+ *image_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
+ }
+ }
+ break;
+
+ case D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE:
+ case D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE:
+ case D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE:
+ *access_mask = 0;
+ *stage_flags = 0;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ break;
+
+ case D3D12_RESOURCE_STATE_COPY_SOURCE:
+ case D3D12_RESOURCE_STATE_RESOLVE_SOURCE:
+ *access_mask = 0;
+ *stage_flags = 0;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ break;
+
+ default:
+ *access_mask = 0;
+ *stage_flags = 0;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_GENERAL;
+ break;
+ }
+
+ /* Handle read-only states. */
+ assert(!is_write_resource_state(state));
+
+ if (state & D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER)
+ {
+ *access_mask |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
+ | VK_ACCESS_UNIFORM_READ_BIT;
+ *stage_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
+ | queue_shader_stages;
+ state &= ~D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
+ }
+
+ if (state & D3D12_RESOURCE_STATE_INDEX_BUFFER)
+ {
+ *access_mask |= VK_ACCESS_INDEX_READ_BIT;
+ *stage_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ state &= ~D3D12_RESOURCE_STATE_INDEX_BUFFER;
+ }
+
+ if (state & D3D12_RESOURCE_STATE_DEPTH_READ)
+ {
+ *access_mask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+ *stage_flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
+ | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ state &= ~D3D12_RESOURCE_STATE_DEPTH_READ;
+ }
+
+ if (state & D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
+ {
+ *access_mask |= VK_ACCESS_SHADER_READ_BIT;
+ *stage_flags |= (queue_shader_stages & ~VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+ state &= ~D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ }
+ if (state & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)
+ {
+ *access_mask |= VK_ACCESS_SHADER_READ_BIT;
+ *stage_flags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ state &= ~D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
+ }
+
+ if (state & D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT) /* D3D12_RESOURCE_STATE_PREDICATION */
+ {
+ *access_mask |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+ *stage_flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ if (vk_info->EXT_conditional_rendering)
+ {
+ *access_mask |= VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT;
+ *stage_flags |= VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT;
+ }
+ state &= ~D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
+ }
+
+ if (state & (D3D12_RESOURCE_STATE_COPY_SOURCE | D3D12_RESOURCE_STATE_RESOLVE_SOURCE))
+ {
+ *access_mask |= VK_ACCESS_TRANSFER_READ_BIT;
+ *stage_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ state &= ~(D3D12_RESOURCE_STATE_COPY_SOURCE | D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
+ }
+
+ if (state)
+ {
+ WARN("Invalid resource state %#x.\n", state);
+ return false;
+ }
+ return true;
+}
+
+static void d3d12_command_list_transition_resource_to_initial_state(struct d3d12_command_list *list,
+ struct d3d12_resource *resource)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ const struct vkd3d_vulkan_info *vk_info = &list->device->vk_info;
+ VkPipelineStageFlags src_stage_mask, dst_stage_mask;
+ const struct vkd3d_format *format;
+ VkImageMemoryBarrier barrier;
+
+ assert(d3d12_resource_is_texture(resource));
+
+ if (!(format = vkd3d_format_from_d3d12_resource_desc(list->device, &resource->desc, 0)))
+ {
+ ERR("Resource %p has invalid format %#x.\n", resource, resource->desc.Format);
+ return;
+ }
+
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.pNext = NULL;
+
+ /* vkQueueSubmit() defines a memory dependency with prior host writes. */
+ src_stage_mask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ barrier.srcAccessMask = 0;
+ barrier.oldLayout = d3d12_resource_is_cpu_accessible(resource) ?
+ VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED;
+
+ if (!vk_barrier_parameters_from_d3d12_resource_state(resource->initial_state, 0,
+ resource, list->vk_queue_flags, vk_info, &barrier.dstAccessMask, &dst_stage_mask, &barrier.newLayout))
+ {
+ FIXME("Unhandled state %#x.\n", resource->initial_state);
+ return;
+ }
+
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = resource->u.vk_image;
+ barrier.subresourceRange.aspectMask = format->vk_aspect_mask;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+
+ TRACE("Initial state %#x transition for resource %p (old layout %#x, new layout %#x).\n",
+ resource->initial_state, resource, barrier.oldLayout, barrier.newLayout);
+
+ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, src_stage_mask, dst_stage_mask, 0,
+ 0, NULL, 0, NULL, 1, &barrier));
+}
+
+static void d3d12_command_list_track_resource_usage(struct d3d12_command_list *list,
+ struct d3d12_resource *resource)
+{
+ if (resource->flags & VKD3D_RESOURCE_INITIAL_STATE_TRANSITION)
+ {
+ d3d12_command_list_end_current_render_pass(list);
+
+ d3d12_command_list_transition_resource_to_initial_state(list, resource);
+ resource->flags &= ~VKD3D_RESOURCE_INITIAL_STATE_TRANSITION;
+ }
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(ID3D12GraphicsCommandList2 *iface,
+ REFIID iid, void **object)
+{
+ TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
+
+ if (IsEqualGUID(iid, &IID_ID3D12GraphicsCommandList2)
+ || IsEqualGUID(iid, &IID_ID3D12GraphicsCommandList1)
+ || IsEqualGUID(iid, &IID_ID3D12GraphicsCommandList)
+ || IsEqualGUID(iid, &IID_ID3D12CommandList)
+ || IsEqualGUID(iid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(iid, &IID_ID3D12Object)
+ || IsEqualGUID(iid, &IID_IUnknown))
+ {
+ ID3D12GraphicsCommandList2_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_command_list_AddRef(ID3D12GraphicsCommandList2 *iface)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ ULONG refcount = InterlockedIncrement(&list->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", list, refcount);
+
+ return refcount;
+}
+
+static void vkd3d_pipeline_bindings_cleanup(struct vkd3d_pipeline_bindings *bindings)
+{
+ vkd3d_free(bindings->vk_uav_counter_views);
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(ID3D12GraphicsCommandList2 *iface)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ ULONG refcount = InterlockedDecrement(&list->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", list, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = list->device;
+
+ vkd3d_private_store_destroy(&list->private_store);
+
+ /* When command pool is destroyed, all command buffers are implicitly freed. */
+ if (list->allocator)
+ d3d12_command_allocator_free_command_buffer(list->allocator, list);
+
+ vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE]);
+ vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS]);
+
+ vkd3d_free(list);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_GetPrivateData(ID3D12GraphicsCommandList2 *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&list->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_SetPrivateData(ID3D12GraphicsCommandList2 *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&list->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_SetPrivateDataInterface(ID3D12GraphicsCommandList2 *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&list->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_SetName(ID3D12GraphicsCommandList2 *iface, const WCHAR *name)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, list->device->wchar_size));
+
+ return name ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_GetDevice(ID3D12GraphicsCommandList2 *iface, REFIID iid, void **device)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(list->device, iid, device);
+}
+
+static D3D12_COMMAND_LIST_TYPE STDMETHODCALLTYPE d3d12_command_list_GetType(ID3D12GraphicsCommandList2 *iface)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ return list->type;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_Close(ID3D12GraphicsCommandList2 *iface)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkResult vr;
+
+ TRACE("iface %p.\n", iface);
+
+ if (!list->is_recording)
+ {
+ WARN("Command list is not in the recording state.\n");
+ return E_FAIL;
+ }
+
+ vk_procs = &list->device->vk_procs;
+
+ d3d12_command_list_end_current_render_pass(list);
+ if (list->is_predicated)
+ VK_CALL(vkCmdEndConditionalRenderingEXT(list->vk_command_buffer));
+
+ if ((vr = VK_CALL(vkEndCommandBuffer(list->vk_command_buffer))) < 0)
+ {
+ WARN("Failed to end command buffer, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ if (list->allocator)
+ {
+ d3d12_command_allocator_free_command_buffer(list->allocator, list);
+ list->allocator = NULL;
+ }
+
+ list->is_recording = false;
+
+ if (!list->is_valid)
+ {
+ WARN("Error occurred during command list recording.\n");
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
+}
+
+static void d3d12_command_list_reset_state(struct d3d12_command_list *list,
+ ID3D12PipelineState *initial_pipeline_state)
+{
+ ID3D12GraphicsCommandList2 *iface = &list->ID3D12GraphicsCommandList2_iface;
+
+ memset(list->strides, 0, sizeof(list->strides));
+ list->primitive_topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
+
+ list->index_buffer_format = DXGI_FORMAT_UNKNOWN;
+
+ memset(list->rtvs, 0, sizeof(list->rtvs));
+ list->dsv = VK_NULL_HANDLE;
+ list->dsv_format = VK_FORMAT_UNDEFINED;
+ list->fb_width = 0;
+ list->fb_height = 0;
+ list->fb_layer_count = 0;
+
+ list->xfb_enabled = false;
+
+ list->is_predicated = false;
+
+ list->current_framebuffer = VK_NULL_HANDLE;
+ list->current_pipeline = VK_NULL_HANDLE;
+ list->pso_render_pass = VK_NULL_HANDLE;
+ list->current_render_pass = VK_NULL_HANDLE;
+
+ vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE]);
+ vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS]);
+ memset(list->pipeline_bindings, 0, sizeof(list->pipeline_bindings));
+ list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS].vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE].vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
+
+ list->state = NULL;
+
+ memset(list->so_counter_buffers, 0, sizeof(list->so_counter_buffers));
+ memset(list->so_counter_buffer_offsets, 0, sizeof(list->so_counter_buffer_offsets));
+
+ ID3D12GraphicsCommandList2_SetPipelineState(iface, initial_pipeline_state);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_Reset(ID3D12GraphicsCommandList2 *iface,
+ ID3D12CommandAllocator *allocator, ID3D12PipelineState *initial_pipeline_state)
+{
+ struct d3d12_command_allocator *allocator_impl = unsafe_impl_from_ID3D12CommandAllocator(allocator);
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ HRESULT hr;
+
+ TRACE("iface %p, allocator %p, initial_pipeline_state %p.\n",
+ iface, allocator, initial_pipeline_state);
+
+ if (!allocator_impl)
+ {
+ WARN("Command allocator is NULL.\n");
+ return E_INVALIDARG;
+ }
+
+ if (list->is_recording)
+ {
+ WARN("Command list is in the recording state.\n");
+ return E_FAIL;
+ }
+
+ if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator_impl, list)))
+ {
+ list->allocator = allocator_impl;
+ d3d12_command_list_reset_state(list, initial_pipeline_state);
+ }
+
+ return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_list_ClearState(ID3D12GraphicsCommandList2 *iface,
+ ID3D12PipelineState *pipeline_state)
+{
+ FIXME("iface %p, pipline_state %p stub!\n", iface, pipeline_state);
+
+ return E_NOTIMPL;
+}
+
+static bool d3d12_command_list_has_depth_stencil_view(struct d3d12_command_list *list)
+{
+ struct d3d12_graphics_pipeline_state *graphics;
+
+ assert(d3d12_pipeline_state_is_graphics(list->state));
+ graphics = &list->state->u.graphics;
+
+ return graphics->dsv_format || (d3d12_pipeline_state_has_unknown_dsv_format(list->state) && list->dsv_format);
+}
+
+static void d3d12_command_list_get_fb_extent(struct d3d12_command_list *list,
+ uint32_t *width, uint32_t *height, uint32_t *layer_count)
+{
+ struct d3d12_graphics_pipeline_state *graphics = &list->state->u.graphics;
+ struct d3d12_device *device = list->device;
+
+ if (graphics->rt_count || d3d12_command_list_has_depth_stencil_view(list))
+ {
+ *width = list->fb_width;
+ *height = list->fb_height;
+ if (layer_count)
+ *layer_count = list->fb_layer_count;
+ }
+ else
+ {
+ *width = device->vk_info.device_limits.maxFramebufferWidth;
+ *height = device->vk_info.device_limits.maxFramebufferHeight;
+ if (layer_count)
+ *layer_count = 1;
+ }
+}
+
+static bool d3d12_command_list_update_current_framebuffer(struct d3d12_command_list *list)
+{
+ struct d3d12_device *device = list->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkImageView views[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT + 1];
+ struct d3d12_graphics_pipeline_state *graphics;
+ struct VkFramebufferCreateInfo fb_desc;
+ VkFramebuffer vk_framebuffer;
+ unsigned int view_count;
+ unsigned int i;
+ VkResult vr;
+
+ if (list->current_framebuffer != VK_NULL_HANDLE)
+ return true;
+
+ graphics = &list->state->u.graphics;
+
+ for (i = 0, view_count = 0; i < graphics->rt_count; ++i)
+ {
+ if (graphics->null_attachment_mask & (1u << i))
+ {
+ if (list->rtvs[i])
+ WARN("Expected NULL RTV for attachment %u.\n", i);
+ continue;
+ }
+
+ if (!list->rtvs[i])
+ {
+ FIXME("Invalid RTV for attachment %u.\n", i);
+ return false;
+ }
+
+ views[view_count++] = list->rtvs[i];
+ }
+
+ if (d3d12_command_list_has_depth_stencil_view(list))
+ {
+ if (!(views[view_count++] = list->dsv))
+ {
+ FIXME("Invalid DSV.\n");
+ return false;
+ }
+ }
+
+ fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fb_desc.pNext = NULL;
+ fb_desc.flags = 0;
+ fb_desc.renderPass = list->pso_render_pass;
+ fb_desc.attachmentCount = view_count;
+ fb_desc.pAttachments = views;
+ d3d12_command_list_get_fb_extent(list, &fb_desc.width, &fb_desc.height, &fb_desc.layers);
+ if ((vr = VK_CALL(vkCreateFramebuffer(device->vk_device, &fb_desc, NULL, &vk_framebuffer))) < 0)
+ {
+ WARN("Failed to create Vulkan framebuffer, vr %d.\n", vr);
+ return false;
+ }
+
+ if (!d3d12_command_allocator_add_framebuffer(list->allocator, vk_framebuffer))
+ {
+ WARN("Failed to add framebuffer.\n");
+ VK_CALL(vkDestroyFramebuffer(device->vk_device, vk_framebuffer, NULL));
+ return false;
+ }
+
+ list->current_framebuffer = vk_framebuffer;
+
+ return true;
+}
+
+static bool d3d12_command_list_update_compute_pipeline(struct d3d12_command_list *list)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+
+ if (list->current_pipeline != VK_NULL_HANDLE)
+ return true;
+
+ if (!d3d12_pipeline_state_is_compute(list->state))
+ {
+ WARN("Pipeline state %p is not a compute pipeline.\n", list->state);
+ return false;
+ }
+
+ VK_CALL(vkCmdBindPipeline(list->vk_command_buffer, list->state->vk_bind_point, list->state->u.compute.vk_pipeline));
+ list->current_pipeline = list->state->u.compute.vk_pipeline;
+
+ return true;
+}
+
+static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_list *list)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ VkRenderPass vk_render_pass;
+ VkPipeline vk_pipeline;
+
+ if (list->current_pipeline != VK_NULL_HANDLE)
+ return true;
+
+ if (!d3d12_pipeline_state_is_graphics(list->state))
+ {
+ WARN("Pipeline state %p is not a graphics pipeline.\n", list->state);
+ return false;
+ }
+
+ if (!(vk_pipeline = d3d12_pipeline_state_get_or_create_pipeline(list->state,
+ list->primitive_topology, list->strides, list->dsv_format, &vk_render_pass)))
+ return false;
+
+ /* The render pass cache ensures that we use the same Vulkan render pass
+ * object for compatible render passes. */
+ if (list->pso_render_pass != vk_render_pass)
+ {
+ list->pso_render_pass = vk_render_pass;
+ d3d12_command_list_invalidate_current_framebuffer(list);
+ d3d12_command_list_invalidate_current_render_pass(list);
+ }
+
+ VK_CALL(vkCmdBindPipeline(list->vk_command_buffer, list->state->vk_bind_point, vk_pipeline));
+ list->current_pipeline = vk_pipeline;
+
+ return true;
+}
+
+static void d3d12_command_list_prepare_descriptors(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+ const struct d3d12_root_signature *root_signature = bindings->root_signature;
+
+ if (bindings->descriptor_set && !bindings->in_use)
+ return;
+
+ /* We cannot modify bound descriptor sets. We need a new descriptor set if
+ * we are about to update resource bindings.
+ *
+ * The Vulkan spec says:
+ *
+ * "The descriptor set contents bound by a call to
+ * vkCmdBindDescriptorSets may be consumed during host execution of the
+ * command, or during shader execution of the resulting draws, or any
+ * time in between. Thus, the contents must not be altered (overwritten
+ * by an update command, or freed) between when the command is recorded
+ * and when the command completes executing on the queue."
+ */
+ bindings->descriptor_set = d3d12_command_allocator_allocate_descriptor_set(list->allocator,
+ root_signature->vk_set_layout);
+ bindings->in_use = false;
+
+ bindings->descriptor_table_dirty_mask |= bindings->descriptor_table_active_mask & root_signature->descriptor_table_mask;
+ bindings->push_descriptor_dirty_mask |= bindings->push_descriptor_active_mask & root_signature->push_descriptor_mask;
+}
+
+static bool vk_write_descriptor_set_from_d3d12_desc(VkWriteDescriptorSet *vk_descriptor_write,
+ VkDescriptorImageInfo *vk_image_info, const struct d3d12_desc *descriptor,
+ uint32_t descriptor_range_magic, VkDescriptorSet vk_descriptor_set,
+ uint32_t vk_binding, unsigned int index)
+{
+ const struct vkd3d_view *view = descriptor->u.view;
+
+ if (descriptor->magic != descriptor_range_magic)
+ return false;
+
+ vk_descriptor_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ vk_descriptor_write->pNext = NULL;
+ vk_descriptor_write->dstSet = vk_descriptor_set;
+ vk_descriptor_write->dstBinding = vk_binding + index;
+ vk_descriptor_write->dstArrayElement = 0;
+ vk_descriptor_write->descriptorCount = 1;
+ vk_descriptor_write->descriptorType = descriptor->vk_descriptor_type;
+ vk_descriptor_write->pImageInfo = NULL;
+ vk_descriptor_write->pBufferInfo = NULL;
+ vk_descriptor_write->pTexelBufferView = NULL;
+
+ switch (descriptor->magic)
+ {
+ case VKD3D_DESCRIPTOR_MAGIC_CBV:
+ vk_descriptor_write->pBufferInfo = &descriptor->u.vk_cbv_info;
+ break;
+
+ case VKD3D_DESCRIPTOR_MAGIC_SRV:
+ case VKD3D_DESCRIPTOR_MAGIC_UAV:
+ /* We use separate bindings for buffer and texture SRVs/UAVs.
+ * See d3d12_root_signature_init(). */
+ vk_descriptor_write->dstBinding = vk_binding + 2 * index;
+ if (descriptor->vk_descriptor_type != VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
+ && descriptor->vk_descriptor_type != VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
+ ++vk_descriptor_write->dstBinding;
+
+ if (descriptor->vk_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
+ || descriptor->vk_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
+ {
+ vk_descriptor_write->pTexelBufferView = &view->u.vk_buffer_view;
+ }
+ else
+ {
+ vk_image_info->sampler = VK_NULL_HANDLE;
+ vk_image_info->imageView = view->u.vk_image_view;
+ vk_image_info->imageLayout = descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SRV
+ ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL;
+
+ vk_descriptor_write->pImageInfo = vk_image_info;
+ }
+ break;
+
+ case VKD3D_DESCRIPTOR_MAGIC_SAMPLER:
+ vk_image_info->sampler = view->u.vk_sampler;
+ vk_image_info->imageView = VK_NULL_HANDLE;
+ vk_image_info->imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ vk_descriptor_write->pImageInfo = vk_image_info;
+ break;
+
+ default:
+ ERR("Invalid descriptor %#x.\n", descriptor->magic);
+ return false;
+ }
+
+ return true;
+}
+
+static void d3d12_command_list_update_descriptor_table(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point, unsigned int index, struct d3d12_desc *base_descriptor)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+ struct VkWriteDescriptorSet descriptor_writes[24], *current_descriptor_write;
+ const struct d3d12_root_signature *root_signature = bindings->root_signature;
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ struct VkDescriptorImageInfo image_infos[24], *current_image_info;
+ const struct d3d12_root_descriptor_table *descriptor_table;
+ const struct d3d12_pipeline_state *state = list->state;
+ const struct d3d12_root_descriptor_table_range *range;
+ VkDevice vk_device = list->device->vk_device;
+ unsigned int i, j, k, descriptor_count;
+ struct d3d12_desc *descriptor;
+
+ descriptor_table = root_signature_get_descriptor_table(root_signature, index);
+
+ descriptor = base_descriptor;
+ descriptor_count = 0;
+ current_descriptor_write = descriptor_writes;
+ current_image_info = image_infos;
+ for (i = 0; i < descriptor_table->range_count; ++i)
+ {
+ range = &descriptor_table->ranges[i];
+
+ if (range->offset != D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
+ {
+ descriptor = base_descriptor + range->offset;
+ }
+
+ for (j = 0; j < range->descriptor_count; ++j, ++descriptor)
+ {
+ unsigned int register_idx = range->base_register_idx + j;
+
+ /* Track UAV counters. */
+ if (range->descriptor_magic == VKD3D_DESCRIPTOR_MAGIC_UAV)
+ {
+ for (k = 0; k < state->uav_counter_count; ++k)
+ {
+ if (state->uav_counters[k].register_space == range->register_space
+ && state->uav_counters[k].register_index == register_idx)
+ {
+ VkBufferView vk_counter_view = descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_UAV
+ ? descriptor->u.view->vk_counter_view : VK_NULL_HANDLE;
+ if (bindings->vk_uav_counter_views[k] != vk_counter_view)
+ bindings->uav_counters_dirty = true;
+ bindings->vk_uav_counter_views[k] = vk_counter_view;
+ break;
+ }
+ }
+ }
+
+ if (!vk_write_descriptor_set_from_d3d12_desc(current_descriptor_write,
+ current_image_info, descriptor, range->descriptor_magic,
+ bindings->descriptor_set, range->binding, j))
+ continue;
+
+ ++descriptor_count;
+ ++current_descriptor_write;
+ ++current_image_info;
+
+ if (descriptor_count == ARRAY_SIZE(descriptor_writes))
+ {
+ VK_CALL(vkUpdateDescriptorSets(vk_device, descriptor_count, descriptor_writes, 0, NULL));
+ descriptor_count = 0;
+ current_descriptor_write = descriptor_writes;
+ current_image_info = image_infos;
+ }
+ }
+ }
+
+ VK_CALL(vkUpdateDescriptorSets(vk_device, descriptor_count, descriptor_writes, 0, NULL));
+}
+
+static bool vk_write_descriptor_set_from_root_descriptor(VkWriteDescriptorSet *vk_descriptor_write,
+ const struct d3d12_root_parameter *root_parameter, VkDescriptorSet vk_descriptor_set,
+ VkBufferView *vk_buffer_view, const VkDescriptorBufferInfo *vk_buffer_info)
+{
+ const struct d3d12_root_descriptor *root_descriptor;
+
+ switch (root_parameter->parameter_type)
+ {
+ case D3D12_ROOT_PARAMETER_TYPE_CBV:
+ vk_descriptor_write->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ break;
+ case D3D12_ROOT_PARAMETER_TYPE_SRV:
+ vk_descriptor_write->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ break;
+ case D3D12_ROOT_PARAMETER_TYPE_UAV:
+ vk_descriptor_write->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ break;
+ default:
+ ERR("Invalid root descriptor %#x.\n", root_parameter->parameter_type);
+ return false;
+ }
+
+ root_descriptor = &root_parameter->u.descriptor;
+
+ vk_descriptor_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ vk_descriptor_write->pNext = NULL;
+ vk_descriptor_write->dstSet = vk_descriptor_set;
+ vk_descriptor_write->dstBinding = root_descriptor->binding;
+ vk_descriptor_write->dstArrayElement = 0;
+ vk_descriptor_write->descriptorCount = 1;
+ vk_descriptor_write->pImageInfo = NULL;
+ vk_descriptor_write->pBufferInfo = vk_buffer_info;
+ vk_descriptor_write->pTexelBufferView = vk_buffer_view;
+
+ return true;
+}
+
+static void d3d12_command_list_update_push_descriptors(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+ const struct d3d12_root_signature *root_signature = bindings->root_signature;
+ VkWriteDescriptorSet *descriptor_writes = NULL, *current_descriptor_write;
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ VkDescriptorBufferInfo *buffer_infos = NULL, *current_buffer_info;
+ const struct d3d12_root_parameter *root_parameter;
+ struct vkd3d_push_descriptor *push_descriptor;
+ struct d3d12_device *device = list->device;
+ VkDescriptorBufferInfo *vk_buffer_info;
+ unsigned int i, descriptor_count;
+ VkBufferView *vk_buffer_view;
+
+ if (!bindings->push_descriptor_dirty_mask)
+ return;
+
+ descriptor_count = vkd3d_popcount(bindings->push_descriptor_dirty_mask);
+
+ if (!(descriptor_writes = vkd3d_calloc(descriptor_count, sizeof(*descriptor_writes))))
+ return;
+ if (!(buffer_infos = vkd3d_calloc(descriptor_count, sizeof(*buffer_infos))))
+ goto done;
+
+ descriptor_count = 0;
+ current_buffer_info = buffer_infos;
+ current_descriptor_write = descriptor_writes;
+ for (i = 0; i < ARRAY_SIZE(bindings->push_descriptors); ++i)
+ {
+ if (!(bindings->push_descriptor_dirty_mask & (1u << i)))
+ continue;
+
+ root_parameter = root_signature_get_root_descriptor(root_signature, i);
+ push_descriptor = &bindings->push_descriptors[i];
+
+ if (root_parameter->parameter_type == D3D12_ROOT_PARAMETER_TYPE_CBV)
+ {
+ vk_buffer_view = NULL;
+ vk_buffer_info = current_buffer_info;
+ vk_buffer_info->buffer = push_descriptor->u.cbv.vk_buffer;
+ vk_buffer_info->offset = push_descriptor->u.cbv.offset;
+ vk_buffer_info->range = VK_WHOLE_SIZE;
+ }
+ else
+ {
+ vk_buffer_view = &push_descriptor->u.vk_buffer_view;
+ vk_buffer_info = NULL;
+ }
+
+ if (!vk_write_descriptor_set_from_root_descriptor(current_descriptor_write,
+ root_parameter, bindings->descriptor_set, vk_buffer_view, vk_buffer_info))
+ continue;
+
+ ++descriptor_count;
+ ++current_descriptor_write;
+ ++current_buffer_info;
+ }
+
+ VK_CALL(vkUpdateDescriptorSets(device->vk_device, descriptor_count, descriptor_writes, 0, NULL));
+ bindings->push_descriptor_dirty_mask = 0;
+
+done:
+ vkd3d_free(descriptor_writes);
+ vkd3d_free(buffer_infos);
+}
+
+static void d3d12_command_list_update_uav_counter_descriptors(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ const struct d3d12_pipeline_state *state = list->state;
+ VkDevice vk_device = list->device->vk_device;
+ VkWriteDescriptorSet *vk_descriptor_writes;
+ VkDescriptorSet vk_descriptor_set;
+ unsigned int uav_counter_count;
+ unsigned int i;
+
+ if (!state || !bindings->uav_counters_dirty)
+ return;
+
+ uav_counter_count = state->uav_counter_count;
+ if (!(vk_descriptor_writes = vkd3d_calloc(uav_counter_count, sizeof(*vk_descriptor_writes))))
+ return;
+ if (!(vk_descriptor_set = d3d12_command_allocator_allocate_descriptor_set(list->allocator, state->vk_set_layout)))
+ goto done;
+
+ for (i = 0; i < uav_counter_count; ++i)
+ {
+ const struct vkd3d_shader_uav_counter_binding *uav_counter = &state->uav_counters[i];
+ const VkBufferView *vk_uav_counter_views = bindings->vk_uav_counter_views;
+
+ assert(vk_uav_counter_views[i]);
+
+ vk_descriptor_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ vk_descriptor_writes[i].pNext = NULL;
+ vk_descriptor_writes[i].dstSet = vk_descriptor_set;
+ vk_descriptor_writes[i].dstBinding = uav_counter->binding.binding;
+ vk_descriptor_writes[i].dstArrayElement = 0;
+ vk_descriptor_writes[i].descriptorCount = 1;
+ vk_descriptor_writes[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ vk_descriptor_writes[i].pImageInfo = NULL;
+ vk_descriptor_writes[i].pBufferInfo = NULL;
+ vk_descriptor_writes[i].pTexelBufferView = &vk_uav_counter_views[i];
+ }
+
+ VK_CALL(vkUpdateDescriptorSets(vk_device, uav_counter_count, vk_descriptor_writes, 0, NULL));
+
+ VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point,
+ state->vk_pipeline_layout, state->set_index, 1, &vk_descriptor_set, 0, NULL));
+
+ bindings->uav_counters_dirty = false;
+
+done:
+ vkd3d_free(vk_descriptor_writes);
+}
+
+static void d3d12_command_list_update_descriptors(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ const struct d3d12_root_signature *rs = bindings->root_signature;
+ struct d3d12_desc *base_descriptor;
+ unsigned int i;
+
+ if (!rs || !rs->vk_set_layout)
+ return;
+
+ if (bindings->descriptor_table_dirty_mask || bindings->push_descriptor_dirty_mask)
+ d3d12_command_list_prepare_descriptors(list, bind_point);
+
+ for (i = 0; i < ARRAY_SIZE(bindings->descriptor_tables); ++i)
+ {
+ if (bindings->descriptor_table_dirty_mask & ((uint64_t)1 << i))
+ {
+ if ((base_descriptor = d3d12_desc_from_gpu_handle(bindings->descriptor_tables[i])))
+ d3d12_command_list_update_descriptor_table(list, bind_point, i, base_descriptor);
+ else
+ WARN("Descriptor table %u is not set.\n", i);
+ }
+ }
+ bindings->descriptor_table_dirty_mask = 0;
+
+ d3d12_command_list_update_push_descriptors(list, bind_point);
+
+ if (bindings->descriptor_set)
+ {
+ VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point,
+ rs->vk_pipeline_layout, rs->main_set, 1, &bindings->descriptor_set, 0, NULL));
+ bindings->in_use = true;
+ }
+
+ d3d12_command_list_update_uav_counter_descriptors(list, bind_point);
+}
+
+static bool d3d12_command_list_update_compute_state(struct d3d12_command_list *list)
+{
+ d3d12_command_list_end_current_render_pass(list);
+
+ if (!d3d12_command_list_update_compute_pipeline(list))
+ return false;
+
+ d3d12_command_list_update_descriptors(list, VK_PIPELINE_BIND_POINT_COMPUTE);
+
+ return true;
+}
+
+static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ struct d3d12_graphics_pipeline_state *graphics;
+ struct VkRenderPassBeginInfo begin_desc;
+ VkRenderPass vk_render_pass;
+
+ if (!d3d12_command_list_update_graphics_pipeline(list))
+ return false;
+ if (!d3d12_command_list_update_current_framebuffer(list))
+ return false;
+
+ d3d12_command_list_update_descriptors(list, VK_PIPELINE_BIND_POINT_GRAPHICS);
+
+ if (list->current_render_pass != VK_NULL_HANDLE)
+ return true;
+
+ vk_render_pass = list->pso_render_pass;
+ assert(vk_render_pass);
+
+ begin_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ begin_desc.pNext = NULL;
+ begin_desc.renderPass = vk_render_pass;
+ begin_desc.framebuffer = list->current_framebuffer;
+ begin_desc.renderArea.offset.x = 0;
+ begin_desc.renderArea.offset.y = 0;
+ d3d12_command_list_get_fb_extent(list,
+ &begin_desc.renderArea.extent.width, &begin_desc.renderArea.extent.height, NULL);
+ begin_desc.clearValueCount = 0;
+ begin_desc.pClearValues = NULL;
+ VK_CALL(vkCmdBeginRenderPass(list->vk_command_buffer, &begin_desc, VK_SUBPASS_CONTENTS_INLINE));
+
+ list->current_render_pass = vk_render_pass;
+
+ graphics = &list->state->u.graphics;
+ if (graphics->xfb_enabled)
+ {
+ VK_CALL(vkCmdBeginTransformFeedbackEXT(list->vk_command_buffer, 0, ARRAY_SIZE(list->so_counter_buffers),
+ list->so_counter_buffers, list->so_counter_buffer_offsets));
+
+ list->xfb_enabled = true;
+ }
+
+ return true;
+}
+
+static void d3d12_command_list_check_index_buffer_strip_cut_value(struct d3d12_command_list *list)
+{
+ struct d3d12_graphics_pipeline_state *graphics = &list->state->u.graphics;
+
+ /* In Vulkan, the strip cut value is derived from the index buffer format. */
+ switch (graphics->index_buffer_strip_cut_value)
+ {
+ case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF:
+ if (list->index_buffer_format != DXGI_FORMAT_R16_UINT)
+ {
+ FIXME("Strip cut value 0xffff is not supported with index buffer format %#x.\n",
+ list->index_buffer_format);
+ }
+ break;
+
+ case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF:
+ if (list->index_buffer_format != DXGI_FORMAT_R32_UINT)
+ {
+ FIXME("Strip cut value 0xffffffff is not supported with index buffer format %#x.\n",
+ list->index_buffer_format);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_DrawInstanced(ID3D12GraphicsCommandList2 *iface,
+ UINT vertex_count_per_instance, UINT instance_count, UINT start_vertex_location,
+ UINT start_instance_location)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+
+ TRACE("iface %p, vertex_count_per_instance %u, instance_count %u, "
+ "start_vertex_location %u, start_instance_location %u.\n",
+ iface, vertex_count_per_instance, instance_count,
+ start_vertex_location, start_instance_location);
+
+ vk_procs = &list->device->vk_procs;
+
+ if (!d3d12_command_list_begin_render_pass(list))
+ {
+ WARN("Failed to begin render pass, ignoring draw call.\n");
+ return;
+ }
+
+ VK_CALL(vkCmdDraw(list->vk_command_buffer, vertex_count_per_instance,
+ instance_count, start_vertex_location, start_instance_location));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_DrawIndexedInstanced(ID3D12GraphicsCommandList2 *iface,
+ UINT index_count_per_instance, UINT instance_count, UINT start_vertex_location,
+ INT base_vertex_location, UINT start_instance_location)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+
+ TRACE("iface %p, index_count_per_instance %u, instance_count %u, start_vertex_location %u, "
+ "base_vertex_location %d, start_instance_location %u.\n",
+ iface, index_count_per_instance, instance_count, start_vertex_location,
+ base_vertex_location, start_instance_location);
+
+ if (!d3d12_command_list_begin_render_pass(list))
+ {
+ WARN("Failed to begin render pass, ignoring draw call.\n");
+ return;
+ }
+
+ vk_procs = &list->device->vk_procs;
+
+ d3d12_command_list_check_index_buffer_strip_cut_value(list);
+
+ VK_CALL(vkCmdDrawIndexed(list->vk_command_buffer, index_count_per_instance,
+ instance_count, start_vertex_location, base_vertex_location, start_instance_location));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_Dispatch(ID3D12GraphicsCommandList2 *iface,
+ UINT x, UINT y, UINT z)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+
+ TRACE("iface %p, x %u, y %u, z %u.\n", iface, x, y, z);
+
+ if (!d3d12_command_list_update_compute_state(list))
+ {
+ WARN("Failed to update compute state, ignoring dispatch.\n");
+ return;
+ }
+
+ vk_procs = &list->device->vk_procs;
+
+ VK_CALL(vkCmdDispatch(list->vk_command_buffer, x, y, z));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_CopyBufferRegion(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst, UINT64 dst_offset, ID3D12Resource *src, UINT64 src_offset, UINT64 byte_count)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_resource *dst_resource, *src_resource;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkBufferCopy buffer_copy;
+
+ TRACE("iface %p, dst_resource %p, dst_offset %#"PRIx64", src_resource %p, "
+ "src_offset %#"PRIx64", byte_count %#"PRIx64".\n",
+ iface, dst, dst_offset, src, src_offset, byte_count);
+
+ vk_procs = &list->device->vk_procs;
+
+ dst_resource = unsafe_impl_from_ID3D12Resource(dst);
+ assert(d3d12_resource_is_buffer(dst_resource));
+ src_resource = unsafe_impl_from_ID3D12Resource(src);
+ assert(d3d12_resource_is_buffer(src_resource));
+
+ d3d12_command_list_track_resource_usage(list, dst_resource);
+ d3d12_command_list_track_resource_usage(list, src_resource);
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ buffer_copy.srcOffset = src_offset;
+ buffer_copy.dstOffset = dst_offset;
+ buffer_copy.size = byte_count;
+
+ VK_CALL(vkCmdCopyBuffer(list->vk_command_buffer,
+ src_resource->u.vk_buffer, dst_resource->u.vk_buffer, 1, &buffer_copy));
+}
+
+static void vk_image_subresource_layers_from_d3d12(VkImageSubresourceLayers *subresource,
+ const struct vkd3d_format *format, unsigned int sub_resource_idx, unsigned int miplevel_count)
+{
+ subresource->aspectMask = format->vk_aspect_mask;
+ subresource->mipLevel = sub_resource_idx % miplevel_count;
+ subresource->baseArrayLayer = sub_resource_idx / miplevel_count;
+ subresource->layerCount = 1;
+}
+
+static void vk_extent_3d_from_d3d12_miplevel(VkExtent3D *extent,
+ const D3D12_RESOURCE_DESC *resource_desc, unsigned int miplevel_idx)
+{
+ extent->width = d3d12_resource_desc_get_width(resource_desc, miplevel_idx);
+ extent->height = d3d12_resource_desc_get_height(resource_desc, miplevel_idx);
+ extent->depth = d3d12_resource_desc_get_depth(resource_desc, miplevel_idx);
+}
+
+static void vk_buffer_image_copy_from_d3d12(VkBufferImageCopy *copy,
+ const D3D12_PLACED_SUBRESOURCE_FOOTPRINT *footprint, unsigned int sub_resource_idx,
+ const D3D12_RESOURCE_DESC *image_desc, const struct vkd3d_format *format,
+ const D3D12_BOX *src_box, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z)
+{
+ copy->bufferOffset = footprint->Offset;
+ if (src_box)
+ {
+ VkDeviceSize row_count = footprint->Footprint.Height / format->block_height;
+ copy->bufferOffset += vkd3d_format_get_data_offset(format, footprint->Footprint.RowPitch,
+ row_count * footprint->Footprint.RowPitch, src_box->left, src_box->top, src_box->front);
+ }
+ copy->bufferRowLength = footprint->Footprint.RowPitch /
+ (format->byte_count * format->block_byte_count) * format->block_width;
+ copy->bufferImageHeight = footprint->Footprint.Height;
+ vk_image_subresource_layers_from_d3d12(©->imageSubresource,
+ format, sub_resource_idx, image_desc->MipLevels);
+ copy->imageOffset.x = dst_x;
+ copy->imageOffset.y = dst_y;
+ copy->imageOffset.z = dst_z;
+
+ vk_extent_3d_from_d3d12_miplevel(©->imageExtent, image_desc,
+ copy->imageSubresource.mipLevel);
+ copy->imageExtent.width -= copy->imageOffset.x;
+ copy->imageExtent.height -= copy->imageOffset.y;
+ copy->imageExtent.depth -= copy->imageOffset.z;
+
+ if (src_box)
+ {
+ copy->imageExtent.width = min(copy->imageExtent.width, src_box->right - src_box->left);
+ copy->imageExtent.height = min(copy->imageExtent.height, src_box->bottom - src_box->top);
+ copy->imageExtent.depth = min(copy->imageExtent.depth, src_box->back - src_box->front);
+ }
+ else
+ {
+ copy->imageExtent.width = min(copy->imageExtent.width, footprint->Footprint.Width);
+ copy->imageExtent.height = min(copy->imageExtent.height, footprint->Footprint.Height);
+ copy->imageExtent.depth = min(copy->imageExtent.depth, footprint->Footprint.Depth);
+ }
+}
+
+static void vk_image_buffer_copy_from_d3d12(VkBufferImageCopy *copy,
+ const D3D12_PLACED_SUBRESOURCE_FOOTPRINT *footprint, unsigned int sub_resource_idx,
+ const D3D12_RESOURCE_DESC *image_desc, const struct vkd3d_format *format,
+ const D3D12_BOX *src_box, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z)
+{
+ VkDeviceSize row_count = footprint->Footprint.Height / format->block_height;
+
+ copy->bufferOffset = footprint->Offset + vkd3d_format_get_data_offset(format,
+ footprint->Footprint.RowPitch, row_count * footprint->Footprint.RowPitch, dst_x, dst_y, dst_z);
+ copy->bufferRowLength = footprint->Footprint.RowPitch /
+ (format->byte_count * format->block_byte_count) * format->block_width;
+ copy->bufferImageHeight = footprint->Footprint.Height;
+ vk_image_subresource_layers_from_d3d12(©->imageSubresource,
+ format, sub_resource_idx, image_desc->MipLevels);
+ copy->imageOffset.x = src_box ? src_box->left : 0;
+ copy->imageOffset.y = src_box ? src_box->top : 0;
+ copy->imageOffset.z = src_box ? src_box->front : 0;
+ if (src_box)
+ {
+ copy->imageExtent.width = src_box->right - src_box->left;
+ copy->imageExtent.height = src_box->bottom - src_box->top;
+ copy->imageExtent.depth = src_box->back - src_box->front;
+ }
+ else
+ {
+ unsigned int miplevel = copy->imageSubresource.mipLevel;
+ vk_extent_3d_from_d3d12_miplevel(©->imageExtent, image_desc, miplevel);
+ }
+}
+
+static void vk_image_copy_from_d3d12(VkImageCopy *image_copy,
+ unsigned int src_sub_resource_idx, unsigned int dst_sub_resource_idx,
+ const D3D12_RESOURCE_DESC *src_desc, const D3D12_RESOURCE_DESC *dst_desc,
+ const struct vkd3d_format *src_format, const struct vkd3d_format *dst_format,
+ const D3D12_BOX *src_box, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z)
+{
+ vk_image_subresource_layers_from_d3d12(&image_copy->srcSubresource,
+ src_format, src_sub_resource_idx, src_desc->MipLevels);
+ image_copy->srcOffset.x = src_box ? src_box->left : 0;
+ image_copy->srcOffset.y = src_box ? src_box->top : 0;
+ image_copy->srcOffset.z = src_box ? src_box->front : 0;
+ vk_image_subresource_layers_from_d3d12(&image_copy->dstSubresource,
+ dst_format, dst_sub_resource_idx, dst_desc->MipLevels);
+ image_copy->dstOffset.x = dst_x;
+ image_copy->dstOffset.y = dst_y;
+ image_copy->dstOffset.z = dst_z;
+ if (src_box)
+ {
+ image_copy->extent.width = src_box->right - src_box->left;
+ image_copy->extent.height = src_box->bottom - src_box->top;
+ image_copy->extent.depth = src_box->back - src_box->front;
+ }
+ else
+ {
+ unsigned int miplevel = image_copy->srcSubresource.mipLevel;
+ vk_extent_3d_from_d3d12_miplevel(&image_copy->extent, src_desc, miplevel);
+ }
+}
+
+static HRESULT d3d12_command_list_allocate_transfer_buffer(struct d3d12_command_list *list,
+ VkDeviceSize size, struct vkd3d_buffer *buffer)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ struct d3d12_device *device = list->device;
+ D3D12_HEAP_PROPERTIES heap_properties;
+ D3D12_RESOURCE_DESC buffer_desc;
+ HRESULT hr;
+
+ memset(&heap_properties, 0, sizeof(heap_properties));
+ heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
+
+ buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ buffer_desc.Alignment = 0;
+ buffer_desc.Width = size;
+ buffer_desc.Height = 1;
+ buffer_desc.DepthOrArraySize = 1;
+ buffer_desc.MipLevels = 1;
+ buffer_desc.Format = DXGI_FORMAT_UNKNOWN;
+ buffer_desc.SampleDesc.Count = 1;
+ buffer_desc.SampleDesc.Quality = 0;
+ buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ buffer_desc.Flags = D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
+
+ if (FAILED(hr = vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
+ &buffer_desc, &buffer->vk_buffer)))
+ return hr;
+ if (FAILED(hr = vkd3d_allocate_buffer_memory(device, buffer->vk_buffer,
+ &heap_properties, D3D12_HEAP_FLAG_NONE, &buffer->vk_memory, NULL, NULL)))
+ {
+ VK_CALL(vkDestroyBuffer(device->vk_device, buffer->vk_buffer, NULL));
+ return hr;
+ }
+
+ if (!d3d12_command_allocator_add_transfer_buffer(list->allocator, buffer))
+ {
+ ERR("Failed to add transfer buffer.\n");
+ vkd3d_buffer_destroy(buffer, device);
+ return E_OUTOFMEMORY;
+ }
+
+ return S_OK;
+}
+
+/* In Vulkan, each depth/stencil format is only compatible with itself.
+ * This means that we are not allowed to copy texture regions directly between
+ * depth/stencil and color formats.
+ *
+ * FIXME: Implement color <-> depth/stencil blits in shaders.
+ */
+static void d3d12_command_list_copy_incompatible_texture_region(struct d3d12_command_list *list,
+ struct d3d12_resource *dst_resource, unsigned int dst_sub_resource_idx,
+ const struct vkd3d_format *dst_format, struct d3d12_resource *src_resource,
+ unsigned int src_sub_resource_idx, const struct vkd3d_format *src_format)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ const D3D12_RESOURCE_DESC *dst_desc = &dst_resource->desc;
+ const D3D12_RESOURCE_DESC *src_desc = &src_resource->desc;
+ unsigned int dst_miplevel_idx, src_miplevel_idx;
+ struct vkd3d_buffer transfer_buffer;
+ VkBufferImageCopy buffer_image_copy;
+ VkBufferMemoryBarrier vk_barrier;
+ VkDeviceSize buffer_size;
+ HRESULT hr;
+
+ WARN("Copying incompatible texture formats %#x, %#x -> %#x, %#x.\n",
+ src_format->dxgi_format, src_format->vk_format,
+ dst_format->dxgi_format, dst_format->vk_format);
+
+ assert(d3d12_resource_is_texture(dst_resource));
+ assert(d3d12_resource_is_texture(src_resource));
+ assert(!vkd3d_format_is_compressed(dst_format));
+ assert(!vkd3d_format_is_compressed(src_format));
+ assert(dst_format->byte_count == src_format->byte_count);
+
+ buffer_image_copy.bufferOffset = 0;
+ buffer_image_copy.bufferRowLength = 0;
+ buffer_image_copy.bufferImageHeight = 0;
+ vk_image_subresource_layers_from_d3d12(&buffer_image_copy.imageSubresource,
+ src_format, src_sub_resource_idx, src_desc->MipLevels);
+ src_miplevel_idx = buffer_image_copy.imageSubresource.mipLevel;
+ buffer_image_copy.imageOffset.x = 0;
+ buffer_image_copy.imageOffset.y = 0;
+ buffer_image_copy.imageOffset.z = 0;
+ vk_extent_3d_from_d3d12_miplevel(&buffer_image_copy.imageExtent, src_desc, src_miplevel_idx);
+
+ buffer_size = src_format->byte_count * buffer_image_copy.imageExtent.width *
+ buffer_image_copy.imageExtent.height * buffer_image_copy.imageExtent.depth;
+ if (FAILED(hr = d3d12_command_list_allocate_transfer_buffer(list, buffer_size, &transfer_buffer)))
+ {
+ ERR("Failed to allocate transfer buffer, hr %#x.\n", hr);
+ return;
+ }
+
+ VK_CALL(vkCmdCopyImageToBuffer(list->vk_command_buffer,
+ src_resource->u.vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ transfer_buffer.vk_buffer, 1, &buffer_image_copy));
+
+ vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ vk_barrier.pNext = NULL;
+ vk_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ vk_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vk_barrier.buffer = transfer_buffer.vk_buffer;
+ vk_barrier.offset = 0;
+ vk_barrier.size = VK_WHOLE_SIZE;
+ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
+ 0, NULL, 1, &vk_barrier, 0, NULL));
+
+ vk_image_subresource_layers_from_d3d12(&buffer_image_copy.imageSubresource,
+ dst_format, dst_sub_resource_idx, dst_desc->MipLevels);
+ dst_miplevel_idx = buffer_image_copy.imageSubresource.mipLevel;
+
+ assert(d3d12_resource_desc_get_width(src_desc, src_miplevel_idx) ==
+ d3d12_resource_desc_get_width(dst_desc, dst_miplevel_idx));
+ assert(d3d12_resource_desc_get_height(src_desc, src_miplevel_idx) ==
+ d3d12_resource_desc_get_height(dst_desc, dst_miplevel_idx));
+ assert(d3d12_resource_desc_get_depth(src_desc, src_miplevel_idx) ==
+ d3d12_resource_desc_get_depth(dst_desc, dst_miplevel_idx));
+
+ VK_CALL(vkCmdCopyBufferToImage(list->vk_command_buffer,
+ transfer_buffer.vk_buffer, dst_resource->u.vk_image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy));
+}
+
+static bool validate_d3d12_box(const D3D12_BOX *box)
+{
+ return box->right > box->left
+ && box->bottom > box->top
+ && box->back > box->front;
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_CopyTextureRegion(ID3D12GraphicsCommandList2 *iface,
+ const D3D12_TEXTURE_COPY_LOCATION *dst, UINT dst_x, UINT dst_y, UINT dst_z,
+ const D3D12_TEXTURE_COPY_LOCATION *src, const D3D12_BOX *src_box)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_resource *dst_resource, *src_resource;
+ const struct vkd3d_format *src_format, *dst_format;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkBufferImageCopy buffer_image_copy;
+ VkImageCopy image_copy;
+
+ TRACE("iface %p, dst %p, dst_x %u, dst_y %u, dst_z %u, src %p, src_box %p.\n",
+ iface, dst, dst_x, dst_y, dst_z, src, src_box);
+
+ if (src_box && !validate_d3d12_box(src_box))
+ {
+ WARN("Empty box %s.\n", debug_d3d12_box(src_box));
+ return;
+ }
+
+ vk_procs = &list->device->vk_procs;
+
+ dst_resource = unsafe_impl_from_ID3D12Resource(dst->pResource);
+ src_resource = unsafe_impl_from_ID3D12Resource(src->pResource);
+
+ d3d12_command_list_track_resource_usage(list, dst_resource);
+ d3d12_command_list_track_resource_usage(list, src_resource);
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ if (src->Type == D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX
+ && dst->Type == D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT)
+ {
+ assert(d3d12_resource_is_buffer(dst_resource));
+ assert(d3d12_resource_is_texture(src_resource));
+
+ if (!(dst_format = vkd3d_format_from_d3d12_resource_desc(list->device,
+ &src_resource->desc, dst->u.PlacedFootprint.Footprint.Format)))
+ {
+ WARN("Invalid format %#x.\n", dst->u.PlacedFootprint.Footprint.Format);
+ return;
+ }
+
+ if (dst_format->is_emulated)
+ {
+ FIXME("Format %#x is not supported yet.\n", dst_format->dxgi_format);
+ return;
+ }
+
+ if ((dst_format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
+ && (dst_format->vk_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT))
+ FIXME("Depth-stencil format %#x not fully supported yet.\n", dst_format->dxgi_format);
+
+ vk_image_buffer_copy_from_d3d12(&buffer_image_copy, &dst->u.PlacedFootprint,
+ src->u.SubresourceIndex, &src_resource->desc, dst_format, src_box, dst_x, dst_y, dst_z);
+ VK_CALL(vkCmdCopyImageToBuffer(list->vk_command_buffer,
+ src_resource->u.vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ dst_resource->u.vk_buffer, 1, &buffer_image_copy));
+ }
+ else if (src->Type == D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT
+ && dst->Type == D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX)
+ {
+ assert(d3d12_resource_is_texture(dst_resource));
+ assert(d3d12_resource_is_buffer(src_resource));
+
+ if (!(src_format = vkd3d_format_from_d3d12_resource_desc(list->device,
+ &dst_resource->desc, src->u.PlacedFootprint.Footprint.Format)))
+ {
+ WARN("Invalid format %#x.\n", src->u.PlacedFootprint.Footprint.Format);
+ return;
+ }
+
+ if (src_format->is_emulated)
+ {
+ FIXME("Format %#x is not supported yet.\n", src_format->dxgi_format);
+ return;
+ }
+
+ if ((src_format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
+ && (src_format->vk_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT))
+ FIXME("Depth-stencil format %#x not fully supported yet.\n", src_format->dxgi_format);
+
+ vk_buffer_image_copy_from_d3d12(&buffer_image_copy, &src->u.PlacedFootprint,
+ dst->u.SubresourceIndex, &dst_resource->desc, src_format, src_box, dst_x, dst_y, dst_z);
+ VK_CALL(vkCmdCopyBufferToImage(list->vk_command_buffer,
+ src_resource->u.vk_buffer, dst_resource->u.vk_image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy));
+ }
+ else if (src->Type == D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX
+ && dst->Type == D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX)
+ {
+ assert(d3d12_resource_is_texture(dst_resource));
+ assert(d3d12_resource_is_texture(src_resource));
+
+ if (!(dst_format = vkd3d_format_from_d3d12_resource_desc(list->device,
+ &dst_resource->desc, DXGI_FORMAT_UNKNOWN)))
+ {
+ WARN("Invalid format %#x.\n", dst_resource->desc.Format);
+ return;
+ }
+ if (!(src_format = vkd3d_format_from_d3d12_resource_desc(list->device,
+ &src_resource->desc, DXGI_FORMAT_UNKNOWN)))
+ {
+ WARN("Invalid format %#x.\n", src_resource->desc.Format);
+ return;
+ }
+
+ if ((dst_format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
+ && (dst_format->vk_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT))
+ FIXME("Depth-stencil format %#x not fully supported yet.\n", dst_format->dxgi_format);
+ if ((src_format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
+ && (src_format->vk_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT))
+ FIXME("Depth-stencil format %#x not fully supported yet.\n", src_format->dxgi_format);
+
+ if (dst_format->vk_aspect_mask != src_format->vk_aspect_mask)
+ {
+ d3d12_command_list_copy_incompatible_texture_region(list,
+ dst_resource, dst->u.SubresourceIndex, dst_format,
+ src_resource, src->u.SubresourceIndex, src_format);
+ return;
+ }
+
+ vk_image_copy_from_d3d12(&image_copy, src->u.SubresourceIndex, dst->u.SubresourceIndex,
+ &src_resource->desc, &dst_resource->desc, src_format, dst_format,
+ src_box, dst_x, dst_y, dst_z);
+ VK_CALL(vkCmdCopyImage(list->vk_command_buffer, src_resource->u.vk_image,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_resource->u.vk_image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy));
+ }
+ else
+ {
+ FIXME("Copy type %#x -> %#x not implemented.\n", src->Type, dst->Type);
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_CopyResource(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst, ID3D12Resource *src)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_resource *dst_resource, *src_resource;
+ const struct vkd3d_format *src_format, *dst_format;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkBufferCopy vk_buffer_copy;
+ VkImageCopy vk_image_copy;
+ unsigned int layer_count;
+ unsigned int i;
+
+ TRACE("iface %p, dst_resource %p, src_resource %p.\n", iface, dst, src);
+
+ vk_procs = &list->device->vk_procs;
+
+ dst_resource = unsafe_impl_from_ID3D12Resource(dst);
+ src_resource = unsafe_impl_from_ID3D12Resource(src);
+
+ d3d12_command_list_track_resource_usage(list, dst_resource);
+ d3d12_command_list_track_resource_usage(list, src_resource);
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ if (d3d12_resource_is_buffer(dst_resource))
+ {
+ assert(d3d12_resource_is_buffer(src_resource));
+ assert(src_resource->desc.Width == dst_resource->desc.Width);
+
+ vk_buffer_copy.srcOffset = 0;
+ vk_buffer_copy.dstOffset = 0;
+ vk_buffer_copy.size = dst_resource->desc.Width;
+ VK_CALL(vkCmdCopyBuffer(list->vk_command_buffer,
+ src_resource->u.vk_buffer, dst_resource->u.vk_buffer, 1, &vk_buffer_copy));
+ }
+ else
+ {
+ if (!(dst_format = vkd3d_format_from_d3d12_resource_desc(list->device,
+ &dst_resource->desc, DXGI_FORMAT_UNKNOWN)))
+ {
+ WARN("Invalid format %#x.\n", dst_resource->desc.Format);
+ return;
+ }
+ if (!(src_format = vkd3d_format_from_d3d12_resource_desc(list->device,
+ &src_resource->desc, DXGI_FORMAT_UNKNOWN)))
+ {
+ WARN("Invalid format %#x.\n", src_resource->desc.Format);
+ return;
+ }
+
+ layer_count = d3d12_resource_desc_get_layer_count(&dst_resource->desc);
+
+ assert(d3d12_resource_is_texture(dst_resource));
+ assert(d3d12_resource_is_texture(src_resource));
+ assert(dst_resource->desc.MipLevels == src_resource->desc.MipLevels);
+ assert(layer_count == d3d12_resource_desc_get_layer_count(&src_resource->desc));
+
+ for (i = 0; i < dst_resource->desc.MipLevels; ++i)
+ {
+ vk_image_copy_from_d3d12(&vk_image_copy, i, i,
+ &src_resource->desc, &dst_resource->desc, src_format, dst_format, NULL, 0, 0, 0);
+ vk_image_copy.dstSubresource.layerCount = layer_count;
+ vk_image_copy.srcSubresource.layerCount = layer_count;
+ VK_CALL(vkCmdCopyImage(list->vk_command_buffer, src_resource->u.vk_image,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_resource->u.vk_image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vk_image_copy));
+ }
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_CopyTiles(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *tiled_resource, const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *tile_region_size, ID3D12Resource *buffer, UINT64 buffer_offset,
+ D3D12_TILE_COPY_FLAGS flags)
+{
+ FIXME("iface %p, tiled_resource %p, tile_region_start_coordinate %p, tile_region_size %p, "
+ "buffer %p, buffer_offset %#"PRIx64", flags %#x stub!\n",
+ iface, tiled_resource, tile_region_start_coordinate, tile_region_size,
+ buffer, buffer_offset, flags);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ResolveSubresource(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst, UINT dst_sub_resource_idx,
+ ID3D12Resource *src, UINT src_sub_resource_idx, DXGI_FORMAT format)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_format *src_format, *dst_format, *vk_format;
+ struct d3d12_resource *dst_resource, *src_resource;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ const struct d3d12_device *device;
+ VkImageResolve vk_image_resolve;
+
+ TRACE("iface %p, dst_resource %p, dst_sub_resource_idx %u, src_resource %p, src_sub_resource_idx %u, "
+ "format %#x.\n", iface, dst, dst_sub_resource_idx, src, src_sub_resource_idx, format);
+
+ device = list->device;
+ vk_procs = &device->vk_procs;
+
+ dst_resource = unsafe_impl_from_ID3D12Resource(dst);
+ src_resource = unsafe_impl_from_ID3D12Resource(src);
+
+ assert(d3d12_resource_is_texture(dst_resource));
+ assert(d3d12_resource_is_texture(src_resource));
+
+ d3d12_command_list_track_resource_usage(list, dst_resource);
+ d3d12_command_list_track_resource_usage(list, src_resource);
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ if (!(dst_format = vkd3d_format_from_d3d12_resource_desc(device, &dst_resource->desc, DXGI_FORMAT_UNKNOWN)))
+ {
+ WARN("Invalid format %#x.\n", dst_resource->desc.Format);
+ return;
+ }
+ if (!(src_format = vkd3d_format_from_d3d12_resource_desc(device, &src_resource->desc, DXGI_FORMAT_UNKNOWN)))
+ {
+ WARN("Invalid format %#x.\n", src_resource->desc.Format);
+ return;
+ }
+
+ if (dst_format->type == VKD3D_FORMAT_TYPE_TYPELESS || src_format->type == VKD3D_FORMAT_TYPE_TYPELESS)
+ {
+ if (!(vk_format = vkd3d_format_from_d3d12_resource_desc(device, &dst_resource->desc, format)))
+ {
+ WARN("Invalid format %#x.\n", format);
+ return;
+ }
+ if (dst_format->vk_format != src_format->vk_format || dst_format->vk_format != vk_format->vk_format)
+ {
+ FIXME("Not implemented for typeless resources.\n");
+ return;
+ }
+ }
+
+ /* Resolve of depth/stencil images is not supported in Vulkan. */
+ if ((dst_format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
+ || (src_format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))
+ {
+ FIXME("Resolve of depth/stencil images is not implemented yet.\n");
+ return;
+ }
+
+ vk_image_subresource_layers_from_d3d12(&vk_image_resolve.srcSubresource,
+ src_format, src_sub_resource_idx, src_resource->desc.MipLevels);
+ memset(&vk_image_resolve.srcOffset, 0, sizeof(vk_image_resolve.srcOffset));
+ vk_image_subresource_layers_from_d3d12(&vk_image_resolve.dstSubresource,
+ dst_format, dst_sub_resource_idx, dst_resource->desc.MipLevels);
+ memset(&vk_image_resolve.dstOffset, 0, sizeof(vk_image_resolve.dstOffset));
+ vk_extent_3d_from_d3d12_miplevel(&vk_image_resolve.extent,
+ &dst_resource->desc, vk_image_resolve.dstSubresource.mipLevel);
+
+ VK_CALL(vkCmdResolveImage(list->vk_command_buffer, src_resource->u.vk_image,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_resource->u.vk_image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vk_image_resolve));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_IASetPrimitiveTopology(ID3D12GraphicsCommandList2 *iface,
+ D3D12_PRIMITIVE_TOPOLOGY topology)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, topology %#x.\n", iface, topology);
+
+ if (topology == D3D_PRIMITIVE_TOPOLOGY_UNDEFINED)
+ {
+ WARN("Ignoring D3D_PRIMITIVE_TOPOLOGY_UNDEFINED.\n");
+ return;
+ }
+
+ if (list->primitive_topology == topology)
+ return;
+
+ list->primitive_topology = topology;
+ d3d12_command_list_invalidate_current_pipeline(list);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(ID3D12GraphicsCommandList2 *iface,
+ UINT viewport_count, const D3D12_VIEWPORT *viewports)
+{
+ VkViewport vk_viewports[D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ unsigned int i;
+
+ TRACE("iface %p, viewport_count %u, viewports %p.\n", iface, viewport_count, viewports);
+
+ if (viewport_count > ARRAY_SIZE(vk_viewports))
+ {
+ FIXME("Viewport count %u > D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE.\n", viewport_count);
+ viewport_count = ARRAY_SIZE(vk_viewports);
+ }
+
+ for (i = 0; i < viewport_count; ++i)
+ {
+ vk_viewports[i].x = viewports[i].TopLeftX;
+ vk_viewports[i].y = viewports[i].TopLeftY + viewports[i].Height;
+ vk_viewports[i].width = viewports[i].Width;
+ vk_viewports[i].height = -viewports[i].Height;
+ vk_viewports[i].minDepth = viewports[i].MinDepth;
+ vk_viewports[i].maxDepth = viewports[i].MaxDepth;
+
+ if (!vk_viewports[i].width || !vk_viewports[i].height)
+ {
+ FIXME_ONCE("Invalid viewport %u, ignoring RSSetViewports().\n", i);
+ return;
+ }
+ }
+
+ vk_procs = &list->device->vk_procs;
+ VK_CALL(vkCmdSetViewport(list->vk_command_buffer, 0, viewport_count, vk_viewports));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_RSSetScissorRects(ID3D12GraphicsCommandList2 *iface,
+ UINT rect_count, const D3D12_RECT *rects)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ VkRect2D vk_rects[D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ const struct vkd3d_vk_device_procs *vk_procs;
+ unsigned int i;
+
+ TRACE("iface %p, rect_count %u, rects %p.\n", iface, rect_count, rects);
+
+ if (rect_count > ARRAY_SIZE(vk_rects))
+ {
+ FIXME("Rect count %u > D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE.\n", rect_count);
+ rect_count = ARRAY_SIZE(vk_rects);
+ }
+
+ for (i = 0; i < rect_count; ++i)
+ {
+ vk_rects[i].offset.x = rects[i].left;
+ vk_rects[i].offset.y = rects[i].top;
+ vk_rects[i].extent.width = rects[i].right - rects[i].left;
+ vk_rects[i].extent.height = rects[i].bottom - rects[i].top;
+ }
+
+ vk_procs = &list->device->vk_procs;
+ VK_CALL(vkCmdSetScissor(list->vk_command_buffer, 0, rect_count, vk_rects));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_OMSetBlendFactor(ID3D12GraphicsCommandList2 *iface,
+ const FLOAT blend_factor[4])
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+
+ TRACE("iface %p, blend_factor %p.\n", iface, blend_factor);
+
+ vk_procs = &list->device->vk_procs;
+ VK_CALL(vkCmdSetBlendConstants(list->vk_command_buffer, blend_factor));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_OMSetStencilRef(ID3D12GraphicsCommandList2 *iface,
+ UINT stencil_ref)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+
+ TRACE("iface %p, stencil_ref %u.\n", iface, stencil_ref);
+
+ vk_procs = &list->device->vk_procs;
+ VK_CALL(vkCmdSetStencilReference(list->vk_command_buffer, VK_STENCIL_FRONT_AND_BACK, stencil_ref));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetPipelineState(ID3D12GraphicsCommandList2 *iface,
+ ID3D12PipelineState *pipeline_state)
+{
+ struct d3d12_pipeline_state *state = unsafe_impl_from_ID3D12PipelineState(pipeline_state);
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, pipeline_state %p.\n", iface, pipeline_state);
+
+ if (list->state == state)
+ return;
+
+ d3d12_command_list_invalidate_bindings(list, state);
+ d3d12_command_list_invalidate_current_pipeline(list);
+
+ list->state = state;
+}
+
+static bool is_ds_multiplanar_resolvable(unsigned int first_state, unsigned int second_state)
+{
+ /* Only combinations of depth/stencil read/write are supported. */
+ return first_state == second_state
+ || ((first_state & (D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_DEPTH_WRITE))
+ && (second_state & (D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_DEPTH_WRITE)));
+}
+
+static unsigned int d3d12_find_ds_multiplanar_transition(const D3D12_RESOURCE_BARRIER *barriers,
+ unsigned int i, unsigned int barrier_count, unsigned int sub_resource_count)
+{
+ unsigned int sub_resource_idx = barriers[i].u.Transition.Subresource;
+ unsigned int j;
+
+ for (j = i + 1; j < barrier_count; ++j)
+ {
+ if (barriers[j].Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION
+ && barriers[j].u.Transition.pResource == barriers[i].u.Transition.pResource
+ && sub_resource_idx % sub_resource_count == barriers[j].u.Transition.Subresource % sub_resource_count)
+ {
+ /* Second barrier must be for a different plane. */
+ if (barriers[j].u.Transition.Subresource == sub_resource_idx)
+ return 0;
+
+ /* Validate the second barrier and check if the combination of two states is supported. */
+ if (!is_valid_resource_state(barriers[j].u.Transition.StateBefore)
+ || !is_ds_multiplanar_resolvable(barriers[i].u.Transition.StateBefore, barriers[j].u.Transition.StateBefore)
+ || !is_valid_resource_state(barriers[j].u.Transition.StateAfter)
+ || !is_ds_multiplanar_resolvable(barriers[i].u.Transition.StateAfter, barriers[j].u.Transition.StateAfter)
+ || barriers[j].u.Transition.Subresource >= sub_resource_count * 2u)
+ return 0;
+
+ return j;
+ }
+ }
+ return 0;
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsCommandList2 *iface,
+ UINT barrier_count, const D3D12_RESOURCE_BARRIER *barriers)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ bool have_aliasing_barriers = false, have_split_barriers = false;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ const struct vkd3d_vulkan_info *vk_info;
+ bool *multiplanar_handled = NULL;
+ unsigned int i;
+
+ TRACE("iface %p, barrier_count %u, barriers %p.\n", iface, barrier_count, barriers);
+
+ vk_procs = &list->device->vk_procs;
+ vk_info = &list->device->vk_info;
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ for (i = 0; i < barrier_count; ++i)
+ {
+ unsigned int sub_resource_idx = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ VkPipelineStageFlags src_stage_mask = 0, dst_stage_mask = 0;
+ VkAccessFlags src_access_mask = 0, dst_access_mask = 0;
+ const D3D12_RESOURCE_BARRIER *current = &barriers[i];
+ VkImageLayout layout_before, layout_after;
+ struct d3d12_resource *resource;
+
+ have_split_barriers = have_split_barriers
+ || (current->Flags & D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY)
+ || (current->Flags & D3D12_RESOURCE_BARRIER_FLAG_END_ONLY);
+
+ if (current->Flags & D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY)
+ continue;
+
+ switch (current->Type)
+ {
+ case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION:
+ {
+ unsigned int state_before, state_after, stencil_state_before = 0, stencil_state_after = 0;
+ const D3D12_RESOURCE_TRANSITION_BARRIER *transition = ¤t->u.Transition;
+
+ if (!is_valid_resource_state(transition->StateBefore))
+ {
+ d3d12_command_list_mark_as_invalid(list,
+ "Invalid StateBefore %#x (barrier %u).", transition->StateBefore, i);
+ continue;
+ }
+ if (!is_valid_resource_state(transition->StateAfter))
+ {
+ d3d12_command_list_mark_as_invalid(list,
+ "Invalid StateAfter %#x (barrier %u).", transition->StateAfter, i);
+ continue;
+ }
+
+ if (!(resource = unsafe_impl_from_ID3D12Resource(transition->pResource)))
+ {
+ d3d12_command_list_mark_as_invalid(list, "A resource pointer is NULL.");
+ continue;
+ }
+
+ if (multiplanar_handled && multiplanar_handled[i])
+ continue;
+
+ state_before = transition->StateBefore;
+ state_after = transition->StateAfter;
+
+ sub_resource_idx = transition->Subresource;
+
+ if (sub_resource_idx != D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES
+ && (resource->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
+ {
+ unsigned int sub_resource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc);
+ unsigned int j = d3d12_find_ds_multiplanar_transition(barriers, i, barrier_count, sub_resource_count);
+ if (j && (multiplanar_handled || (multiplanar_handled = vkd3d_calloc(barrier_count, sizeof(*multiplanar_handled)))))
+ {
+ multiplanar_handled[j] = true;
+ if (sub_resource_idx >= sub_resource_count)
+ {
+ sub_resource_idx -= sub_resource_count;
+ /* The stencil barrier is at i, depth at j. */
+ state_before = barriers[j].u.Transition.StateBefore;
+ state_after = barriers[j].u.Transition.StateAfter;
+ stencil_state_before = transition->StateBefore;
+ stencil_state_after = transition->StateAfter;
+ }
+ else
+ {
+ /* Depth at i, stencil at j. */
+ stencil_state_before = barriers[j].u.Transition.StateBefore;
+ stencil_state_after = barriers[j].u.Transition.StateAfter;
+ }
+ }
+ else if (sub_resource_idx >= sub_resource_count)
+ {
+ FIXME_ONCE("Unhandled sub-resource idx %u.\n", sub_resource_idx);
+ continue;
+ }
+ }
+
+ if (!vk_barrier_parameters_from_d3d12_resource_state(state_before, stencil_state_before,
+ resource, list->vk_queue_flags, vk_info, &src_access_mask, &src_stage_mask, &layout_before))
+ {
+ FIXME("Unhandled state %#x.\n", state_before);
+ continue;
+ }
+ if (!vk_barrier_parameters_from_d3d12_resource_state(state_after, stencil_state_after,
+ resource, list->vk_queue_flags, vk_info, &dst_access_mask, &dst_stage_mask, &layout_after))
+ {
+ FIXME("Unhandled state %#x.\n", state_after);
+ continue;
+ }
+
+ TRACE("Transition barrier (resource %p, subresource %#x, before %#x, after %#x).\n",
+ resource, transition->Subresource, transition->StateBefore, transition->StateAfter);
+ break;
+ }
+
+ case D3D12_RESOURCE_BARRIER_TYPE_UAV:
+ {
+ const D3D12_RESOURCE_UAV_BARRIER *uav = ¤t->u.UAV;
+ VkPipelineStageFlags stage_mask;
+ VkImageLayout image_layout;
+ VkAccessFlags access_mask;
+
+ resource = unsafe_impl_from_ID3D12Resource(uav->pResource);
+ vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0,
+ resource, list->vk_queue_flags, vk_info, &access_mask, &stage_mask, &image_layout);
+ src_access_mask = dst_access_mask = access_mask;
+ src_stage_mask = dst_stage_mask = stage_mask;
+ layout_before = layout_after = image_layout;
+
+ TRACE("UAV barrier (resource %p).\n", resource);
+ break;
+ }
+
+ case D3D12_RESOURCE_BARRIER_TYPE_ALIASING:
+ have_aliasing_barriers = true;
+ continue;
+ default:
+ WARN("Invalid barrier type %#x.\n", current->Type);
+ continue;
+ }
+
+ if (resource)
+ d3d12_command_list_track_resource_usage(list, resource);
+
+ if (!resource)
+ {
+ VkMemoryBarrier vk_barrier;
+
+ vk_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ vk_barrier.pNext = NULL;
+ vk_barrier.srcAccessMask = src_access_mask;
+ vk_barrier.dstAccessMask = dst_access_mask;
+
+ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, src_stage_mask, dst_stage_mask, 0,
+ 1, &vk_barrier, 0, NULL, 0, NULL));
+ }
+ else if (d3d12_resource_is_buffer(resource))
+ {
+ VkBufferMemoryBarrier vk_barrier;
+
+ vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ vk_barrier.pNext = NULL;
+ vk_barrier.srcAccessMask = src_access_mask;
+ vk_barrier.dstAccessMask = dst_access_mask;
+ vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vk_barrier.buffer = resource->u.vk_buffer;
+ vk_barrier.offset = 0;
+ vk_barrier.size = VK_WHOLE_SIZE;
+
+ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, src_stage_mask, dst_stage_mask, 0,
+ 0, NULL, 1, &vk_barrier, 0, NULL));
+ }
+ else
+ {
+ const struct vkd3d_format *format;
+ VkImageMemoryBarrier vk_barrier;
+
+ if (!(format = vkd3d_format_from_d3d12_resource_desc(list->device, &resource->desc, 0)))
+ {
+ ERR("Resource %p has invalid format %#x.\n", resource, resource->desc.Format);
+ continue;
+ }
+
+ vk_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ vk_barrier.pNext = NULL;
+ vk_barrier.srcAccessMask = src_access_mask;
+ vk_barrier.dstAccessMask = dst_access_mask;
+ vk_barrier.oldLayout = layout_before;
+ vk_barrier.newLayout = layout_after;
+ vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vk_barrier.image = resource->u.vk_image;
+
+ vk_barrier.subresourceRange.aspectMask = format->vk_aspect_mask;
+ if (sub_resource_idx == D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)
+ {
+ vk_barrier.subresourceRange.baseMipLevel = 0;
+ vk_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ vk_barrier.subresourceRange.baseArrayLayer = 0;
+ vk_barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ }
+ else
+ {
+ /* FIXME: Some formats in D3D12 are planar. Each plane is a separate sub-resource. */
+ if (sub_resource_idx >= d3d12_resource_desc_get_sub_resource_count(&resource->desc))
+ {
+ FIXME_ONCE("Unhandled sub-resource idx %u.\n", sub_resource_idx);
+ continue;
+ }
+
+ vk_barrier.subresourceRange.baseMipLevel = sub_resource_idx % resource->desc.MipLevels;
+ vk_barrier.subresourceRange.levelCount = 1;
+ vk_barrier.subresourceRange.baseArrayLayer = sub_resource_idx / resource->desc.MipLevels;
+ vk_barrier.subresourceRange.layerCount = 1;
+ }
+
+ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, src_stage_mask, dst_stage_mask, 0,
+ 0, NULL, 0, NULL, 1, &vk_barrier));
+ }
+ }
+
+ vkd3d_free(multiplanar_handled);
+
+ if (have_aliasing_barriers)
+ FIXME_ONCE("Aliasing barriers not implemented yet.\n");
+
+ /* Vulkan doesn't support split barriers. */
+ if (have_split_barriers)
+ WARN("Issuing split barrier(s) on D3D12_RESOURCE_BARRIER_FLAG_END_ONLY.\n");
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ExecuteBundle(ID3D12GraphicsCommandList2 *iface,
+ ID3D12GraphicsCommandList *command_list)
+{
+ FIXME("iface %p, command_list %p stub!\n", iface, command_list);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetDescriptorHeaps(ID3D12GraphicsCommandList2 *iface,
+ UINT heap_count, ID3D12DescriptorHeap *const *heaps)
+{
+ TRACE("iface %p, heap_count %u, heaps %p.\n", iface, heap_count, heaps);
+
+ /* Our current implementation does not need this method.
+ *
+ * It could be used to validate descriptor tables but we do not have an
+ * equivalent of the D3D12 Debug Layer. */
+}
+
+static void d3d12_command_list_set_root_signature(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point, const struct d3d12_root_signature *root_signature)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+
+ if (bindings->root_signature == root_signature)
+ return;
+
+ bindings->root_signature = root_signature;
+
+ d3d12_command_list_invalidate_root_parameters(list, bind_point);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetComputeRootSignature(ID3D12GraphicsCommandList2 *iface,
+ ID3D12RootSignature *root_signature)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_signature %p.\n", iface, root_signature);
+
+ d3d12_command_list_set_root_signature(list, VK_PIPELINE_BIND_POINT_COMPUTE,
+ unsafe_impl_from_ID3D12RootSignature(root_signature));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRootSignature(ID3D12GraphicsCommandList2 *iface,
+ ID3D12RootSignature *root_signature)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_signature %p.\n", iface, root_signature);
+
+ d3d12_command_list_set_root_signature(list, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ unsafe_impl_from_ID3D12RootSignature(root_signature));
+}
+
+static void d3d12_command_list_set_descriptor_table(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point, unsigned int index, D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+ const struct d3d12_root_signature *root_signature = bindings->root_signature;
+
+ assert(root_signature_get_descriptor_table(root_signature, index));
+
+ assert(index < ARRAY_SIZE(bindings->descriptor_tables));
+ bindings->descriptor_tables[index] = base_descriptor;
+ bindings->descriptor_table_dirty_mask |= (uint64_t)1 << index;
+ bindings->descriptor_table_active_mask |= (uint64_t)1 << index;
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetComputeRootDescriptorTable(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, base_descriptor %#"PRIx64".\n",
+ iface, root_parameter_index, base_descriptor.ptr);
+
+ d3d12_command_list_set_descriptor_table(list, VK_PIPELINE_BIND_POINT_COMPUTE,
+ root_parameter_index, base_descriptor);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRootDescriptorTable(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, D3D12_GPU_DESCRIPTOR_HANDLE base_descriptor)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, base_descriptor %#"PRIx64".\n",
+ iface, root_parameter_index, base_descriptor.ptr);
+
+ d3d12_command_list_set_descriptor_table(list, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ root_parameter_index, base_descriptor);
+}
+
+static void d3d12_command_list_set_root_constants(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point, unsigned int index, unsigned int offset,
+ unsigned int count, const void *data)
+{
+ const struct d3d12_root_signature *root_signature = list->pipeline_bindings[bind_point].root_signature;
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ const struct d3d12_root_constant *c;
+
+ c = root_signature_get_32bit_constants(root_signature, index);
+ VK_CALL(vkCmdPushConstants(list->vk_command_buffer, root_signature->vk_pipeline_layout,
+ c->stage_flags, c->offset + offset * sizeof(uint32_t), count * sizeof(uint32_t), data));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetComputeRoot32BitConstant(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, UINT data, UINT dst_offset)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, data 0x%08x, dst_offset %u.\n",
+ iface, root_parameter_index, data, dst_offset);
+
+ d3d12_command_list_set_root_constants(list, VK_PIPELINE_BIND_POINT_COMPUTE,
+ root_parameter_index, dst_offset, 1, &data);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRoot32BitConstant(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, UINT data, UINT dst_offset)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, data 0x%08x, dst_offset %u.\n",
+ iface, root_parameter_index, data, dst_offset);
+
+ d3d12_command_list_set_root_constants(list, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ root_parameter_index, dst_offset, 1, &data);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetComputeRoot32BitConstants(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, UINT constant_count, const void *data, UINT dst_offset)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, constant_count %u, data %p, dst_offset %u.\n",
+ iface, root_parameter_index, constant_count, data, dst_offset);
+
+ d3d12_command_list_set_root_constants(list, VK_PIPELINE_BIND_POINT_COMPUTE,
+ root_parameter_index, dst_offset, constant_count, data);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRoot32BitConstants(ID3D12GraphicsCommandList2 *iface,
+ UINT root_parameter_index, UINT constant_count, const void *data, UINT dst_offset)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, constant_count %u, data %p, dst_offset %u.\n",
+ iface, root_parameter_index, constant_count, data, dst_offset);
+
+ d3d12_command_list_set_root_constants(list, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ root_parameter_index, dst_offset, constant_count, data);
+}
+
+static void d3d12_command_list_set_root_cbv(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point, unsigned int index, D3D12_GPU_VIRTUAL_ADDRESS gpu_address)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+ const struct d3d12_root_signature *root_signature = bindings->root_signature;
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ const struct vkd3d_vulkan_info *vk_info = &list->device->vk_info;
+ const struct d3d12_root_parameter *root_parameter;
+ struct VkWriteDescriptorSet descriptor_write;
+ struct VkDescriptorBufferInfo buffer_info;
+ struct d3d12_resource *resource;
+
+ root_parameter = root_signature_get_root_descriptor(root_signature, index);
+ assert(root_parameter->parameter_type == D3D12_ROOT_PARAMETER_TYPE_CBV);
+
+ resource = vkd3d_gpu_va_allocator_dereference(&list->device->gpu_va_allocator, gpu_address);
+ buffer_info.buffer = resource->u.vk_buffer;
+ buffer_info.offset = gpu_address - resource->gpu_address;
+ buffer_info.range = resource->desc.Width - buffer_info.offset;
+ buffer_info.range = min(buffer_info.range, vk_info->device_limits.maxUniformBufferRange);
+
+ if (vk_info->KHR_push_descriptor)
+ {
+ vk_write_descriptor_set_from_root_descriptor(&descriptor_write,
+ root_parameter, VK_NULL_HANDLE, NULL, &buffer_info);
+ VK_CALL(vkCmdPushDescriptorSetKHR(list->vk_command_buffer, bindings->vk_bind_point,
+ root_signature->vk_pipeline_layout, 0, 1, &descriptor_write));
+ }
+ else
+ {
+ d3d12_command_list_prepare_descriptors(list, bind_point);
+ vk_write_descriptor_set_from_root_descriptor(&descriptor_write,
+ root_parameter, bindings->descriptor_set, NULL, &buffer_info);
+ VK_CALL(vkUpdateDescriptorSets(list->device->vk_device, 1, &descriptor_write, 0, NULL));
+
+ assert(index < ARRAY_SIZE(bindings->push_descriptors));
+ bindings->push_descriptors[index].u.cbv.vk_buffer = buffer_info.buffer;
+ bindings->push_descriptors[index].u.cbv.offset = buffer_info.offset;
+ bindings->push_descriptor_dirty_mask |= 1u << index;
+ bindings->push_descriptor_active_mask |= 1u << index;
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetComputeRootConstantBufferView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, address %#"PRIx64".\n",
+ iface, root_parameter_index, address);
+
+ d3d12_command_list_set_root_cbv(list, VK_PIPELINE_BIND_POINT_COMPUTE, root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRootConstantBufferView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, address %#"PRIx64".\n",
+ iface, root_parameter_index, address);
+
+ d3d12_command_list_set_root_cbv(list, VK_PIPELINE_BIND_POINT_GRAPHICS, root_parameter_index, address);
+}
+
+static void d3d12_command_list_set_root_descriptor(struct d3d12_command_list *list,
+ enum vkd3d_pipeline_bind_point bind_point, unsigned int index, D3D12_GPU_VIRTUAL_ADDRESS gpu_address)
+{
+ struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
+ const struct d3d12_root_signature *root_signature = bindings->root_signature;
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ const struct vkd3d_vulkan_info *vk_info = &list->device->vk_info;
+ const struct d3d12_root_parameter *root_parameter;
+ struct VkWriteDescriptorSet descriptor_write;
+ VkDevice vk_device = list->device->vk_device;
+ VkBufferView vk_buffer_view;
+
+ root_parameter = root_signature_get_root_descriptor(root_signature, index);
+ assert(root_parameter->parameter_type != D3D12_ROOT_PARAMETER_TYPE_CBV);
+
+ /* FIXME: Re-use buffer views. */
+ if (!vkd3d_create_raw_buffer_view(list->device, gpu_address, &vk_buffer_view))
+ {
+ ERR("Failed to create buffer view.\n");
+ return;
+ }
+
+ if (!(d3d12_command_allocator_add_buffer_view(list->allocator, vk_buffer_view)))
+ {
+ ERR("Failed to add buffer view.\n");
+ VK_CALL(vkDestroyBufferView(vk_device, vk_buffer_view, NULL));
+ return;
+ }
+
+ if (vk_info->KHR_push_descriptor)
+ {
+ vk_write_descriptor_set_from_root_descriptor(&descriptor_write,
+ root_parameter, VK_NULL_HANDLE, &vk_buffer_view, NULL);
+ VK_CALL(vkCmdPushDescriptorSetKHR(list->vk_command_buffer, bindings->vk_bind_point,
+ root_signature->vk_pipeline_layout, 0, 1, &descriptor_write));
+ }
+ else
+ {
+ d3d12_command_list_prepare_descriptors(list, bind_point);
+ vk_write_descriptor_set_from_root_descriptor(&descriptor_write,
+ root_parameter, bindings->descriptor_set, &vk_buffer_view, NULL);
+ VK_CALL(vkUpdateDescriptorSets(list->device->vk_device, 1, &descriptor_write, 0, NULL));
+
+ assert(index < ARRAY_SIZE(bindings->push_descriptors));
+ bindings->push_descriptors[index].u.vk_buffer_view = vk_buffer_view;
+ bindings->push_descriptor_dirty_mask |= 1u << index;
+ bindings->push_descriptor_active_mask |= 1u << index;
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetComputeRootShaderResourceView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, address %#"PRIx64".\n",
+ iface, root_parameter_index, address);
+
+ d3d12_command_list_set_root_descriptor(list, VKD3D_PIPELINE_BIND_POINT_COMPUTE,
+ root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRootShaderResourceView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, address %#"PRIx64".\n",
+ iface, root_parameter_index, address);
+
+ d3d12_command_list_set_root_descriptor(list, VKD3D_PIPELINE_BIND_POINT_GRAPHICS,
+ root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetComputeRootUnorderedAccessView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, address %#"PRIx64".\n",
+ iface, root_parameter_index, address);
+
+ d3d12_command_list_set_root_descriptor(list, VKD3D_PIPELINE_BIND_POINT_COMPUTE,
+ root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRootUnorderedAccessView(
+ ID3D12GraphicsCommandList2 *iface, UINT root_parameter_index, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+
+ TRACE("iface %p, root_parameter_index %u, address %#"PRIx64".\n",
+ iface, root_parameter_index, address);
+
+ d3d12_command_list_set_root_descriptor(list, VKD3D_PIPELINE_BIND_POINT_GRAPHICS,
+ root_parameter_index, address);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_IASetIndexBuffer(ID3D12GraphicsCommandList2 *iface,
+ const D3D12_INDEX_BUFFER_VIEW *view)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ struct d3d12_resource *resource;
+ enum VkIndexType index_type;
+
+ TRACE("iface %p, view %p.\n", iface, view);
+
+ if (!view)
+ {
+ WARN("Ignoring NULL index buffer view.\n");
+ return;
+ }
+
+ vk_procs = &list->device->vk_procs;
+
+ switch (view->Format)
+ {
+ case DXGI_FORMAT_R16_UINT:
+ index_type = VK_INDEX_TYPE_UINT16;
+ break;
+ case DXGI_FORMAT_R32_UINT:
+ index_type = VK_INDEX_TYPE_UINT32;
+ break;
+ default:
+ WARN("Invalid index format %#x.\n", view->Format);
+ return;
+ }
+
+ list->index_buffer_format = view->Format;
+
+ resource = vkd3d_gpu_va_allocator_dereference(&list->device->gpu_va_allocator, view->BufferLocation);
+ VK_CALL(vkCmdBindIndexBuffer(list->vk_command_buffer, resource->u.vk_buffer,
+ view->BufferLocation - resource->gpu_address, index_type));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_IASetVertexBuffers(ID3D12GraphicsCommandList2 *iface,
+ UINT start_slot, UINT view_count, const D3D12_VERTEX_BUFFER_VIEW *views)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct vkd3d_null_resources *null_resources;
+ struct vkd3d_gpu_va_allocator *gpu_va_allocator;
+ VkDeviceSize offsets[ARRAY_SIZE(list->strides)];
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkBuffer buffers[ARRAY_SIZE(list->strides)];
+ struct d3d12_resource *resource;
+ bool invalidate = false;
+ unsigned int i, stride;
+
+ TRACE("iface %p, start_slot %u, view_count %u, views %p.\n", iface, start_slot, view_count, views);
+
+ vk_procs = &list->device->vk_procs;
+ null_resources = &list->device->null_resources;
+ gpu_va_allocator = &list->device->gpu_va_allocator;
+
+ if (start_slot >= ARRAY_SIZE(list->strides) || view_count > ARRAY_SIZE(list->strides) - start_slot)
+ {
+ WARN("Invalid start slot %u / view count %u.\n", start_slot, view_count);
+ return;
+ }
+
+ for (i = 0; i < view_count; ++i)
+ {
+ if (views[i].BufferLocation)
+ {
+ resource = vkd3d_gpu_va_allocator_dereference(gpu_va_allocator, views[i].BufferLocation);
+ buffers[i] = resource->u.vk_buffer;
+ offsets[i] = views[i].BufferLocation - resource->gpu_address;
+ stride = views[i].StrideInBytes;
+ }
+ else
+ {
+ buffers[i] = null_resources->vk_buffer;
+ offsets[i] = 0;
+ stride = 0;
+ }
+
+ invalidate |= list->strides[start_slot + i] != stride;
+ list->strides[start_slot + i] = stride;
+ }
+
+ if (view_count)
+ VK_CALL(vkCmdBindVertexBuffers(list->vk_command_buffer, start_slot, view_count, buffers, offsets));
+
+ if (invalidate)
+ d3d12_command_list_invalidate_current_pipeline(list);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SOSetTargets(ID3D12GraphicsCommandList2 *iface,
+ UINT start_slot, UINT view_count, const D3D12_STREAM_OUTPUT_BUFFER_VIEW *views)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ VkDeviceSize offsets[ARRAY_SIZE(list->so_counter_buffers)];
+ VkDeviceSize sizes[ARRAY_SIZE(list->so_counter_buffers)];
+ VkBuffer buffers[ARRAY_SIZE(list->so_counter_buffers)];
+ struct vkd3d_gpu_va_allocator *gpu_va_allocator;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ struct d3d12_resource *resource;
+ unsigned int i, first, count;
+
+ TRACE("iface %p, start_slot %u, view_count %u, views %p.\n", iface, start_slot, view_count, views);
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ if (!list->device->vk_info.EXT_transform_feedback)
+ {
+ FIXME("Transform feedback is not supported by Vulkan implementation.\n");
+ return;
+ }
+
+ if (start_slot >= ARRAY_SIZE(buffers) || view_count > ARRAY_SIZE(buffers) - start_slot)
+ {
+ WARN("Invalid start slot %u / view count %u.\n", start_slot, view_count);
+ return;
+ }
+
+ vk_procs = &list->device->vk_procs;
+ gpu_va_allocator = &list->device->gpu_va_allocator;
+
+ count = 0;
+ first = start_slot;
+ for (i = 0; i < view_count; ++i)
+ {
+ if (views[i].BufferLocation && views[i].SizeInBytes)
+ {
+ resource = vkd3d_gpu_va_allocator_dereference(gpu_va_allocator, views[i].BufferLocation);
+ buffers[count] = resource->u.vk_buffer;
+ offsets[count] = views[i].BufferLocation - resource->gpu_address;
+ sizes[count] = views[i].SizeInBytes;
+
+ resource = vkd3d_gpu_va_allocator_dereference(gpu_va_allocator, views[i].BufferFilledSizeLocation);
+ list->so_counter_buffers[start_slot + i] = resource->u.vk_buffer;
+ list->so_counter_buffer_offsets[start_slot + i] = views[i].BufferFilledSizeLocation - resource->gpu_address;
+ ++count;
+ }
+ else
+ {
+ if (count)
+ VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(list->vk_command_buffer, first, count, buffers, offsets, sizes));
+ count = 0;
+ first = start_slot + i + 1;
+
+ list->so_counter_buffers[start_slot + i] = VK_NULL_HANDLE;
+ list->so_counter_buffer_offsets[start_slot + i] = 0;
+
+ WARN("Trying to unbind transform feedback buffer %u. Ignoring.\n", start_slot + i);
+ }
+ }
+
+ if (count)
+ VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(list->vk_command_buffer, first, count, buffers, offsets, sizes));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12GraphicsCommandList2 *iface,
+ UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors,
+ BOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct d3d12_rtv_desc *rtv_desc;
+ const struct d3d12_dsv_desc *dsv_desc;
+ VkFormat prev_dsv_format;
+ struct vkd3d_view *view;
+ unsigned int i;
+
+ TRACE("iface %p, render_target_descriptor_count %u, render_target_descriptors %p, "
+ "single_descriptor_handle %#x, depth_stencil_descriptor %p.\n",
+ iface, render_target_descriptor_count, render_target_descriptors,
+ single_descriptor_handle, depth_stencil_descriptor);
+
+ if (render_target_descriptor_count > ARRAY_SIZE(list->rtvs))
+ {
+ WARN("Descriptor count %u > %zu, ignoring extra descriptors.\n",
+ render_target_descriptor_count, ARRAY_SIZE(list->rtvs));
+ render_target_descriptor_count = ARRAY_SIZE(list->rtvs);
+ }
+
+ list->fb_width = 0;
+ list->fb_height = 0;
+ list->fb_layer_count = 0;
+ for (i = 0; i < render_target_descriptor_count; ++i)
+ {
+ if (single_descriptor_handle)
+ {
+ if ((rtv_desc = d3d12_rtv_desc_from_cpu_handle(*render_target_descriptors)))
+ rtv_desc += i;
+ }
+ else
+ {
+ rtv_desc = d3d12_rtv_desc_from_cpu_handle(render_target_descriptors[i]);
+ }
+
+ if (!rtv_desc || !rtv_desc->resource)
+ {
+ WARN("RTV descriptor %u is not initialized.\n", i);
+ list->rtvs[i] = VK_NULL_HANDLE;
+ continue;
+ }
+
+ d3d12_command_list_track_resource_usage(list, rtv_desc->resource);
+
+ /* In D3D12 CPU descriptors are consumed when a command is recorded. */
+ view = rtv_desc->view;
+ if (!d3d12_command_allocator_add_view(list->allocator, view))
+ {
+ WARN("Failed to add view.\n");
+ }
+
+ list->rtvs[i] = view->u.vk_image_view;
+ list->fb_width = max(list->fb_width, rtv_desc->width);
+ list->fb_height = max(list->fb_height, rtv_desc->height);
+ list->fb_layer_count = max(list->fb_layer_count, rtv_desc->layer_count);
+ }
+
+ prev_dsv_format = list->dsv_format;
+ list->dsv = VK_NULL_HANDLE;
+ list->dsv_format = VK_FORMAT_UNDEFINED;
+ if (depth_stencil_descriptor)
+ {
+ if ((dsv_desc = d3d12_dsv_desc_from_cpu_handle(*depth_stencil_descriptor))
+ && dsv_desc->resource)
+ {
+ d3d12_command_list_track_resource_usage(list, dsv_desc->resource);
+
+ /* In D3D12 CPU descriptors are consumed when a command is recorded. */
+ view = dsv_desc->view;
+ if (!d3d12_command_allocator_add_view(list->allocator, view))
+ {
+ WARN("Failed to add view.\n");
+ list->dsv = VK_NULL_HANDLE;
+ }
+
+ list->dsv = view->u.vk_image_view;
+ list->fb_width = max(list->fb_width, dsv_desc->width);
+ list->fb_height = max(list->fb_height, dsv_desc->height);
+ list->fb_layer_count = max(list->fb_layer_count, dsv_desc->layer_count);
+ list->dsv_format = dsv_desc->format->vk_format;
+ }
+ else
+ {
+ WARN("DSV descriptor is not initialized.\n");
+ }
+ }
+
+ if (prev_dsv_format != list->dsv_format && d3d12_pipeline_state_has_unknown_dsv_format(list->state))
+ d3d12_command_list_invalidate_current_pipeline(list);
+
+ d3d12_command_list_invalidate_current_framebuffer(list);
+ d3d12_command_list_invalidate_current_render_pass(list);
+}
+
+static void d3d12_command_list_clear(struct d3d12_command_list *list,
+ const struct VkAttachmentDescription *attachment_desc,
+ const struct VkAttachmentReference *color_reference, const struct VkAttachmentReference *ds_reference,
+ struct vkd3d_view *view, size_t width, size_t height, unsigned int layer_count,
+ const union VkClearValue *clear_value, unsigned int rect_count, const D3D12_RECT *rects)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ struct VkSubpassDescription sub_pass_desc;
+ struct VkRenderPassCreateInfo pass_desc;
+ struct VkRenderPassBeginInfo begin_desc;
+ struct VkFramebufferCreateInfo fb_desc;
+ VkFramebuffer vk_framebuffer;
+ VkRenderPass vk_render_pass;
+ D3D12_RECT full_rect;
+ unsigned int i;
+ VkResult vr;
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ if (!rect_count)
+ {
+ full_rect.top = 0;
+ full_rect.left = 0;
+ full_rect.bottom = height;
+ full_rect.right = width;
+
+ rect_count = 1;
+ rects = &full_rect;
+ }
+
+ sub_pass_desc.flags = 0;
+ sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ sub_pass_desc.inputAttachmentCount = 0;
+ sub_pass_desc.pInputAttachments = NULL;
+ sub_pass_desc.colorAttachmentCount = !!color_reference;
+ sub_pass_desc.pColorAttachments = color_reference;
+ sub_pass_desc.pResolveAttachments = NULL;
+ sub_pass_desc.pDepthStencilAttachment = ds_reference;
+ sub_pass_desc.preserveAttachmentCount = 0;
+ sub_pass_desc.pPreserveAttachments = NULL;
+
+ pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ pass_desc.pNext = NULL;
+ pass_desc.flags = 0;
+ pass_desc.attachmentCount = 1;
+ pass_desc.pAttachments = attachment_desc;
+ pass_desc.subpassCount = 1;
+ pass_desc.pSubpasses = &sub_pass_desc;
+ pass_desc.dependencyCount = 0;
+ pass_desc.pDependencies = NULL;
+ if ((vr = VK_CALL(vkCreateRenderPass(list->device->vk_device, &pass_desc, NULL, &vk_render_pass))) < 0)
+ {
+ WARN("Failed to create Vulkan render pass, vr %d.\n", vr);
+ return;
+ }
+
+ if (!d3d12_command_allocator_add_render_pass(list->allocator, vk_render_pass))
+ {
+ WARN("Failed to add render pass.\n");
+ VK_CALL(vkDestroyRenderPass(list->device->vk_device, vk_render_pass, NULL));
+ return;
+ }
+
+ if (!d3d12_command_allocator_add_view(list->allocator, view))
+ {
+ WARN("Failed to add view.\n");
+ }
+
+ fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fb_desc.pNext = NULL;
+ fb_desc.flags = 0;
+ fb_desc.renderPass = vk_render_pass;
+ fb_desc.attachmentCount = 1;
+ fb_desc.pAttachments = &view->u.vk_image_view;
+ fb_desc.width = width;
+ fb_desc.height = height;
+ fb_desc.layers = layer_count;
+ if ((vr = VK_CALL(vkCreateFramebuffer(list->device->vk_device, &fb_desc, NULL, &vk_framebuffer))) < 0)
+ {
+ WARN("Failed to create Vulkan framebuffer, vr %d.\n", vr);
+ return;
+ }
+
+ if (!d3d12_command_allocator_add_framebuffer(list->allocator, vk_framebuffer))
+ {
+ WARN("Failed to add framebuffer.\n");
+ VK_CALL(vkDestroyFramebuffer(list->device->vk_device, vk_framebuffer, NULL));
+ return;
+ }
+
+ begin_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ begin_desc.pNext = NULL;
+ begin_desc.renderPass = vk_render_pass;
+ begin_desc.framebuffer = vk_framebuffer;
+ begin_desc.clearValueCount = 1;
+ begin_desc.pClearValues = clear_value;
+
+ for (i = 0; i < rect_count; ++i)
+ {
+ begin_desc.renderArea.offset.x = rects[i].left;
+ begin_desc.renderArea.offset.y = rects[i].top;
+ begin_desc.renderArea.extent.width = rects[i].right - rects[i].left;
+ begin_desc.renderArea.extent.height = rects[i].bottom - rects[i].top;
+ VK_CALL(vkCmdBeginRenderPass(list->vk_command_buffer, &begin_desc, VK_SUBPASS_CONTENTS_INLINE));
+ VK_CALL(vkCmdEndRenderPass(list->vk_command_buffer));
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ClearDepthStencilView(ID3D12GraphicsCommandList2 *iface,
+ D3D12_CPU_DESCRIPTOR_HANDLE dsv, D3D12_CLEAR_FLAGS flags, float depth, UINT8 stencil,
+ UINT rect_count, const D3D12_RECT *rects)
+{
+ const union VkClearValue clear_value = {.depthStencil = {depth, stencil}};
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct d3d12_dsv_desc *dsv_desc = d3d12_dsv_desc_from_cpu_handle(dsv);
+ struct VkAttachmentDescription attachment_desc;
+ struct VkAttachmentReference ds_reference;
+
+ TRACE("iface %p, dsv %#lx, flags %#x, depth %.8e, stencil 0x%02x, rect_count %u, rects %p.\n",
+ iface, dsv.ptr, flags, depth, stencil, rect_count, rects);
+
+ d3d12_command_list_track_resource_usage(list, dsv_desc->resource);
+
+ attachment_desc.flags = 0;
+ attachment_desc.format = dsv_desc->format->vk_format;
+ attachment_desc.samples = dsv_desc->sample_count;
+ if (flags & D3D12_CLEAR_FLAG_DEPTH)
+ {
+ attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ }
+ else
+ {
+ attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ }
+ if (flags & D3D12_CLEAR_FLAG_STENCIL)
+ {
+ attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+ }
+ else
+ {
+ attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ }
+ attachment_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ attachment_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ ds_reference.attachment = 0;
+ ds_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ d3d12_command_list_clear(list, &attachment_desc, NULL, &ds_reference,
+ dsv_desc->view, dsv_desc->width, dsv_desc->height, dsv_desc->layer_count,
+ &clear_value, rect_count, rects);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12GraphicsCommandList2 *iface,
+ D3D12_CPU_DESCRIPTOR_HANDLE rtv, const FLOAT color[4], UINT rect_count, const D3D12_RECT *rects)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const struct d3d12_rtv_desc *rtv_desc = d3d12_rtv_desc_from_cpu_handle(rtv);
+ struct VkAttachmentDescription attachment_desc;
+ struct VkAttachmentReference color_reference;
+ VkClearValue clear_value;
+
+ TRACE("iface %p, rtv %#lx, color %p, rect_count %u, rects %p.\n",
+ iface, rtv.ptr, color, rect_count, rects);
+
+ d3d12_command_list_track_resource_usage(list, rtv_desc->resource);
+
+ attachment_desc.flags = 0;
+ attachment_desc.format = rtv_desc->format->vk_format;
+ attachment_desc.samples = rtv_desc->sample_count;
+ attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attachment_desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ color_reference.attachment = 0;
+ color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ if (rtv_desc->format->type == VKD3D_FORMAT_TYPE_UINT)
+ {
+ clear_value.color.uint32[0] = max(0, color[0]);
+ clear_value.color.uint32[1] = max(0, color[1]);
+ clear_value.color.uint32[2] = max(0, color[2]);
+ clear_value.color.uint32[3] = max(0, color[3]);
+ }
+ else if (rtv_desc->format->type == VKD3D_FORMAT_TYPE_SINT)
+ {
+ clear_value.color.int32[0] = color[0];
+ clear_value.color.int32[1] = color[1];
+ clear_value.color.int32[2] = color[2];
+ clear_value.color.int32[3] = color[3];
+ }
+ else
+ {
+ clear_value.color.float32[0] = color[0];
+ clear_value.color.float32[1] = color[1];
+ clear_value.color.float32[2] = color[2];
+ clear_value.color.float32[3] = color[3];
+ }
+
+ d3d12_command_list_clear(list, &attachment_desc, &color_reference, NULL,
+ rtv_desc->view, rtv_desc->width, rtv_desc->height, rtv_desc->layer_count,
+ &clear_value, rect_count, rects);
+}
+
+struct vkd3d_uav_clear_pipeline
+{
+ VkDescriptorSetLayout vk_set_layout;
+ VkPipelineLayout vk_pipeline_layout;
+ VkPipeline vk_pipeline;
+ VkExtent3D group_size;
+};
+
+static void vkd3d_uav_clear_state_get_buffer_pipeline(const struct vkd3d_uav_clear_state *state,
+ enum vkd3d_format_type format_type, struct vkd3d_uav_clear_pipeline *info)
+{
+ const struct vkd3d_uav_clear_pipelines *pipelines;
+
+ pipelines = format_type == VKD3D_FORMAT_TYPE_UINT ? &state->pipelines_uint : &state->pipelines_float;
+ info->vk_set_layout = state->vk_set_layout_buffer;
+ info->vk_pipeline_layout = state->vk_pipeline_layout_buffer;
+ info->vk_pipeline = pipelines->buffer;
+ info->group_size = (VkExtent3D){128, 1, 1};
+}
+
+static void vkd3d_uav_clear_state_get_image_pipeline(const struct vkd3d_uav_clear_state *state,
+ VkImageViewType image_view_type, enum vkd3d_format_type format_type, struct vkd3d_uav_clear_pipeline *info)
+{
+ const struct vkd3d_uav_clear_pipelines *pipelines;
+
+ pipelines = format_type == VKD3D_FORMAT_TYPE_UINT ? &state->pipelines_uint : &state->pipelines_float;
+ info->vk_set_layout = state->vk_set_layout_image;
+ info->vk_pipeline_layout = state->vk_pipeline_layout_image;
+
+ switch (image_view_type)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ info->vk_pipeline = pipelines->image_1d;
+ info->group_size = (VkExtent3D){64, 1, 1};
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ info->vk_pipeline = pipelines->image_1d_array;
+ info->group_size = (VkExtent3D){64, 1, 1};
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D:
+ info->vk_pipeline = pipelines->image_2d;
+ info->group_size = (VkExtent3D){8, 8, 1};
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ info->vk_pipeline = pipelines->image_2d_array;
+ info->group_size = (VkExtent3D){8, 8, 1};
+ break;
+
+ case VK_IMAGE_VIEW_TYPE_3D:
+ info->vk_pipeline = pipelines->image_3d;
+ info->group_size = (VkExtent3D){8, 8, 1};
+ break;
+
+ default:
+ ERR("Unhandled view type %#x.\n", image_view_type);
+ info->vk_pipeline = VK_NULL_HANDLE;
+ info->group_size = (VkExtent3D){0, 0, 0};
+ break;
+ }
+}
+
+static void d3d12_command_list_clear_uav(struct d3d12_command_list *list,
+ struct d3d12_resource *resource, struct vkd3d_view *view, const VkClearColorValue *clear_colour,
+ unsigned int rect_count, const D3D12_RECT *rects)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ unsigned int i, miplevel_idx, layer_count;
+ struct vkd3d_uav_clear_pipeline pipeline;
+ struct vkd3d_uav_clear_args clear_args;
+ VkDescriptorImageInfo image_info;
+ D3D12_RECT full_rect, curr_rect;
+ VkWriteDescriptorSet write_set;
+
+ d3d12_command_list_track_resource_usage(list, resource);
+ d3d12_command_list_end_current_render_pass(list);
+
+ d3d12_command_list_invalidate_current_pipeline(list);
+ d3d12_command_list_invalidate_bindings(list, list->state);
+ d3d12_command_list_invalidate_root_parameters(list, VK_PIPELINE_BIND_POINT_COMPUTE);
+
+ if (!d3d12_command_allocator_add_view(list->allocator, view))
+ WARN("Failed to add view.\n");
+
+ clear_args.colour = *clear_colour;
+
+ write_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write_set.pNext = NULL;
+ write_set.dstBinding = 0;
+ write_set.dstArrayElement = 0;
+ write_set.descriptorCount = 1;
+
+ if (d3d12_resource_is_buffer(resource))
+ {
+ write_set.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ write_set.pImageInfo = NULL;
+ write_set.pBufferInfo = NULL;
+ write_set.pTexelBufferView = &view->u.vk_buffer_view;
+
+ miplevel_idx = 0;
+ layer_count = 1;
+ vkd3d_uav_clear_state_get_buffer_pipeline(&list->device->uav_clear_state,
+ view->format->type, &pipeline);
+ }
+ else
+ {
+ image_info.sampler = VK_NULL_HANDLE;
+ image_info.imageView = view->u.vk_image_view;
+ image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+ write_set.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ write_set.pImageInfo = &image_info;
+ write_set.pBufferInfo = NULL;
+ write_set.pTexelBufferView = NULL;
+
+ miplevel_idx = view->info.texture.miplevel_idx;
+ layer_count = view->info.texture.vk_view_type == VK_IMAGE_VIEW_TYPE_3D
+ ? d3d12_resource_desc_get_depth(&resource->desc, miplevel_idx)
+ : view->info.texture.layer_count;
+ vkd3d_uav_clear_state_get_image_pipeline(&list->device->uav_clear_state,
+ view->info.texture.vk_view_type, view->format->type, &pipeline);
+ }
+
+ if (!(write_set.dstSet = d3d12_command_allocator_allocate_descriptor_set(
+ list->allocator, pipeline.vk_set_layout)))
+ {
+ ERR("Failed to allocate descriptor set.\n");
+ return;
+ }
+
+ VK_CALL(vkUpdateDescriptorSets(list->device->vk_device, 1, &write_set, 0, NULL));
+
+ full_rect.left = 0;
+ full_rect.right = d3d12_resource_desc_get_width(&resource->desc, miplevel_idx);
+ full_rect.top = 0;
+ full_rect.bottom = d3d12_resource_desc_get_height(&resource->desc, miplevel_idx);
+
+ if (!rect_count)
+ {
+ rects = &full_rect;
+ rect_count = 1;
+ }
+
+ VK_CALL(vkCmdBindPipeline(list->vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.vk_pipeline));
+
+ VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE,
+ pipeline.vk_pipeline_layout, 0, 1, &write_set.dstSet, 0, NULL));
+
+ for (i = 0; i < rect_count; ++i)
+ {
+ /* Clamp to the actual resource region and skip empty rectangles. */
+ curr_rect.left = max(rects[i].left, full_rect.left);
+ curr_rect.top = max(rects[i].top, full_rect.top);
+ curr_rect.right = min(rects[i].right, full_rect.right);
+ curr_rect.bottom = min(rects[i].bottom, full_rect.bottom);
+
+ if (curr_rect.left >= curr_rect.right || curr_rect.top >= curr_rect.bottom)
+ continue;
+
+ clear_args.offset.x = curr_rect.left;
+ clear_args.offset.y = curr_rect.top;
+ clear_args.extent.width = curr_rect.right - curr_rect.left;
+ clear_args.extent.height = curr_rect.bottom - curr_rect.top;
+
+ VK_CALL(vkCmdPushConstants(list->vk_command_buffer, pipeline.vk_pipeline_layout,
+ VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(clear_args), &clear_args));
+
+ VK_CALL(vkCmdDispatch(list->vk_command_buffer,
+ vkd3d_compute_workgroup_count(clear_args.extent.width, pipeline.group_size.width),
+ vkd3d_compute_workgroup_count(clear_args.extent.height, pipeline.group_size.height),
+ vkd3d_compute_workgroup_count(layer_count, pipeline.group_size.depth)));
+ }
+}
+
+static const struct vkd3d_format *vkd3d_fixup_clear_uav_uint_colour(struct d3d12_device *device,
+ DXGI_FORMAT dxgi_format, VkClearColorValue *colour)
+{
+ switch (dxgi_format)
+ {
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ colour->uint32[0] = (colour->uint32[0] & 0x7ff)
+ | ((colour->uint32[1] & 0x7ff) << 11)
+ | ((colour->uint32[2] & 0x3ff) << 22);
+ return vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
+
+ default:
+ return NULL;
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID3D12GraphicsCommandList2 *iface,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource,
+ const UINT values[4], UINT rect_count, const D3D12_RECT *rects)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_device *device = list->device;
+ struct vkd3d_view *view, *uint_view = NULL;
+ struct vkd3d_texture_view_desc view_desc;
+ const struct vkd3d_format *uint_format;
+ struct d3d12_resource *resource_impl;
+ VkClearColorValue colour;
+
+ TRACE("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p.\n",
+ iface, gpu_handle.ptr, cpu_handle.ptr, resource, values, rect_count, rects);
+
+ resource_impl = unsafe_impl_from_ID3D12Resource(resource);
+ view = d3d12_desc_from_cpu_handle(cpu_handle)->u.view;
+ memcpy(colour.uint32, values, sizeof(colour.uint32));
+
+ if (view->format->type != VKD3D_FORMAT_TYPE_UINT)
+ {
+ if (!(uint_format = vkd3d_find_uint_format(device, view->format->dxgi_format))
+ && !(uint_format = vkd3d_fixup_clear_uav_uint_colour(device, view->format->dxgi_format, &colour)))
+ {
+ ERR("Unhandled format %#x.\n", view->format->dxgi_format);
+ return;
+ }
+
+ if (d3d12_resource_is_buffer(resource_impl))
+ {
+ if (!vkd3d_create_buffer_view(device, resource_impl->u.vk_buffer, uint_format,
+ view->info.buffer.offset, view->info.buffer.size, &uint_view))
+ {
+ ERR("Failed to create buffer view.\n");
+ return;
+ }
+ }
+ else
+ {
+ memset(&view_desc, 0, sizeof(view_desc));
+ view_desc.view_type = view->info.texture.vk_view_type;
+ view_desc.format = uint_format;
+ view_desc.miplevel_idx = view->info.texture.miplevel_idx;
+ view_desc.miplevel_count = 1;
+ view_desc.layer_idx = view->info.texture.layer_idx;
+ view_desc.layer_count = view->info.texture.layer_count;
+
+ if (!vkd3d_create_texture_view(device, resource_impl->u.vk_image, &view_desc, &uint_view))
+ {
+ ERR("Failed to create image view.\n");
+ return;
+ }
+ }
+ view = uint_view;
+ }
+
+ d3d12_command_list_clear_uav(list, resource_impl, view, &colour, rect_count, rects);
+
+ if (uint_view)
+ vkd3d_view_decref(uint_view, device);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList2 *iface,
+ D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource,
+ const float values[4], UINT rect_count, const D3D12_RECT *rects)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_resource *resource_impl;
+ VkClearColorValue colour;
+ struct vkd3d_view *view;
+
+ TRACE("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p.\n",
+ iface, gpu_handle.ptr, cpu_handle.ptr, resource, values, rect_count, rects);
+
+ resource_impl = unsafe_impl_from_ID3D12Resource(resource);
+ view = d3d12_desc_from_cpu_handle(cpu_handle)->u.view;
+ memcpy(colour.float32, values, sizeof(colour.float32));
+
+ d3d12_command_list_clear_uav(list, resource_impl, view, &colour, rect_count, rects);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *resource, const D3D12_DISCARD_REGION *region)
+{
+ FIXME_ONCE("iface %p, resource %p, region %p stub!\n", iface, resource, region);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_BeginQuery(ID3D12GraphicsCommandList2 *iface,
+ ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT index)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_query_heap *query_heap = unsafe_impl_from_ID3D12QueryHeap(heap);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkQueryControlFlags flags = 0;
+
+ TRACE("iface %p, heap %p, type %#x, index %u.\n", iface, heap, type, index);
+
+ vk_procs = &list->device->vk_procs;
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ VK_CALL(vkCmdResetQueryPool(list->vk_command_buffer, query_heap->vk_query_pool, index, 1));
+
+ if (type == D3D12_QUERY_TYPE_OCCLUSION)
+ flags = VK_QUERY_CONTROL_PRECISE_BIT;
+
+ if (D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 <= type && type <= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3)
+ {
+ unsigned int stream_index = type - D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0;
+ VK_CALL(vkCmdBeginQueryIndexedEXT(list->vk_command_buffer,
+ query_heap->vk_query_pool, index, flags, stream_index));
+ return;
+ }
+
+ VK_CALL(vkCmdBeginQuery(list->vk_command_buffer, query_heap->vk_query_pool, index, flags));
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_EndQuery(ID3D12GraphicsCommandList2 *iface,
+ ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT index)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_query_heap *query_heap = unsafe_impl_from_ID3D12QueryHeap(heap);
+ const struct vkd3d_vk_device_procs *vk_procs;
+
+ TRACE("iface %p, heap %p, type %#x, index %u.\n", iface, heap, type, index);
+
+ vk_procs = &list->device->vk_procs;
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ d3d12_query_heap_mark_result_as_available(query_heap, index);
+
+ if (type == D3D12_QUERY_TYPE_TIMESTAMP)
+ {
+ VK_CALL(vkCmdResetQueryPool(list->vk_command_buffer, query_heap->vk_query_pool, index, 1));
+ VK_CALL(vkCmdWriteTimestamp(list->vk_command_buffer,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, query_heap->vk_query_pool, index));
+ return;
+ }
+
+ if (D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 <= type && type <= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3)
+ {
+ unsigned int stream_index = type - D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0;
+ VK_CALL(vkCmdEndQueryIndexedEXT(list->vk_command_buffer,
+ query_heap->vk_query_pool, index, stream_index));
+ return;
+ }
+
+ VK_CALL(vkCmdEndQuery(list->vk_command_buffer, query_heap->vk_query_pool, index));
+}
+
+static size_t get_query_stride(D3D12_QUERY_TYPE type)
+{
+ if (type == D3D12_QUERY_TYPE_PIPELINE_STATISTICS)
+ return sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS);
+
+ if (D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0 <= type && type <= D3D12_QUERY_TYPE_SO_STATISTICS_STREAM3)
+ return sizeof(D3D12_QUERY_DATA_SO_STATISTICS);
+
+ return sizeof(uint64_t);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ResolveQueryData(ID3D12GraphicsCommandList2 *iface,
+ ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT start_index, UINT query_count,
+ ID3D12Resource *dst_buffer, UINT64 aligned_dst_buffer_offset)
+{
+ const struct d3d12_query_heap *query_heap = unsafe_impl_from_ID3D12QueryHeap(heap);
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_resource *buffer = unsafe_impl_from_ID3D12Resource(dst_buffer);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ unsigned int i, first, count;
+ VkDeviceSize offset, stride;
+
+ TRACE("iface %p, heap %p, type %#x, start_index %u, query_count %u, "
+ "dst_buffer %p, aligned_dst_buffer_offset %#"PRIx64".\n",
+ iface, heap, type, start_index, query_count,
+ dst_buffer, aligned_dst_buffer_offset);
+
+ vk_procs = &list->device->vk_procs;
+
+ /* Vulkan is less strict than D3D12 here. Vulkan implementations are free
+ * to return any non-zero result for binary occlusion with at least one
+ * sample passing, while D3D12 guarantees that the result is 1 then.
+ *
+ * For example, the Nvidia binary blob drivers on Linux seem to always
+ * count precisely, even when it was signalled that non-precise is enough.
+ */
+ if (type == D3D12_QUERY_TYPE_BINARY_OCCLUSION)
+ FIXME_ONCE("D3D12 guarantees binary occlusion queries result in only 0 and 1.\n");
+
+ if (!d3d12_resource_is_buffer(buffer))
+ {
+ WARN("Destination resource is not a buffer.\n");
+ return;
+ }
+
+ d3d12_command_list_end_current_render_pass(list);
+
+ stride = get_query_stride(type);
+
+ count = 0;
+ first = start_index;
+ offset = aligned_dst_buffer_offset;
+ for (i = 0; i < query_count; ++i)
+ {
+ if (d3d12_query_heap_is_result_available(query_heap, start_index + i))
+ {
+ ++count;
+ }
+ else
+ {
+ if (count)
+ {
+ VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer,
+ query_heap->vk_query_pool, first, count, buffer->u.vk_buffer,
+ offset, stride, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
+ }
+ count = 0;
+ first = start_index + i;
+ offset = aligned_dst_buffer_offset + i * stride;
+
+ /* We cannot copy query results if a query was not issued:
+ *
+ * "If the query does not become available in a finite amount of
+ * time (e.g. due to not issuing a query since the last reset),
+ * a VK_ERROR_DEVICE_LOST error may occur."
+ */
+ VK_CALL(vkCmdFillBuffer(list->vk_command_buffer,
+ buffer->u.vk_buffer, offset, stride, 0x00000000));
+
+ ++first;
+ offset += stride;
+ }
+ }
+
+ if (count)
+ {
+ VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer,
+ query_heap->vk_query_pool, first, count, buffer->u.vk_buffer,
+ offset, stride, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetPredication(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *buffer, UINT64 aligned_buffer_offset, D3D12_PREDICATION_OP operation)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_resource *resource = unsafe_impl_from_ID3D12Resource(buffer);
+ const struct vkd3d_vulkan_info *vk_info = &list->device->vk_info;
+ const struct vkd3d_vk_device_procs *vk_procs;
+
+ TRACE("iface %p, buffer %p, aligned_buffer_offset %#"PRIx64", operation %#x.\n",
+ iface, buffer, aligned_buffer_offset, operation);
+
+ if (!vk_info->EXT_conditional_rendering)
+ {
+ FIXME("Vulkan conditional rendering extension not present. Conditional rendering not supported.\n");
+ return;
+ }
+
+ vk_procs = &list->device->vk_procs;
+
+ /* FIXME: Add support for conditional rendering in render passes. */
+ d3d12_command_list_end_current_render_pass(list);
+
+ if (resource)
+ {
+ VkConditionalRenderingBeginInfoEXT cond_info;
+
+ if (aligned_buffer_offset & (sizeof(uint64_t) - 1))
+ {
+ WARN("Unaligned predicate argument buffer offset %#"PRIx64".\n", aligned_buffer_offset);
+ return;
+ }
+
+ if (!d3d12_resource_is_buffer(resource))
+ {
+ WARN("Predicate arguments must be stored in a buffer resource.\n");
+ return;
+ }
+
+ FIXME_ONCE("Predication doesn't support clear and copy commands, "
+ "and predication values are treated as 32-bit values.\n");
+
+ cond_info.sType = VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT;
+ cond_info.pNext = NULL;
+ cond_info.buffer = resource->u.vk_buffer;
+ cond_info.offset = aligned_buffer_offset;
+ switch (operation)
+ {
+ case D3D12_PREDICATION_OP_EQUAL_ZERO:
+ cond_info.flags = 0;
+ break;
+
+ case D3D12_PREDICATION_OP_NOT_EQUAL_ZERO:
+ cond_info.flags = VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT;
+ break;
+
+ default:
+ FIXME("Unhandled predication operation %#x.\n", operation);
+ return;
+ }
+
+ if (list->is_predicated)
+ VK_CALL(vkCmdEndConditionalRenderingEXT(list->vk_command_buffer));
+ VK_CALL(vkCmdBeginConditionalRenderingEXT(list->vk_command_buffer, &cond_info));
+ list->is_predicated = true;
+ }
+ else if (list->is_predicated)
+ {
+ VK_CALL(vkCmdEndConditionalRenderingEXT(list->vk_command_buffer));
+ list->is_predicated = false;
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetMarker(ID3D12GraphicsCommandList2 *iface,
+ UINT metadata, const void *data, UINT size)
+{
+ FIXME("iface %p, metadata %#x, data %p, size %u stub!\n", iface, metadata, data, size);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_BeginEvent(ID3D12GraphicsCommandList2 *iface,
+ UINT metadata, const void *data, UINT size)
+{
+ FIXME("iface %p, metadata %#x, data %p, size %u stub!\n", iface, metadata, data, size);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_EndEvent(ID3D12GraphicsCommandList2 *iface)
+{
+ FIXME("iface %p stub!\n", iface);
+}
+
+STATIC_ASSERT(sizeof(VkDispatchIndirectCommand) == sizeof(D3D12_DISPATCH_ARGUMENTS));
+STATIC_ASSERT(sizeof(VkDrawIndexedIndirectCommand) == sizeof(D3D12_DRAW_INDEXED_ARGUMENTS));
+STATIC_ASSERT(sizeof(VkDrawIndirectCommand) == sizeof(D3D12_DRAW_ARGUMENTS));
+
+static void STDMETHODCALLTYPE d3d12_command_list_ExecuteIndirect(ID3D12GraphicsCommandList2 *iface,
+ ID3D12CommandSignature *command_signature, UINT max_command_count, ID3D12Resource *arg_buffer,
+ UINT64 arg_buffer_offset, ID3D12Resource *count_buffer, UINT64 count_buffer_offset)
+{
+ struct d3d12_command_signature *sig_impl = unsafe_impl_from_ID3D12CommandSignature(command_signature);
+ struct d3d12_resource *count_impl = unsafe_impl_from_ID3D12Resource(count_buffer);
+ struct d3d12_resource *arg_impl = unsafe_impl_from_ID3D12Resource(arg_buffer);
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ const D3D12_COMMAND_SIGNATURE_DESC *signature_desc;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ unsigned int i;
+
+ TRACE("iface %p, command_signature %p, max_command_count %u, arg_buffer %p, "
+ "arg_buffer_offset %#"PRIx64", count_buffer %p, count_buffer_offset %#"PRIx64".\n",
+ iface, command_signature, max_command_count, arg_buffer, arg_buffer_offset,
+ count_buffer, count_buffer_offset);
+
+ vk_procs = &list->device->vk_procs;
+
+ if (count_buffer && !list->device->vk_info.KHR_draw_indirect_count)
+ {
+ FIXME("Count buffers not supported by Vulkan implementation.\n");
+ return;
+ }
+
+ signature_desc = &sig_impl->desc;
+ for (i = 0; i < signature_desc->NumArgumentDescs; ++i)
+ {
+ const D3D12_INDIRECT_ARGUMENT_DESC *arg_desc = &signature_desc->pArgumentDescs[i];
+
+ switch (arg_desc->Type)
+ {
+ case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW:
+ if (!d3d12_command_list_begin_render_pass(list))
+ {
+ WARN("Failed to begin render pass, ignoring draw.\n");
+ break;
+ }
+
+ if (count_buffer)
+ {
+ VK_CALL(vkCmdDrawIndirectCountKHR(list->vk_command_buffer, arg_impl->u.vk_buffer,
+ arg_buffer_offset, count_impl->u.vk_buffer, count_buffer_offset,
+ max_command_count, signature_desc->ByteStride));
+ }
+ else
+ {
+ VK_CALL(vkCmdDrawIndirect(list->vk_command_buffer, arg_impl->u.vk_buffer,
+ arg_buffer_offset, max_command_count, signature_desc->ByteStride));
+ }
+ break;
+
+ case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:
+ if (!d3d12_command_list_begin_render_pass(list))
+ {
+ WARN("Failed to begin render pass, ignoring draw.\n");
+ break;
+ }
+
+ d3d12_command_list_check_index_buffer_strip_cut_value(list);
+
+ if (count_buffer)
+ {
+ VK_CALL(vkCmdDrawIndexedIndirectCountKHR(list->vk_command_buffer, arg_impl->u.vk_buffer,
+ arg_buffer_offset, count_impl->u.vk_buffer, count_buffer_offset,
+ max_command_count, signature_desc->ByteStride));
+ }
+ else
+ {
+ VK_CALL(vkCmdDrawIndexedIndirect(list->vk_command_buffer, arg_impl->u.vk_buffer,
+ arg_buffer_offset, max_command_count, signature_desc->ByteStride));
+ }
+ break;
+
+ case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH:
+ if (max_command_count != 1)
+ FIXME("Ignoring command count %u.\n", max_command_count);
+
+ if (count_buffer)
+ {
+ FIXME("Count buffers not supported for indirect dispatch.\n");
+ break;
+ }
+
+ if (!d3d12_command_list_update_compute_state(list))
+ {
+ WARN("Failed to update compute state, ignoring dispatch.\n");
+ return;
+ }
+
+ VK_CALL(vkCmdDispatchIndirect(list->vk_command_buffer,
+ arg_impl->u.vk_buffer, arg_buffer_offset));
+ break;
+
+ default:
+ FIXME("Ignoring unhandled argument type %#x.\n", arg_desc->Type);
+ break;
+ }
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_AtomicCopyBufferUINT(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst_buffer, UINT64 dst_offset,
+ ID3D12Resource *src_buffer, UINT64 src_offset,
+ UINT dependent_resource_count, ID3D12Resource * const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges)
+{
+ FIXME("iface %p, dst_resource %p, dst_offset %#"PRIx64", src_resource %p, "
+ "src_offset %#"PRIx64", dependent_resource_count %u, "
+ "dependent_resources %p, dependent_sub_resource_ranges %p stub!\n",
+ iface, dst_buffer, dst_offset, src_buffer, src_offset,
+ dependent_resource_count, dependent_resources, dependent_sub_resource_ranges);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_AtomicCopyBufferUINT64(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst_buffer, UINT64 dst_offset,
+ ID3D12Resource *src_buffer, UINT64 src_offset,
+ UINT dependent_resource_count, ID3D12Resource * const *dependent_resources,
+ const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges)
+{
+ FIXME("iface %p, dst_resource %p, dst_offset %#"PRIx64", src_resource %p, "
+ "src_offset %#"PRIx64", dependent_resource_count %u, "
+ "dependent_resources %p, dependent_sub_resource_ranges %p stub!\n",
+ iface, dst_buffer, dst_offset, src_buffer, src_offset,
+ dependent_resource_count, dependent_resources, dependent_sub_resource_ranges);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_OMSetDepthBounds(ID3D12GraphicsCommandList2 *iface,
+ FLOAT min, FLOAT max)
+{
+ FIXME("iface %p, min %.8e, max %.8e stub!\n", iface, min, max);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetSamplePositions(ID3D12GraphicsCommandList2 *iface,
+ UINT sample_count, UINT pixel_count, D3D12_SAMPLE_POSITION *sample_positions)
+{
+ FIXME("iface %p, sample_count %u, pixel_count %u, sample_positions %p stub!\n",
+ iface, sample_count, pixel_count, sample_positions);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_ResolveSubresourceRegion(ID3D12GraphicsCommandList2 *iface,
+ ID3D12Resource *dst_resource, UINT dst_sub_resource_idx, UINT dst_x, UINT dst_y,
+ ID3D12Resource *src_resource, UINT src_sub_resource_idx,
+ D3D12_RECT *src_rect, DXGI_FORMAT format, D3D12_RESOLVE_MODE mode)
+{
+ FIXME("iface %p, dst_resource %p, dst_sub_resource_idx %u, "
+ "dst_x %u, dst_y %u, src_resource %p, src_sub_resource_idx %u, "
+ "src_rect %p, format %#x, mode %#x stub!\n",
+ iface, dst_resource, dst_sub_resource_idx, dst_x, dst_y,
+ src_resource, src_sub_resource_idx, src_rect, format, mode);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_SetViewInstanceMask(ID3D12GraphicsCommandList2 *iface, UINT mask)
+{
+ FIXME("iface %p, mask %#x stub!\n", iface, mask);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_list_WriteBufferImmediate(ID3D12GraphicsCommandList2 *iface,
+ UINT count, const D3D12_WRITEBUFFERIMMEDIATE_PARAMETER *parameters,
+ const D3D12_WRITEBUFFERIMMEDIATE_MODE *modes)
+{
+ struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface);
+ struct d3d12_resource *resource;
+ unsigned int i;
+
+ FIXME("iface %p, count %u, parameters %p, modes %p stub!\n", iface, count, parameters, modes);
+
+ for (i = 0; i < count; ++i)
+ {
+ resource = vkd3d_gpu_va_allocator_dereference(&list->device->gpu_va_allocator, parameters[i].Dest);
+ d3d12_command_list_track_resource_usage(list, resource);
+ }
+}
+
+static const struct ID3D12GraphicsCommandList2Vtbl d3d12_command_list_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_command_list_QueryInterface,
+ d3d12_command_list_AddRef,
+ d3d12_command_list_Release,
+ /* ID3D12Object methods */
+ d3d12_command_list_GetPrivateData,
+ d3d12_command_list_SetPrivateData,
+ d3d12_command_list_SetPrivateDataInterface,
+ d3d12_command_list_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_command_list_GetDevice,
+ /* ID3D12CommandList methods */
+ d3d12_command_list_GetType,
+ /* ID3D12GraphicsCommandList methods */
+ d3d12_command_list_Close,
+ d3d12_command_list_Reset,
+ d3d12_command_list_ClearState,
+ d3d12_command_list_DrawInstanced,
+ d3d12_command_list_DrawIndexedInstanced,
+ d3d12_command_list_Dispatch,
+ d3d12_command_list_CopyBufferRegion,
+ d3d12_command_list_CopyTextureRegion,
+ d3d12_command_list_CopyResource,
+ d3d12_command_list_CopyTiles,
+ d3d12_command_list_ResolveSubresource,
+ d3d12_command_list_IASetPrimitiveTopology,
+ d3d12_command_list_RSSetViewports,
+ d3d12_command_list_RSSetScissorRects,
+ d3d12_command_list_OMSetBlendFactor,
+ d3d12_command_list_OMSetStencilRef,
+ d3d12_command_list_SetPipelineState,
+ d3d12_command_list_ResourceBarrier,
+ d3d12_command_list_ExecuteBundle,
+ d3d12_command_list_SetDescriptorHeaps,
+ d3d12_command_list_SetComputeRootSignature,
+ d3d12_command_list_SetGraphicsRootSignature,
+ d3d12_command_list_SetComputeRootDescriptorTable,
+ d3d12_command_list_SetGraphicsRootDescriptorTable,
+ d3d12_command_list_SetComputeRoot32BitConstant,
+ d3d12_command_list_SetGraphicsRoot32BitConstant,
+ d3d12_command_list_SetComputeRoot32BitConstants,
+ d3d12_command_list_SetGraphicsRoot32BitConstants,
+ d3d12_command_list_SetComputeRootConstantBufferView,
+ d3d12_command_list_SetGraphicsRootConstantBufferView,
+ d3d12_command_list_SetComputeRootShaderResourceView,
+ d3d12_command_list_SetGraphicsRootShaderResourceView,
+ d3d12_command_list_SetComputeRootUnorderedAccessView,
+ d3d12_command_list_SetGraphicsRootUnorderedAccessView,
+ d3d12_command_list_IASetIndexBuffer,
+ d3d12_command_list_IASetVertexBuffers,
+ d3d12_command_list_SOSetTargets,
+ d3d12_command_list_OMSetRenderTargets,
+ d3d12_command_list_ClearDepthStencilView,
+ d3d12_command_list_ClearRenderTargetView,
+ d3d12_command_list_ClearUnorderedAccessViewUint,
+ d3d12_command_list_ClearUnorderedAccessViewFloat,
+ d3d12_command_list_DiscardResource,
+ d3d12_command_list_BeginQuery,
+ d3d12_command_list_EndQuery,
+ d3d12_command_list_ResolveQueryData,
+ d3d12_command_list_SetPredication,
+ d3d12_command_list_SetMarker,
+ d3d12_command_list_BeginEvent,
+ d3d12_command_list_EndEvent,
+ d3d12_command_list_ExecuteIndirect,
+ /* ID3D12GraphicsCommandList1 methods */
+ d3d12_command_list_AtomicCopyBufferUINT,
+ d3d12_command_list_AtomicCopyBufferUINT64,
+ d3d12_command_list_OMSetDepthBounds,
+ d3d12_command_list_SetSamplePositions,
+ d3d12_command_list_ResolveSubresourceRegion,
+ d3d12_command_list_SetViewInstanceMask,
+ /* ID3D12GraphicsCommandList2 methods */
+ d3d12_command_list_WriteBufferImmediate,
+};
+
+static struct d3d12_command_list *unsafe_impl_from_ID3D12CommandList(ID3D12CommandList *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == (struct ID3D12CommandListVtbl *)&d3d12_command_list_vtbl);
+ return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandList2_iface);
+}
+
+static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d3d12_device *device,
+ D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_allocator *allocator,
+ ID3D12PipelineState *initial_pipeline_state)
+{
+ HRESULT hr;
+
+ list->ID3D12GraphicsCommandList2_iface.lpVtbl = &d3d12_command_list_vtbl;
+ list->refcount = 1;
+
+ list->type = type;
+
+ if (FAILED(hr = vkd3d_private_store_init(&list->private_store)))
+ return hr;
+
+ d3d12_device_add_ref(list->device = device);
+
+ list->allocator = allocator;
+
+ if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator, list)))
+ {
+ list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS].vk_uav_counter_views = NULL;
+ list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE].vk_uav_counter_views = NULL;
+ d3d12_command_list_reset_state(list, initial_pipeline_state);
+ }
+ else
+ {
+ vkd3d_private_store_destroy(&list->private_store);
+ d3d12_device_release(device);
+ }
+
+ return hr;
+}
+
+HRESULT d3d12_command_list_create(struct d3d12_device *device,
+ UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface,
+ ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list)
+{
+ struct d3d12_command_allocator *allocator;
+ struct d3d12_command_list *object;
+ HRESULT hr;
+
+ if (!(allocator = unsafe_impl_from_ID3D12CommandAllocator(allocator_iface)))
+ {
+ WARN("Command allocator is NULL.\n");
+ return E_INVALIDARG;
+ }
+
+ if (allocator->type != type)
+ {
+ WARN("Command list types do not match (allocator %#x, list %#x).\n",
+ allocator->type, type);
+ return E_INVALIDARG;
+ }
+
+ debug_ignored_node_mask(node_mask);
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_command_list_init(object, device, type, allocator, initial_pipeline_state)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created command list %p.\n", object);
+
+ *list = object;
+
+ return S_OK;
+}
+
+/* ID3D12CommandQueue */
+static inline struct d3d12_command_queue *impl_from_ID3D12CommandQueue(ID3D12CommandQueue *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_command_queue, ID3D12CommandQueue_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_QueryInterface(ID3D12CommandQueue *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12CommandQueue)
+ || IsEqualGUID(riid, &IID_ID3D12Pageable)
+ || IsEqualGUID(riid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12CommandQueue_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_command_queue_AddRef(ID3D12CommandQueue *iface)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ ULONG refcount = InterlockedIncrement(&command_queue->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", command_queue, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_command_queue_Release(ID3D12CommandQueue *iface)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ ULONG refcount = InterlockedDecrement(&command_queue->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", command_queue, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = command_queue->device;
+
+ vkd3d_private_store_destroy(&command_queue->private_store);
+
+ vkd3d_free(command_queue);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetPrivateData(ID3D12CommandQueue *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&command_queue->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_SetPrivateData(ID3D12CommandQueue *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&command_queue->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_SetPrivateDataInterface(ID3D12CommandQueue *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&command_queue->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_SetName(ID3D12CommandQueue *iface, const WCHAR *name)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ VkQueue vk_queue;
+ HRESULT hr;
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, command_queue->device->wchar_size));
+
+ if (!(vk_queue = vkd3d_queue_acquire(command_queue->vkd3d_queue)))
+ {
+ ERR("Failed to acquire queue %p.\n", command_queue->vkd3d_queue);
+ return E_FAIL;
+ }
+
+ hr = vkd3d_set_vk_object_name(command_queue->device, (uint64_t)(uintptr_t)vk_queue,
+ VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, name);
+ vkd3d_queue_release(command_queue->vkd3d_queue);
+ return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetDevice(ID3D12CommandQueue *iface, REFIID iid, void **device)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(command_queue->device, iid, device);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_queue_UpdateTileMappings(ID3D12CommandQueue *iface,
+ ID3D12Resource *resource, UINT region_count,
+ const D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates,
+ const D3D12_TILE_REGION_SIZE *region_sizes,
+ UINT range_count,
+ const D3D12_TILE_RANGE_FLAGS *range_flags,
+ UINT *heap_range_offsets,
+ UINT *range_tile_counts,
+ D3D12_TILE_MAPPING_FLAGS flags)
+{
+ FIXME("iface %p, resource %p, region_count %u, region_start_coordinates %p, "
+ "region_sizes %p, range_count %u, range_flags %p, heap_range_offsets %p, "
+ "range_tile_counts %p, flags %#x stub!\n",
+ iface, resource, region_count, region_start_coordinates, region_sizes, range_count,
+ range_flags, heap_range_offsets, range_tile_counts, flags);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12CommandQueue *iface,
+ ID3D12Resource *dst_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *dst_region_start_coordinate,
+ ID3D12Resource *src_resource,
+ const D3D12_TILED_RESOURCE_COORDINATE *src_region_start_coordinate,
+ const D3D12_TILE_REGION_SIZE *region_size,
+ D3D12_TILE_MAPPING_FLAGS flags)
+{
+ FIXME("iface %p, dst_resource %p, dst_region_start_coordinate %p, "
+ "src_resource %p, src_region_start_coordinate %p, region_size %p, flags %#x stub!\n",
+ iface, dst_resource, dst_region_start_coordinate, src_resource,
+ src_region_start_coordinate, region_size, flags);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_queue_ExecuteCommandLists(ID3D12CommandQueue *iface,
+ UINT command_list_count, ID3D12CommandList * const *command_lists)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ struct d3d12_command_list *cmd_list;
+ struct VkSubmitInfo submit_desc;
+ VkCommandBuffer *buffers;
+ VkQueue vk_queue;
+ unsigned int i;
+ VkResult vr;
+
+ TRACE("iface %p, command_list_count %u, command_lists %p.\n",
+ iface, command_list_count, command_lists);
+
+ vk_procs = &command_queue->device->vk_procs;
+
+ if (!(buffers = vkd3d_calloc(command_list_count, sizeof(*buffers))))
+ {
+ ERR("Failed to allocate command buffer array.\n");
+ return;
+ }
+
+ for (i = 0; i < command_list_count; ++i)
+ {
+ cmd_list = unsafe_impl_from_ID3D12CommandList(command_lists[i]);
+
+ if (cmd_list->is_recording)
+ {
+ d3d12_device_mark_as_removed(command_queue->device, DXGI_ERROR_INVALID_CALL,
+ "Command list %p is in recording state.\n", command_lists[i]);
+ vkd3d_free(buffers);
+ return;
+ }
+
+ buffers[i] = cmd_list->vk_command_buffer;
+ }
+
+ submit_desc.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_desc.pNext = NULL;
+ submit_desc.waitSemaphoreCount = 0;
+ submit_desc.pWaitSemaphores = NULL;
+ submit_desc.pWaitDstStageMask = NULL;
+ submit_desc.commandBufferCount = command_list_count;
+ submit_desc.pCommandBuffers = buffers;
+ submit_desc.signalSemaphoreCount = 0;
+ submit_desc.pSignalSemaphores = NULL;
+
+ if (!(vk_queue = vkd3d_queue_acquire(command_queue->vkd3d_queue)))
+ {
+ ERR("Failed to acquire queue %p.\n", command_queue->vkd3d_queue);
+ vkd3d_free(buffers);
+ return;
+ }
+
+ if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_desc, VK_NULL_HANDLE))) < 0)
+ ERR("Failed to submit queue(s), vr %d.\n", vr);
+
+ vkd3d_queue_release(command_queue->vkd3d_queue);
+
+ vkd3d_free(buffers);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_queue_SetMarker(ID3D12CommandQueue *iface,
+ UINT metadata, const void *data, UINT size)
+{
+ FIXME("iface %p, metadata %#x, data %p, size %u stub!\n",
+ iface, metadata, data, size);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_queue_BeginEvent(ID3D12CommandQueue *iface,
+ UINT metadata, const void *data, UINT size)
+{
+ FIXME("iface %p, metatdata %#x, data %p, size %u stub!\n",
+ iface, metadata, data, size);
+}
+
+static void STDMETHODCALLTYPE d3d12_command_queue_EndEvent(ID3D12CommandQueue *iface)
+{
+ FIXME("iface %p stub!\n", iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Signal(ID3D12CommandQueue *iface,
+ ID3D12Fence *fence_iface, UINT64 value)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkSemaphore vk_semaphore = VK_NULL_HANDLE;
+ VkFence vk_fence = VK_NULL_HANDLE;
+ struct vkd3d_queue *vkd3d_queue;
+ struct d3d12_device *device;
+ struct d3d12_fence *fence;
+ VkSubmitInfo submit_info;
+ uint64_t sequence_number;
+ VkQueue vk_queue;
+ VkResult vr;
+ HRESULT hr;
+
+ TRACE("iface %p, fence %p, value %#"PRIx64".\n", iface, fence_iface, value);
+
+ device = command_queue->device;
+ vk_procs = &device->vk_procs;
+ vkd3d_queue = command_queue->vkd3d_queue;
+
+ fence = unsafe_impl_from_ID3D12Fence(fence_iface);
+
+ if ((vr = d3d12_fence_create_vk_fence(fence, &vk_fence)) < 0)
+ {
+ WARN("Failed to create Vulkan fence, vr %d.\n", vr);
+ goto fail_vkresult;
+ }
+
+ if (!(vk_queue = vkd3d_queue_acquire(vkd3d_queue)))
+ {
+ ERR("Failed to acquire queue %p.\n", vkd3d_queue);
+ hr = E_FAIL;
+ goto fail;
+ }
+
+ if ((vr = vkd3d_queue_create_vk_semaphore_locked(vkd3d_queue, device, &vk_semaphore)) < 0)
+ {
+ ERR("Failed to create Vulkan semaphore, vr %d.\n", vr);
+ vk_semaphore = VK_NULL_HANDLE;
+ }
+
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.pNext = NULL;
+ submit_info.waitSemaphoreCount = 0;
+ submit_info.pWaitSemaphores = NULL;
+ submit_info.pWaitDstStageMask = NULL;
+ submit_info.commandBufferCount = 0;
+ submit_info.pCommandBuffers = NULL;
+ submit_info.signalSemaphoreCount = vk_semaphore ? 1 : 0;
+ submit_info.pSignalSemaphores = &vk_semaphore;
+
+ if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_info, vk_fence))) >= 0)
+ {
+ sequence_number = ++vkd3d_queue->submitted_sequence_number;
+
+ /* We don't expect to overrun the 64-bit counter, but we handle it gracefully anyway. */
+ if (!sequence_number)
+ sequence_number = vkd3d_queue_reset_sequence_number_locked(vkd3d_queue);
+ }
+
+ vkd3d_queue_release(vkd3d_queue);
+
+ if (vr < 0)
+ {
+ WARN("Failed to submit signal operation, vr %d.\n", vr);
+ goto fail_vkresult;
+ }
+
+ if (vk_semaphore && SUCCEEDED(hr = d3d12_fence_add_vk_semaphore(fence, vk_semaphore, vk_fence, value)))
+ vk_semaphore = VK_NULL_HANDLE;
+
+ vr = VK_CALL(vkGetFenceStatus(device->vk_device, vk_fence));
+ if (vr == VK_NOT_READY)
+ {
+ if (SUCCEEDED(hr = vkd3d_enqueue_gpu_fence(&device->fence_worker, vk_fence, fence, value, vkd3d_queue, sequence_number)))
+ vk_fence = VK_NULL_HANDLE;
+ }
+ else if (vr == VK_SUCCESS)
+ {
+ TRACE("Already signaled %p, value %#"PRIx64".\n", fence, value);
+ hr = d3d12_fence_signal(fence, value, vk_fence);
+ vk_fence = VK_NULL_HANDLE;
+ vkd3d_queue_update_sequence_number(vkd3d_queue, sequence_number, device);
+ }
+ else
+ {
+ FIXME("Failed to get fence status, vr %d.\n", vr);
+ hr = hresult_from_vk_result(vr);
+ }
+
+ if (vk_fence || vk_semaphore)
+ {
+ /* In case of an unexpected failure, try to safely destroy Vulkan objects. */
+ vkd3d_queue_wait_idle(vkd3d_queue, vk_procs);
+ goto fail;
+ }
+
+ return hr;
+
+fail_vkresult:
+ hr = hresult_from_vk_result(vr);
+fail:
+ VK_CALL(vkDestroyFence(device->vk_device, vk_fence, NULL));
+ VK_CALL(vkDestroySemaphore(device->vk_device, vk_semaphore, NULL));
+ return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *iface,
+ ID3D12Fence *fence_iface, UINT64 value)
+{
+ static const VkPipelineStageFlagBits wait_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ struct vkd3d_signaled_semaphore *semaphore;
+ uint64_t completed_value = 0;
+ struct vkd3d_queue *queue;
+ struct d3d12_fence *fence;
+ VkSubmitInfo submit_info;
+ VkQueue vk_queue;
+ VkResult vr;
+ HRESULT hr;
+
+ TRACE("iface %p, fence %p, value %#"PRIx64".\n", iface, fence_iface, value);
+
+ vk_procs = &command_queue->device->vk_procs;
+ queue = command_queue->vkd3d_queue;
+
+ fence = unsafe_impl_from_ID3D12Fence(fence_iface);
+
+ semaphore = d3d12_fence_acquire_vk_semaphore(fence, value, &completed_value);
+ if (!semaphore && completed_value >= value)
+ {
+ /* We don't get a Vulkan semaphore if the fence was signaled on CPU. */
+ TRACE("Already signaled %p, value %#"PRIx64".\n", fence, completed_value);
+ return S_OK;
+ }
+
+ if (!(vk_queue = vkd3d_queue_acquire(queue)))
+ {
+ ERR("Failed to acquire queue %p.\n", queue);
+ hr = E_FAIL;
+ goto fail;
+ }
+
+ if (!semaphore)
+ {
+ if (command_queue->last_waited_fence == fence && command_queue->last_waited_fence_value >= value)
+ {
+ WARN("Already waited on fence %p, value %#"PRIx64".\n", fence, value);
+ }
+ else
+ {
+ FIXME("Failed to acquire Vulkan semaphore for fence %p, value %#"PRIx64
+ ", completed value %#"PRIx64".\n", fence, value, completed_value);
+ }
+
+ vkd3d_queue_release(queue);
+ return S_OK;
+ }
+
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.pNext = NULL;
+ submit_info.waitSemaphoreCount = 1;
+ submit_info.pWaitSemaphores = &semaphore->vk_semaphore;
+ submit_info.pWaitDstStageMask = &wait_stage_mask;
+ submit_info.commandBufferCount = 0;
+ submit_info.pCommandBuffers = NULL;
+ submit_info.signalSemaphoreCount = 0;
+ submit_info.pSignalSemaphores = NULL;
+
+ if (!vkd3d_array_reserve((void **)&queue->semaphores, &queue->semaphores_size,
+ queue->semaphore_count + 1, sizeof(*queue->semaphores)))
+ {
+ ERR("Failed to allocate memory for semaphore.\n");
+ vkd3d_queue_release(queue);
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_info, VK_NULL_HANDLE))) >= 0)
+ {
+ queue->semaphores[queue->semaphore_count].vk_semaphore = semaphore->vk_semaphore;
+ queue->semaphores[queue->semaphore_count].sequence_number = queue->submitted_sequence_number + 1;
+ ++queue->semaphore_count;
+
+ command_queue->last_waited_fence = fence;
+ command_queue->last_waited_fence_value = value;
+ }
+
+ vkd3d_queue_release(queue);
+
+ if (vr < 0)
+ {
+ WARN("Failed to submit wait operation, vr %d.\n", vr);
+ hr = hresult_from_vk_result(vr);
+ goto fail;
+ }
+
+ d3d12_fence_remove_vk_semaphore(fence, semaphore);
+ return S_OK;
+
+fail:
+ d3d12_fence_release_vk_semaphore(fence, semaphore);
+ return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetTimestampFrequency(ID3D12CommandQueue *iface,
+ UINT64 *frequency)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ struct d3d12_device *device = command_queue->device;
+
+ TRACE("iface %p, frequency %p.\n", iface, frequency);
+
+ if (!command_queue->vkd3d_queue->timestamp_bits)
+ {
+ WARN("Timestamp queries not supported.\n");
+ return E_FAIL;
+ }
+
+ *frequency = 1000000000 / device->vk_info.device_limits.timestampPeriod;
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetClockCalibration(ID3D12CommandQueue *iface,
+ UINT64 *gpu_timestamp, UINT64 *cpu_timestamp)
+{
+ FIXME("iface %p, gpu_timestamp %p, cpu_timestamp %p stub!\n",
+ iface, gpu_timestamp, cpu_timestamp);
+
+ return E_NOTIMPL;
+}
+
+static D3D12_COMMAND_QUEUE_DESC * STDMETHODCALLTYPE d3d12_command_queue_GetDesc(ID3D12CommandQueue *iface,
+ D3D12_COMMAND_QUEUE_DESC *desc)
+{
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+
+ TRACE("iface %p, desc %p.\n", iface, desc);
+
+ *desc = command_queue->desc;
+ return desc;
+}
+
+static const struct ID3D12CommandQueueVtbl d3d12_command_queue_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_command_queue_QueryInterface,
+ d3d12_command_queue_AddRef,
+ d3d12_command_queue_Release,
+ /* ID3D12Object methods */
+ d3d12_command_queue_GetPrivateData,
+ d3d12_command_queue_SetPrivateData,
+ d3d12_command_queue_SetPrivateDataInterface,
+ d3d12_command_queue_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_command_queue_GetDevice,
+ /* ID3D12CommandQueue methods */
+ d3d12_command_queue_UpdateTileMappings,
+ d3d12_command_queue_CopyTileMappings,
+ d3d12_command_queue_ExecuteCommandLists,
+ d3d12_command_queue_SetMarker,
+ d3d12_command_queue_BeginEvent,
+ d3d12_command_queue_EndEvent,
+ d3d12_command_queue_Signal,
+ d3d12_command_queue_Wait,
+ d3d12_command_queue_GetTimestampFrequency,
+ d3d12_command_queue_GetClockCalibration,
+ d3d12_command_queue_GetDesc,
+};
+
+static HRESULT d3d12_command_queue_init(struct d3d12_command_queue *queue,
+ struct d3d12_device *device, const D3D12_COMMAND_QUEUE_DESC *desc)
+{
+ HRESULT hr;
+
+ queue->ID3D12CommandQueue_iface.lpVtbl = &d3d12_command_queue_vtbl;
+ queue->refcount = 1;
+
+ queue->desc = *desc;
+ if (!queue->desc.NodeMask)
+ queue->desc.NodeMask = 0x1;
+
+ if (!(queue->vkd3d_queue = d3d12_device_get_vkd3d_queue(device, desc->Type)))
+ return E_NOTIMPL;
+
+ queue->last_waited_fence = NULL;
+ queue->last_waited_fence_value = 0;
+
+ if (desc->Priority == D3D12_COMMAND_QUEUE_PRIORITY_GLOBAL_REALTIME)
+ {
+ FIXME("Global realtime priority is not implemented.\n");
+ return E_NOTIMPL;
+ }
+
+ if (desc->Priority)
+ FIXME("Ignoring priority %#x.\n", desc->Priority);
+ if (desc->Flags)
+ FIXME("Ignoring flags %#x.\n", desc->Flags);
+
+ if (FAILED(hr = vkd3d_private_store_init(&queue->private_store)))
+ return hr;
+
+ d3d12_device_add_ref(queue->device = device);
+
+ return S_OK;
+}
+
+HRESULT d3d12_command_queue_create(struct d3d12_device *device,
+ const D3D12_COMMAND_QUEUE_DESC *desc, struct d3d12_command_queue **queue)
+{
+ struct d3d12_command_queue *object;
+ HRESULT hr;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_command_queue_init(object, device, desc)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created command queue %p.\n", object);
+
+ *queue = object;
+
+ return S_OK;
+}
+
+uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue)
+{
+ struct d3d12_command_queue *d3d12_queue = impl_from_ID3D12CommandQueue(queue);
+
+ return d3d12_queue->vkd3d_queue->vk_family_index;
+}
+
+VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue)
+{
+ struct d3d12_command_queue *d3d12_queue = impl_from_ID3D12CommandQueue(queue);
+
+ return vkd3d_queue_acquire(d3d12_queue->vkd3d_queue);
+}
+
+void vkd3d_release_vk_queue(ID3D12CommandQueue *queue)
+{
+ struct d3d12_command_queue *d3d12_queue = impl_from_ID3D12CommandQueue(queue);
+
+ return vkd3d_queue_release(d3d12_queue->vkd3d_queue);
+}
+
+/* ID3D12CommandSignature */
+static inline struct d3d12_command_signature *impl_from_ID3D12CommandSignature(ID3D12CommandSignature *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_command_signature, ID3D12CommandSignature_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_signature_QueryInterface(ID3D12CommandSignature *iface,
+ REFIID iid, void **out)
+{
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_ID3D12CommandSignature)
+ || IsEqualGUID(iid, &IID_ID3D12Pageable)
+ || IsEqualGUID(iid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(iid, &IID_ID3D12Object)
+ || IsEqualGUID(iid, &IID_IUnknown))
+ {
+ ID3D12CommandSignature_AddRef(iface);
+ *out = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_command_signature_AddRef(ID3D12CommandSignature *iface)
+{
+ struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface);
+ ULONG refcount = InterlockedIncrement(&signature->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", signature, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_command_signature_Release(ID3D12CommandSignature *iface)
+{
+ struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface);
+ ULONG refcount = InterlockedDecrement(&signature->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", signature, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = signature->device;
+
+ vkd3d_private_store_destroy(&signature->private_store);
+
+ vkd3d_free((void *)signature->desc.pArgumentDescs);
+ vkd3d_free(signature);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_signature_GetPrivateData(ID3D12CommandSignature *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&signature->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_signature_SetPrivateData(ID3D12CommandSignature *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&signature->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_signature_SetPrivateDataInterface(ID3D12CommandSignature *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&signature->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_signature_SetName(ID3D12CommandSignature *iface, const WCHAR *name)
+{
+ struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, signature->device->wchar_size));
+
+ return name ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_command_signature_GetDevice(ID3D12CommandSignature *iface, REFIID iid, void **device)
+{
+ struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(signature->device, iid, device);
+}
+
+static const struct ID3D12CommandSignatureVtbl d3d12_command_signature_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_command_signature_QueryInterface,
+ d3d12_command_signature_AddRef,
+ d3d12_command_signature_Release,
+ /* ID3D12Object methods */
+ d3d12_command_signature_GetPrivateData,
+ d3d12_command_signature_SetPrivateData,
+ d3d12_command_signature_SetPrivateDataInterface,
+ d3d12_command_signature_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_command_signature_GetDevice,
+};
+
+struct d3d12_command_signature *unsafe_impl_from_ID3D12CommandSignature(ID3D12CommandSignature *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_command_signature_vtbl);
+ return CONTAINING_RECORD(iface, struct d3d12_command_signature, ID3D12CommandSignature_iface);
+}
+
+HRESULT d3d12_command_signature_create(struct d3d12_device *device, const D3D12_COMMAND_SIGNATURE_DESC *desc,
+ struct d3d12_command_signature **signature)
+{
+ struct d3d12_command_signature *object;
+ unsigned int i;
+ HRESULT hr;
+
+ for (i = 0; i < desc->NumArgumentDescs; ++i)
+ {
+ const D3D12_INDIRECT_ARGUMENT_DESC *argument_desc = &desc->pArgumentDescs[i];
+ switch (argument_desc->Type)
+ {
+ case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW:
+ case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:
+ case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH:
+ if (i != desc->NumArgumentDescs - 1)
+ {
+ WARN("Draw/dispatch must be the last element of a command signature.\n");
+ return E_INVALIDARG;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ object->ID3D12CommandSignature_iface.lpVtbl = &d3d12_command_signature_vtbl;
+ object->refcount = 1;
+
+ object->desc = *desc;
+ if (!(object->desc.pArgumentDescs = vkd3d_calloc(desc->NumArgumentDescs, sizeof(*desc->pArgumentDescs))))
+ {
+ vkd3d_free(object);
+ return E_OUTOFMEMORY;
+ }
+ memcpy((void *)object->desc.pArgumentDescs, desc->pArgumentDescs,
+ desc->NumArgumentDescs * sizeof(*desc->pArgumentDescs));
+
+ if (FAILED(hr = vkd3d_private_store_init(&object->private_store)))
+ {
+ vkd3d_free((void *)object->desc.pArgumentDescs);
+ vkd3d_free(object);
+ return hr;
+ }
+
+ d3d12_device_add_ref(object->device = device);
+
+ TRACE("Created command signature %p.\n", object);
+
+ *signature = object;
+
+ return S_OK;
+}
diff --git a/dlls/vkd3d/libs/vkd3d/device.c b/dlls/vkd3d/libs/vkd3d/device.c
new file mode 100644
index 00000000000..bef6477347f
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/device.c
@@ -0,0 +1,3857 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_private.h"
+#include "vkd3d_version.h"
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+
+static void *vkd3d_dlopen(const char *name)
+{
+ return dlopen(name, RTLD_NOW);
+}
+
+static void *vkd3d_dlsym(void *handle, const char *symbol)
+{
+ return dlsym(handle, symbol);
+}
+
+static int vkd3d_dlclose(void *handle)
+{
+ return dlclose(handle);
+}
+
+static const char *vkd3d_dlerror(void)
+{
+ return dlerror();
+}
+#else
+static void *vkd3d_dlopen(const char *name)
+{
+ FIXME("Not implemented for this platform.\n");
+ return NULL;
+}
+
+static void *vkd3d_dlsym(void *handle, const char *symbol)
+{
+ return NULL;
+}
+
+static int vkd3d_dlclose(void *handle)
+{
+ return 0;
+}
+
+static const char *vkd3d_dlerror(void)
+{
+ return "Not implemented for this platform.\n";
+}
+#endif
+
+struct vkd3d_struct
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+};
+
+#define vkd3d_find_struct(c, t) vkd3d_find_struct_(c, VKD3D_STRUCTURE_TYPE_##t)
+static const void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
+ enum vkd3d_structure_type type)
+{
+ while (chain)
+ {
+ if (chain->type == type)
+ return chain;
+
+ chain = chain->next;
+ }
+
+ return NULL;
+}
+
+static uint32_t vkd3d_get_vk_version(void)
+{
+ int major, minor;
+
+ vkd3d_parse_version(PACKAGE_VERSION, &major, &minor);
+ return VK_MAKE_VERSION(major, minor, 0);
+}
+
+struct vkd3d_optional_extension_info
+{
+ const char *extension_name;
+ ptrdiff_t vulkan_info_offset;
+ bool is_debug_only;
+};
+
+#define VK_EXTENSION(name, member) \
+ {VK_ ## name ## _EXTENSION_NAME, offsetof(struct vkd3d_vulkan_info, member)}
+#define VK_DEBUG_EXTENSION(name, member) \
+ {VK_ ## name ## _EXTENSION_NAME, offsetof(struct vkd3d_vulkan_info, member), true}
+
+static const struct vkd3d_optional_extension_info optional_instance_extensions[] =
+{
+ /* KHR extensions */
+ VK_EXTENSION(KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, KHR_get_physical_device_properties2),
+ /* EXT extensions */
+ VK_DEBUG_EXTENSION(EXT_DEBUG_REPORT, EXT_debug_report),
+};
+
+static const char * const required_device_extensions[] =
+{
+ VK_KHR_MAINTENANCE1_EXTENSION_NAME,
+ VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,
+};
+
+static const struct vkd3d_optional_extension_info optional_device_extensions[] =
+{
+ /* KHR extensions */
+ VK_EXTENSION(KHR_DEDICATED_ALLOCATION, KHR_dedicated_allocation),
+ VK_EXTENSION(KHR_DRAW_INDIRECT_COUNT, KHR_draw_indirect_count),
+ VK_EXTENSION(KHR_GET_MEMORY_REQUIREMENTS_2, KHR_get_memory_requirements2),
+ VK_EXTENSION(KHR_IMAGE_FORMAT_LIST, KHR_image_format_list),
+ VK_EXTENSION(KHR_MAINTENANCE3, KHR_maintenance3),
+ VK_EXTENSION(KHR_PUSH_DESCRIPTOR, KHR_push_descriptor),
+ /* EXT extensions */
+ VK_EXTENSION(EXT_CONDITIONAL_RENDERING, EXT_conditional_rendering),
+ VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker),
+ VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable),
+ VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing),
+ VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation),
+ VK_EXTENSION(EXT_TEXEL_BUFFER_ALIGNMENT, EXT_texel_buffer_alignment),
+ VK_EXTENSION(EXT_TRANSFORM_FEEDBACK, EXT_transform_feedback),
+ VK_EXTENSION(EXT_VERTEX_ATTRIBUTE_DIVISOR, EXT_vertex_attribute_divisor),
+};
+
+static unsigned int get_spec_version(const VkExtensionProperties *extensions,
+ unsigned int count, const char *extension_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; ++i)
+ {
+ if (!strcmp(extensions[i].extensionName, extension_name))
+ return extensions[i].specVersion;
+ }
+ return 0;
+}
+
+static bool is_extension_disabled(const char *extension_name)
+{
+ const char *disabled_extensions;
+
+ if (!(disabled_extensions = getenv("VKD3D_DISABLE_EXTENSIONS")))
+ return false;
+
+ return vkd3d_debug_list_has_member(disabled_extensions, extension_name);
+}
+
+static bool has_extension(const VkExtensionProperties *extensions,
+ unsigned int count, const char *extension_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; ++i)
+ {
+ if (is_extension_disabled(extension_name))
+ {
+ WARN("Extension %s is disabled.\n", debugstr_a(extension_name));
+ continue;
+ }
+ if (!strcmp(extensions[i].extensionName, extension_name))
+ return true;
+ }
+ return false;
+}
+
+static unsigned int vkd3d_check_extensions(const VkExtensionProperties *extensions, unsigned int count,
+ const char * const *required_extensions, unsigned int required_extension_count,
+ const struct vkd3d_optional_extension_info *optional_extensions, unsigned int optional_extension_count,
+ const char * const *user_extensions, unsigned int user_extension_count,
+ const char * const *optional_user_extensions, unsigned int optional_user_extension_count,
+ bool *user_extension_supported, struct vkd3d_vulkan_info *vulkan_info, const char *extension_type,
+ bool is_debug_enabled)
+{
+ unsigned int extension_count = 0;
+ unsigned int i;
+
+ for (i = 0; i < required_extension_count; ++i)
+ {
+ if (!has_extension(extensions, count, required_extensions[i]))
+ ERR("Required %s extension %s is not supported.\n",
+ extension_type, debugstr_a(required_extensions[i]));
+ ++extension_count;
+ }
+
+ for (i = 0; i < optional_extension_count; ++i)
+ {
+ const char *extension_name = optional_extensions[i].extension_name;
+ ptrdiff_t offset = optional_extensions[i].vulkan_info_offset;
+ bool *supported = (void *)((uintptr_t)vulkan_info + offset);
+
+ if (!is_debug_enabled && optional_extensions[i].is_debug_only)
+ {
+ *supported = false;
+ TRACE("Skipping debug-only extension %s.\n", debugstr_a(extension_name));
+ continue;
+ }
+
+ if ((*supported = has_extension(extensions, count, extension_name)))
+ {
+ TRACE("Found %s extension.\n", debugstr_a(extension_name));
+ ++extension_count;
+ }
+ }
+
+ for (i = 0; i < user_extension_count; ++i)
+ {
+ if (!has_extension(extensions, count, user_extensions[i]))
+ ERR("Required user %s extension %s is not supported.\n",
+ extension_type, debugstr_a(user_extensions[i]));
+ ++extension_count;
+ }
+
+ assert(!optional_user_extension_count || user_extension_supported);
+ for (i = 0; i < optional_user_extension_count; ++i)
+ {
+ if (has_extension(extensions, count, optional_user_extensions[i]))
+ {
+ user_extension_supported[i] = true;
+ ++extension_count;
+ }
+ else
+ {
+ user_extension_supported[i] = false;
+ WARN("Optional user %s extension %s is not supported.\n",
+ extension_type, debugstr_a(optional_user_extensions[i]));
+ }
+ }
+
+ return extension_count;
+}
+
+static unsigned int vkd3d_append_extension(const char *extensions[],
+ unsigned int extension_count, const char *extension_name)
+{
+ unsigned int i;
+
+ /* avoid duplicates */
+ for (i = 0; i < extension_count; ++i)
+ {
+ if (!strcmp(extensions[i], extension_name))
+ return extension_count;
+ }
+
+ extensions[extension_count++] = extension_name;
+ return extension_count;
+}
+
+static unsigned int vkd3d_enable_extensions(const char *extensions[],
+ const char * const *required_extensions, unsigned int required_extension_count,
+ const struct vkd3d_optional_extension_info *optional_extensions, unsigned int optional_extension_count,
+ const char * const *user_extensions, unsigned int user_extension_count,
+ const char * const *optional_user_extensions, unsigned int optional_user_extension_count,
+ bool *user_extension_supported, const struct vkd3d_vulkan_info *vulkan_info)
+{
+ unsigned int extension_count = 0;
+ unsigned int i;
+
+ for (i = 0; i < required_extension_count; ++i)
+ {
+ extensions[extension_count++] = required_extensions[i];
+ }
+ for (i = 0; i < optional_extension_count; ++i)
+ {
+ ptrdiff_t offset = optional_extensions[i].vulkan_info_offset;
+ const bool *supported = (void *)((uintptr_t)vulkan_info + offset);
+
+ if (*supported)
+ extensions[extension_count++] = optional_extensions[i].extension_name;
+ }
+
+ for (i = 0; i < user_extension_count; ++i)
+ {
+ extension_count = vkd3d_append_extension(extensions, extension_count, user_extensions[i]);
+ }
+ assert(!optional_user_extension_count || user_extension_supported);
+ for (i = 0; i < optional_user_extension_count; ++i)
+ {
+ if (!user_extension_supported[i])
+ continue;
+ extension_count = vkd3d_append_extension(extensions, extension_count, optional_user_extensions[i]);
+ }
+
+ return extension_count;
+}
+
+static HRESULT vkd3d_init_instance_caps(struct vkd3d_instance *instance,
+ const struct vkd3d_instance_create_info *create_info,
+ uint32_t *instance_extension_count, bool **user_extension_supported)
+{
+ const struct vkd3d_vk_global_procs *vk_procs = &instance->vk_global_procs;
+ const struct vkd3d_optional_instance_extensions_info *optional_extensions;
+ struct vkd3d_vulkan_info *vulkan_info = &instance->vk_info;
+ VkExtensionProperties *vk_extensions;
+ uint32_t count;
+ VkResult vr;
+
+ memset(vulkan_info, 0, sizeof(*vulkan_info));
+ *instance_extension_count = 0;
+
+ if ((vr = vk_procs->vkEnumerateInstanceExtensionProperties(NULL, &count, NULL)) < 0)
+ {
+ ERR("Failed to enumerate instance extensions, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+ if (!count)
+ return S_OK;
+
+ if (!(vk_extensions = vkd3d_calloc(count, sizeof(*vk_extensions))))
+ return E_OUTOFMEMORY;
+
+ TRACE("Enumerating %u instance extensions.\n", count);
+ if ((vr = vk_procs->vkEnumerateInstanceExtensionProperties(NULL, &count, vk_extensions)) < 0)
+ {
+ ERR("Failed to enumerate instance extensions, vr %d.\n", vr);
+ vkd3d_free(vk_extensions);
+ return hresult_from_vk_result(vr);
+ }
+
+ optional_extensions = vkd3d_find_struct(create_info->next, OPTIONAL_INSTANCE_EXTENSIONS_INFO);
+ if (optional_extensions && optional_extensions->extension_count)
+ {
+ if (!(*user_extension_supported = vkd3d_calloc(optional_extensions->extension_count, sizeof(bool))))
+ {
+ vkd3d_free(vk_extensions);
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ *user_extension_supported = NULL;
+ }
+
+ *instance_extension_count = vkd3d_check_extensions(vk_extensions, count, NULL, 0,
+ optional_instance_extensions, ARRAY_SIZE(optional_instance_extensions),
+ create_info->instance_extensions, create_info->instance_extension_count,
+ optional_extensions ? optional_extensions->extensions : NULL,
+ optional_extensions ? optional_extensions->extension_count : 0,
+ *user_extension_supported, vulkan_info, "instance",
+ instance->config_flags & VKD3D_CONFIG_FLAG_VULKAN_DEBUG);
+
+ vkd3d_free(vk_extensions);
+ return S_OK;
+}
+
+static HRESULT vkd3d_init_vk_global_procs(struct vkd3d_instance *instance,
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr)
+{
+ HRESULT hr;
+
+ if (!vkGetInstanceProcAddr)
+ {
+ if (!(instance->libvulkan = vkd3d_dlopen(SONAME_LIBVULKAN)))
+ {
+ ERR("Failed to load libvulkan: %s.\n", vkd3d_dlerror());
+ return E_FAIL;
+ }
+
+ if (!(vkGetInstanceProcAddr = vkd3d_dlsym(instance->libvulkan, "vkGetInstanceProcAddr")))
+ {
+ ERR("Could not load function pointer for vkGetInstanceProcAddr().\n");
+ vkd3d_dlclose(instance->libvulkan);
+ instance->libvulkan = NULL;
+ return E_FAIL;
+ }
+ }
+ else
+ {
+ instance->libvulkan = NULL;
+ }
+
+ if (FAILED(hr = vkd3d_load_vk_global_procs(&instance->vk_global_procs, vkGetInstanceProcAddr)))
+ {
+ if (instance->libvulkan)
+ vkd3d_dlclose(instance->libvulkan);
+ instance->libvulkan = NULL;
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static VkBool32 VKAPI_PTR vkd3d_debug_report_callback(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT object_type, uint64_t object, size_t location,
+ int32_t message_code, const char *layer_prefix, const char *message, void *user_data)
+{
+ FIXME("%s\n", debugstr_a(message));
+ return VK_FALSE;
+}
+
+static void vkd3d_init_debug_report(struct vkd3d_instance *instance)
+{
+ const struct vkd3d_vk_instance_procs *vk_procs = &instance->vk_procs;
+ VkDebugReportCallbackCreateInfoEXT callback_info;
+ VkInstance vk_instance = instance->vk_instance;
+ VkDebugReportCallbackEXT callback;
+ VkResult vr;
+
+ callback_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
+ callback_info.pNext = NULL;
+ callback_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ callback_info.pfnCallback = vkd3d_debug_report_callback;
+ callback_info.pUserData = NULL;
+ if ((vr = VK_CALL(vkCreateDebugReportCallbackEXT(vk_instance, &callback_info, NULL, &callback)) < 0))
+ {
+ WARN("Failed to create debug report callback, vr %d.\n", vr);
+ return;
+ }
+
+ instance->vk_debug_callback = callback;
+}
+
+static const struct vkd3d_debug_option vkd3d_config_options[] =
+{
+ {"vk_debug", VKD3D_CONFIG_FLAG_VULKAN_DEBUG}, /* enable Vulkan debug extensions */
+};
+
+static uint64_t vkd3d_init_config_flags(void)
+{
+ uint64_t config_flags;
+ const char *config;
+
+ config = getenv("VKD3D_CONFIG");
+ config_flags = vkd3d_parse_debug_options(config, vkd3d_config_options, ARRAY_SIZE(vkd3d_config_options));
+
+ if (config_flags)
+ TRACE("VKD3D_CONFIG='%s'.\n", config);
+
+ return config_flags;
+}
+
+static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
+ const struct vkd3d_instance_create_info *create_info)
+{
+ const struct vkd3d_vk_global_procs *vk_global_procs = &instance->vk_global_procs;
+ const struct vkd3d_optional_instance_extensions_info *optional_extensions;
+ const struct vkd3d_application_info *vkd3d_application_info;
+ bool *user_extension_supported = NULL;
+ VkApplicationInfo application_info;
+ VkInstanceCreateInfo instance_info;
+ char application_name[PATH_MAX];
+ uint32_t extension_count;
+ const char **extensions;
+ VkInstance vk_instance;
+ VkResult vr;
+ HRESULT hr;
+
+ TRACE("Build: " PACKAGE_STRING VKD3D_VCS_ID ".\n");
+
+ if (!create_info->pfn_signal_event)
+ {
+ ERR("Invalid signal event function pointer.\n");
+ return E_INVALIDARG;
+ }
+ if (!create_info->pfn_create_thread != !create_info->pfn_join_thread)
+ {
+ ERR("Invalid create/join thread function pointers.\n");
+ return E_INVALIDARG;
+ }
+ if (create_info->wchar_size != 2 && create_info->wchar_size != 4)
+ {
+ ERR("Unexpected WCHAR size %zu.\n", create_info->wchar_size);
+ return E_INVALIDARG;
+ }
+
+ instance->signal_event = create_info->pfn_signal_event;
+ instance->create_thread = create_info->pfn_create_thread;
+ instance->join_thread = create_info->pfn_join_thread;
+ instance->wchar_size = create_info->wchar_size;
+
+ instance->config_flags = vkd3d_init_config_flags();
+
+ if (FAILED(hr = vkd3d_init_vk_global_procs(instance, create_info->pfn_vkGetInstanceProcAddr)))
+ {
+ ERR("Failed to initialize Vulkan global procs, hr %#x.\n", hr);
+ return hr;
+ }
+
+ if (FAILED(hr = vkd3d_init_instance_caps(instance, create_info,
+ &extension_count, &user_extension_supported)))
+ {
+ if (instance->libvulkan)
+ vkd3d_dlclose(instance->libvulkan);
+ return hr;
+ }
+
+ application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ application_info.pNext = NULL;
+ application_info.pApplicationName = NULL;
+ application_info.applicationVersion = 0;
+ application_info.pEngineName = PACKAGE_NAME;
+ application_info.engineVersion = vkd3d_get_vk_version();
+ application_info.apiVersion = VK_API_VERSION_1_0;
+ instance->api_version = VKD3D_API_VERSION_1_0;
+
+ if ((vkd3d_application_info = vkd3d_find_struct(create_info->next, APPLICATION_INFO)))
+ {
+ if (vkd3d_application_info->application_name)
+ application_info.pApplicationName = vkd3d_application_info->application_name;
+ else if (vkd3d_get_program_name(application_name))
+ application_info.pApplicationName = application_name;
+ application_info.applicationVersion = vkd3d_application_info->application_version;
+ if (vkd3d_application_info->engine_name)
+ {
+ application_info.pEngineName = vkd3d_application_info->engine_name;
+ application_info.engineVersion = vkd3d_application_info->engine_version;
+ }
+ instance->api_version = vkd3d_application_info->api_version;
+ }
+ else if (vkd3d_get_program_name(application_name))
+ {
+ application_info.pApplicationName = application_name;
+ }
+
+ TRACE("Application: %s.\n", debugstr_a(application_info.pApplicationName));
+ TRACE("vkd3d API version: %u.\n", instance->api_version);
+
+ if (!(extensions = vkd3d_calloc(extension_count, sizeof(*extensions))))
+ {
+ if (instance->libvulkan)
+ vkd3d_dlclose(instance->libvulkan);
+ vkd3d_free(user_extension_supported);
+ return E_OUTOFMEMORY;
+ }
+
+ optional_extensions = vkd3d_find_struct(create_info->next, OPTIONAL_INSTANCE_EXTENSIONS_INFO);
+
+ instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ instance_info.pNext = NULL;
+ instance_info.flags = 0;
+ instance_info.pApplicationInfo = &application_info;
+ instance_info.enabledLayerCount = 0;
+ instance_info.ppEnabledLayerNames = NULL;
+ instance_info.enabledExtensionCount = vkd3d_enable_extensions(extensions, NULL, 0,
+ optional_instance_extensions, ARRAY_SIZE(optional_instance_extensions),
+ create_info->instance_extensions, create_info->instance_extension_count,
+ optional_extensions ? optional_extensions->extensions : NULL,
+ optional_extensions ? optional_extensions->extension_count : 0,
+ user_extension_supported, &instance->vk_info);
+ instance_info.ppEnabledExtensionNames = extensions;
+ vkd3d_free(user_extension_supported);
+
+ vr = vk_global_procs->vkCreateInstance(&instance_info, NULL, &vk_instance);
+ vkd3d_free(extensions);
+ if (vr < 0)
+ {
+ ERR("Failed to create Vulkan instance, vr %d.\n", vr);
+ if (instance->libvulkan)
+ vkd3d_dlclose(instance->libvulkan);
+ return hresult_from_vk_result(vr);
+ }
+
+ if (FAILED(hr = vkd3d_load_vk_instance_procs(&instance->vk_procs, vk_global_procs, vk_instance)))
+ {
+ ERR("Failed to load instance procs, hr %#x.\n", hr);
+ if (instance->vk_procs.vkDestroyInstance)
+ instance->vk_procs.vkDestroyInstance(vk_instance, NULL);
+ if (instance->libvulkan)
+ vkd3d_dlclose(instance->libvulkan);
+ return hr;
+ }
+
+ instance->vk_instance = vk_instance;
+
+ TRACE("Created Vulkan instance %p.\n", vk_instance);
+
+ instance->refcount = 1;
+
+ instance->vk_debug_callback = VK_NULL_HANDLE;
+ if (instance->vk_info.EXT_debug_report)
+ vkd3d_init_debug_report(instance);
+
+ return S_OK;
+}
+
+HRESULT vkd3d_create_instance(const struct vkd3d_instance_create_info *create_info,
+ struct vkd3d_instance **instance)
+{
+ struct vkd3d_instance *object;
+ HRESULT hr;
+
+ TRACE("create_info %p, instance %p.\n", create_info, instance);
+
+ if (!create_info || !instance)
+ return E_INVALIDARG;
+ if (create_info->type != VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO)
+ {
+ WARN("Invalid structure type %#x.\n", create_info->type);
+ return E_INVALIDARG;
+ }
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = vkd3d_instance_init(object, create_info)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created instance %p.\n", object);
+
+ *instance = object;
+
+ return S_OK;
+}
+
+static void vkd3d_destroy_instance(struct vkd3d_instance *instance)
+{
+ const struct vkd3d_vk_instance_procs *vk_procs = &instance->vk_procs;
+ VkInstance vk_instance = instance->vk_instance;
+
+ if (instance->vk_debug_callback)
+ VK_CALL(vkDestroyDebugReportCallbackEXT(vk_instance, instance->vk_debug_callback, NULL));
+
+ VK_CALL(vkDestroyInstance(vk_instance, NULL));
+
+ if (instance->libvulkan)
+ vkd3d_dlclose(instance->libvulkan);
+
+ vkd3d_free(instance);
+}
+
+ULONG vkd3d_instance_incref(struct vkd3d_instance *instance)
+{
+ ULONG refcount = InterlockedIncrement(&instance->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", instance, refcount);
+
+ return refcount;
+}
+
+ULONG vkd3d_instance_decref(struct vkd3d_instance *instance)
+{
+ ULONG refcount = InterlockedDecrement(&instance->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", instance, refcount);
+
+ if (!refcount)
+ vkd3d_destroy_instance(instance);
+
+ return refcount;
+}
+
+VkInstance vkd3d_instance_get_vk_instance(struct vkd3d_instance *instance)
+{
+ return instance->vk_instance;
+}
+
+struct vkd3d_physical_device_info
+{
+ /* properties */
+ VkPhysicalDeviceDescriptorIndexingPropertiesEXT descriptor_indexing_properties;
+ VkPhysicalDeviceMaintenance3Properties maintenance3_properties;
+ VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties;
+ VkPhysicalDeviceTransformFeedbackPropertiesEXT xfb_properties;
+ VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT vertex_divisor_properties;
+
+ VkPhysicalDeviceProperties2KHR properties2;
+
+ /* features */
+ VkPhysicalDeviceConditionalRenderingFeaturesEXT conditional_rendering_features;
+ VkPhysicalDeviceDepthClipEnableFeaturesEXT depth_clip_features;
+ VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing_features;
+ VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote_features;
+ VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT texel_buffer_alignment_features;
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features;
+ VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
+
+ VkPhysicalDeviceFeatures2 features2;
+};
+
+static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *info, struct d3d12_device *device)
+{
+ const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs;
+ VkPhysicalDeviceConditionalRenderingFeaturesEXT *conditional_rendering_features;
+ VkPhysicalDeviceDescriptorIndexingPropertiesEXT *descriptor_indexing_properties;
+ VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *vertex_divisor_properties;
+ VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment_properties;
+ VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features;
+ VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features;
+ VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features;
+ VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features;
+ VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_features;
+ VkPhysicalDeviceMaintenance3Properties *maintenance3_properties;
+ VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb_properties;
+ VkPhysicalDevice physical_device = device->vk_physical_device;
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb_features;
+ struct vkd3d_vulkan_info *vulkan_info = &device->vk_info;
+
+ memset(info, 0, sizeof(*info));
+ conditional_rendering_features = &info->conditional_rendering_features;
+ depth_clip_features = &info->depth_clip_features;
+ descriptor_indexing_features = &info->descriptor_indexing_features;
+ descriptor_indexing_properties = &info->descriptor_indexing_properties;
+ maintenance3_properties = &info->maintenance3_properties;
+ demote_features = &info->demote_features;
+ buffer_alignment_features = &info->texel_buffer_alignment_features;
+ buffer_alignment_properties = &info->texel_buffer_alignment_properties;
+ vertex_divisor_features = &info->vertex_divisor_features;
+ vertex_divisor_properties = &info->vertex_divisor_properties;
+ xfb_features = &info->xfb_features;
+ xfb_properties = &info->xfb_properties;
+
+ info->features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+
+ conditional_rendering_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT;
+ vk_prepend_struct(&info->features2, conditional_rendering_features);
+ depth_clip_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT;
+ vk_prepend_struct(&info->features2, depth_clip_features);
+ descriptor_indexing_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
+ vk_prepend_struct(&info->features2, descriptor_indexing_features);
+ demote_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT;
+ vk_prepend_struct(&info->features2, demote_features);
+ buffer_alignment_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT;
+ vk_prepend_struct(&info->features2, buffer_alignment_features);
+ xfb_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
+ vk_prepend_struct(&info->features2, xfb_features);
+ vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
+ vk_prepend_struct(&info->features2, vertex_divisor_features);
+
+ if (vulkan_info->KHR_get_physical_device_properties2)
+ VK_CALL(vkGetPhysicalDeviceFeatures2KHR(physical_device, &info->features2));
+ else
+ VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &info->features2.features));
+
+ info->properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+
+ maintenance3_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES;
+ vk_prepend_struct(&info->properties2, maintenance3_properties);
+ descriptor_indexing_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT;
+ vk_prepend_struct(&info->properties2, descriptor_indexing_properties);
+ buffer_alignment_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
+ vk_prepend_struct(&info->properties2, buffer_alignment_properties);
+ xfb_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
+ vk_prepend_struct(&info->properties2, xfb_properties);
+ vertex_divisor_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
+ vk_prepend_struct(&info->properties2, vertex_divisor_properties);
+
+ if (vulkan_info->KHR_get_physical_device_properties2)
+ VK_CALL(vkGetPhysicalDeviceProperties2KHR(physical_device, &info->properties2));
+ else
+ VK_CALL(vkGetPhysicalDeviceProperties(physical_device, &info->properties2.properties));
+}
+
+static void vkd3d_trace_physical_device_properties(const VkPhysicalDeviceProperties *properties)
+{
+ const uint32_t driver_version = properties->driverVersion;
+ const uint32_t api_version = properties->apiVersion;
+
+ TRACE("Device name: %s.\n", properties->deviceName);
+ TRACE("Vendor ID: %#x, Device ID: %#x.\n", properties->vendorID, properties->deviceID);
+ TRACE("Driver version: %#x (%u.%u.%u, %u.%u.%u.%u).\n", driver_version,
+ VK_VERSION_MAJOR(driver_version), VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version),
+ driver_version >> 22, (driver_version >> 14) & 0xff, (driver_version >> 6) & 0xff, driver_version & 0x3f);
+ TRACE("API version: %u.%u.%u.\n",
+ VK_VERSION_MAJOR(api_version), VK_VERSION_MINOR(api_version), VK_VERSION_PATCH(api_version));
+}
+
+static void vkd3d_trace_physical_device(VkPhysicalDevice device,
+ const struct vkd3d_physical_device_info *info,
+ const struct vkd3d_vk_instance_procs *vk_procs)
+{
+ VkPhysicalDeviceMemoryProperties memory_properties;
+ VkQueueFamilyProperties *queue_properties;
+ unsigned int i, j;
+ uint32_t count;
+
+ vkd3d_trace_physical_device_properties(&info->properties2.properties);
+
+ VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(device, &count, NULL));
+ TRACE("Queue families [%u]:\n", count);
+
+ if (!(queue_properties = vkd3d_calloc(count, sizeof(VkQueueFamilyProperties))))
+ return;
+ VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(device, &count, queue_properties));
+
+ for (i = 0; i < count; ++i)
+ {
+ TRACE(" Queue family [%u]: flags %s, count %u, timestamp bits %u, image transfer granularity %s.\n",
+ i, debug_vk_queue_flags(queue_properties[i].queueFlags),
+ queue_properties[i].queueCount, queue_properties[i].timestampValidBits,
+ debug_vk_extent_3d(queue_properties[i].minImageTransferGranularity));
+ }
+ vkd3d_free(queue_properties);
+
+ VK_CALL(vkGetPhysicalDeviceMemoryProperties(device, &memory_properties));
+ for (i = 0; i < memory_properties.memoryHeapCount; ++i)
+ {
+ const VkMemoryHeap *heap = &memory_properties.memoryHeaps[i];
+ TRACE("Memory heap [%u]: size %#"PRIx64" (%"PRIu64" MiB), flags %s, memory types:\n",
+ i, heap->size, heap->size / 1024 / 1024, debug_vk_memory_heap_flags(heap->flags));
+ for (j = 0; j < memory_properties.memoryTypeCount; ++j)
+ {
+ const VkMemoryType *type = &memory_properties.memoryTypes[j];
+ if (type->heapIndex != i)
+ continue;
+ TRACE(" Memory type [%u]: flags %s.\n", j, debug_vk_memory_property_flags(type->propertyFlags));
+ }
+ }
+}
+
+static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_device_info *info)
+{
+ const VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *divisor_properties;
+ const VkPhysicalDeviceLimits *limits = &info->properties2.properties.limits;
+ const VkPhysicalDeviceDescriptorIndexingPropertiesEXT *descriptor_indexing;
+ const VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment;
+ const VkPhysicalDeviceMaintenance3Properties *maintenance3;
+ const VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb;
+
+ TRACE("Device limits:\n");
+ TRACE(" maxImageDimension1D: %u.\n", limits->maxImageDimension1D);
+ TRACE(" maxImageDimension2D: %u.\n", limits->maxImageDimension2D);
+ TRACE(" maxImageDimension3D: %u.\n", limits->maxImageDimension3D);
+ TRACE(" maxImageDimensionCube: %u.\n", limits->maxImageDimensionCube);
+ TRACE(" maxImageArrayLayers: %u.\n", limits->maxImageArrayLayers);
+ TRACE(" maxTexelBufferElements: %u.\n", limits->maxTexelBufferElements);
+ TRACE(" maxUniformBufferRange: %u.\n", limits->maxUniformBufferRange);
+ TRACE(" maxStorageBufferRange: %u.\n", limits->maxStorageBufferRange);
+ TRACE(" maxPushConstantsSize: %u.\n", limits->maxPushConstantsSize);
+ TRACE(" maxMemoryAllocationCount: %u.\n", limits->maxMemoryAllocationCount);
+ TRACE(" maxSamplerAllocationCount: %u.\n", limits->maxSamplerAllocationCount);
+ TRACE(" bufferImageGranularity: %#"PRIx64".\n", limits->bufferImageGranularity);
+ TRACE(" sparseAddressSpaceSize: %#"PRIx64".\n", limits->sparseAddressSpaceSize);
+ TRACE(" maxBoundDescriptorSets: %u.\n", limits->maxBoundDescriptorSets);
+ TRACE(" maxPerStageDescriptorSamplers: %u.\n", limits->maxPerStageDescriptorSamplers);
+ TRACE(" maxPerStageDescriptorUniformBuffers: %u.\n", limits->maxPerStageDescriptorUniformBuffers);
+ TRACE(" maxPerStageDescriptorStorageBuffers: %u.\n", limits->maxPerStageDescriptorStorageBuffers);
+ TRACE(" maxPerStageDescriptorSampledImages: %u.\n", limits->maxPerStageDescriptorSampledImages);
+ TRACE(" maxPerStageDescriptorStorageImages: %u.\n", limits->maxPerStageDescriptorStorageImages);
+ TRACE(" maxPerStageDescriptorInputAttachments: %u.\n", limits->maxPerStageDescriptorInputAttachments);
+ TRACE(" maxPerStageResources: %u.\n", limits->maxPerStageResources);
+ TRACE(" maxDescriptorSetSamplers: %u.\n", limits->maxDescriptorSetSamplers);
+ TRACE(" maxDescriptorSetUniformBuffers: %u.\n", limits->maxDescriptorSetUniformBuffers);
+ TRACE(" maxDescriptorSetUniformBuffersDynamic: %u.\n", limits->maxDescriptorSetUniformBuffersDynamic);
+ TRACE(" maxDescriptorSetStorageBuffers: %u.\n", limits->maxDescriptorSetStorageBuffers);
+ TRACE(" maxDescriptorSetStorageBuffersDynamic: %u.\n", limits->maxDescriptorSetStorageBuffersDynamic);
+ TRACE(" maxDescriptorSetSampledImages: %u.\n", limits->maxDescriptorSetSampledImages);
+ TRACE(" maxDescriptorSetStorageImages: %u.\n", limits->maxDescriptorSetStorageImages);
+ TRACE(" maxDescriptorSetInputAttachments: %u.\n", limits->maxDescriptorSetInputAttachments);
+ TRACE(" maxVertexInputAttributes: %u.\n", limits->maxVertexInputAttributes);
+ TRACE(" maxVertexInputBindings: %u.\n", limits->maxVertexInputBindings);
+ TRACE(" maxVertexInputAttributeOffset: %u.\n", limits->maxVertexInputAttributeOffset);
+ TRACE(" maxVertexInputBindingStride: %u.\n", limits->maxVertexInputBindingStride);
+ TRACE(" maxVertexOutputComponents: %u.\n", limits->maxVertexOutputComponents);
+ TRACE(" maxTessellationGenerationLevel: %u.\n", limits->maxTessellationGenerationLevel);
+ TRACE(" maxTessellationPatchSize: %u.\n", limits->maxTessellationPatchSize);
+ TRACE(" maxTessellationControlPerVertexInputComponents: %u.\n",
+ limits->maxTessellationControlPerVertexInputComponents);
+ TRACE(" maxTessellationControlPerVertexOutputComponents: %u.\n",
+ limits->maxTessellationControlPerVertexOutputComponents);
+ TRACE(" maxTessellationControlPerPatchOutputComponents: %u.\n",
+ limits->maxTessellationControlPerPatchOutputComponents);
+ TRACE(" maxTessellationControlTotalOutputComponents: %u.\n",
+ limits->maxTessellationControlTotalOutputComponents);
+ TRACE(" maxTessellationEvaluationInputComponents: %u.\n",
+ limits->maxTessellationEvaluationInputComponents);
+ TRACE(" maxTessellationEvaluationOutputComponents: %u.\n",
+ limits->maxTessellationEvaluationOutputComponents);
+ TRACE(" maxGeometryShaderInvocations: %u.\n", limits->maxGeometryShaderInvocations);
+ TRACE(" maxGeometryInputComponents: %u.\n", limits->maxGeometryInputComponents);
+ TRACE(" maxGeometryOutputComponents: %u.\n", limits->maxGeometryOutputComponents);
+ TRACE(" maxGeometryOutputVertices: %u.\n", limits->maxGeometryOutputVertices);
+ TRACE(" maxGeometryTotalOutputComponents: %u.\n", limits->maxGeometryTotalOutputComponents);
+ TRACE(" maxFragmentInputComponents: %u.\n", limits->maxFragmentInputComponents);
+ TRACE(" maxFragmentOutputAttachments: %u.\n", limits->maxFragmentOutputAttachments);
+ TRACE(" maxFragmentDualSrcAttachments: %u.\n", limits->maxFragmentDualSrcAttachments);
+ TRACE(" maxFragmentCombinedOutputResources: %u.\n", limits->maxFragmentCombinedOutputResources);
+ TRACE(" maxComputeSharedMemorySize: %u.\n", limits->maxComputeSharedMemorySize);
+ TRACE(" maxComputeWorkGroupCount: %u, %u, %u.\n", limits->maxComputeWorkGroupCount[0],
+ limits->maxComputeWorkGroupCount[1], limits->maxComputeWorkGroupCount[2]);
+ TRACE(" maxComputeWorkGroupInvocations: %u.\n", limits->maxComputeWorkGroupInvocations);
+ TRACE(" maxComputeWorkGroupSize: %u, %u, %u.\n", limits->maxComputeWorkGroupSize[0],
+ limits->maxComputeWorkGroupSize[1], limits->maxComputeWorkGroupSize[2]);
+ TRACE(" subPixelPrecisionBits: %u.\n", limits->subPixelPrecisionBits);
+ TRACE(" subTexelPrecisionBits: %u.\n", limits->subTexelPrecisionBits);
+ TRACE(" mipmapPrecisionBits: %u.\n", limits->mipmapPrecisionBits);
+ TRACE(" maxDrawIndexedIndexValue: %u.\n", limits->maxDrawIndexedIndexValue);
+ TRACE(" maxDrawIndirectCount: %u.\n", limits->maxDrawIndirectCount);
+ TRACE(" maxSamplerLodBias: %f.\n", limits->maxSamplerLodBias);
+ TRACE(" maxSamplerAnisotropy: %f.\n", limits->maxSamplerAnisotropy);
+ TRACE(" maxViewports: %u.\n", limits->maxViewports);
+ TRACE(" maxViewportDimensions: %u, %u.\n", limits->maxViewportDimensions[0],
+ limits->maxViewportDimensions[1]);
+ TRACE(" viewportBoundsRange: %f, %f.\n", limits->viewportBoundsRange[0], limits->viewportBoundsRange[1]);
+ TRACE(" viewportSubPixelBits: %u.\n", limits->viewportSubPixelBits);
+ TRACE(" minMemoryMapAlignment: %u.\n", (unsigned int)limits->minMemoryMapAlignment);
+ TRACE(" minTexelBufferOffsetAlignment: %#"PRIx64".\n", limits->minTexelBufferOffsetAlignment);
+ TRACE(" minUniformBufferOffsetAlignment: %#"PRIx64".\n", limits->minUniformBufferOffsetAlignment);
+ TRACE(" minStorageBufferOffsetAlignment: %#"PRIx64".\n", limits->minStorageBufferOffsetAlignment);
+ TRACE(" minTexelOffset: %d.\n", limits->minTexelOffset);
+ TRACE(" maxTexelOffset: %u.\n", limits->maxTexelOffset);
+ TRACE(" minTexelGatherOffset: %d.\n", limits->minTexelGatherOffset);
+ TRACE(" maxTexelGatherOffset: %u.\n", limits->maxTexelGatherOffset);
+ TRACE(" minInterpolationOffset: %f.\n", limits->minInterpolationOffset);
+ TRACE(" maxInterpolationOffset: %f.\n", limits->maxInterpolationOffset);
+ TRACE(" subPixelInterpolationOffsetBits: %u.\n", limits->subPixelInterpolationOffsetBits);
+ TRACE(" maxFramebufferWidth: %u.\n", limits->maxFramebufferWidth);
+ TRACE(" maxFramebufferHeight: %u.\n", limits->maxFramebufferHeight);
+ TRACE(" maxFramebufferLayers: %u.\n", limits->maxFramebufferLayers);
+ TRACE(" framebufferColorSampleCounts: %#x.\n", limits->framebufferColorSampleCounts);
+ TRACE(" framebufferDepthSampleCounts: %#x.\n", limits->framebufferDepthSampleCounts);
+ TRACE(" framebufferStencilSampleCounts: %#x.\n", limits->framebufferStencilSampleCounts);
+ TRACE(" framebufferNoAttachmentsSampleCounts: %#x.\n", limits->framebufferNoAttachmentsSampleCounts);
+ TRACE(" maxColorAttachments: %u.\n", limits->maxColorAttachments);
+ TRACE(" sampledImageColorSampleCounts: %#x.\n", limits->sampledImageColorSampleCounts);
+ TRACE(" sampledImageIntegerSampleCounts: %#x.\n", limits->sampledImageIntegerSampleCounts);
+ TRACE(" sampledImageDepthSampleCounts: %#x.\n", limits->sampledImageDepthSampleCounts);
+ TRACE(" sampledImageStencilSampleCounts: %#x.\n", limits->sampledImageStencilSampleCounts);
+ TRACE(" storageImageSampleCounts: %#x.\n", limits->storageImageSampleCounts);
+ TRACE(" maxSampleMaskWords: %u.\n", limits->maxSampleMaskWords);
+ TRACE(" timestampComputeAndGraphics: %#x.\n", limits->timestampComputeAndGraphics);
+ TRACE(" timestampPeriod: %f.\n", limits->timestampPeriod);
+ TRACE(" maxClipDistances: %u.\n", limits->maxClipDistances);
+ TRACE(" maxCullDistances: %u.\n", limits->maxCullDistances);
+ TRACE(" maxCombinedClipAndCullDistances: %u.\n", limits->maxCombinedClipAndCullDistances);
+ TRACE(" discreteQueuePriorities: %u.\n", limits->discreteQueuePriorities);
+ TRACE(" pointSizeRange: %f, %f.\n", limits->pointSizeRange[0], limits->pointSizeRange[1]);
+ TRACE(" lineWidthRange: %f, %f,\n", limits->lineWidthRange[0], limits->lineWidthRange[1]);
+ TRACE(" pointSizeGranularity: %f.\n", limits->pointSizeGranularity);
+ TRACE(" lineWidthGranularity: %f.\n", limits->lineWidthGranularity);
+ TRACE(" strictLines: %#x.\n", limits->strictLines);
+ TRACE(" standardSampleLocations: %#x.\n", limits->standardSampleLocations);
+ TRACE(" optimalBufferCopyOffsetAlignment: %#"PRIx64".\n", limits->optimalBufferCopyOffsetAlignment);
+ TRACE(" optimalBufferCopyRowPitchAlignment: %#"PRIx64".\n", limits->optimalBufferCopyRowPitchAlignment);
+ TRACE(" nonCoherentAtomSize: %#"PRIx64".\n", limits->nonCoherentAtomSize);
+
+ descriptor_indexing = &info->descriptor_indexing_properties;
+ TRACE(" VkPhysicalDeviceDescriptorIndexingPropertiesEXT:\n");
+
+ TRACE(" maxUpdateAfterBindDescriptorsInAllPools: %u.\n",
+ descriptor_indexing->maxUpdateAfterBindDescriptorsInAllPools);
+
+ TRACE(" shaderUniformBufferArrayNonUniformIndexingNative: %#x.\n",
+ descriptor_indexing->shaderUniformBufferArrayNonUniformIndexingNative);
+ TRACE(" shaderSampledImageArrayNonUniformIndexingNative: %#x.\n",
+ descriptor_indexing->shaderSampledImageArrayNonUniformIndexingNative);
+ TRACE(" shaderStorageBufferArrayNonUniformIndexingNative: %#x.\n",
+ descriptor_indexing->shaderStorageBufferArrayNonUniformIndexingNative);
+ TRACE(" shaderStorageImageArrayNonUniformIndexingNative: %#x.\n",
+ descriptor_indexing->shaderStorageImageArrayNonUniformIndexingNative);
+ TRACE(" shaderInputAttachmentArrayNonUniformIndexingNative: %#x.\n",
+ descriptor_indexing->shaderInputAttachmentArrayNonUniformIndexingNative);
+
+ TRACE(" robustBufferAccessUpdateAfterBind: %#x.\n",
+ descriptor_indexing->robustBufferAccessUpdateAfterBind);
+ TRACE(" quadDivergentImplicitLod: %#x.\n",
+ descriptor_indexing->quadDivergentImplicitLod);
+
+ TRACE(" maxPerStageDescriptorUpdateAfterBindSamplers: %u.\n",
+ descriptor_indexing->maxPerStageDescriptorUpdateAfterBindSamplers);
+ TRACE(" maxPerStageDescriptorUpdateAfterBindUniformBuffers: %u.\n",
+ descriptor_indexing->maxPerStageDescriptorUpdateAfterBindUniformBuffers);
+ TRACE(" maxPerStageDescriptorUpdateAfterBindStorageBuffers: %u.\n",
+ descriptor_indexing->maxPerStageDescriptorUpdateAfterBindStorageBuffers);
+ TRACE(" maxPerStageDescriptorUpdateAfterBindSampledImages: %u.\n",
+ descriptor_indexing->maxPerStageDescriptorUpdateAfterBindSampledImages);
+ TRACE(" maxPerStageDescriptorUpdateAfterBindStorageImages: %u.\n",
+ descriptor_indexing->maxPerStageDescriptorUpdateAfterBindStorageImages);
+ TRACE(" maxPerStageDescriptorUpdateAfterBindInputAttachments: %u.\n",
+ descriptor_indexing->maxPerStageDescriptorUpdateAfterBindInputAttachments);
+ TRACE(" maxPerStageUpdateAfterBindResources: %u.\n",
+ descriptor_indexing->maxPerStageUpdateAfterBindResources);
+
+ TRACE(" maxDescriptorSetUpdateAfterBindSamplers: %u.\n",
+ descriptor_indexing->maxDescriptorSetUpdateAfterBindSamplers);
+ TRACE(" maxDescriptorSetUpdateAfterBindUniformBuffers: %u.\n",
+ descriptor_indexing->maxDescriptorSetUpdateAfterBindUniformBuffers);
+ TRACE(" maxDescriptorSetUpdateAfterBindUniformBuffersDynamic: %u.\n",
+ descriptor_indexing->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic);
+ TRACE(" maxDescriptorSetUpdateAfterBindStorageBuffers: %u.\n",
+ descriptor_indexing->maxDescriptorSetUpdateAfterBindStorageBuffers);
+ TRACE(" maxDescriptorSetUpdateAfterBindStorageBuffersDynamic: %u.\n",
+ descriptor_indexing->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic);
+ TRACE(" maxDescriptorSetUpdateAfterBindSampledImages: %u.\n",
+ descriptor_indexing->maxDescriptorSetUpdateAfterBindSampledImages);
+ TRACE(" maxDescriptorSetUpdateAfterBindStorageImages: %u.\n",
+ descriptor_indexing->maxDescriptorSetUpdateAfterBindStorageImages);
+ TRACE(" maxDescriptorSetUpdateAfterBindInputAttachments: %u.\n",
+ descriptor_indexing->maxDescriptorSetUpdateAfterBindInputAttachments);
+
+ maintenance3 = &info->maintenance3_properties;
+ TRACE(" VkPhysicalDeviceMaintenance3Properties:\n");
+ TRACE(" maxPerSetDescriptors: %u.\n", maintenance3->maxPerSetDescriptors);
+ TRACE(" maxMemoryAllocationSize: %#"PRIx64".\n", maintenance3->maxMemoryAllocationSize);
+
+ buffer_alignment = &info->texel_buffer_alignment_properties;
+ TRACE(" VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT:\n");
+ TRACE(" storageTexelBufferOffsetAlignmentBytes: %#"PRIx64".\n",
+ buffer_alignment->storageTexelBufferOffsetAlignmentBytes);
+ TRACE(" storageTexelBufferOffsetSingleTexelAlignment: %#x.\n",
+ buffer_alignment->storageTexelBufferOffsetSingleTexelAlignment);
+ TRACE(" uniformTexelBufferOffsetAlignmentBytes: %#"PRIx64".\n",
+ buffer_alignment->uniformTexelBufferOffsetAlignmentBytes);
+ TRACE(" uniformTexelBufferOffsetSingleTexelAlignment: %#x.\n",
+ buffer_alignment->uniformTexelBufferOffsetSingleTexelAlignment);
+
+ xfb = &info->xfb_properties;
+ TRACE(" VkPhysicalDeviceTransformFeedbackPropertiesEXT:\n");
+ TRACE(" maxTransformFeedbackStreams: %u.\n", xfb->maxTransformFeedbackStreams);
+ TRACE(" maxTransformFeedbackBuffers: %u.\n", xfb->maxTransformFeedbackBuffers);
+ TRACE(" maxTransformFeedbackBufferSize: %#"PRIx64".\n", xfb->maxTransformFeedbackBufferSize);
+ TRACE(" maxTransformFeedbackStreamDataSize: %u.\n", xfb->maxTransformFeedbackStreamDataSize);
+ TRACE(" maxTransformFeedbackBufferDataSize: %u.\n", xfb->maxTransformFeedbackBufferDataSize);
+ TRACE(" maxTransformFeedbackBufferDataStride: %u.\n", xfb->maxTransformFeedbackBufferDataStride);
+ TRACE(" transformFeedbackQueries: %#x.\n", xfb->transformFeedbackQueries);
+ TRACE(" transformFeedbackStreamsLinesTriangles: %#x.\n", xfb->transformFeedbackStreamsLinesTriangles);
+ TRACE(" transformFeedbackRasterizationStreamSelect: %#x.\n", xfb->transformFeedbackRasterizationStreamSelect);
+ TRACE(" transformFeedbackDraw: %x.\n", xfb->transformFeedbackDraw);
+
+ divisor_properties = &info->vertex_divisor_properties;
+ TRACE(" VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT:\n");
+ TRACE(" maxVertexAttribDivisor: %u.\n", divisor_properties->maxVertexAttribDivisor);
+}
+
+static void vkd3d_trace_physical_device_features(const struct vkd3d_physical_device_info *info)
+{
+ const VkPhysicalDeviceConditionalRenderingFeaturesEXT *conditional_rendering_features;
+ const VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features;
+ const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features;
+ const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *divisor_features;
+ const VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing;
+ const VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_features;
+ const VkPhysicalDeviceFeatures *features = &info->features2.features;
+ const VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb;
+
+ TRACE("Device features:\n");
+ TRACE(" robustBufferAccess: %#x.\n", features->robustBufferAccess);
+ TRACE(" fullDrawIndexUint32: %#x.\n", features->fullDrawIndexUint32);
+ TRACE(" imageCubeArray: %#x.\n", features->imageCubeArray);
+ TRACE(" independentBlend: %#x.\n", features->independentBlend);
+ TRACE(" geometryShader: %#x.\n", features->geometryShader);
+ TRACE(" tessellationShader: %#x.\n", features->tessellationShader);
+ TRACE(" sampleRateShading: %#x.\n", features->sampleRateShading);
+ TRACE(" dualSrcBlend: %#x.\n", features->dualSrcBlend);
+ TRACE(" logicOp: %#x.\n", features->logicOp);
+ TRACE(" multiDrawIndirect: %#x.\n", features->multiDrawIndirect);
+ TRACE(" drawIndirectFirstInstance: %#x.\n", features->drawIndirectFirstInstance);
+ TRACE(" depthClamp: %#x.\n", features->depthClamp);
+ TRACE(" depthBiasClamp: %#x.\n", features->depthBiasClamp);
+ TRACE(" fillModeNonSolid: %#x.\n", features->fillModeNonSolid);
+ TRACE(" depthBounds: %#x.\n", features->depthBounds);
+ TRACE(" wideLines: %#x.\n", features->wideLines);
+ TRACE(" largePoints: %#x.\n", features->largePoints);
+ TRACE(" alphaToOne: %#x.\n", features->alphaToOne);
+ TRACE(" multiViewport: %#x.\n", features->multiViewport);
+ TRACE(" samplerAnisotropy: %#x.\n", features->samplerAnisotropy);
+ TRACE(" textureCompressionETC2: %#x.\n", features->textureCompressionETC2);
+ TRACE(" textureCompressionASTC_LDR: %#x.\n", features->textureCompressionASTC_LDR);
+ TRACE(" textureCompressionBC: %#x.\n", features->textureCompressionBC);
+ TRACE(" occlusionQueryPrecise: %#x.\n", features->occlusionQueryPrecise);
+ TRACE(" pipelineStatisticsQuery: %#x.\n", features->pipelineStatisticsQuery);
+ TRACE(" vertexOipelineStoresAndAtomics: %#x.\n", features->vertexPipelineStoresAndAtomics);
+ TRACE(" fragmentStoresAndAtomics: %#x.\n", features->fragmentStoresAndAtomics);
+ TRACE(" shaderTessellationAndGeometryPointSize: %#x.\n", features->shaderTessellationAndGeometryPointSize);
+ TRACE(" shaderImageGatherExtended: %#x.\n", features->shaderImageGatherExtended);
+ TRACE(" shaderStorageImageExtendedFormats: %#x.\n", features->shaderStorageImageExtendedFormats);
+ TRACE(" shaderStorageImageMultisample: %#x.\n", features->shaderStorageImageMultisample);
+ TRACE(" shaderStorageImageReadWithoutFormat: %#x.\n", features->shaderStorageImageReadWithoutFormat);
+ TRACE(" shaderStorageImageWriteWithoutFormat: %#x.\n", features->shaderStorageImageWriteWithoutFormat);
+ TRACE(" shaderUniformBufferArrayDynamicIndexing: %#x.\n", features->shaderUniformBufferArrayDynamicIndexing);
+ TRACE(" shaderSampledImageArrayDynamicIndexing: %#x.\n", features->shaderSampledImageArrayDynamicIndexing);
+ TRACE(" shaderStorageBufferArrayDynamicIndexing: %#x.\n", features->shaderStorageBufferArrayDynamicIndexing);
+ TRACE(" shaderStorageImageArrayDynamicIndexing: %#x.\n", features->shaderStorageImageArrayDynamicIndexing);
+ TRACE(" shaderClipDistance: %#x.\n", features->shaderClipDistance);
+ TRACE(" shaderCullDistance: %#x.\n", features->shaderCullDistance);
+ TRACE(" shaderFloat64: %#x.\n", features->shaderFloat64);
+ TRACE(" shaderInt64: %#x.\n", features->shaderInt64);
+ TRACE(" shaderInt16: %#x.\n", features->shaderInt16);
+ TRACE(" shaderResourceResidency: %#x.\n", features->shaderResourceResidency);
+ TRACE(" shaderResourceMinLod: %#x.\n", features->shaderResourceMinLod);
+ TRACE(" sparseBinding: %#x.\n", features->sparseBinding);
+ TRACE(" sparseResidencyBuffer: %#x.\n", features->sparseResidencyBuffer);
+ TRACE(" sparseResidencyImage2D: %#x.\n", features->sparseResidencyImage2D);
+ TRACE(" sparseResidencyImage3D: %#x.\n", features->sparseResidencyImage3D);
+ TRACE(" sparseResidency2Samples: %#x.\n", features->sparseResidency2Samples);
+ TRACE(" sparseResidency4Samples: %#x.\n", features->sparseResidency4Samples);
+ TRACE(" sparseResidency8Samples: %#x.\n", features->sparseResidency8Samples);
+ TRACE(" sparseResidency16Samples: %#x.\n", features->sparseResidency16Samples);
+ TRACE(" sparseResidencyAliased: %#x.\n", features->sparseResidencyAliased);
+ TRACE(" variableMultisampleRate: %#x.\n", features->variableMultisampleRate);
+ TRACE(" inheritedQueries: %#x.\n", features->inheritedQueries);
+
+ descriptor_indexing = &info->descriptor_indexing_features;
+ TRACE(" VkPhysicalDeviceDescriptorIndexingFeaturesEXT:\n");
+
+ TRACE(" shaderInputAttachmentArrayDynamicIndexing: %#x.\n",
+ descriptor_indexing->shaderInputAttachmentArrayDynamicIndexing);
+ TRACE(" shaderUniformTexelBufferArrayDynamicIndexing: %#x.\n",
+ descriptor_indexing->shaderUniformTexelBufferArrayDynamicIndexing);
+ TRACE(" shaderStorageTexelBufferArrayDynamicIndexing: %#x.\n",
+ descriptor_indexing->shaderStorageTexelBufferArrayDynamicIndexing);
+
+ TRACE(" shaderUniformBufferArrayNonUniformIndexing: %#x.\n",
+ descriptor_indexing->shaderUniformBufferArrayNonUniformIndexing);
+ TRACE(" shaderSampledImageArrayNonUniformIndexing: %#x.\n",
+ descriptor_indexing->shaderSampledImageArrayNonUniformIndexing);
+ TRACE(" shaderStorageBufferArrayNonUniformIndexing: %#x.\n",
+ descriptor_indexing->shaderStorageBufferArrayNonUniformIndexing);
+ TRACE(" shaderStorageImageArrayNonUniformIndexing: %#x.\n",
+ descriptor_indexing->shaderStorageImageArrayNonUniformIndexing);
+ TRACE(" shaderInputAttachmentArrayNonUniformIndexing: %#x.\n",
+ descriptor_indexing->shaderInputAttachmentArrayNonUniformIndexing);
+ TRACE(" shaderUniformTexelBufferArrayNonUniformIndexing: %#x.\n",
+ descriptor_indexing->shaderUniformTexelBufferArrayNonUniformIndexing);
+ TRACE(" shaderStorageTexelBufferArrayNonUniformIndexing: %#x.\n",
+ descriptor_indexing->shaderStorageTexelBufferArrayNonUniformIndexing);
+
+ TRACE(" descriptorBindingUniformBufferUpdateAfterBind: %#x.\n",
+ descriptor_indexing->descriptorBindingUniformBufferUpdateAfterBind);
+ TRACE(" descriptorBindingSampledImageUpdateAfterBind: %#x.\n",
+ descriptor_indexing->descriptorBindingSampledImageUpdateAfterBind);
+ TRACE(" descriptorBindingStorageImageUpdateAfterBind: %#x.\n",
+ descriptor_indexing->descriptorBindingStorageImageUpdateAfterBind);
+ TRACE(" descriptorBindingStorageBufferUpdateAfterBind: %#x.\n",
+ descriptor_indexing->descriptorBindingStorageBufferUpdateAfterBind);
+ TRACE(" descriptorBindingUniformTexelBufferUpdateAfterBind: %#x.\n",
+ descriptor_indexing->descriptorBindingUniformTexelBufferUpdateAfterBind);
+ TRACE(" descriptorBindingStorageTexelBufferUpdateAfterBind: %#x.\n",
+ descriptor_indexing->descriptorBindingStorageTexelBufferUpdateAfterBind);
+
+ TRACE(" descriptorBindingUpdateUnusedWhilePending: %#x.\n",
+ descriptor_indexing->descriptorBindingUpdateUnusedWhilePending);
+ TRACE(" descriptorBindingPartiallyBound: %#x.\n",
+ descriptor_indexing->descriptorBindingPartiallyBound);
+ TRACE(" descriptorBindingVariableDescriptorCount: %#x.\n",
+ descriptor_indexing->descriptorBindingVariableDescriptorCount);
+ TRACE(" runtimeDescriptorArray: %#x.\n",
+ descriptor_indexing->runtimeDescriptorArray);
+
+ conditional_rendering_features = &info->conditional_rendering_features;
+ TRACE(" VkPhysicalDeviceConditionalRenderingFeaturesEXT:\n");
+ TRACE(" conditionalRendering: %#x.\n", conditional_rendering_features->conditionalRendering);
+
+ depth_clip_features = &info->depth_clip_features;
+ TRACE(" VkPhysicalDeviceDepthClipEnableFeaturesEXT:\n");
+ TRACE(" depthClipEnable: %#x.\n", depth_clip_features->depthClipEnable);
+
+ demote_features = &info->demote_features;
+ TRACE(" VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT:\n");
+ TRACE(" shaderDemoteToHelperInvocation: %#x.\n", demote_features->shaderDemoteToHelperInvocation);
+
+ buffer_alignment_features = &info->texel_buffer_alignment_features;
+ TRACE(" VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT:\n");
+ TRACE(" texelBufferAlignment: %#x.\n", buffer_alignment_features->texelBufferAlignment);
+
+ xfb = &info->xfb_features;
+ TRACE(" VkPhysicalDeviceTransformFeedbackFeaturesEXT:\n");
+ TRACE(" transformFeedback: %#x.\n", xfb->transformFeedback);
+ TRACE(" geometryStreams: %#x.\n", xfb->geometryStreams);
+
+ divisor_features = &info->vertex_divisor_features;
+ TRACE(" VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT:\n");
+ TRACE(" vertexAttributeInstanceRateDivisor: %#x.\n",
+ divisor_features->vertexAttributeInstanceRateDivisor);
+ TRACE(" vertexAttributeInstanceRateZeroDivisor: %#x.\n",
+ divisor_features->vertexAttributeInstanceRateZeroDivisor);
+}
+
+static void vkd3d_init_feature_level(struct vkd3d_vulkan_info *vk_info,
+ const VkPhysicalDeviceFeatures *features,
+ const D3D12_FEATURE_DATA_D3D12_OPTIONS *d3d12_options)
+{
+ bool have_11_0 = true;
+
+#define CHECK_MIN_REQUIREMENT(name, value) \
+ if (vk_info->device_limits.name < value) \
+ WARN(#name " does not meet feature level 11_0 requirements.\n");
+#define CHECK_MAX_REQUIREMENT(name, value) \
+ if (vk_info->device_limits.name > value) \
+ WARN(#name " does not meet feature level 11_0 requirements.\n");
+#define CHECK_FEATURE(name) \
+ if (!features->name) \
+ { \
+ WARN(#name " is not supported.\n"); \
+ have_11_0 = false; \
+ }
+
+ if (!vk_info->device_limits.timestampComputeAndGraphics)
+ WARN("Timestamps are not supported on all graphics and compute queues.\n");
+
+ CHECK_MIN_REQUIREMENT(maxPushConstantsSize, D3D12_MAX_ROOT_COST * sizeof(uint32_t));
+ CHECK_MIN_REQUIREMENT(maxComputeSharedMemorySize, D3D12_CS_TGSM_REGISTER_COUNT * sizeof(uint32_t));
+
+ CHECK_MAX_REQUIREMENT(viewportBoundsRange[0], D3D12_VIEWPORT_BOUNDS_MIN);
+ CHECK_MIN_REQUIREMENT(viewportBoundsRange[1], D3D12_VIEWPORT_BOUNDS_MAX);
+ CHECK_MIN_REQUIREMENT(viewportSubPixelBits, 8);
+
+ CHECK_MIN_REQUIREMENT(maxPerStageDescriptorUniformBuffers,
+ D3D12_COMMONSHADER_CONSTANT_BUFFER_REGISTER_COUNT);
+
+ CHECK_FEATURE(depthBiasClamp);
+ CHECK_FEATURE(depthClamp);
+ CHECK_FEATURE(drawIndirectFirstInstance);
+ CHECK_FEATURE(dualSrcBlend);
+ CHECK_FEATURE(fragmentStoresAndAtomics);
+ CHECK_FEATURE(fullDrawIndexUint32);
+ CHECK_FEATURE(geometryShader);
+ CHECK_FEATURE(imageCubeArray);
+ CHECK_FEATURE(independentBlend);
+ CHECK_FEATURE(multiDrawIndirect);
+ CHECK_FEATURE(multiViewport);
+ CHECK_FEATURE(occlusionQueryPrecise);
+ CHECK_FEATURE(pipelineStatisticsQuery);
+ CHECK_FEATURE(samplerAnisotropy);
+ CHECK_FEATURE(sampleRateShading);
+ CHECK_FEATURE(shaderClipDistance);
+ CHECK_FEATURE(shaderCullDistance);
+ CHECK_FEATURE(shaderImageGatherExtended);
+ CHECK_FEATURE(shaderStorageImageWriteWithoutFormat);
+ CHECK_FEATURE(tessellationShader);
+
+ if (!vk_info->EXT_depth_clip_enable)
+ WARN("Depth clip enable is not supported.\n");
+ if (!vk_info->EXT_transform_feedback)
+ WARN("Stream output is not supported.\n");
+
+ if (!vk_info->EXT_vertex_attribute_divisor)
+ WARN("Vertex attribute instance rate divisor is not supported.\n");
+ else if (!vk_info->vertex_attrib_zero_divisor)
+ WARN("Vertex attribute instance rate zero divisor is not supported.\n");
+
+#undef CHECK_MIN_REQUIREMENT
+#undef CHECK_MAX_REQUIREMENT
+#undef CHECK_FEATURE
+
+ vk_info->max_feature_level = D3D_FEATURE_LEVEL_11_0;
+
+ if (have_11_0
+ && d3d12_options->OutputMergerLogicOp
+ && features->vertexPipelineStoresAndAtomics
+ && vk_info->device_limits.maxPerStageDescriptorStorageBuffers >= D3D12_UAV_SLOT_COUNT
+ && vk_info->device_limits.maxPerStageDescriptorStorageImages >= D3D12_UAV_SLOT_COUNT)
+ vk_info->max_feature_level = D3D_FEATURE_LEVEL_11_1;
+
+ /* TODO: MinMaxFiltering */
+ if (vk_info->max_feature_level >= D3D_FEATURE_LEVEL_11_1
+ && d3d12_options->TiledResourcesTier >= D3D12_TILED_RESOURCES_TIER_2
+ && d3d12_options->ResourceBindingTier >= D3D12_RESOURCE_BINDING_TIER_2
+ && d3d12_options->TypedUAVLoadAdditionalFormats)
+ vk_info->max_feature_level = D3D_FEATURE_LEVEL_12_0;
+
+ if (vk_info->max_feature_level >= D3D_FEATURE_LEVEL_12_0
+ && d3d12_options->ROVsSupported
+ && d3d12_options->ConservativeRasterizationTier >= D3D12_CONSERVATIVE_RASTERIZATION_TIER_1)
+ vk_info->max_feature_level = D3D_FEATURE_LEVEL_12_1;
+
+ TRACE("Max feature level: %#x.\n", vk_info->max_feature_level);
+}
+
+static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
+ const struct vkd3d_device_create_info *create_info,
+ struct vkd3d_physical_device_info *physical_device_info,
+ uint32_t *device_extension_count, bool **user_extension_supported)
+{
+ const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs;
+ const struct vkd3d_optional_device_extensions_info *optional_extensions;
+ VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing;
+ VkPhysicalDevice physical_device = device->vk_physical_device;
+ struct vkd3d_vulkan_info *vulkan_info = &device->vk_info;
+ VkExtensionProperties *vk_extensions;
+ VkPhysicalDeviceFeatures *features;
+ uint32_t count;
+ VkResult vr;
+
+ *device_extension_count = 0;
+
+ vkd3d_trace_physical_device(physical_device, physical_device_info, vk_procs);
+ vkd3d_trace_physical_device_features(physical_device_info);
+ vkd3d_trace_physical_device_limits(physical_device_info);
+
+ features = &physical_device_info->features2.features;
+
+ if (!features->sparseResidencyBuffer || !features->sparseResidencyImage2D)
+ {
+ features->sparseResidencyBuffer = VK_FALSE;
+ features->sparseResidencyImage2D = VK_FALSE;
+ physical_device_info->properties2.properties.sparseProperties.residencyNonResidentStrict = VK_FALSE;
+ }
+
+ vulkan_info->device_limits = physical_device_info->properties2.properties.limits;
+ vulkan_info->sparse_properties = physical_device_info->properties2.properties.sparseProperties;
+ vulkan_info->rasterization_stream = physical_device_info->xfb_properties.transformFeedbackRasterizationStreamSelect;
+ vulkan_info->transform_feedback_queries = physical_device_info->xfb_properties.transformFeedbackQueries;
+ vulkan_info->max_vertex_attrib_divisor = max(physical_device_info->vertex_divisor_properties.maxVertexAttribDivisor, 1);
+
+ device->feature_options.DoublePrecisionFloatShaderOps = features->shaderFloat64;
+ device->feature_options.OutputMergerLogicOp = features->logicOp;
+ /* SPV_KHR_16bit_storage */
+ device->feature_options.MinPrecisionSupport = D3D12_SHADER_MIN_PRECISION_SUPPORT_NONE;
+
+ if (!features->sparseBinding)
+ device->feature_options.TiledResourcesTier = D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED;
+ else if (!device->vk_info.sparse_properties.residencyNonResidentStrict)
+ device->feature_options.TiledResourcesTier = D3D12_TILED_RESOURCES_TIER_1;
+ else if (!features->sparseResidencyImage3D)
+ device->feature_options.TiledResourcesTier = D3D12_TILED_RESOURCES_TIER_2;
+ else
+ device->feature_options.TiledResourcesTier = D3D12_TILED_RESOURCES_TIER_3;
+
+ /* FIXME: Implement tiled resources. */
+ if (device->feature_options.TiledResourcesTier)
+ {
+ WARN("Tiled resources are not implemented yet.\n");
+ device->feature_options.TiledResourcesTier = D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED;
+ }
+
+ if (device->vk_info.device_limits.maxPerStageDescriptorSamplers <= 16)
+ device->feature_options.ResourceBindingTier = D3D12_RESOURCE_BINDING_TIER_1;
+ else if (device->vk_info.device_limits.maxPerStageDescriptorUniformBuffers <= 14)
+ device->feature_options.ResourceBindingTier = D3D12_RESOURCE_BINDING_TIER_2;
+ else
+ device->feature_options.ResourceBindingTier = D3D12_RESOURCE_BINDING_TIER_3;
+
+ device->feature_options.PSSpecifiedStencilRefSupported = FALSE;
+ device->feature_options.TypedUAVLoadAdditionalFormats = features->shaderStorageImageExtendedFormats;
+ /* GL_INTEL_fragment_shader_ordering, no Vulkan equivalent. */
+ device->feature_options.ROVsSupported = FALSE;
+ /* GL_INTEL_conservative_rasterization, no Vulkan equivalent. */
+ device->feature_options.ConservativeRasterizationTier = D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED;
+ device->feature_options.MaxGPUVirtualAddressBitsPerResource = 40; /* FIXME */
+ device->feature_options.StandardSwizzle64KBSupported = FALSE;
+ device->feature_options.CrossNodeSharingTier = D3D12_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED;
+ device->feature_options.CrossAdapterRowMajorTextureSupported = FALSE;
+ /* SPV_EXT_shader_viewport_index_layer */
+ device->feature_options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = FALSE;
+ device->feature_options.ResourceHeapTier = D3D12_RESOURCE_HEAP_TIER_2;
+
+ /* Shader Model 6 support. */
+ device->feature_options1.WaveOps = FALSE;
+ device->feature_options1.WaveLaneCountMin = 0;
+ device->feature_options1.WaveLaneCountMax = 0;
+ device->feature_options1.TotalLaneCount = 0;
+ device->feature_options1.ExpandedComputeResourceStates = TRUE;
+ device->feature_options1.Int64ShaderOps = features->shaderInt64;
+
+ /* Depth bounds test is enabled in D3D12_DEPTH_STENCIL_DESC1, which is not
+ * supported. */
+ device->feature_options2.DepthBoundsTestSupported = FALSE;
+ /* d3d12_command_list_SetSamplePositions() is not implemented. */
+ device->feature_options2.ProgrammableSamplePositionsTier = D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED;
+
+ device->feature_options3.CopyQueueTimestampQueriesSupported = FALSE;
+ device->feature_options3.CastingFullyTypedFormatSupported = FALSE;
+ device->feature_options3.WriteBufferImmediateSupportFlags = D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE;
+ device->feature_options3.ViewInstancingTier = D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED;
+ device->feature_options3.BarycentricsSupported = FALSE;
+
+ device->feature_options4.MSAA64KBAlignedTextureSupported = FALSE;
+ device->feature_options4.SharedResourceCompatibilityTier = D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_0;
+ /* An SM 6.2 feature. This would require features->shaderInt16 and
+ * VK_KHR_shader_float16_int8. */
+ device->feature_options4.Native16BitShaderOpsSupported = FALSE;
+
+ device->feature_options5.SRVOnlyTiledResourceTier3 = FALSE;
+ device->feature_options5.RenderPassesTier = D3D12_RENDER_PASS_TIER_0;
+ device->feature_options5.RaytracingTier = D3D12_RAYTRACING_TIER_NOT_SUPPORTED;
+
+ if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
+ {
+ ERR("Failed to enumerate device extensions, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+ if (!count)
+ return S_OK;
+
+ if (!(vk_extensions = vkd3d_calloc(count, sizeof(*vk_extensions))))
+ return E_OUTOFMEMORY;
+
+ TRACE("Enumerating %u device extensions.\n", count);
+ if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, vk_extensions))) < 0)
+ {
+ ERR("Failed to enumerate device extensions, vr %d.\n", vr);
+ vkd3d_free(vk_extensions);
+ return hresult_from_vk_result(vr);
+ }
+
+ optional_extensions = vkd3d_find_struct(create_info->next, OPTIONAL_DEVICE_EXTENSIONS_INFO);
+ if (optional_extensions && optional_extensions->extension_count)
+ {
+ if (!(*user_extension_supported = vkd3d_calloc(optional_extensions->extension_count, sizeof(bool))))
+ {
+ vkd3d_free(vk_extensions);
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ *user_extension_supported = NULL;
+ }
+
+ *device_extension_count = vkd3d_check_extensions(vk_extensions, count,
+ required_device_extensions, ARRAY_SIZE(required_device_extensions),
+ optional_device_extensions, ARRAY_SIZE(optional_device_extensions),
+ create_info->device_extensions, create_info->device_extension_count,
+ optional_extensions ? optional_extensions->extensions : NULL,
+ optional_extensions ? optional_extensions->extension_count : 0,
+ *user_extension_supported, vulkan_info, "device",
+ device->vkd3d_instance->config_flags & VKD3D_CONFIG_FLAG_VULKAN_DEBUG);
+
+ if (!physical_device_info->conditional_rendering_features.conditionalRendering)
+ vulkan_info->EXT_conditional_rendering = false;
+ if (!physical_device_info->depth_clip_features.depthClipEnable)
+ vulkan_info->EXT_depth_clip_enable = false;
+ if (!physical_device_info->demote_features.shaderDemoteToHelperInvocation)
+ vulkan_info->EXT_shader_demote_to_helper_invocation = false;
+ if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment)
+ vulkan_info->EXT_texel_buffer_alignment = false;
+
+ vulkan_info->texel_buffer_alignment_properties = physical_device_info->texel_buffer_alignment_properties;
+
+ if (get_spec_version(vk_extensions, count, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3)
+ {
+ const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *divisor_features;
+ divisor_features = &physical_device_info->vertex_divisor_features;
+ if (!divisor_features->vertexAttributeInstanceRateDivisor)
+ vulkan_info->EXT_vertex_attribute_divisor = false;
+ vulkan_info->vertex_attrib_zero_divisor = divisor_features->vertexAttributeInstanceRateZeroDivisor;
+ }
+ else
+ {
+ vulkan_info->vertex_attrib_zero_divisor = false;
+ }
+
+ vkd3d_free(vk_extensions);
+
+ vkd3d_init_feature_level(vulkan_info, features, &device->feature_options);
+ if (vulkan_info->max_feature_level < create_info->minimum_feature_level)
+ {
+ WARN("Feature level %#x is not supported.\n", create_info->minimum_feature_level);
+ vkd3d_free(*user_extension_supported);
+ *user_extension_supported = NULL;
+ return E_INVALIDARG;
+ }
+
+ /* Shader extensions. */
+ if (vulkan_info->EXT_shader_demote_to_helper_invocation)
+ {
+ vulkan_info->shader_extension_count = 1;
+ vulkan_info->shader_extensions[0] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_DEMOTE_TO_HELPER_INVOCATION;
+ }
+
+ /* Disable unused Vulkan features. */
+ features->shaderTessellationAndGeometryPointSize = VK_FALSE;
+
+ descriptor_indexing = &physical_device_info->descriptor_indexing_features;
+ if (descriptor_indexing)
+ {
+ descriptor_indexing->shaderInputAttachmentArrayDynamicIndexing = VK_FALSE;
+ descriptor_indexing->shaderInputAttachmentArrayNonUniformIndexing = VK_FALSE;
+
+ /* We do not use storage buffers currently. */
+ features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE;
+ descriptor_indexing->shaderStorageBufferArrayNonUniformIndexing = VK_FALSE;
+ descriptor_indexing->descriptorBindingStorageBufferUpdateAfterBind = VK_FALSE;
+ }
+
+ if (vulkan_info->EXT_descriptor_indexing && descriptor_indexing
+ && (descriptor_indexing->descriptorBindingUniformBufferUpdateAfterBind
+ || descriptor_indexing->descriptorBindingStorageBufferUpdateAfterBind
+ || descriptor_indexing->descriptorBindingUniformTexelBufferUpdateAfterBind
+ || descriptor_indexing->descriptorBindingStorageTexelBufferUpdateAfterBind)
+ && !physical_device_info->descriptor_indexing_properties.robustBufferAccessUpdateAfterBind)
+ {
+ WARN("Disabling robust buffer access for the update after bind feature.\n");
+ features->robustBufferAccess = VK_FALSE;
+ }
+
+ return S_OK;
+}
+
+static HRESULT vkd3d_select_physical_device(struct vkd3d_instance *instance,
+ unsigned int device_index, VkPhysicalDevice *selected_device)
+{
+ VkPhysicalDevice dgpu_device = VK_NULL_HANDLE, igpu_device = VK_NULL_HANDLE;
+ const struct vkd3d_vk_instance_procs *vk_procs = &instance->vk_procs;
+ VkInstance vk_instance = instance->vk_instance;
+ VkPhysicalDeviceProperties device_properties;
+ VkPhysicalDevice device = VK_NULL_HANDLE;
+ VkPhysicalDevice *physical_devices;
+ uint32_t count;
+ unsigned int i;
+ VkResult vr;
+
+ count = 0;
+ if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_instance, &count, NULL))) < 0)
+ {
+ ERR("Failed to enumerate physical devices, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+ if (!count)
+ {
+ ERR("No physical device available.\n");
+ return E_FAIL;
+ }
+ if (!(physical_devices = vkd3d_calloc(count, sizeof(*physical_devices))))
+ return E_OUTOFMEMORY;
+
+ TRACE("Enumerating %u physical device(s).\n", count);
+ if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_instance, &count, physical_devices))) < 0)
+ {
+ ERR("Failed to enumerate physical devices, vr %d.\n", vr);
+ vkd3d_free(physical_devices);
+ return hresult_from_vk_result(vr);
+ }
+
+ if (device_index != ~0u && device_index >= count)
+ WARN("Device index %u is out of range.\n", device_index);
+
+ for (i = 0; i < count; ++i)
+ {
+ VK_CALL(vkGetPhysicalDeviceProperties(physical_devices[i], &device_properties));
+ vkd3d_trace_physical_device_properties(&device_properties);
+
+ if (i == device_index)
+ device = physical_devices[i];
+
+ if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && !dgpu_device)
+ dgpu_device = physical_devices[i];
+ else if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && !igpu_device)
+ igpu_device = physical_devices[i];
+ }
+
+ if (!device)
+ device = dgpu_device ? dgpu_device : igpu_device;
+ if (!device)
+ device = physical_devices[0];
+
+ vkd3d_free(physical_devices);
+
+ VK_CALL(vkGetPhysicalDeviceProperties(device, &device_properties));
+ TRACE("Using device: %s, %#x:%#x.\n", device_properties.deviceName,
+ device_properties.vendorID, device_properties.deviceID);
+
+ *selected_device = device;
+
+ return S_OK;
+}
+
+/* Vulkan queues */
+enum vkd3d_queue_family
+{
+ VKD3D_QUEUE_FAMILY_DIRECT,
+ VKD3D_QUEUE_FAMILY_COMPUTE,
+ VKD3D_QUEUE_FAMILY_TRANSFER,
+
+ VKD3D_QUEUE_FAMILY_COUNT,
+};
+
+struct vkd3d_device_queue_info
+{
+ unsigned int family_index[VKD3D_QUEUE_FAMILY_COUNT];
+ VkQueueFamilyProperties vk_properties[VKD3D_QUEUE_FAMILY_COUNT];
+
+ unsigned int vk_family_count;
+ VkDeviceQueueCreateInfo vk_queue_create_info[VKD3D_QUEUE_FAMILY_COUNT];
+};
+
+static void d3d12_device_destroy_vkd3d_queues(struct d3d12_device *device)
+{
+ if (device->direct_queue)
+ vkd3d_queue_destroy(device->direct_queue, device);
+ if (device->compute_queue && device->compute_queue != device->direct_queue)
+ vkd3d_queue_destroy(device->compute_queue, device);
+ if (device->copy_queue && device->copy_queue != device->direct_queue
+ && device->copy_queue != device->compute_queue)
+ vkd3d_queue_destroy(device->copy_queue, device);
+
+ device->direct_queue = NULL;
+ device->compute_queue = NULL;
+ device->copy_queue = NULL;
+}
+
+static HRESULT d3d12_device_create_vkd3d_queues(struct d3d12_device *device,
+ const struct vkd3d_device_queue_info *queue_info)
+{
+ uint32_t transfer_family_index = queue_info->family_index[VKD3D_QUEUE_FAMILY_TRANSFER];
+ uint32_t compute_family_index = queue_info->family_index[VKD3D_QUEUE_FAMILY_COMPUTE];
+ uint32_t direct_family_index = queue_info->family_index[VKD3D_QUEUE_FAMILY_DIRECT];
+ HRESULT hr;
+
+ device->direct_queue = NULL;
+ device->compute_queue = NULL;
+ device->copy_queue = NULL;
+
+ device->queue_family_count = 0;
+ memset(device->queue_family_indices, 0, sizeof(device->queue_family_indices));
+
+ if (SUCCEEDED((hr = vkd3d_queue_create(device, direct_family_index,
+ &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_DIRECT], &device->direct_queue))))
+ device->queue_family_indices[device->queue_family_count++] = direct_family_index;
+ else
+ goto out_destroy_queues;
+
+ if (compute_family_index == direct_family_index)
+ device->compute_queue = device->direct_queue;
+ else if (SUCCEEDED(hr = vkd3d_queue_create(device, compute_family_index,
+ &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_COMPUTE], &device->compute_queue)))
+ device->queue_family_indices[device->queue_family_count++] = compute_family_index;
+ else
+ goto out_destroy_queues;
+
+ if (transfer_family_index == direct_family_index)
+ device->copy_queue = device->direct_queue;
+ else if (transfer_family_index == compute_family_index)
+ device->copy_queue = device->compute_queue;
+ else if (SUCCEEDED(hr = vkd3d_queue_create(device, transfer_family_index,
+ &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_TRANSFER], &device->copy_queue)))
+ device->queue_family_indices[device->queue_family_count++] = transfer_family_index;
+ else
+ goto out_destroy_queues;
+
+ device->feature_options3.CopyQueueTimestampQueriesSupported = !!device->copy_queue->timestamp_bits;
+
+ return S_OK;
+
+out_destroy_queues:
+ d3d12_device_destroy_vkd3d_queues(device);
+ return hr;
+}
+
+static float queue_priorities[] = {1.0f};
+
+static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance,
+ VkPhysicalDevice physical_device, struct vkd3d_device_queue_info *info)
+{
+ const struct vkd3d_vk_instance_procs *vk_procs = &vkd3d_instance->vk_procs;
+ VkQueueFamilyProperties *queue_properties = NULL;
+ VkDeviceQueueCreateInfo *queue_info = NULL;
+ unsigned int i;
+ uint32_t count;
+
+ memset(info, 0, sizeof(*info));
+ for (i = 0; i < ARRAY_SIZE(info->family_index); ++i)
+ info->family_index[i] = ~0u;
+
+ VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, NULL));
+ if (!(queue_properties = vkd3d_calloc(count, sizeof(*queue_properties))))
+ return E_OUTOFMEMORY;
+ VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queue_properties));
+
+ for (i = 0; i < count; ++i)
+ {
+ enum vkd3d_queue_family vkd3d_family = VKD3D_QUEUE_FAMILY_COUNT;
+
+ if ((queue_properties[i].queueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
+ == (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
+ {
+ vkd3d_family = VKD3D_QUEUE_FAMILY_DIRECT;
+ }
+ if ((queue_properties[i].queueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
+ == VK_QUEUE_COMPUTE_BIT)
+ {
+ vkd3d_family = VKD3D_QUEUE_FAMILY_COMPUTE;
+ }
+ if ((queue_properties[i].queueFlags & ~VK_QUEUE_SPARSE_BINDING_BIT) == VK_QUEUE_TRANSFER_BIT)
+ {
+ vkd3d_family = VKD3D_QUEUE_FAMILY_TRANSFER;
+ }
+
+ if (vkd3d_family == VKD3D_QUEUE_FAMILY_COUNT)
+ continue;
+
+ info->family_index[vkd3d_family] = i;
+ info->vk_properties[vkd3d_family] = queue_properties[i];
+ queue_info = &info->vk_queue_create_info[vkd3d_family];
+
+ queue_info->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queue_info->pNext = NULL;
+ queue_info->flags = 0;
+ queue_info->queueFamilyIndex = i;
+ queue_info->queueCount = 1; /* FIXME: Use multiple queues. */
+ queue_info->pQueuePriorities = queue_priorities;
+ }
+
+ vkd3d_free(queue_properties);
+
+ if (info->family_index[VKD3D_QUEUE_FAMILY_DIRECT] == ~0u)
+ {
+ FIXME("Could not find a suitable queue family for a direct command queue.\n");
+ return E_FAIL;
+ }
+
+ /* No compute-only queue family, reuse the direct queue family with graphics and compute. */
+ if (info->family_index[VKD3D_QUEUE_FAMILY_COMPUTE] == ~0u)
+ {
+ info->family_index[VKD3D_QUEUE_FAMILY_COMPUTE] = info->family_index[VKD3D_QUEUE_FAMILY_DIRECT];
+ info->vk_properties[VKD3D_QUEUE_FAMILY_COMPUTE] = info->vk_properties[VKD3D_QUEUE_FAMILY_DIRECT];
+ }
+ if (info->family_index[VKD3D_QUEUE_FAMILY_TRANSFER] == ~0u)
+ {
+ info->family_index[VKD3D_QUEUE_FAMILY_TRANSFER] = info->family_index[VKD3D_QUEUE_FAMILY_DIRECT];
+ info->vk_properties[VKD3D_QUEUE_FAMILY_TRANSFER] = info->vk_properties[VKD3D_QUEUE_FAMILY_DIRECT];
+ }
+
+ /* Compact the array. */
+ info->vk_family_count = 1;
+ for (i = info->vk_family_count; i < ARRAY_SIZE(info->vk_queue_create_info); ++i)
+ {
+ if (info->vk_queue_create_info[i].queueCount)
+ info->vk_queue_create_info[info->vk_family_count++] = info->vk_queue_create_info[i];
+ }
+
+ return S_OK;
+}
+
+/* The 4 MiB alignment requirement for MSAA resources was lowered to 64KB on
+ * hardware that supports it. This is distinct from the small MSAA requirement
+ * which applies to resources of a total size of 4 MiB or less. */
+static bool d3d12_is_64k_msaa_supported(struct d3d12_device *device)
+{
+ D3D12_RESOURCE_ALLOCATION_INFO info;
+ D3D12_RESOURCE_DESC resource_desc;
+
+ memset(&resource_desc, 0, sizeof(resource_desc));
+ resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resource_desc.Width = 1024;
+ resource_desc.Height = 1025;
+ resource_desc.DepthOrArraySize = 1;
+ resource_desc.MipLevels = 1;
+ resource_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ resource_desc.SampleDesc.Count = 4;
+ resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+
+ /* FIXME: in some cases Vulkan requires 0x20000 or more for non-MSAA
+ * resources, which must have 0x10000 in their description, so we might
+ * reasonably return true here for 0x20000 or 0x40000. */
+ return SUCCEEDED(vkd3d_get_image_allocation_info(device, &resource_desc, &info))
+ && info.Alignment <= 0x10000;
+}
+
+static HRESULT vkd3d_create_vk_device(struct d3d12_device *device,
+ const struct vkd3d_device_create_info *create_info)
+{
+ const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs;
+ const struct vkd3d_optional_device_extensions_info *optional_extensions;
+ struct vkd3d_physical_device_info physical_device_info;
+ struct vkd3d_device_queue_info device_queue_info;
+ bool *user_extension_supported = NULL;
+ VkPhysicalDevice physical_device;
+ VkDeviceCreateInfo device_info;
+ unsigned int device_index;
+ uint32_t extension_count;
+ const char **extensions;
+ VkDevice vk_device;
+ VkResult vr;
+ HRESULT hr;
+
+ TRACE("device %p, create_info %p.\n", device, create_info);
+
+ physical_device = create_info->vk_physical_device;
+ device_index = vkd3d_env_var_as_uint("VKD3D_VULKAN_DEVICE", ~0u);
+ if ((!physical_device || device_index != ~0u)
+ && FAILED(hr = vkd3d_select_physical_device(device->vkd3d_instance, device_index, &physical_device)))
+ return hr;
+
+ device->vk_physical_device = physical_device;
+
+ if (FAILED(hr = vkd3d_select_queues(device->vkd3d_instance, physical_device, &device_queue_info)))
+ return hr;
+
+ TRACE("Using queue family %u for direct command queues.\n",
+ device_queue_info.family_index[VKD3D_QUEUE_FAMILY_DIRECT]);
+ TRACE("Using queue family %u for compute command queues.\n",
+ device_queue_info.family_index[VKD3D_QUEUE_FAMILY_COMPUTE]);
+ TRACE("Using queue family %u for copy command queues.\n",
+ device_queue_info.family_index[VKD3D_QUEUE_FAMILY_TRANSFER]);
+
+ VK_CALL(vkGetPhysicalDeviceMemoryProperties(physical_device, &device->memory_properties));
+
+ vkd3d_physical_device_info_init(&physical_device_info, device);
+
+ if (FAILED(hr = vkd3d_init_device_caps(device, create_info, &physical_device_info,
+ &extension_count, &user_extension_supported)))
+ return hr;
+
+ if (!(extensions = vkd3d_calloc(extension_count, sizeof(*extensions))))
+ {
+ vkd3d_free(user_extension_supported);
+ return E_OUTOFMEMORY;
+ }
+
+ optional_extensions = vkd3d_find_struct(create_info->next, OPTIONAL_DEVICE_EXTENSIONS_INFO);
+
+ /* Create device */
+ device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ device_info.pNext = physical_device_info.features2.pNext;
+ device_info.flags = 0;
+ device_info.queueCreateInfoCount = device_queue_info.vk_family_count;
+ device_info.pQueueCreateInfos = device_queue_info.vk_queue_create_info;
+ device_info.enabledLayerCount = 0;
+ device_info.ppEnabledLayerNames = NULL;
+ device_info.enabledExtensionCount = vkd3d_enable_extensions(extensions,
+ required_device_extensions, ARRAY_SIZE(required_device_extensions),
+ optional_device_extensions, ARRAY_SIZE(optional_device_extensions),
+ create_info->device_extensions, create_info->device_extension_count,
+ optional_extensions ? optional_extensions->extensions : NULL,
+ optional_extensions ? optional_extensions->extension_count : 0,
+ user_extension_supported, &device->vk_info);
+ device_info.ppEnabledExtensionNames = extensions;
+ device_info.pEnabledFeatures = &physical_device_info.features2.features;
+ vkd3d_free(user_extension_supported);
+
+ vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device));
+ vkd3d_free(extensions);
+ if (vr < 0)
+ {
+ ERR("Failed to create Vulkan device, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ if (FAILED(hr = vkd3d_load_vk_device_procs(&device->vk_procs, vk_procs, vk_device)))
+ {
+ ERR("Failed to load device procs, hr %#x.\n", hr);
+ if (device->vk_procs.vkDestroyDevice)
+ device->vk_procs.vkDestroyDevice(vk_device, NULL);
+ return hr;
+ }
+
+ device->vk_device = vk_device;
+
+ if (FAILED(hr = d3d12_device_create_vkd3d_queues(device, &device_queue_info)))
+ {
+ ERR("Failed to create queues, hr %#x.\n", hr);
+ device->vk_procs.vkDestroyDevice(vk_device, NULL);
+ return hr;
+ }
+
+ device->feature_options4.MSAA64KBAlignedTextureSupported = d3d12_is_64k_msaa_supported(device);
+
+ TRACE("Created Vulkan device %p.\n", vk_device);
+
+ return hr;
+}
+
+static HRESULT d3d12_device_init_pipeline_cache(struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkPipelineCacheCreateInfo cache_info;
+ VkResult vr;
+ int rc;
+
+ if ((rc = pthread_mutex_init(&device->mutex, NULL)))
+ {
+ ERR("Failed to initialize mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ cache_info.pNext = NULL;
+ cache_info.flags = 0;
+ cache_info.initialDataSize = 0;
+ cache_info.pInitialData = NULL;
+ if ((vr = VK_CALL(vkCreatePipelineCache(device->vk_device, &cache_info, NULL,
+ &device->vk_pipeline_cache))) < 0)
+ {
+ ERR("Failed to create Vulkan pipeline cache, vr %d.\n", vr);
+ device->vk_pipeline_cache = VK_NULL_HANDLE;
+ }
+
+ return S_OK;
+}
+
+static void d3d12_device_destroy_pipeline_cache(struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ if (device->vk_pipeline_cache)
+ VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL));
+
+ pthread_mutex_destroy(&device->mutex);
+}
+
+#define VKD3D_VA_FALLBACK_BASE 0x8000000000000000ull
+#define VKD3D_VA_SLAB_BASE 0x0000001000000000ull
+#define VKD3D_VA_SLAB_SIZE_SHIFT 32
+#define VKD3D_VA_SLAB_SIZE (1ull << VKD3D_VA_SLAB_SIZE_SHIFT)
+#define VKD3D_VA_SLAB_COUNT (64 * 1024)
+
+static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_slab(struct vkd3d_gpu_va_allocator *allocator,
+ size_t aligned_size, void *ptr)
+{
+ struct vkd3d_gpu_va_slab *slab;
+ D3D12_GPU_VIRTUAL_ADDRESS address;
+ unsigned slab_idx;
+
+ slab = allocator->free_slab;
+ allocator->free_slab = slab->ptr;
+ slab->size = aligned_size;
+ slab->ptr = ptr;
+
+ /* It is critical that the multiplication happens in 64-bit to not
+ * overflow. */
+ slab_idx = slab - allocator->slabs;
+ address = VKD3D_VA_SLAB_BASE + slab_idx * VKD3D_VA_SLAB_SIZE;
+
+ TRACE("Allocated address %#"PRIx64", slab %u, size %zu.\n", address, slab_idx, aligned_size);
+
+ return address;
+}
+
+static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_fallback(struct vkd3d_gpu_va_allocator *allocator,
+ size_t alignment, size_t aligned_size, void *ptr)
+{
+ struct vkd3d_gpu_va_allocation *allocation;
+ D3D12_GPU_VIRTUAL_ADDRESS base, ceiling;
+
+ base = allocator->fallback_floor;
+ ceiling = ~(D3D12_GPU_VIRTUAL_ADDRESS)0;
+ ceiling -= alignment - 1;
+ if (aligned_size > ceiling || ceiling - aligned_size < base)
+ return 0;
+
+ base = (base + (alignment - 1)) & ~((D3D12_GPU_VIRTUAL_ADDRESS)alignment - 1);
+
+ if (!vkd3d_array_reserve((void **)&allocator->fallback_allocations, &allocator->fallback_allocations_size,
+ allocator->fallback_allocation_count + 1, sizeof(*allocator->fallback_allocations)))
+ return 0;
+
+ allocation = &allocator->fallback_allocations[allocator->fallback_allocation_count++];
+ allocation->base = base;
+ allocation->size = aligned_size;
+ allocation->ptr = ptr;
+
+ /* This pointer is bumped and never lowered on a free. However, this will
+ * only fail once we have exhausted 63 bits of address space. */
+ allocator->fallback_floor = base + aligned_size;
+
+ TRACE("Allocated address %#"PRIx64", size %zu.\n", base, aligned_size);
+
+ return base;
+}
+
+D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator,
+ size_t alignment, size_t size, void *ptr)
+{
+ D3D12_GPU_VIRTUAL_ADDRESS address;
+ int rc;
+
+ if (size > ~(size_t)0 - (alignment - 1))
+ return 0;
+ size = align(size, alignment);
+
+ if ((rc = pthread_mutex_lock(&allocator->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return 0;
+ }
+
+ if (size <= VKD3D_VA_SLAB_SIZE && allocator->free_slab)
+ address = vkd3d_gpu_va_allocator_allocate_slab(allocator, size, ptr);
+ else
+ address = vkd3d_gpu_va_allocator_allocate_fallback(allocator, alignment, size, ptr);
+
+ pthread_mutex_unlock(&allocator->mutex);
+
+ return address;
+}
+
+static void *vkd3d_gpu_va_allocator_dereference_slab(struct vkd3d_gpu_va_allocator *allocator,
+ D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ const struct vkd3d_gpu_va_slab *slab;
+ D3D12_GPU_VIRTUAL_ADDRESS base_offset;
+ unsigned int slab_idx;
+
+ base_offset = address - VKD3D_VA_SLAB_BASE;
+ slab_idx = base_offset >> VKD3D_VA_SLAB_SIZE_SHIFT;
+
+ if (slab_idx >= VKD3D_VA_SLAB_COUNT)
+ {
+ ERR("Invalid slab index %u for address %#"PRIx64".\n", slab_idx, address);
+ return NULL;
+ }
+
+ slab = &allocator->slabs[slab_idx];
+ base_offset -= slab_idx * VKD3D_VA_SLAB_SIZE;
+ if (base_offset >= slab->size)
+ {
+ ERR("Address %#"PRIx64" is %#"PRIx64" bytes into slab %u of size %zu.\n",
+ address, base_offset, slab_idx, slab->size);
+ return NULL;
+ }
+ return slab->ptr;
+}
+
+static int vkd3d_gpu_va_allocation_compare(const void *k, const void *e)
+{
+ const struct vkd3d_gpu_va_allocation *allocation = e;
+ const D3D12_GPU_VIRTUAL_ADDRESS *address = k;
+
+ if (*address < allocation->base)
+ return -1;
+ if (*address - allocation->base >= allocation->size)
+ return 1;
+ return 0;
+}
+
+static void *vkd3d_gpu_va_allocator_dereference_fallback(struct vkd3d_gpu_va_allocator *allocator,
+ D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ struct vkd3d_gpu_va_allocation *allocation;
+
+ allocation = bsearch(&address, allocator->fallback_allocations, allocator->fallback_allocation_count,
+ sizeof(*allocation), vkd3d_gpu_va_allocation_compare);
+
+ return allocation ? allocation->ptr : NULL;
+}
+
+void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocator,
+ D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ void *ret;
+ int rc;
+
+ /* If we land in the non-fallback region, dereferencing VA is lock-less.
+ * The base pointer is immutable, and the only way we can have a data race
+ * is if some other thread is poking into the
+ * slab_mem_allocation[base_index] block. This can only happen if someone
+ * is trying to free the entry while we're dereferencing it, which would
+ * be a serious application bug. */
+ if (address < VKD3D_VA_FALLBACK_BASE)
+ return vkd3d_gpu_va_allocator_dereference_slab(allocator, address);
+
+ /* Slow fallback. */
+ if ((rc = pthread_mutex_lock(&allocator->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return NULL;
+ }
+
+ ret = vkd3d_gpu_va_allocator_dereference_fallback(allocator, address);
+
+ pthread_mutex_unlock(&allocator->mutex);
+
+ return ret;
+}
+
+static void vkd3d_gpu_va_allocator_free_slab(struct vkd3d_gpu_va_allocator *allocator,
+ D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ D3D12_GPU_VIRTUAL_ADDRESS base_offset;
+ struct vkd3d_gpu_va_slab *slab;
+ unsigned int slab_idx;
+
+ base_offset = address - VKD3D_VA_SLAB_BASE;
+ slab_idx = base_offset >> VKD3D_VA_SLAB_SIZE_SHIFT;
+
+ if (slab_idx >= VKD3D_VA_SLAB_COUNT)
+ {
+ ERR("Invalid slab index %u for address %#"PRIx64".\n", slab_idx, address);
+ return;
+ }
+
+ TRACE("Freeing address %#"PRIx64", slab %u.\n", address, slab_idx);
+
+ slab = &allocator->slabs[slab_idx];
+ slab->size = 0;
+ slab->ptr = allocator->free_slab;
+ allocator->free_slab = slab;
+}
+
+static void vkd3d_gpu_va_allocator_free_fallback(struct vkd3d_gpu_va_allocator *allocator,
+ D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ struct vkd3d_gpu_va_allocation *allocation;
+ unsigned int index;
+
+ allocation = bsearch(&address, allocator->fallback_allocations, allocator->fallback_allocation_count,
+ sizeof(*allocation), vkd3d_gpu_va_allocation_compare);
+
+ if (!allocation || allocation->base != address)
+ {
+ ERR("Address %#"PRIx64" does not match any allocation.\n", address);
+ return;
+ }
+
+ index = allocation - allocator->fallback_allocations;
+ --allocator->fallback_allocation_count;
+ if (index != allocator->fallback_allocation_count)
+ memmove(&allocator->fallback_allocations[index], &allocator->fallback_allocations[index + 1],
+ (allocator->fallback_allocation_count - index) * sizeof(*allocation));
+}
+
+void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address)
+{
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&allocator->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return;
+ }
+
+ if (address < VKD3D_VA_FALLBACK_BASE)
+ {
+ vkd3d_gpu_va_allocator_free_slab(allocator, address);
+ pthread_mutex_unlock(&allocator->mutex);
+ return;
+ }
+
+ vkd3d_gpu_va_allocator_free_fallback(allocator, address);
+
+ pthread_mutex_unlock(&allocator->mutex);
+}
+
+static bool vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator)
+{
+ unsigned int i;
+ int rc;
+
+ memset(allocator, 0, sizeof(*allocator));
+ allocator->fallback_floor = VKD3D_VA_FALLBACK_BASE;
+
+ /* To remain lock-less, we cannot grow the slabs array after the fact. If
+ * we commit to a maximum number of allocations here, we can dereference
+ * without taking a lock as the base pointer never changes. We would be
+ * able to grow more seamlessly using an array of pointers, but that would
+ * make dereferencing slightly less efficient. */
+ if (!(allocator->slabs = vkd3d_calloc(VKD3D_VA_SLAB_COUNT, sizeof(*allocator->slabs))))
+ return false;
+
+ /* Mark all slabs as free. */
+ allocator->free_slab = &allocator->slabs[0];
+ for (i = 0; i < VKD3D_VA_SLAB_COUNT - 1; ++i)
+ {
+ allocator->slabs[i].ptr = &allocator->slabs[i + 1];
+ }
+
+ if ((rc = pthread_mutex_init(&allocator->mutex, NULL)))
+ {
+ ERR("Failed to initialize mutex, error %d.\n", rc);
+ vkd3d_free(allocator->slabs);
+ return false;
+ }
+
+ return true;
+}
+
+static void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *allocator)
+{
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&allocator->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return;
+ }
+ vkd3d_free(allocator->slabs);
+ vkd3d_free(allocator->fallback_allocations);
+ pthread_mutex_unlock(&allocator->mutex);
+ pthread_mutex_destroy(&allocator->mutex);
+}
+
+/* ID3D12Device */
+static inline struct d3d12_device *impl_from_ID3D12Device(ID3D12Device *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12Device_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12Device)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12Device_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device *iface)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ ULONG refcount = InterlockedIncrement(&device->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", device, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ ULONG refcount = InterlockedDecrement(&device->refcount);
+ size_t i;
+
+ TRACE("%p decreasing refcount to %u.\n", device, refcount);
+
+ if (!refcount)
+ {
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ vkd3d_private_store_destroy(&device->private_store);
+
+ vkd3d_cleanup_format_info(device);
+ vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device);
+ vkd3d_destroy_null_resources(&device->null_resources, device);
+ vkd3d_gpu_va_allocator_cleanup(&device->gpu_va_allocator);
+ vkd3d_render_pass_cache_cleanup(&device->render_pass_cache, device);
+ vkd3d_fence_worker_stop(&device->fence_worker, device);
+ d3d12_device_destroy_pipeline_cache(device);
+ d3d12_device_destroy_vkd3d_queues(device);
+ for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i)
+ pthread_mutex_destroy(&device->desc_mutex[i]);
+ VK_CALL(vkDestroyDevice(device->vk_device, NULL));
+ if (device->parent)
+ IUnknown_Release(device->parent);
+ vkd3d_instance_decref(device->vkd3d_instance);
+
+ vkd3d_free(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_GetPrivateData(ID3D12Device *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n",
+ iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&device->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateData(ID3D12Device *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n",
+ iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&device->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateDataInterface(ID3D12Device *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&device->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetName(ID3D12Device *iface, const WCHAR *name)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, device->wchar_size));
+
+ return vkd3d_set_vk_object_name(device, (uint64_t)(uintptr_t)device->vk_device,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, name);
+}
+
+static UINT STDMETHODCALLTYPE d3d12_device_GetNodeCount(ID3D12Device *iface)
+{
+ TRACE("iface %p.\n", iface);
+
+ return 1;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandQueue(ID3D12Device *iface,
+ const D3D12_COMMAND_QUEUE_DESC *desc, REFIID riid, void **command_queue)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_command_queue *object;
+ HRESULT hr;
+
+ TRACE("iface %p, desc %p, riid %s, command_queue %p.\n",
+ iface, desc, debugstr_guid(riid), command_queue);
+
+ if (FAILED(hr = d3d12_command_queue_create(device, desc, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12CommandQueue_iface, &IID_ID3D12CommandQueue,
+ riid, command_queue);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Device *iface,
+ D3D12_COMMAND_LIST_TYPE type, REFIID riid, void **command_allocator)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_command_allocator *object;
+ HRESULT hr;
+
+ TRACE("iface %p, type %#x, riid %s, command_allocator %p.\n",
+ iface, type, debugstr_guid(riid), command_allocator);
+
+ if (FAILED(hr = d3d12_command_allocator_create(device, type, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12CommandAllocator_iface, &IID_ID3D12CommandAllocator,
+ riid, command_allocator);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12Device *iface,
+ const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, REFIID riid, void **pipeline_state)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_pipeline_state *object;
+ HRESULT hr;
+
+ TRACE("iface %p, desc %p, riid %s, pipeline_state %p.\n",
+ iface, desc, debugstr_guid(riid), pipeline_state);
+
+ if (FAILED(hr = d3d12_pipeline_state_create_graphics(device, desc, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12PipelineState_iface,
+ &IID_ID3D12PipelineState, riid, pipeline_state);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateComputePipelineState(ID3D12Device *iface,
+ const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, REFIID riid, void **pipeline_state)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_pipeline_state *object;
+ HRESULT hr;
+
+ TRACE("iface %p, desc %p, riid %s, pipeline_state %p.\n",
+ iface, desc, debugstr_guid(riid), pipeline_state);
+
+ if (FAILED(hr = d3d12_pipeline_state_create_compute(device, desc, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12PipelineState_iface,
+ &IID_ID3D12PipelineState, riid, pipeline_state);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device *iface,
+ UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *command_allocator,
+ ID3D12PipelineState *initial_pipeline_state, REFIID riid, void **command_list)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_command_list *object;
+ HRESULT hr;
+
+ TRACE("iface %p, node_mask 0x%08x, type %#x, command_allocator %p, "
+ "initial_pipeline_state %p, riid %s, command_list %p.\n",
+ iface, node_mask, type, command_allocator,
+ initial_pipeline_state, debugstr_guid(riid), command_list);
+
+ if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, command_allocator,
+ initial_pipeline_state, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12GraphicsCommandList2_iface,
+ &IID_ID3D12GraphicsCommandList2, riid, command_list);
+}
+
+/* Direct3D feature levels restrict which formats can be optionally supported. */
+static void vkd3d_restrict_format_support_for_feature_level(D3D12_FEATURE_DATA_FORMAT_SUPPORT *format_support)
+{
+ static const D3D12_FEATURE_DATA_FORMAT_SUPPORT blacklisted_format_features[] =
+ {
+ {DXGI_FORMAT_B8G8R8A8_TYPELESS, D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW,
+ D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE},
+ {DXGI_FORMAT_B8G8R8A8_UNORM, D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW,
+ D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE},
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(blacklisted_format_features); ++i)
+ {
+ if (blacklisted_format_features[i].Format == format_support->Format)
+ {
+ format_support->Support1 &= ~blacklisted_format_features[i].Support1;
+ format_support->Support2 &= ~blacklisted_format_features[i].Support2;
+ break;
+ }
+ }
+}
+
+static HRESULT d3d12_device_check_multisample_quality_levels(struct d3d12_device *device,
+ D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS *data)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkImageFormatProperties vk_properties;
+ const struct vkd3d_format *format;
+ VkSampleCountFlagBits vk_samples;
+ VkImageUsageFlags vk_usage = 0;
+ VkResult vr;
+
+ TRACE("Format %#x, sample count %u, flags %#x.\n", data->Format, data->SampleCount, data->Flags);
+
+ data->NumQualityLevels = 0;
+
+ if (!(vk_samples = vk_samples_from_sample_count(data->SampleCount)))
+ WARN("Invalid sample count %u.\n", data->SampleCount);
+ if (!data->SampleCount)
+ return E_FAIL;
+
+ if (data->SampleCount == 1)
+ {
+ data->NumQualityLevels = 1;
+ goto done;
+ }
+
+ if (data->Format == DXGI_FORMAT_UNKNOWN)
+ goto done;
+
+ if (!(format = vkd3d_get_format(device, data->Format, false)))
+ format = vkd3d_get_format(device, data->Format, true);
+ if (!format)
+ {
+ FIXME("Unhandled format %#x.\n", data->Format);
+ return E_INVALIDARG;
+ }
+ if (data->Flags)
+ FIXME("Ignoring flags %#x.\n", data->Flags);
+
+ if (format->vk_aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT)
+ vk_usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ else
+ vk_usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ vr = VK_CALL(vkGetPhysicalDeviceImageFormatProperties(device->vk_physical_device,
+ format->vk_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, vk_usage, 0, &vk_properties));
+ if (vr == VK_ERROR_FORMAT_NOT_SUPPORTED)
+ {
+ WARN("Format %#x is not supported.\n", format->dxgi_format);
+ goto done;
+ }
+ if (vr < 0)
+ {
+ ERR("Failed to get image format properties, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ if (vk_properties.sampleCounts & vk_samples)
+ data->NumQualityLevels = 1;
+
+done:
+ TRACE("Returning %u quality levels.\n", data->NumQualityLevels);
+ return S_OK;
+}
+
+bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent)
+{
+ unsigned int i;
+
+ if (coherent)
+ *coherent = true;
+
+ for (i = 0; i < device->memory_properties.memoryTypeCount; ++i)
+ {
+ if (!(device->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
+ return false;
+ if (coherent && !(device->memory_properties.memoryTypes[i].propertyFlags
+ & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
+ *coherent = false;
+ }
+
+ return true;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *iface,
+ D3D12_FEATURE feature, void *feature_data, UINT feature_data_size)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ TRACE("iface %p, feature %#x, feature_data %p, feature_data_size %u.\n",
+ iface, feature, feature_data, feature_data_size);
+
+ switch (feature)
+ {
+ case D3D12_FEATURE_D3D12_OPTIONS:
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ *data = device->feature_options;
+
+ TRACE("Double precision shader ops %#x.\n", data->DoublePrecisionFloatShaderOps);
+ TRACE("Output merger logic op %#x.\n", data->OutputMergerLogicOp);
+ TRACE("Shader min precision support %#x.\n", data->MinPrecisionSupport);
+ TRACE("Tiled resources tier %#x.\n", data->TiledResourcesTier);
+ TRACE("Resource binding tier %#x.\n", data->ResourceBindingTier);
+ TRACE("PS specified stencil ref %#x.\n", data->PSSpecifiedStencilRefSupported);
+ TRACE("Typed UAV load and additional formats %#x.\n", data->TypedUAVLoadAdditionalFormats);
+ TRACE("ROV %#x.\n", data->ROVsSupported);
+ TRACE("Conservative rasterization tier %#x.\n", data->ConservativeRasterizationTier);
+ TRACE("Max GPU virtual address bits per resource %u.\n", data->MaxGPUVirtualAddressBitsPerResource);
+ TRACE("Standard swizzle 64KB %#x.\n", data->StandardSwizzle64KBSupported);
+ TRACE("Cross-node sharing tier %#x.\n", data->CrossNodeSharingTier);
+ TRACE("Cross-adapter row-major texture %#x.\n", data->CrossAdapterRowMajorTextureSupported);
+ TRACE("VP and RT array index from any shader without GS emulation %#x.\n",
+ data->VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation);
+ TRACE("Resource heap tier %#x.\n", data->ResourceHeapTier);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_ARCHITECTURE:
+ {
+ D3D12_FEATURE_DATA_ARCHITECTURE *data = feature_data;
+ bool coherent;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ if (data->NodeIndex)
+ {
+ FIXME("Multi-adapter not supported.\n");
+ return E_INVALIDARG;
+ }
+
+ WARN("Assuming device does not support tile based rendering.\n");
+ data->TileBasedRenderer = FALSE;
+
+ data->UMA = d3d12_device_is_uma(device, &coherent);
+ data->CacheCoherentUMA = data->UMA && coherent;
+
+ TRACE("Tile based renderer %#x, UMA %#x, cache coherent UMA %#x.\n",
+ data->TileBasedRenderer, data->UMA, data->CacheCoherentUMA);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_FEATURE_LEVELS:
+ {
+ struct vkd3d_vulkan_info *vulkan_info = &device->vk_info;
+ D3D12_FEATURE_DATA_FEATURE_LEVELS *data = feature_data;
+ unsigned int i;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+ if (!data->NumFeatureLevels)
+ return E_INVALIDARG;
+
+ data->MaxSupportedFeatureLevel = 0;
+ for (i = 0; i < data->NumFeatureLevels; ++i)
+ {
+ D3D_FEATURE_LEVEL fl = data->pFeatureLevelsRequested[i];
+ if (data->MaxSupportedFeatureLevel < fl && fl <= vulkan_info->max_feature_level)
+ data->MaxSupportedFeatureLevel = fl;
+ }
+
+ TRACE("Max supported feature level %#x.\n", data->MaxSupportedFeatureLevel);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_FORMAT_SUPPORT:
+ {
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ D3D12_FEATURE_DATA_FORMAT_SUPPORT *data = feature_data;
+ VkFormatFeatureFlagBits image_features;
+ const struct vkd3d_format *format;
+ VkFormatProperties properties;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ data->Support1 = D3D12_FORMAT_SUPPORT1_NONE;
+ data->Support2 = D3D12_FORMAT_SUPPORT2_NONE;
+ if (!(format = vkd3d_get_format(device, data->Format, false)))
+ format = vkd3d_get_format(device, data->Format, true);
+ if (!format)
+ {
+ FIXME("Unhandled format %#x.\n", data->Format);
+ return E_INVALIDARG;
+ }
+
+ VK_CALL(vkGetPhysicalDeviceFormatProperties(device->vk_physical_device, format->vk_format, &properties));
+ image_features = properties.linearTilingFeatures | properties.optimalTilingFeatures;
+
+ if (properties.bufferFeatures)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_BUFFER;
+ if (properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER;
+ if (data->Format == DXGI_FORMAT_R16_UINT || data->Format == DXGI_FORMAT_R32_UINT)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER;
+ if (image_features)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_TEXTURE1D | D3D12_FORMAT_SUPPORT1_TEXTURE2D
+ | D3D12_FORMAT_SUPPORT1_TEXTURE3D | D3D12_FORMAT_SUPPORT1_TEXTURECUBE;
+ if (image_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)
+ {
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_SHADER_LOAD | D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD
+ | D3D12_FORMAT_SUPPORT1_SHADER_GATHER;
+ if (image_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)
+ {
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE
+ | D3D12_FORMAT_SUPPORT1_MIP;
+ }
+ if (format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_COMPARISON
+ | D3D12_FORMAT_SUPPORT1_SHADER_GATHER_COMPARISON;
+ }
+ if (image_features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_RENDER_TARGET | D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET;
+ if (image_features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_BLENDABLE;
+ if (image_features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL;
+ if (image_features & VK_FORMAT_FEATURE_BLIT_SRC_BIT)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE;
+ if (image_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)
+ data->Support1 |= D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW;
+
+ if (image_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)
+ data->Support2 |= D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_ADD
+ | D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS
+ | D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE
+ | D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE
+ | D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX
+ | D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX;
+
+ vkd3d_restrict_format_support_for_feature_level(data);
+
+ TRACE("Format %#x, support1 %#x, support2 %#x.\n", data->Format, data->Support1, data->Support2);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS:
+ {
+ D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ return d3d12_device_check_multisample_quality_levels(device, data);
+ }
+
+ case D3D12_FEATURE_FORMAT_INFO:
+ {
+ D3D12_FEATURE_DATA_FORMAT_INFO *data = feature_data;
+ const struct vkd3d_format *format;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ if (data->Format == DXGI_FORMAT_UNKNOWN)
+ {
+ data->PlaneCount = 1;
+ return S_OK;
+ }
+
+ if (!(format = vkd3d_get_format(device, data->Format, false)))
+ format = vkd3d_get_format(device, data->Format, true);
+ if (!format)
+ {
+ FIXME("Unhandled format %#x.\n", data->Format);
+ return E_INVALIDARG;
+ }
+
+ data->PlaneCount = format->plane_count;
+
+ TRACE("Format %#x, plane count %"PRIu8".\n", data->Format, data->PlaneCount);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT:
+ {
+ const D3D12_FEATURE_DATA_D3D12_OPTIONS *options = &device->feature_options;
+ D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ data->MaxGPUVirtualAddressBitsPerResource = options->MaxGPUVirtualAddressBitsPerResource;
+ data->MaxGPUVirtualAddressBitsPerProcess = options->MaxGPUVirtualAddressBitsPerResource;
+
+ TRACE("Max GPU virtual address bits per resource %u, Max GPU virtual address bits per process %u.\n",
+ data->MaxGPUVirtualAddressBitsPerResource, data->MaxGPUVirtualAddressBitsPerProcess);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_SHADER_MODEL:
+ {
+ D3D12_FEATURE_DATA_SHADER_MODEL *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ TRACE("Request shader model %#x.\n", data->HighestShaderModel);
+
+ data->HighestShaderModel = D3D_SHADER_MODEL_5_1;
+
+ TRACE("Shader model %#x.\n", data->HighestShaderModel);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_D3D12_OPTIONS1:
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS1 *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ *data = device->feature_options1;
+
+ TRACE("Wave ops %#x.\n", data->WaveOps);
+ TRACE("Min wave lane count %#x.\n", data->WaveLaneCountMin);
+ TRACE("Max wave lane count %#x.\n", data->WaveLaneCountMax);
+ TRACE("Total lane count %#x.\n", data->TotalLaneCount);
+ TRACE("Expanded compute resource states %#x.\n", data->ExpandedComputeResourceStates);
+ TRACE("Int64 shader ops %#x.\n", data->Int64ShaderOps);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_ROOT_SIGNATURE:
+ {
+ D3D12_FEATURE_DATA_ROOT_SIGNATURE *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ TRACE("Root signature requested %#x.\n", data->HighestVersion);
+ data->HighestVersion = min(data->HighestVersion, D3D_ROOT_SIGNATURE_VERSION_1_1);
+ if (device->vkd3d_instance->api_version < VKD3D_API_VERSION_1_2)
+ data->HighestVersion = min(data->HighestVersion, D3D_ROOT_SIGNATURE_VERSION_1_0);
+
+ TRACE("Root signature version %#x.\n", data->HighestVersion);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_ARCHITECTURE1:
+ {
+ D3D12_FEATURE_DATA_ARCHITECTURE1 *data = feature_data;
+ bool coherent;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ if (data->NodeIndex)
+ {
+ FIXME("Multi-adapter not supported.\n");
+ return E_INVALIDARG;
+ }
+
+ WARN("Assuming device does not support tile based rendering.\n");
+ data->TileBasedRenderer = FALSE;
+
+ data->UMA = d3d12_device_is_uma(device, &coherent);
+ data->CacheCoherentUMA = data->UMA && coherent;
+
+ WARN("Assuming device does not have an isolated memory management unit.\n");
+ data->IsolatedMMU = FALSE;
+
+ TRACE("Tile based renderer %#x, UMA %#x, cache coherent UMA %#x, isolated MMU %#x.\n",
+ data->TileBasedRenderer, data->UMA, data->CacheCoherentUMA, data->IsolatedMMU);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_D3D12_OPTIONS2:
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS2 *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ *data = device->feature_options2;
+
+ TRACE("Depth bounds test %#x.\n", data->DepthBoundsTestSupported);
+ TRACE("Programmable sample positions tier %#x.\n", data->ProgrammableSamplePositionsTier);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_SHADER_CACHE:
+ {
+ D3D12_FEATURE_DATA_SHADER_CACHE *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ /* FIXME: The d3d12 documentation states that
+ * D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO is always supported, but
+ * the CachedPSO field of D3D12_GRAPHICS_PIPELINE_STATE_DESC is
+ * ignored and GetCachedBlob() is a stub. */
+ data->SupportFlags = D3D12_SHADER_CACHE_SUPPORT_NONE;
+
+ TRACE("Shader cache support %#x.\n", data->SupportFlags);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_COMMAND_QUEUE_PRIORITY:
+ {
+ D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ switch (data->CommandListType)
+ {
+ case D3D12_COMMAND_LIST_TYPE_DIRECT:
+ case D3D12_COMMAND_LIST_TYPE_COMPUTE:
+ case D3D12_COMMAND_LIST_TYPE_COPY:
+ data->PriorityForTypeIsSupported = FALSE;
+ TRACE("Command list type %#x, priority %u, supported %#x.\n",
+ data->CommandListType, data->Priority, data->PriorityForTypeIsSupported);
+ return S_OK;
+
+ default:
+ FIXME("Unhandled command list type %#x.\n", data->CommandListType);
+ return E_INVALIDARG;
+ }
+ }
+
+ case D3D12_FEATURE_D3D12_OPTIONS3:
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS3 *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ *data = device->feature_options3;
+
+ TRACE("Copy queue timestamp queries %#x.\n", data->CopyQueueTimestampQueriesSupported);
+ TRACE("Casting fully typed format %#x.\n", data->CastingFullyTypedFormatSupported);
+ TRACE("Write buffer immediate %#x.\n", data->WriteBufferImmediateSupportFlags);
+ TRACE("View instancing tier %#x.\n", data->ViewInstancingTier);
+ TRACE("Barycentrics %#x.\n", data->BarycentricsSupported);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_EXISTING_HEAPS:
+ {
+ D3D12_FEATURE_DATA_EXISTING_HEAPS *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ data->Supported = FALSE;
+
+ TRACE("Existing heaps %#x.\n", data->Supported);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_D3D12_OPTIONS4:
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS4 *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ *data = device->feature_options4;
+
+ TRACE("64 KiB aligned MSAA textures %#x.\n", data->MSAA64KBAlignedTextureSupported);
+ TRACE("Shared resource compatibility tier %#x.\n", data->SharedResourceCompatibilityTier);
+ TRACE("Native 16-bit shader ops %#x.\n", data->Native16BitShaderOpsSupported);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_SERIALIZATION:
+ {
+ D3D12_FEATURE_DATA_SERIALIZATION *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ if (data->NodeIndex)
+ {
+ FIXME("Multi-adapter not supported.\n");
+ return E_INVALIDARG;
+ }
+
+ data->HeapSerializationTier = D3D12_HEAP_SERIALIZATION_TIER_0;
+
+ TRACE("Heap serialisation tier %#x.\n", data->HeapSerializationTier);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_CROSS_NODE:
+ {
+ D3D12_FEATURE_DATA_CROSS_NODE *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ data->SharingTier = device->feature_options.CrossNodeSharingTier;
+ data->AtomicShaderInstructions = FALSE;
+
+ TRACE("Cross node sharing tier %#x.\n", data->SharingTier);
+ TRACE("Cross node shader atomics %#x.\n", data->AtomicShaderInstructions);
+ return S_OK;
+ }
+
+ case D3D12_FEATURE_D3D12_OPTIONS5:
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS5 *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ *data = device->feature_options5;
+
+ TRACE("SRV tiled resource tier 3 only %#x.\n", data->SRVOnlyTiledResourceTier3);
+ TRACE("Render pass tier %#x.\n", data->RenderPassesTier);
+ TRACE("Ray tracing tier %#x.\n", data->RaytracingTier);
+ return S_OK;
+ }
+
+ default:
+ FIXME("Unhandled feature %#x.\n", feature);
+ return E_NOTIMPL;
+ }
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateDescriptorHeap(ID3D12Device *iface,
+ const D3D12_DESCRIPTOR_HEAP_DESC *desc, REFIID riid, void **descriptor_heap)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_descriptor_heap *object;
+ HRESULT hr;
+
+ TRACE("iface %p, desc %p, riid %s, descriptor_heap %p.\n",
+ iface, desc, debugstr_guid(riid), descriptor_heap);
+
+ if (FAILED(hr = d3d12_descriptor_heap_create(device, desc, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12DescriptorHeap_iface,
+ &IID_ID3D12DescriptorHeap, riid, descriptor_heap);
+}
+
+static UINT STDMETHODCALLTYPE d3d12_device_GetDescriptorHandleIncrementSize(ID3D12Device *iface,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type)
+{
+ TRACE("iface %p, descriptor_heap_type %#x.\n", iface, descriptor_heap_type);
+
+ switch (descriptor_heap_type)
+ {
+ case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
+ case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
+ return sizeof(struct d3d12_desc);
+
+ case D3D12_DESCRIPTOR_HEAP_TYPE_RTV:
+ return sizeof(struct d3d12_rtv_desc);
+
+ case D3D12_DESCRIPTOR_HEAP_TYPE_DSV:
+ return sizeof(struct d3d12_dsv_desc);
+
+ default:
+ FIXME("Unhandled type %#x.\n", descriptor_heap_type);
+ return 0;
+ }
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateRootSignature(ID3D12Device *iface,
+ UINT node_mask, const void *bytecode, SIZE_T bytecode_length,
+ REFIID riid, void **root_signature)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_root_signature *object;
+ HRESULT hr;
+
+ TRACE("iface %p, node_mask 0x%08x, bytecode %p, bytecode_length %lu, riid %s, root_signature %p.\n",
+ iface, node_mask, bytecode, bytecode_length, debugstr_guid(riid), root_signature);
+
+ debug_ignored_node_mask(node_mask);
+
+ if (FAILED(hr = d3d12_root_signature_create(device, bytecode, bytecode_length, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12RootSignature_iface,
+ &IID_ID3D12RootSignature, riid, root_signature);
+}
+
+static void STDMETHODCALLTYPE d3d12_device_CreateConstantBufferView(ID3D12Device *iface,
+ const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_desc tmp = {0};
+
+ TRACE("iface %p, desc %p, descriptor %#lx.\n", iface, desc, descriptor.ptr);
+
+ d3d12_desc_create_cbv(&tmp, device, desc);
+ d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device);
+}
+
+static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(ID3D12Device *iface,
+ ID3D12Resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_desc tmp = {0};
+
+ TRACE("iface %p, resource %p, desc %p, descriptor %#lx.\n",
+ iface, resource, desc, descriptor.ptr);
+
+ d3d12_desc_create_srv(&tmp, device, unsafe_impl_from_ID3D12Resource(resource), desc);
+ d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device);
+}
+
+static void STDMETHODCALLTYPE d3d12_device_CreateUnorderedAccessView(ID3D12Device *iface,
+ ID3D12Resource *resource, ID3D12Resource *counter_resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_desc tmp = {0};
+
+ TRACE("iface %p, resource %p, counter_resource %p, desc %p, descriptor %#lx.\n",
+ iface, resource, counter_resource, desc, descriptor.ptr);
+
+ d3d12_desc_create_uav(&tmp, device, unsafe_impl_from_ID3D12Resource(resource),
+ unsafe_impl_from_ID3D12Resource(counter_resource), desc);
+ d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device);
+}
+
+static void STDMETHODCALLTYPE d3d12_device_CreateRenderTargetView(ID3D12Device *iface,
+ ID3D12Resource *resource, const D3D12_RENDER_TARGET_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
+{
+ TRACE("iface %p, resource %p, desc %p, descriptor %#lx.\n",
+ iface, resource, desc, descriptor.ptr);
+
+ d3d12_rtv_desc_create_rtv(d3d12_rtv_desc_from_cpu_handle(descriptor),
+ impl_from_ID3D12Device(iface), unsafe_impl_from_ID3D12Resource(resource), desc);
+}
+
+static void STDMETHODCALLTYPE d3d12_device_CreateDepthStencilView(ID3D12Device *iface,
+ ID3D12Resource *resource, const D3D12_DEPTH_STENCIL_VIEW_DESC *desc,
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
+{
+ TRACE("iface %p, resource %p, desc %p, descriptor %#lx.\n",
+ iface, resource, desc, descriptor.ptr);
+
+ d3d12_dsv_desc_create_dsv(d3d12_dsv_desc_from_cpu_handle(descriptor),
+ impl_from_ID3D12Device(iface), unsafe_impl_from_ID3D12Resource(resource), desc);
+}
+
+static void STDMETHODCALLTYPE d3d12_device_CreateSampler(ID3D12Device *iface,
+ const D3D12_SAMPLER_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_desc tmp = {0};
+
+ TRACE("iface %p, desc %p, descriptor %#lx.\n", iface, desc, descriptor.ptr);
+
+ d3d12_desc_create_sampler(&tmp, device, desc);
+ d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device);
+}
+
+static void STDMETHODCALLTYPE d3d12_device_CopyDescriptors(ID3D12Device *iface,
+ UINT dst_descriptor_range_count, const D3D12_CPU_DESCRIPTOR_HANDLE *dst_descriptor_range_offsets,
+ const UINT *dst_descriptor_range_sizes,
+ UINT src_descriptor_range_count, const D3D12_CPU_DESCRIPTOR_HANDLE *src_descriptor_range_offsets,
+ const UINT *src_descriptor_range_sizes,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ unsigned int dst_range_idx, dst_idx, src_range_idx, src_idx;
+ unsigned int dst_range_size, src_range_size;
+ const struct d3d12_desc *src;
+ struct d3d12_desc *dst;
+
+ TRACE("iface %p, dst_descriptor_range_count %u, dst_descriptor_range_offsets %p, "
+ "dst_descriptor_range_sizes %p, src_descriptor_range_count %u, "
+ "src_descriptor_range_offsets %p, src_descriptor_range_sizes %p, "
+ "descriptor_heap_type %#x.\n",
+ iface, dst_descriptor_range_count, dst_descriptor_range_offsets,
+ dst_descriptor_range_sizes, src_descriptor_range_count, src_descriptor_range_offsets,
+ src_descriptor_range_sizes, descriptor_heap_type);
+
+ if (descriptor_heap_type != D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
+ && descriptor_heap_type != D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER)
+ {
+ FIXME("Unhandled descriptor heap type %#x.\n", descriptor_heap_type);
+ return;
+ }
+
+ dst_range_idx = dst_idx = 0;
+ src_range_idx = src_idx = 0;
+ while (dst_range_idx < dst_descriptor_range_count && src_range_idx < src_descriptor_range_count)
+ {
+ dst_range_size = dst_descriptor_range_sizes ? dst_descriptor_range_sizes[dst_range_idx] : 1;
+ src_range_size = src_descriptor_range_sizes ? src_descriptor_range_sizes[src_range_idx] : 1;
+
+ dst = d3d12_desc_from_cpu_handle(dst_descriptor_range_offsets[dst_range_idx]);
+ src = d3d12_desc_from_cpu_handle(src_descriptor_range_offsets[src_range_idx]);
+
+ while (dst_idx < dst_range_size && src_idx < src_range_size)
+ d3d12_desc_copy(&dst[dst_idx++], &src[src_idx++], device);
+
+ if (dst_idx >= dst_range_size)
+ {
+ ++dst_range_idx;
+ dst_idx = 0;
+ }
+ if (src_idx >= src_range_size)
+ {
+ ++src_range_idx;
+ src_idx = 0;
+ }
+ }
+}
+
+static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device *iface,
+ UINT descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE dst_descriptor_range_offset,
+ const D3D12_CPU_DESCRIPTOR_HANDLE src_descriptor_range_offset,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type)
+{
+ TRACE("iface %p, descriptor_count %u, dst_descriptor_range_offset %#lx, "
+ "src_descriptor_range_offset %#lx, descriptor_heap_type %#x.\n",
+ iface, descriptor_count, dst_descriptor_range_offset.ptr, src_descriptor_range_offset.ptr,
+ descriptor_heap_type);
+
+ d3d12_device_CopyDescriptors(iface, 1, &dst_descriptor_range_offset, &descriptor_count,
+ 1, &src_descriptor_range_offset, &descriptor_count, descriptor_heap_type);
+}
+
+static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo(
+ ID3D12Device *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask,
+ UINT count, const D3D12_RESOURCE_DESC *resource_descs)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ const D3D12_RESOURCE_DESC *desc;
+ uint64_t requested_alignment;
+
+ TRACE("iface %p, info %p, visible_mask 0x%08x, count %u, resource_descs %p.\n",
+ iface, info, visible_mask, count, resource_descs);
+
+ debug_ignored_node_mask(visible_mask);
+
+ info->SizeInBytes = 0;
+ info->Alignment = 0;
+
+ if (count != 1)
+ {
+ FIXME("Multiple resource descriptions not supported.\n");
+ return info;
+ }
+
+ desc = &resource_descs[0];
+
+ if (FAILED(d3d12_resource_validate_desc(desc, device)))
+ {
+ WARN("Invalid resource desc.\n");
+ goto invalid;
+ }
+
+ if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
+ {
+ info->SizeInBytes = desc->Width;
+ info->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+ }
+ else
+ {
+ if (FAILED(vkd3d_get_image_allocation_info(device, desc, info)))
+ {
+ WARN("Failed to get allocation info for texture.\n");
+ goto invalid;
+ }
+
+ requested_alignment = desc->Alignment
+ ? desc->Alignment : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+ info->Alignment = max(info->Alignment, requested_alignment);
+ }
+
+ info->SizeInBytes = align(info->SizeInBytes, info->Alignment);
+
+ TRACE("Size %#"PRIx64", alignment %#"PRIx64".\n", info->SizeInBytes, info->Alignment);
+
+ return info;
+
+invalid:
+ info->SizeInBytes = ~(uint64_t)0;
+
+ /* FIXME: Should we support D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT for small MSSA resources? */
+ if (desc->SampleDesc.Count != 1)
+ info->Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;
+ else
+ info->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+
+ TRACE("Alignment %#"PRIx64".\n", info->Alignment);
+
+ return info;
+}
+
+static D3D12_HEAP_PROPERTIES * STDMETHODCALLTYPE d3d12_device_GetCustomHeapProperties(ID3D12Device *iface,
+ D3D12_HEAP_PROPERTIES *heap_properties, UINT node_mask, D3D12_HEAP_TYPE heap_type)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ bool coherent;
+
+ TRACE("iface %p, heap_properties %p, node_mask 0x%08x, heap_type %#x.\n",
+ iface, heap_properties, node_mask, heap_type);
+
+ debug_ignored_node_mask(node_mask);
+
+ heap_properties->Type = D3D12_HEAP_TYPE_CUSTOM;
+
+ switch (heap_type)
+ {
+ case D3D12_HEAP_TYPE_DEFAULT:
+ heap_properties->CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE;
+ heap_properties->MemoryPoolPreference = d3d12_device_is_uma(device, NULL)
+ ? D3D12_MEMORY_POOL_L0 : D3D12_MEMORY_POOL_L1;
+ break;
+
+ case D3D12_HEAP_TYPE_UPLOAD:
+ heap_properties->CPUPageProperty = d3d12_device_is_uma(device, &coherent) && coherent
+ ? D3D12_CPU_PAGE_PROPERTY_WRITE_BACK : D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE;
+ heap_properties->MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
+ break;
+
+ case D3D12_HEAP_TYPE_READBACK:
+ heap_properties->CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
+ heap_properties->MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
+ break;
+
+ default:
+ FIXME("Unhandled heap type %#x.\n", heap_type);
+ break;
+ };
+
+ heap_properties->CreationNodeMask = 1;
+ heap_properties->VisibleNodeMask = 1;
+
+ return heap_properties;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Device *iface,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, REFIID iid, void **resource)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_resource *object;
+ HRESULT hr;
+
+ TRACE("iface %p, heap_properties %p, heap_flags %#x, desc %p, initial_state %#x, "
+ "optimized_clear_value %p, iid %s, resource %p.\n",
+ iface, heap_properties, heap_flags, desc, initial_state,
+ optimized_clear_value, debugstr_guid(iid), resource);
+
+ if (FAILED(hr = d3d12_committed_resource_create(device, heap_properties, heap_flags,
+ desc, initial_state, optimized_clear_value, &object)))
+ {
+ *resource = NULL;
+ return hr;
+ }
+
+ return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device *iface,
+ const D3D12_HEAP_DESC *desc, REFIID iid, void **heap)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_heap *object;
+ HRESULT hr;
+
+ TRACE("iface %p, desc %p, iid %s, heap %p.\n",
+ iface, desc, debugstr_guid(iid), heap);
+
+ if (FAILED(hr = d3d12_heap_create(device, desc, NULL, &object)))
+ {
+ *heap = NULL;
+ return hr;
+ }
+
+ return return_interface(&object->ID3D12Heap_iface, &IID_ID3D12Heap, iid, heap);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device *iface,
+ ID3D12Heap *heap, UINT64 heap_offset,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, REFIID iid, void **resource)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_heap *heap_object;
+ struct d3d12_resource *object;
+ HRESULT hr;
+
+ TRACE("iface %p, heap %p, heap_offset %#"PRIx64", desc %p, initial_state %#x, "
+ "optimized_clear_value %p, iid %s, resource %p.\n",
+ iface, heap, heap_offset, desc, initial_state,
+ optimized_clear_value, debugstr_guid(iid), resource);
+
+ heap_object = unsafe_impl_from_ID3D12Heap(heap);
+
+ if (FAILED(hr = d3d12_placed_resource_create(device, heap_object, heap_offset,
+ desc, initial_state, optimized_clear_value, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Device *iface,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, REFIID iid, void **resource)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_resource *object;
+ HRESULT hr;
+
+ TRACE("iface %p, desc %p, initial_state %#x, optimized_clear_value %p, iid %s, resource %p.\n",
+ iface, desc, initial_state, optimized_clear_value, debugstr_guid(iid), resource);
+
+ if (FAILED(hr = d3d12_reserved_resource_create(device,
+ desc, initial_state, optimized_clear_value, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device *iface,
+ ID3D12DeviceChild *object, const SECURITY_ATTRIBUTES *attributes, DWORD access,
+ const WCHAR *name, HANDLE *handle)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ FIXME("iface %p, object %p, attributes %p, access %#x, name %s, handle %p stub!\n",
+ iface, object, attributes, access, debugstr_w(name, device->wchar_size), handle);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandle(ID3D12Device *iface,
+ HANDLE handle, REFIID riid, void **object)
+{
+ FIXME("iface %p, handle %p, riid %s, object %p stub!\n",
+ iface, handle, debugstr_guid(riid), object);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandleByName(ID3D12Device *iface,
+ const WCHAR *name, DWORD access, HANDLE *handle)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ FIXME("iface %p, name %s, access %#x, handle %p stub!\n",
+ iface, debugstr_w(name, device->wchar_size), access, handle);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_MakeResident(ID3D12Device *iface,
+ UINT object_count, ID3D12Pageable * const *objects)
+{
+ FIXME_ONCE("iface %p, object_count %u, objects %p stub!\n",
+ iface, object_count, objects);
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_Evict(ID3D12Device *iface,
+ UINT object_count, ID3D12Pageable * const *objects)
+{
+ FIXME_ONCE("iface %p, object_count %u, objects %p stub!\n",
+ iface, object_count, objects);
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device *iface,
+ UINT64 initial_value, D3D12_FENCE_FLAGS flags, REFIID riid, void **fence)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_fence *object;
+ HRESULT hr;
+
+ TRACE("iface %p, intial_value %#"PRIx64", flags %#x, riid %s, fence %p.\n",
+ iface, initial_value, flags, debugstr_guid(riid), fence);
+
+ if (FAILED(hr = d3d12_fence_create(device, initial_value, flags, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12Fence_iface, &IID_ID3D12Fence, riid, fence);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_GetDeviceRemovedReason(ID3D12Device *iface)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ return device->removed_reason;
+}
+
+static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device *iface,
+ const D3D12_RESOURCE_DESC *desc, UINT first_sub_resource, UINT sub_resource_count,
+ UINT64 base_offset, D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts,
+ UINT *row_counts, UINT64 *row_sizes, UINT64 *total_bytes)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ static const struct vkd3d_format vkd3d_format_unknown
+ = {DXGI_FORMAT_UNKNOWN, VK_FORMAT_UNDEFINED, 1, 1, 1, 1, 0};
+
+ unsigned int i, sub_resource_idx, miplevel_idx, row_count, row_size, row_pitch;
+ unsigned int width, height, depth, array_size;
+ const struct vkd3d_format *format;
+ uint64_t offset, size, total;
+
+ TRACE("iface %p, desc %p, first_sub_resource %u, sub_resource_count %u, base_offset %#"PRIx64", "
+ "layouts %p, row_counts %p, row_sizes %p, total_bytes %p.\n",
+ iface, desc, first_sub_resource, sub_resource_count, base_offset,
+ layouts, row_counts, row_sizes, total_bytes);
+
+ if (layouts)
+ memset(layouts, 0xff, sizeof(*layouts) * sub_resource_count);
+ if (row_counts)
+ memset(row_counts, 0xff, sizeof(*row_counts) * sub_resource_count);
+ if (row_sizes)
+ memset(row_sizes, 0xff, sizeof(*row_sizes) * sub_resource_count);
+ if (total_bytes)
+ *total_bytes = ~(uint64_t)0;
+
+ if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
+ {
+ format = &vkd3d_format_unknown;
+ }
+ else if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0)))
+ {
+ WARN("Invalid format %#x.\n", desc->Format);
+ return;
+ }
+
+ if (FAILED(d3d12_resource_validate_desc(desc, device)))
+ {
+ WARN("Invalid resource desc.\n");
+ return;
+ }
+
+ array_size = d3d12_resource_desc_get_layer_count(desc);
+
+ if (first_sub_resource >= desc->MipLevels * array_size
+ || sub_resource_count > desc->MipLevels * array_size - first_sub_resource)
+ {
+ WARN("Invalid sub-resource range %u-%u for resource.\n", first_sub_resource, sub_resource_count);
+ return;
+ }
+
+ offset = 0;
+ total = 0;
+ for (i = 0; i < sub_resource_count; ++i)
+ {
+ sub_resource_idx = first_sub_resource + i;
+ miplevel_idx = sub_resource_idx % desc->MipLevels;
+ width = align(d3d12_resource_desc_get_width(desc, miplevel_idx), format->block_width);
+ height = align(d3d12_resource_desc_get_height(desc, miplevel_idx), format->block_height);
+ depth = d3d12_resource_desc_get_depth(desc, miplevel_idx);
+ row_count = height / format->block_height;
+ row_size = (width / format->block_width) * format->byte_count * format->block_byte_count;
+ row_pitch = align(row_size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+
+ if (layouts)
+ {
+ layouts[i].Offset = base_offset + offset;
+ layouts[i].Footprint.Format = desc->Format;
+ layouts[i].Footprint.Width = width;
+ layouts[i].Footprint.Height = height;
+ layouts[i].Footprint.Depth = depth;
+ layouts[i].Footprint.RowPitch = row_pitch;
+ }
+ if (row_counts)
+ row_counts[i] = row_count;
+ if (row_sizes)
+ row_sizes[i] = row_size;
+
+ size = max(0, row_count - 1) * row_pitch + row_size;
+ size = max(0, depth - 1) * align(size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) + size;
+
+ total = offset + size;
+ offset = align(total, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
+ }
+ if (total_bytes)
+ *total_bytes = total;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateQueryHeap(ID3D12Device *iface,
+ const D3D12_QUERY_HEAP_DESC *desc, REFIID iid, void **heap)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_query_heap *object;
+ HRESULT hr;
+
+ TRACE("iface %p, desc %p, iid %s, heap %p.\n",
+ iface, desc, debugstr_guid(iid), heap);
+
+ if (FAILED(hr = d3d12_query_heap_create(device, desc, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12QueryHeap_iface, &IID_ID3D12QueryHeap, iid, heap);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetStablePowerState(ID3D12Device *iface, BOOL enable)
+{
+ FIXME("iface %p, enable %#x stub!\n", iface, enable);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(ID3D12Device *iface,
+ const D3D12_COMMAND_SIGNATURE_DESC *desc, ID3D12RootSignature *root_signature,
+ REFIID iid, void **command_signature)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+ struct d3d12_command_signature *object;
+ HRESULT hr;
+
+ TRACE("iface %p, desc %p, root_signature %p, iid %s, command_signature %p.\n",
+ iface, desc, root_signature, debugstr_guid(iid), command_signature);
+
+ if (FAILED(hr = d3d12_command_signature_create(device, desc, &object)))
+ return hr;
+
+ return return_interface(&object->ID3D12CommandSignature_iface,
+ &IID_ID3D12CommandSignature, iid, command_signature);
+}
+
+static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device *iface,
+ ID3D12Resource *resource, UINT *total_tile_count,
+ D3D12_PACKED_MIP_INFO *packed_mip_info, D3D12_TILE_SHAPE *standard_tile_shape,
+ UINT *sub_resource_tiling_count, UINT first_sub_resource_tiling,
+ D3D12_SUBRESOURCE_TILING *sub_resource_tilings)
+{
+ FIXME("iface %p, resource %p, total_tile_count %p, packed_mip_info %p, "
+ "standard_title_shape %p, sub_resource_tiling_count %p, "
+ "first_sub_resource_tiling %u, sub_resource_tilings %p stub!\n",
+ iface, resource, total_tile_count, packed_mip_info, standard_tile_shape,
+ sub_resource_tiling_count, first_sub_resource_tiling,
+ sub_resource_tilings);
+}
+
+static LUID * STDMETHODCALLTYPE d3d12_device_GetAdapterLuid(ID3D12Device *iface, LUID *luid)
+{
+ struct d3d12_device *device = impl_from_ID3D12Device(iface);
+
+ TRACE("iface %p, luid %p.\n", iface, luid);
+
+ *luid = device->adapter_luid;
+
+ return luid;
+}
+
+static const struct ID3D12DeviceVtbl d3d12_device_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_device_QueryInterface,
+ d3d12_device_AddRef,
+ d3d12_device_Release,
+ /* ID3D12Object methods */
+ d3d12_device_GetPrivateData,
+ d3d12_device_SetPrivateData,
+ d3d12_device_SetPrivateDataInterface,
+ d3d12_device_SetName,
+ /* ID3D12Device methods */
+ d3d12_device_GetNodeCount,
+ d3d12_device_CreateCommandQueue,
+ d3d12_device_CreateCommandAllocator,
+ d3d12_device_CreateGraphicsPipelineState,
+ d3d12_device_CreateComputePipelineState,
+ d3d12_device_CreateCommandList,
+ d3d12_device_CheckFeatureSupport,
+ d3d12_device_CreateDescriptorHeap,
+ d3d12_device_GetDescriptorHandleIncrementSize,
+ d3d12_device_CreateRootSignature,
+ d3d12_device_CreateConstantBufferView,
+ d3d12_device_CreateShaderResourceView,
+ d3d12_device_CreateUnorderedAccessView,
+ d3d12_device_CreateRenderTargetView,
+ d3d12_device_CreateDepthStencilView,
+ d3d12_device_CreateSampler,
+ d3d12_device_CopyDescriptors,
+ d3d12_device_CopyDescriptorsSimple,
+ d3d12_device_GetResourceAllocationInfo,
+ d3d12_device_GetCustomHeapProperties,
+ d3d12_device_CreateCommittedResource,
+ d3d12_device_CreateHeap,
+ d3d12_device_CreatePlacedResource,
+ d3d12_device_CreateReservedResource,
+ d3d12_device_CreateSharedHandle,
+ d3d12_device_OpenSharedHandle,
+ d3d12_device_OpenSharedHandleByName,
+ d3d12_device_MakeResident,
+ d3d12_device_Evict,
+ d3d12_device_CreateFence,
+ d3d12_device_GetDeviceRemovedReason,
+ d3d12_device_GetCopyableFootprints,
+ d3d12_device_CreateQueryHeap,
+ d3d12_device_SetStablePowerState,
+ d3d12_device_CreateCommandSignature,
+ d3d12_device_GetResourceTiling,
+ d3d12_device_GetAdapterLuid,
+};
+
+struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_device_vtbl);
+ return impl_from_ID3D12Device(iface);
+}
+
+static HRESULT d3d12_device_init(struct d3d12_device *device,
+ struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info)
+{
+ const struct vkd3d_vk_device_procs *vk_procs;
+ HRESULT hr;
+ size_t i;
+
+ device->ID3D12Device_iface.lpVtbl = &d3d12_device_vtbl;
+ device->refcount = 1;
+
+ vkd3d_instance_incref(device->vkd3d_instance = instance);
+ device->vk_info = instance->vk_info;
+ device->signal_event = instance->signal_event;
+ device->wchar_size = instance->wchar_size;
+
+ device->adapter_luid = create_info->adapter_luid;
+ device->removed_reason = S_OK;
+
+ device->vk_device = VK_NULL_HANDLE;
+
+ if (FAILED(hr = vkd3d_create_vk_device(device, create_info)))
+ goto out_free_instance;
+
+ if (FAILED(hr = d3d12_device_init_pipeline_cache(device)))
+ goto out_free_vk_resources;
+
+ if (FAILED(hr = vkd3d_private_store_init(&device->private_store)))
+ goto out_free_pipeline_cache;
+
+ if (FAILED(hr = vkd3d_fence_worker_start(&device->fence_worker, device)))
+ goto out_free_private_store;
+
+ if (FAILED(hr = vkd3d_init_format_info(device)))
+ goto out_stop_fence_worker;
+
+ if (FAILED(hr = vkd3d_init_null_resources(&device->null_resources, device)))
+ goto out_cleanup_format_info;
+
+ if (FAILED(hr = vkd3d_uav_clear_state_init(&device->uav_clear_state, device)))
+ goto out_destroy_null_resources;
+
+ vkd3d_render_pass_cache_init(&device->render_pass_cache);
+ vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator);
+
+ for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i)
+ pthread_mutex_init(&device->desc_mutex[i], NULL);
+
+ if ((device->parent = create_info->parent))
+ IUnknown_AddRef(device->parent);
+
+ return S_OK;
+
+out_destroy_null_resources:
+ vkd3d_destroy_null_resources(&device->null_resources, device);
+out_cleanup_format_info:
+ vkd3d_cleanup_format_info(device);
+out_stop_fence_worker:
+ vkd3d_fence_worker_stop(&device->fence_worker, device);
+out_free_private_store:
+ vkd3d_private_store_destroy(&device->private_store);
+out_free_pipeline_cache:
+ d3d12_device_destroy_pipeline_cache(device);
+out_free_vk_resources:
+ vk_procs = &device->vk_procs;
+ VK_CALL(vkDestroyDevice(device->vk_device, NULL));
+out_free_instance:
+ vkd3d_instance_decref(device->vkd3d_instance);
+ return hr;
+}
+
+HRESULT d3d12_device_create(struct vkd3d_instance *instance,
+ const struct vkd3d_device_create_info *create_info, struct d3d12_device **device)
+{
+ struct d3d12_device *object;
+ HRESULT hr;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_device_init(object, instance, create_info)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created device %p.\n", object);
+
+ *device = object;
+
+ return S_OK;
+}
+
+void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason,
+ const char *message, ...)
+{
+ va_list args;
+
+ va_start(args, message);
+ WARN("Device %p is lost (reason %#x, \"%s\").\n",
+ device, reason, vkd3d_dbg_vsprintf(message, args));
+ va_end(args);
+
+ device->removed_reason = reason;
+}
+
+HRESULT vkd3d_create_thread(struct vkd3d_instance *instance,
+ PFN_vkd3d_thread thread_main, void *data, union vkd3d_thread_handle *thread)
+{
+ HRESULT hr = S_OK;
+ int rc;
+
+ if (instance->create_thread)
+ {
+ if (!(thread->handle = instance->create_thread(thread_main, data)))
+ {
+ ERR("Failed to create thread.\n");
+ hr = E_FAIL;
+ }
+ }
+ else
+ {
+ if ((rc = pthread_create(&thread->pthread, NULL, thread_main, data)))
+ {
+ ERR("Failed to create thread, error %d.\n", rc);
+ hr = hresult_from_errno(rc);
+ }
+ }
+
+ return hr;
+}
+
+HRESULT vkd3d_join_thread(struct vkd3d_instance *instance, union vkd3d_thread_handle *thread)
+{
+ HRESULT hr = S_OK;
+ int rc;
+
+ if (instance->join_thread)
+ {
+ if (FAILED(hr = instance->join_thread(thread->handle)))
+ ERR("Failed to join thread, hr %#x.\n", hr);
+ }
+ else
+ {
+ if ((rc = pthread_join(thread->pthread, NULL)))
+ {
+ ERR("Failed to join thread, error %d.\n", rc);
+ hr = hresult_from_errno(rc);
+ }
+ }
+
+ return hr;
+}
+
+IUnknown *vkd3d_get_device_parent(ID3D12Device *device)
+{
+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device(device);
+
+ return d3d12_device->parent;
+}
+
+VkDevice vkd3d_get_vk_device(ID3D12Device *device)
+{
+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device(device);
+
+ return d3d12_device->vk_device;
+}
+
+VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device)
+{
+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device(device);
+
+ return d3d12_device->vk_physical_device;
+}
+
+struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device)
+{
+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device(device);
+
+ return d3d12_device->vkd3d_instance;
+}
diff --git a/dlls/vkd3d/libs/vkd3d/libvkd3d.pc.in b/dlls/vkd3d/libs/vkd3d/libvkd3d.pc.in
new file mode 100644
index 00000000000..e8b27295205
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/libvkd3d.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: vkd3d
+Description: The vkd3d 3D Graphics Library
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}/vkd3d
+Libs: -L${libdir} -lvkd3d
diff --git a/dlls/vkd3d/libs/vkd3d/resource.c b/dlls/vkd3d/libs/vkd3d/resource.c
new file mode 100644
index 00000000000..a9d4d464fe7
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/resource.c
@@ -0,0 +1,4092 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ * Copyright 2019 Conor McCarthy for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_private.h"
+
+#define VKD3D_NULL_BUFFER_SIZE 16
+#define VKD3D_NULL_VIEW_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM
+
+static inline bool is_cpu_accessible_heap(const D3D12_HEAP_PROPERTIES *properties)
+{
+ if (properties->Type == D3D12_HEAP_TYPE_DEFAULT)
+ return false;
+ if (properties->Type == D3D12_HEAP_TYPE_CUSTOM)
+ {
+ return properties->CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE
+ || properties->CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
+ }
+ return true;
+}
+
+static HRESULT vkd3d_select_memory_type(struct d3d12_device *device, uint32_t memory_type_mask,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, unsigned int *type_index)
+{
+ const VkPhysicalDeviceMemoryProperties *memory_info = &device->memory_properties;
+ VkMemoryPropertyFlags flags[3];
+ unsigned int i, j, count = 0;
+
+ switch (heap_properties->Type)
+ {
+ case D3D12_HEAP_TYPE_DEFAULT:
+ flags[count++] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ break;
+
+ case D3D12_HEAP_TYPE_UPLOAD:
+ flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ break;
+
+ case D3D12_HEAP_TYPE_READBACK:
+ flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ break;
+
+ case D3D12_HEAP_TYPE_CUSTOM:
+ if (heap_properties->MemoryPoolPreference == D3D12_MEMORY_POOL_UNKNOWN
+ || (heap_properties->MemoryPoolPreference == D3D12_MEMORY_POOL_L1
+ && (is_cpu_accessible_heap(heap_properties) || d3d12_device_is_uma(device, NULL))))
+ {
+ WARN("Invalid memory pool preference.\n");
+ return E_INVALIDARG;
+ }
+
+ switch (heap_properties->CPUPageProperty)
+ {
+ case D3D12_CPU_PAGE_PROPERTY_WRITE_BACK:
+ flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ /* Fall through. */
+ case D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE:
+ flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ /* Fall through. */
+ case D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE:
+ flags[count++] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ break;
+ case D3D12_CPU_PAGE_PROPERTY_UNKNOWN:
+ default:
+ WARN("Invalid CPU page property.\n");
+ return E_INVALIDARG;
+ }
+ break;
+
+ default:
+ WARN("Invalid heap type %#x.\n", heap_properties->Type);
+ return E_INVALIDARG;
+ }
+
+ for (j = 0; j < count; ++j)
+ {
+ VkMemoryPropertyFlags preferred_flags = flags[j];
+
+ for (i = 0; i < memory_info->memoryTypeCount; ++i)
+ {
+ if (!(memory_type_mask & (1u << i)))
+ continue;
+ if ((memory_info->memoryTypes[i].propertyFlags & preferred_flags) == preferred_flags)
+ {
+ *type_index = i;
+ return S_OK;
+ }
+ }
+ }
+
+ return E_FAIL;
+}
+
+static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const VkMemoryRequirements *memory_requirements,
+ const VkMemoryDedicatedAllocateInfo *dedicated_allocate_info,
+ VkDeviceMemory *vk_memory, uint32_t *vk_memory_type)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkMemoryAllocateInfo allocate_info;
+ VkResult vr;
+ HRESULT hr;
+
+ TRACE("Memory requirements: size %#"PRIx64", alignment %#"PRIx64".\n",
+ memory_requirements->size, memory_requirements->alignment);
+
+ allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocate_info.pNext = dedicated_allocate_info;
+ allocate_info.allocationSize = memory_requirements->size;
+ if (FAILED(hr = vkd3d_select_memory_type(device, memory_requirements->memoryTypeBits,
+ heap_properties, heap_flags, &allocate_info.memoryTypeIndex)))
+ {
+ if (hr != E_INVALIDARG)
+ FIXME("Failed to find suitable memory type (allowed types %#x).\n", memory_requirements->memoryTypeBits);
+ *vk_memory = VK_NULL_HANDLE;
+ return hr;
+ }
+
+ TRACE("Allocating memory type %u.\n", allocate_info.memoryTypeIndex);
+
+ if ((vr = VK_CALL(vkAllocateMemory(device->vk_device, &allocate_info, NULL, vk_memory))) < 0)
+ {
+ WARN("Failed to allocate device memory, vr %d.\n", vr);
+ *vk_memory = VK_NULL_HANDLE;
+ return hresult_from_vk_result(vr);
+ }
+
+ if (vk_memory_type)
+ *vk_memory_type = allocate_info.memoryTypeIndex;
+
+ return S_OK;
+}
+
+HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_buffer,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ VkDeviceMemory *vk_memory, uint32_t *vk_memory_type, VkDeviceSize *vk_memory_size)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkMemoryDedicatedAllocateInfo *dedicated_allocation = NULL;
+ VkMemoryDedicatedRequirements dedicated_requirements;
+ VkMemoryDedicatedAllocateInfo dedicated_info;
+ VkMemoryRequirements2 memory_requirements2;
+ VkMemoryRequirements *memory_requirements;
+ VkBufferMemoryRequirementsInfo2 info;
+ VkResult vr;
+ HRESULT hr;
+
+ memory_requirements = &memory_requirements2.memoryRequirements;
+
+ if (device->vk_info.KHR_dedicated_allocation)
+ {
+ info.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
+ info.pNext = NULL;
+ info.buffer = vk_buffer;
+
+ dedicated_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
+ dedicated_requirements.pNext = NULL;
+
+ memory_requirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
+ memory_requirements2.pNext = &dedicated_requirements;
+
+ VK_CALL(vkGetBufferMemoryRequirements2KHR(device->vk_device, &info, &memory_requirements2));
+
+ if (dedicated_requirements.prefersDedicatedAllocation)
+ {
+ dedicated_allocation = &dedicated_info;
+
+ dedicated_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
+ dedicated_info.pNext = NULL;
+ dedicated_info.image = VK_NULL_HANDLE;
+ dedicated_info.buffer = vk_buffer;
+ }
+ }
+ else
+ {
+ VK_CALL(vkGetBufferMemoryRequirements(device->vk_device, vk_buffer, memory_requirements));
+ }
+
+ if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
+ memory_requirements, dedicated_allocation, vk_memory, vk_memory_type)))
+ return hr;
+
+ if ((vr = VK_CALL(vkBindBufferMemory(device->vk_device, vk_buffer, *vk_memory, 0))) < 0)
+ {
+ WARN("Failed to bind memory, vr %d.\n", vr);
+ VK_CALL(vkFreeMemory(device->vk_device, *vk_memory, NULL));
+ *vk_memory = VK_NULL_HANDLE;
+ }
+
+ if (vk_memory_size)
+ *vk_memory_size = memory_requirements->size;
+
+ return hresult_from_vk_result(vr);
+}
+
+static HRESULT vkd3d_allocate_image_memory(struct d3d12_device *device, VkImage vk_image,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ VkDeviceMemory *vk_memory, uint32_t *vk_memory_type, VkDeviceSize *vk_memory_size)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkMemoryDedicatedAllocateInfo *dedicated_allocation = NULL;
+ VkMemoryDedicatedRequirements dedicated_requirements;
+ VkMemoryDedicatedAllocateInfo dedicated_info;
+ VkMemoryRequirements2 memory_requirements2;
+ VkMemoryRequirements *memory_requirements;
+ VkImageMemoryRequirementsInfo2 info;
+ VkResult vr;
+ HRESULT hr;
+
+ memory_requirements = &memory_requirements2.memoryRequirements;
+
+ if (device->vk_info.KHR_dedicated_allocation)
+ {
+ info.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
+ info.pNext = NULL;
+ info.image = vk_image;
+
+ dedicated_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
+ dedicated_requirements.pNext = NULL;
+
+ memory_requirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
+ memory_requirements2.pNext = &dedicated_requirements;
+
+ VK_CALL(vkGetImageMemoryRequirements2KHR(device->vk_device, &info, &memory_requirements2));
+
+ if (dedicated_requirements.prefersDedicatedAllocation)
+ {
+ dedicated_allocation = &dedicated_info;
+
+ dedicated_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
+ dedicated_info.pNext = NULL;
+ dedicated_info.image = vk_image;
+ dedicated_info.buffer = VK_NULL_HANDLE;
+ }
+ }
+ else
+ {
+ VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, memory_requirements));
+ }
+
+ if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
+ memory_requirements, dedicated_allocation, vk_memory, vk_memory_type)))
+ return hr;
+
+ if ((vr = VK_CALL(vkBindImageMemory(device->vk_device, vk_image, *vk_memory, 0))) < 0)
+ {
+ WARN("Failed to bind memory, vr %d.\n", vr);
+ VK_CALL(vkFreeMemory(device->vk_device, *vk_memory, NULL));
+ *vk_memory = VK_NULL_HANDLE;
+ return hresult_from_vk_result(vr);
+ }
+
+ if (vk_memory_size)
+ *vk_memory_size = memory_requirements->size;
+
+ return S_OK;
+}
+
+/* ID3D12Heap */
+static inline struct d3d12_heap *impl_from_ID3D12Heap(ID3D12Heap *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_heap, ID3D12Heap_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_heap_QueryInterface(ID3D12Heap *iface,
+ REFIID iid, void **object)
+{
+ TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
+
+ if (IsEqualGUID(iid, &IID_ID3D12Heap)
+ || IsEqualGUID(iid, &IID_ID3D12Pageable)
+ || IsEqualGUID(iid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(iid, &IID_ID3D12Object)
+ || IsEqualGUID(iid, &IID_IUnknown))
+ {
+ ID3D12Heap_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface)
+{
+ struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+ ULONG refcount = InterlockedIncrement(&heap->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", heap, refcount);
+
+ assert(!heap->is_private);
+
+ return refcount;
+}
+
+static void d3d12_heap_destroy(struct d3d12_heap *heap)
+{
+ struct d3d12_device *device = heap->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ TRACE("Destroying heap %p.\n", heap);
+
+ vkd3d_private_store_destroy(&heap->private_store);
+
+ VK_CALL(vkFreeMemory(device->vk_device, heap->vk_memory, NULL));
+
+ pthread_mutex_destroy(&heap->mutex);
+
+ if (heap->is_private)
+ device = NULL;
+
+ vkd3d_free(heap);
+
+ if (device)
+ d3d12_device_release(device);
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface)
+{
+ struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+ ULONG refcount = InterlockedDecrement(&heap->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", heap, refcount);
+
+ if (!refcount)
+ d3d12_heap_destroy(heap);
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_heap_GetPrivateData(ID3D12Heap *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&heap->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_heap_SetPrivateData(ID3D12Heap *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&heap->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_heap_SetPrivateDataInterface(ID3D12Heap *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&heap->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_heap_SetName(ID3D12Heap *iface, const WCHAR *name)
+{
+ struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, heap->device->wchar_size));
+
+ return vkd3d_set_vk_object_name(heap->device, (uint64_t)heap->vk_memory,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, name);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_heap_GetDevice(ID3D12Heap *iface, REFIID iid, void **device)
+{
+ struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(heap->device, iid, device);
+}
+
+static D3D12_HEAP_DESC * STDMETHODCALLTYPE d3d12_heap_GetDesc(ID3D12Heap *iface,
+ D3D12_HEAP_DESC *desc)
+{
+ struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+
+ TRACE("iface %p, desc %p.\n", iface, desc);
+
+ *desc = heap->desc;
+ return desc;
+}
+
+static const struct ID3D12HeapVtbl d3d12_heap_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_heap_QueryInterface,
+ d3d12_heap_AddRef,
+ d3d12_heap_Release,
+ /* ID3D12Object methods */
+ d3d12_heap_GetPrivateData,
+ d3d12_heap_SetPrivateData,
+ d3d12_heap_SetPrivateDataInterface,
+ d3d12_heap_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_heap_GetDevice,
+ /* ID3D12Heap methods */
+ d3d12_heap_GetDesc,
+};
+
+struct d3d12_heap *unsafe_impl_from_ID3D12Heap(ID3D12Heap *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_heap_vtbl);
+ return impl_from_ID3D12Heap(iface);
+}
+
+static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset,
+ struct d3d12_resource *resource, void **data)
+{
+ struct d3d12_device *device = heap->device;
+ HRESULT hr = S_OK;
+ VkResult vr;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&heap->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ if (data)
+ *data = NULL;
+ return hresult_from_errno(rc);
+ }
+
+ assert(!resource->map_count || heap->map_ptr);
+
+ if (!resource->map_count)
+ {
+ if (!heap->map_ptr)
+ {
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ TRACE("Mapping heap %p.\n", heap);
+
+ assert(!heap->map_count);
+
+ if ((vr = VK_CALL(vkMapMemory(device->vk_device, heap->vk_memory,
+ 0, VK_WHOLE_SIZE, 0, &heap->map_ptr))) < 0)
+ {
+ WARN("Failed to map device memory, vr %d.\n", vr);
+ heap->map_ptr = NULL;
+ }
+
+ hr = hresult_from_vk_result(vr);
+ }
+
+ if (heap->map_ptr)
+ ++heap->map_count;
+ }
+
+ if (hr == S_OK)
+ {
+ assert(heap->map_ptr);
+ if (data)
+ *data = (BYTE *)heap->map_ptr + offset;
+ ++resource->map_count;
+ }
+ else
+ {
+ assert(!heap->map_ptr);
+ if (data)
+ *data = NULL;
+ }
+
+ pthread_mutex_unlock(&heap->mutex);
+
+ return hr;
+}
+
+static void d3d12_heap_unmap(struct d3d12_heap *heap, struct d3d12_resource *resource)
+{
+ struct d3d12_device *device = heap->device;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&heap->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return;
+ }
+
+ if (!resource->map_count)
+ {
+ WARN("Resource %p is not mapped.\n", resource);
+ goto done;
+ }
+
+ --resource->map_count;
+ if (resource->map_count)
+ goto done;
+
+ if (!heap->map_count)
+ {
+ ERR("Heap %p is not mapped.\n", heap);
+ goto done;
+ }
+
+ --heap->map_count;
+ if (!heap->map_count)
+ {
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ TRACE("Unmapping heap %p, ptr %p.\n", heap, heap->map_ptr);
+
+ VK_CALL(vkUnmapMemory(device->vk_device, heap->vk_memory));
+ heap->map_ptr = NULL;
+ }
+
+done:
+ pthread_mutex_unlock(&heap->mutex);
+}
+
+static HRESULT validate_heap_desc(const D3D12_HEAP_DESC *desc, const struct d3d12_resource *resource)
+{
+ if (!resource && !desc->SizeInBytes)
+ {
+ WARN("Invalid size %"PRIu64".\n", desc->SizeInBytes);
+ return E_INVALIDARG;
+ }
+
+ if (desc->Alignment != D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT
+ && desc->Alignment != D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT)
+ {
+ WARN("Invalid alignment %"PRIu64".\n", desc->Alignment);
+ return E_INVALIDARG;
+ }
+
+ if (!resource && desc->Flags & D3D12_HEAP_FLAG_ALLOW_DISPLAY)
+ {
+ WARN("D3D12_HEAP_FLAG_ALLOW_DISPLAY is only for committed resources.\n");
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
+}
+
+static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
+ struct d3d12_device *device, const D3D12_HEAP_DESC *desc, const struct d3d12_resource *resource)
+{
+ VkMemoryRequirements memory_requirements;
+ VkDeviceSize vk_memory_size;
+ HRESULT hr;
+ int rc;
+
+ heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
+ heap->refcount = 1;
+
+ heap->is_private = !!resource;
+
+ heap->desc = *desc;
+
+ heap->map_ptr = NULL;
+ heap->map_count = 0;
+
+ if (!heap->desc.Properties.CreationNodeMask)
+ heap->desc.Properties.CreationNodeMask = 1;
+ if (!heap->desc.Properties.VisibleNodeMask)
+ heap->desc.Properties.VisibleNodeMask = 1;
+
+ debug_ignored_node_mask(heap->desc.Properties.CreationNodeMask);
+ debug_ignored_node_mask(heap->desc.Properties.VisibleNodeMask);
+
+ if (!heap->desc.Alignment)
+ heap->desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+
+ if (FAILED(hr = validate_heap_desc(&heap->desc, resource)))
+ return hr;
+
+ if ((rc = pthread_mutex_init(&heap->mutex, NULL)))
+ {
+ ERR("Failed to initialize mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ if (FAILED(hr = vkd3d_private_store_init(&heap->private_store)))
+ {
+ pthread_mutex_destroy(&heap->mutex);
+ return hr;
+ }
+
+ if (resource)
+ {
+ if (d3d12_resource_is_buffer(resource))
+ {
+ hr = vkd3d_allocate_buffer_memory(device, resource->u.vk_buffer,
+ &heap->desc.Properties, heap->desc.Flags,
+ &heap->vk_memory, &heap->vk_memory_type, &vk_memory_size);
+ }
+ else
+ {
+ hr = vkd3d_allocate_image_memory(device, resource->u.vk_image,
+ &heap->desc.Properties, heap->desc.Flags,
+ &heap->vk_memory, &heap->vk_memory_type, &vk_memory_size);
+ }
+
+ heap->desc.SizeInBytes = vk_memory_size;
+ }
+ else
+ {
+ memory_requirements.size = heap->desc.SizeInBytes;
+ memory_requirements.alignment = heap->desc.Alignment;
+ memory_requirements.memoryTypeBits = ~(uint32_t)0;
+
+ hr = vkd3d_allocate_device_memory(device, &heap->desc.Properties,
+ heap->desc.Flags, &memory_requirements, NULL,
+ &heap->vk_memory, &heap->vk_memory_type);
+ }
+ if (FAILED(hr))
+ {
+ vkd3d_private_store_destroy(&heap->private_store);
+ pthread_mutex_destroy(&heap->mutex);
+ return hr;
+ }
+
+ heap->device = device;
+ if (!heap->is_private)
+ d3d12_device_add_ref(heap->device);
+
+ return S_OK;
+}
+
+HRESULT d3d12_heap_create(struct d3d12_device *device, const D3D12_HEAP_DESC *desc,
+ const struct d3d12_resource *resource, struct d3d12_heap **heap)
+{
+ struct d3d12_heap *object;
+ HRESULT hr;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_heap_init(object, device, desc, resource)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created %s %p.\n", object->is_private ? "private heap" : "heap", object);
+
+ *heap = object;
+
+ return S_OK;
+}
+
+static VkImageType vk_image_type_from_d3d12_resource_dimension(D3D12_RESOURCE_DIMENSION dimension)
+{
+ switch (dimension)
+ {
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
+ return VK_IMAGE_TYPE_1D;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
+ return VK_IMAGE_TYPE_2D;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
+ return VK_IMAGE_TYPE_3D;
+ default:
+ ERR("Invalid resource dimension %#x.\n", dimension);
+ return VK_IMAGE_TYPE_2D;
+ }
+}
+
+VkSampleCountFlagBits vk_samples_from_sample_count(unsigned int sample_count)
+{
+ switch (sample_count)
+ {
+ case 1:
+ return VK_SAMPLE_COUNT_1_BIT;
+ case 2:
+ return VK_SAMPLE_COUNT_2_BIT;
+ case 4:
+ return VK_SAMPLE_COUNT_4_BIT;
+ case 8:
+ return VK_SAMPLE_COUNT_8_BIT;
+ case 16:
+ return VK_SAMPLE_COUNT_16_BIT;
+ case 32:
+ return VK_SAMPLE_COUNT_32_BIT;
+ case 64:
+ return VK_SAMPLE_COUNT_64_BIT;
+ default:
+ return 0;
+ }
+}
+
+VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_DESC *desc)
+{
+ VkSampleCountFlagBits vk_samples;
+
+ if ((vk_samples = vk_samples_from_sample_count(desc->Count)))
+ return vk_samples;
+
+ FIXME("Unhandled sample count %u.\n", desc->Count);
+ return VK_SAMPLE_COUNT_1_BIT;
+}
+
+HRESULT vkd3d_create_buffer(struct d3d12_device *device,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, VkBuffer *vk_buffer)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ const bool sparse_resource = !heap_properties;
+ VkBufferCreateInfo buffer_info;
+ D3D12_HEAP_TYPE heap_type;
+ VkResult vr;
+
+ heap_type = heap_properties ? heap_properties->Type : D3D12_HEAP_TYPE_DEFAULT;
+
+ buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buffer_info.pNext = NULL;
+ buffer_info.flags = 0;
+ buffer_info.size = desc->Width;
+
+ if (sparse_resource)
+ {
+ buffer_info.flags |= VK_BUFFER_CREATE_SPARSE_BINDING_BIT;
+ if (device->vk_info.sparse_properties.residencyNonResidentStrict)
+ buffer_info.flags |= VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT;
+ }
+
+ buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
+ | VK_BUFFER_USAGE_TRANSFER_DST_BIT
+ | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
+ | VK_BUFFER_USAGE_INDEX_BUFFER_BIT
+ | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
+ | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
+
+ if (device->vk_info.EXT_conditional_rendering)
+ buffer_info.usage |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT;
+
+ if (heap_type == D3D12_HEAP_TYPE_DEFAULT && device->vk_info.EXT_transform_feedback)
+ {
+ buffer_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT
+ | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT;
+ }
+
+ if (heap_type == D3D12_HEAP_TYPE_UPLOAD)
+ buffer_info.usage &= ~VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ else if (heap_type == D3D12_HEAP_TYPE_READBACK)
+ buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+ if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
+ buffer_info.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
+ if (!(desc->Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE))
+ buffer_info.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+
+ /* Buffers always have properties of D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS. */
+ if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS)
+ {
+ WARN("D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS cannot be set for buffers.\n");
+ return E_INVALIDARG;
+ }
+
+ if (device->queue_family_count > 1)
+ {
+ buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
+ buffer_info.queueFamilyIndexCount = device->queue_family_count;
+ buffer_info.pQueueFamilyIndices = device->queue_family_indices;
+ }
+ else
+ {
+ buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ buffer_info.queueFamilyIndexCount = 0;
+ buffer_info.pQueueFamilyIndices = NULL;
+ }
+
+ if (desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
+ FIXME("Unsupported resource flags %#x.\n", desc->Flags);
+
+ if ((vr = VK_CALL(vkCreateBuffer(device->vk_device, &buffer_info, NULL, vk_buffer))) < 0)
+ {
+ WARN("Failed to create Vulkan buffer, vr %d.\n", vr);
+ *vk_buffer = VK_NULL_HANDLE;
+ }
+
+ return hresult_from_vk_result(vr);
+}
+
+static unsigned int max_miplevel_count(const D3D12_RESOURCE_DESC *desc)
+{
+ unsigned int size = max(desc->Width, desc->Height);
+ size = max(size, d3d12_resource_desc_get_depth(desc, 0));
+ return vkd3d_log2i(size) + 1;
+}
+
+static const struct vkd3d_format_compatibility_list *vkd3d_get_format_compatibility_list(
+ const struct d3d12_device *device, DXGI_FORMAT dxgi_format)
+{
+ unsigned int i;
+
+ for (i = 0; i < device->format_compatibility_list_count; ++i)
+ {
+ if (device->format_compatibility_lists[i].typeless_format == dxgi_format)
+ return &device->format_compatibility_lists[i];
+ }
+
+ return NULL;
+}
+
+static bool vkd3d_is_linear_tiling_supported(const struct d3d12_device *device, VkImageCreateInfo *image_info)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkImageFormatProperties properties;
+ VkResult vr;
+
+ if ((vr = VK_CALL(vkGetPhysicalDeviceImageFormatProperties(device->vk_physical_device, image_info->format,
+ image_info->imageType, VK_IMAGE_TILING_LINEAR, image_info->usage, image_info->flags, &properties))) < 0)
+ {
+ if (vr != VK_ERROR_FORMAT_NOT_SUPPORTED)
+ WARN("Failed to get device image format properties, vr %d.\n", vr);
+
+ return false;
+ }
+
+ return image_info->extent.depth <= properties.maxExtent.depth
+ && image_info->mipLevels <= properties.maxMipLevels
+ && image_info->arrayLayers <= properties.maxArrayLayers
+ && (image_info->samples & properties.sampleCounts);
+}
+
+static HRESULT vkd3d_create_image(struct d3d12_device *device,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, struct d3d12_resource *resource, VkImage *vk_image)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ const struct vkd3d_format_compatibility_list *compat_list;
+ const bool sparse_resource = !heap_properties;
+ VkImageFormatListCreateInfoKHR format_list;
+ const struct vkd3d_format *format;
+ VkImageCreateInfo image_info;
+ VkResult vr;
+
+ if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0)))
+ {
+ WARN("Invalid DXGI format %#x.\n", desc->Format);
+ return E_INVALIDARG;
+ }
+
+ image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ image_info.pNext = NULL;
+ image_info.flags = 0;
+ if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
+ {
+ /* Format compatibility rules are more relaxed for UAVs. */
+ if (format->type != VKD3D_FORMAT_TYPE_UINT)
+ image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+ }
+ else if (!(desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) && format->type == VKD3D_FORMAT_TYPE_TYPELESS)
+ {
+ image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+
+ if ((compat_list = vkd3d_get_format_compatibility_list(device, desc->Format)))
+ {
+ format_list.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR;
+ format_list.pNext = NULL;
+ format_list.viewFormatCount = compat_list->format_count;
+ format_list.pViewFormats = compat_list->vk_formats;
+
+ image_info.pNext = &format_list;
+ }
+ }
+ if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
+ && desc->Width == desc->Height && desc->DepthOrArraySize >= 6
+ && desc->SampleDesc.Count == 1)
+ image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+ if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
+ image_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
+
+ if (sparse_resource)
+ {
+ image_info.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
+ if (device->vk_info.sparse_properties.residencyNonResidentStrict)
+ image_info.flags |= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
+ }
+
+ image_info.imageType = vk_image_type_from_d3d12_resource_dimension(desc->Dimension);
+ image_info.format = format->vk_format;
+ image_info.extent.width = desc->Width;
+ image_info.extent.height = desc->Height;
+
+ if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
+ {
+ image_info.extent.depth = desc->DepthOrArraySize;
+ image_info.arrayLayers = 1;
+ }
+ else
+ {
+ image_info.extent.depth = 1;
+ image_info.arrayLayers = desc->DepthOrArraySize;
+ }
+
+ image_info.mipLevels = min(desc->MipLevels, max_miplevel_count(desc));
+ image_info.samples = vk_samples_from_dxgi_sample_desc(&desc->SampleDesc);
+
+ if (sparse_resource)
+ {
+ if (desc->Layout != D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE)
+ {
+ WARN("D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE must be used for reserved texture.\n");
+ return E_INVALIDARG;
+ }
+
+ image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
+ }
+ else if (desc->Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN)
+ {
+ image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
+ }
+ else if (desc->Layout == D3D12_TEXTURE_LAYOUT_ROW_MAJOR)
+ {
+ image_info.tiling = VK_IMAGE_TILING_LINEAR;
+ }
+ else
+ {
+ FIXME("Unsupported layout %#x.\n", desc->Layout);
+ return E_NOTIMPL;
+ }
+
+ image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
+ image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
+ image_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
+ image_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
+ if (!(desc->Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE))
+ image_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+
+ if ((desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS) && device->queue_family_count > 1)
+ {
+ TRACE("Creating image with VK_SHARING_MODE_CONCURRENT.\n");
+ image_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
+ image_info.queueFamilyIndexCount = device->queue_family_count;
+ image_info.pQueueFamilyIndices = device->queue_family_indices;
+ }
+ else
+ {
+ image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ image_info.queueFamilyIndexCount = 0;
+ image_info.pQueueFamilyIndices = NULL;
+ }
+
+ if (heap_properties && is_cpu_accessible_heap(heap_properties))
+ {
+ image_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+
+ if (vkd3d_is_linear_tiling_supported(device, &image_info))
+ {
+ /* Required for ReadFromSubresource(). */
+ WARN("Forcing VK_IMAGE_TILING_LINEAR for CPU readable texture.\n");
+ image_info.tiling = VK_IMAGE_TILING_LINEAR;
+ }
+ }
+ else
+ {
+ image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ }
+
+ if (resource && image_info.tiling == VK_IMAGE_TILING_LINEAR)
+ resource->flags |= VKD3D_RESOURCE_LINEAR_TILING;
+
+ if ((vr = VK_CALL(vkCreateImage(device->vk_device, &image_info, NULL, vk_image))) < 0)
+ WARN("Failed to create Vulkan image, vr %d.\n", vr);
+
+ return hresult_from_vk_result(vr);
+}
+
+HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_ALLOCATION_INFO *allocation_info)
+{
+ static const D3D12_HEAP_PROPERTIES heap_properties = {D3D12_HEAP_TYPE_DEFAULT};
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ D3D12_RESOURCE_DESC validated_desc;
+ VkMemoryRequirements requirements;
+ VkImage vk_image;
+ HRESULT hr;
+
+ assert(desc->Dimension != D3D12_RESOURCE_DIMENSION_BUFFER);
+ assert(d3d12_resource_validate_desc(desc, device) == S_OK);
+
+ if (!desc->MipLevels)
+ {
+ validated_desc = *desc;
+ validated_desc.MipLevels = max_miplevel_count(desc);
+ desc = &validated_desc;
+ }
+
+ /* XXX: We have to create an image to get its memory requirements. */
+ if (SUCCEEDED(hr = vkd3d_create_image(device, &heap_properties, 0, desc, NULL, &vk_image)))
+ {
+ VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, &requirements));
+ VK_CALL(vkDestroyImage(device->vk_device, vk_image, NULL));
+
+ allocation_info->SizeInBytes = requirements.size;
+ allocation_info->Alignment = requirements.alignment;
+ }
+
+ return hr;
+}
+
+static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ if (resource->flags & VKD3D_RESOURCE_EXTERNAL)
+ return;
+
+ if (resource->gpu_address)
+ vkd3d_gpu_va_allocator_free(&device->gpu_va_allocator, resource->gpu_address);
+
+ if (d3d12_resource_is_buffer(resource))
+ VK_CALL(vkDestroyBuffer(device->vk_device, resource->u.vk_buffer, NULL));
+ else
+ VK_CALL(vkDestroyImage(device->vk_device, resource->u.vk_image, NULL));
+
+ if (resource->flags & VKD3D_RESOURCE_DEDICATED_HEAP)
+ d3d12_heap_destroy(resource->heap);
+}
+
+static ULONG d3d12_resource_incref(struct d3d12_resource *resource)
+{
+ ULONG refcount = InterlockedIncrement(&resource->internal_refcount);
+
+ TRACE("%p increasing refcount to %u.\n", resource, refcount);
+
+ return refcount;
+}
+
+static ULONG d3d12_resource_decref(struct d3d12_resource *resource)
+{
+ ULONG refcount = InterlockedDecrement(&resource->internal_refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", resource, refcount);
+
+ if (!refcount)
+ {
+ vkd3d_private_store_destroy(&resource->private_store);
+ d3d12_resource_destroy(resource, resource->device);
+ vkd3d_free(resource);
+ }
+
+ return refcount;
+}
+
+bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource)
+{
+ return resource->heap && is_cpu_accessible_heap(&resource->heap->desc.Properties);
+}
+
+static bool d3d12_resource_validate_box(const struct d3d12_resource *resource,
+ unsigned int sub_resource_idx, const D3D12_BOX *box)
+{
+ unsigned int mip_level = sub_resource_idx % resource->desc.MipLevels;
+ struct d3d12_device *device = resource->device;
+ const struct vkd3d_format *vkd3d_format;
+ uint32_t width_mask, height_mask;
+ uint64_t width, height, depth;
+
+ width = d3d12_resource_desc_get_width(&resource->desc, mip_level);
+ height = d3d12_resource_desc_get_height(&resource->desc, mip_level);
+ depth = d3d12_resource_desc_get_depth(&resource->desc, mip_level);
+
+ vkd3d_format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, 0);
+ assert(vkd3d_format);
+ width_mask = vkd3d_format->block_width - 1;
+ height_mask = vkd3d_format->block_height - 1;
+
+ return box->left <= width && box->right <= width
+ && box->top <= height && box->bottom <= height
+ && box->front <= depth && box->back <= depth
+ && !(box->left & width_mask)
+ && !(box->right & width_mask)
+ && !(box->top & height_mask)
+ && !(box->bottom & height_mask);
+}
+
+static void d3d12_resource_get_level_box(const struct d3d12_resource *resource,
+ unsigned int level, D3D12_BOX *box)
+{
+ box->left = 0;
+ box->top = 0;
+ box->front = 0;
+ box->right = d3d12_resource_desc_get_width(&resource->desc, level);
+ box->bottom = d3d12_resource_desc_get_height(&resource->desc, level);
+ box->back = d3d12_resource_desc_get_depth(&resource->desc, level);
+}
+
+/* ID3D12Resource */
+static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12Resource)
+ || IsEqualGUID(riid, &IID_ID3D12Pageable)
+ || IsEqualGUID(riid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12Resource_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource *iface)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ ULONG refcount = InterlockedIncrement(&resource->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", resource, refcount);
+
+ if (refcount == 1)
+ {
+ struct d3d12_device *device = resource->device;
+
+ d3d12_device_add_ref(device);
+ d3d12_resource_incref(resource);
+ }
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource *iface)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ ULONG refcount = InterlockedDecrement(&resource->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", resource, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = resource->device;
+
+ d3d12_resource_decref(resource);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetPrivateData(ID3D12Resource *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&resource->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateData(ID3D12Resource *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&resource->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateDataInterface(ID3D12Resource *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&resource->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource *iface, const WCHAR *name)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ HRESULT hr;
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, resource->device->wchar_size));
+
+ if (resource->flags & VKD3D_RESOURCE_DEDICATED_HEAP)
+ {
+ if (FAILED(hr = d3d12_heap_SetName(&resource->heap->ID3D12Heap_iface, name)))
+ return hr;
+ }
+
+ if (d3d12_resource_is_buffer(resource))
+ return vkd3d_set_vk_object_name(resource->device, (uint64_t)resource->u.vk_buffer,
+ VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, name);
+ else
+ return vkd3d_set_vk_object_name(resource->device, (uint64_t)resource->u.vk_image,
+ VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, name);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetDevice(ID3D12Resource *iface, REFIID iid, void **device)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(resource->device, iid, device);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT sub_resource,
+ const D3D12_RANGE *read_range, void **data)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ unsigned int sub_resource_count;
+ HRESULT hr;
+
+ TRACE("iface %p, sub_resource %u, read_range %p, data %p.\n",
+ iface, sub_resource, read_range, data);
+
+ if (!d3d12_resource_is_cpu_accessible(resource))
+ {
+ WARN("Resource is not CPU accessible.\n");
+ return E_INVALIDARG;
+ }
+
+ sub_resource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc);
+ if (sub_resource >= sub_resource_count)
+ {
+ WARN("Sub-resource index %u is out of range (%u sub-resources).\n", sub_resource, sub_resource_count);
+ return E_INVALIDARG;
+ }
+
+ if (d3d12_resource_is_texture(resource))
+ {
+ /* Textures seem to be mappable only on UMA adapters. */
+ FIXME("Not implemented for textures.\n");
+ return E_INVALIDARG;
+ }
+
+ if (!resource->heap)
+ {
+ FIXME("Not implemented for this resource type.\n");
+ return E_NOTIMPL;
+ }
+
+ WARN("Ignoring read range %p.\n", read_range);
+
+ if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, resource, data)))
+ WARN("Failed to map resource %p, hr %#x.\n", resource, hr);
+
+ if (data)
+ TRACE("Returning pointer %p.\n", *data);
+
+ return hr;
+}
+
+static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource *iface, UINT sub_resource,
+ const D3D12_RANGE *written_range)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ unsigned int sub_resource_count;
+
+ TRACE("iface %p, sub_resource %u, written_range %p.\n",
+ iface, sub_resource, written_range);
+
+ sub_resource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc);
+ if (sub_resource >= sub_resource_count)
+ {
+ WARN("Sub-resource index %u is out of range (%u sub-resources).\n", sub_resource, sub_resource_count);
+ return;
+ }
+
+ WARN("Ignoring written range %p.\n", written_range);
+
+ d3d12_heap_unmap(resource->heap, resource);
+}
+
+static D3D12_RESOURCE_DESC * STDMETHODCALLTYPE d3d12_resource_GetDesc(ID3D12Resource *iface,
+ D3D12_RESOURCE_DESC *resource_desc)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+
+ TRACE("iface %p, resource_desc %p.\n", iface, resource_desc);
+
+ *resource_desc = resource->desc;
+ return resource_desc;
+}
+
+static D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE d3d12_resource_GetGPUVirtualAddress(ID3D12Resource *iface)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ return resource->gpu_address;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resource *iface,
+ UINT dst_sub_resource, const D3D12_BOX *dst_box, const void *src_data,
+ UINT src_row_pitch, UINT src_slice_pitch)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkImageSubresource vk_sub_resource;
+ const struct vkd3d_format *format;
+ VkSubresourceLayout vk_layout;
+ struct d3d12_device *device;
+ uint8_t *dst_data;
+ D3D12_BOX box;
+ HRESULT hr;
+
+ TRACE("iface %p, src_data %p, src_row_pitch %u, src_slice_pitch %u, "
+ "dst_sub_resource %u, dst_box %s.\n",
+ iface, src_data, src_row_pitch, src_slice_pitch, dst_sub_resource, debug_d3d12_box(dst_box));
+
+ if (d3d12_resource_is_buffer(resource))
+ {
+ WARN("Buffers are not supported.\n");
+ return E_INVALIDARG;
+ }
+
+ device = resource->device;
+ vk_procs = &device->vk_procs;
+
+ if (!(format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, 0)))
+ {
+ ERR("Invalid DXGI format %#x.\n", resource->desc.Format);
+ return E_INVALIDARG;
+ }
+ if (format->vk_aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT)
+ {
+ FIXME("Not supported for format %#x.\n", format->dxgi_format);
+ return E_NOTIMPL;
+ }
+
+ vk_sub_resource.arrayLayer = dst_sub_resource / resource->desc.MipLevels;
+ vk_sub_resource.mipLevel = dst_sub_resource % resource->desc.MipLevels;
+ vk_sub_resource.aspectMask = format->vk_aspect_mask;
+
+ if (!dst_box)
+ {
+ d3d12_resource_get_level_box(resource, vk_sub_resource.mipLevel, &box);
+ dst_box = &box;
+ }
+ else if (!d3d12_resource_validate_box(resource, dst_sub_resource, dst_box))
+ {
+ WARN("Invalid box %s.\n", debug_d3d12_box(dst_box));
+ return E_INVALIDARG;
+ }
+
+ if (d3d12_box_is_empty(dst_box))
+ {
+ WARN("Empty box %s.\n", debug_d3d12_box(dst_box));
+ return S_OK;
+ }
+
+ if (!d3d12_resource_is_cpu_accessible(resource))
+ {
+ FIXME_ONCE("Not implemented for this resource type.\n");
+ return E_NOTIMPL;
+ }
+ if (!(resource->flags & VKD3D_RESOURCE_LINEAR_TILING))
+ {
+ FIXME_ONCE("Not implemented for image tiling other than VK_IMAGE_TILING_LINEAR.\n");
+ return E_NOTIMPL;
+ }
+
+ VK_CALL(vkGetImageSubresourceLayout(device->vk_device, resource->u.vk_image, &vk_sub_resource, &vk_layout));
+ TRACE("Offset %#"PRIx64", size %#"PRIx64", row pitch %#"PRIx64", depth pitch %#"PRIx64".\n",
+ vk_layout.offset, vk_layout.size, vk_layout.rowPitch, vk_layout.depthPitch);
+
+ if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, resource, (void **)&dst_data)))
+ {
+ WARN("Failed to map resource %p, hr %#x.\n", resource, hr);
+ return hr;
+ }
+
+ dst_data += vk_layout.offset + vkd3d_format_get_data_offset(format, vk_layout.rowPitch,
+ vk_layout.depthPitch, dst_box->left, dst_box->top, dst_box->front);
+
+ vkd3d_format_copy_data(format, src_data, src_row_pitch, src_slice_pitch,
+ dst_data, vk_layout.rowPitch, vk_layout.depthPitch, dst_box->right - dst_box->left,
+ dst_box->bottom - dst_box->top, dst_box->back - dst_box->front);
+
+ d3d12_heap_unmap(resource->heap, resource);
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resource *iface,
+ void *dst_data, UINT dst_row_pitch, UINT dst_slice_pitch,
+ UINT src_sub_resource, const D3D12_BOX *src_box)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkImageSubresource vk_sub_resource;
+ const struct vkd3d_format *format;
+ VkSubresourceLayout vk_layout;
+ struct d3d12_device *device;
+ uint8_t *src_data;
+ D3D12_BOX box;
+ HRESULT hr;
+
+ TRACE("iface %p, dst_data %p, dst_row_pitch %u, dst_slice_pitch %u, "
+ "src_sub_resource %u, src_box %s.\n",
+ iface, dst_data, dst_row_pitch, dst_slice_pitch, src_sub_resource, debug_d3d12_box(src_box));
+
+ if (d3d12_resource_is_buffer(resource))
+ {
+ WARN("Buffers are not supported.\n");
+ return E_INVALIDARG;
+ }
+
+ device = resource->device;
+ vk_procs = &device->vk_procs;
+
+ if (!(format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, 0)))
+ {
+ ERR("Invalid DXGI format %#x.\n", resource->desc.Format);
+ return E_INVALIDARG;
+ }
+ if (format->vk_aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT)
+ {
+ FIXME("Not supported for format %#x.\n", format->dxgi_format);
+ return E_NOTIMPL;
+ }
+
+ vk_sub_resource.arrayLayer = src_sub_resource / resource->desc.MipLevels;
+ vk_sub_resource.mipLevel = src_sub_resource % resource->desc.MipLevels;
+ vk_sub_resource.aspectMask = format->vk_aspect_mask;
+
+ if (!src_box)
+ {
+ d3d12_resource_get_level_box(resource, vk_sub_resource.mipLevel, &box);
+ src_box = &box;
+ }
+ else if (!d3d12_resource_validate_box(resource, src_sub_resource, src_box))
+ {
+ WARN("Invalid box %s.\n", debug_d3d12_box(src_box));
+ return E_INVALIDARG;
+ }
+
+ if (d3d12_box_is_empty(src_box))
+ {
+ WARN("Empty box %s.\n", debug_d3d12_box(src_box));
+ return S_OK;
+ }
+
+ if (!d3d12_resource_is_cpu_accessible(resource))
+ {
+ FIXME_ONCE("Not implemented for this resource type.\n");
+ return E_NOTIMPL;
+ }
+ if (!(resource->flags & VKD3D_RESOURCE_LINEAR_TILING))
+ {
+ FIXME_ONCE("Not implemented for image tiling other than VK_IMAGE_TILING_LINEAR.\n");
+ return E_NOTIMPL;
+ }
+
+ VK_CALL(vkGetImageSubresourceLayout(device->vk_device, resource->u.vk_image, &vk_sub_resource, &vk_layout));
+ TRACE("Offset %#"PRIx64", size %#"PRIx64", row pitch %#"PRIx64", depth pitch %#"PRIx64".\n",
+ vk_layout.offset, vk_layout.size, vk_layout.rowPitch, vk_layout.depthPitch);
+
+ if (FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, resource, (void **)&src_data)))
+ {
+ WARN("Failed to map resource %p, hr %#x.\n", resource, hr);
+ return hr;
+ }
+
+ src_data += vk_layout.offset + vkd3d_format_get_data_offset(format, vk_layout.rowPitch,
+ vk_layout.depthPitch, src_box->left, src_box->top, src_box->front);
+
+ vkd3d_format_copy_data(format, src_data, vk_layout.rowPitch, vk_layout.depthPitch,
+ dst_data, dst_row_pitch, dst_slice_pitch, src_box->right - src_box->left,
+ src_box->bottom - src_box->top, src_box->back - src_box->front);
+
+ d3d12_heap_unmap(resource->heap, resource);
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource *iface,
+ D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS *flags)
+{
+ struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_heap *heap;
+
+ TRACE("iface %p, heap_properties %p, flags %p.\n",
+ iface, heap_properties, flags);
+
+ if (resource->flags & VKD3D_RESOURCE_EXTERNAL)
+ {
+ if (heap_properties)
+ {
+ memset(heap_properties, 0, sizeof(*heap_properties));
+ heap_properties->Type = D3D12_HEAP_TYPE_DEFAULT;
+ heap_properties->CreationNodeMask = 1;
+ heap_properties->VisibleNodeMask = 1;
+ }
+ if (flags)
+ *flags = D3D12_HEAP_FLAG_NONE;
+ return S_OK;
+ }
+
+ if (!(heap = resource->heap))
+ {
+ WARN("Cannot get heap properties for reserved resources.\n");
+ return E_INVALIDARG;
+ }
+
+ if (heap_properties)
+ *heap_properties = heap->desc.Properties;
+ if (flags)
+ *flags = heap->desc.Flags;
+
+ return S_OK;
+}
+
+static const struct ID3D12ResourceVtbl d3d12_resource_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_resource_QueryInterface,
+ d3d12_resource_AddRef,
+ d3d12_resource_Release,
+ /* ID3D12Object methods */
+ d3d12_resource_GetPrivateData,
+ d3d12_resource_SetPrivateData,
+ d3d12_resource_SetPrivateDataInterface,
+ d3d12_resource_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_resource_GetDevice,
+ /* ID3D12Resource methods */
+ d3d12_resource_Map,
+ d3d12_resource_Unmap,
+ d3d12_resource_GetDesc,
+ d3d12_resource_GetGPUVirtualAddress,
+ d3d12_resource_WriteToSubresource,
+ d3d12_resource_ReadFromSubresource,
+ d3d12_resource_GetHeapProperties,
+};
+
+struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_resource_vtbl);
+ return impl_from_ID3D12Resource(iface);
+}
+
+static void d3d12_validate_resource_flags(D3D12_RESOURCE_FLAGS flags)
+{
+ unsigned int unknown_flags = flags & ~(D3D12_RESOURCE_FLAG_NONE
+ | D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET
+ | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL
+ | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
+ | D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE
+ | D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER
+ | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
+
+ if (unknown_flags)
+ FIXME("Unknown resource flags %#x.\n", unknown_flags);
+ if (flags & D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER)
+ FIXME("Ignoring D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER.\n");
+}
+
+static bool d3d12_resource_validate_texture_format(const D3D12_RESOURCE_DESC *desc,
+ const struct vkd3d_format *format)
+{
+ if (!vkd3d_format_is_compressed(format))
+ return true;
+
+ if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D && format->block_height > 1)
+ {
+ WARN("1D texture with a format block height > 1.\n");
+ return false;
+ }
+
+ if (align(desc->Width, format->block_width) != desc->Width
+ || align(desc->Height, format->block_height) != desc->Height)
+ {
+ WARN("Invalid size %"PRIu64"x%u for block compressed format %#x.\n",
+ desc->Width, desc->Height, desc->Format);
+ return false;
+ }
+
+ return true;
+}
+
+static bool d3d12_resource_validate_texture_alignment(const D3D12_RESOURCE_DESC *desc,
+ const struct vkd3d_format *format)
+{
+ uint64_t estimated_size;
+
+ if (!desc->Alignment)
+ return true;
+
+ if (desc->Alignment != D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT
+ && desc->Alignment != D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT
+ && (desc->SampleDesc.Count == 1 || desc->Alignment != D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT))
+ {
+ WARN("Invalid resource alignment %#"PRIx64".\n", desc->Alignment);
+ return false;
+ }
+
+ if (desc->Alignment < D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT)
+ {
+ /* Windows uses the slice size to determine small alignment eligibility. DepthOrArraySize is ignored. */
+ estimated_size = desc->Width * desc->Height * format->byte_count * format->block_byte_count
+ / (format->block_width * format->block_height);
+ if (estimated_size > D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT)
+ {
+ WARN("Invalid resource alignment %#"PRIx64" (required %#x).\n",
+ desc->Alignment, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT);
+ return false;
+ }
+ }
+
+ /* The size check for MSAA textures with D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT is probably
+ * not important. The 4MB requirement is no longer universal and Vulkan has no such requirement. */
+
+ return true;
+}
+
+HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device)
+{
+ const struct vkd3d_format *format;
+
+ switch (desc->Dimension)
+ {
+ case D3D12_RESOURCE_DIMENSION_BUFFER:
+ if (desc->MipLevels != 1)
+ {
+ WARN("Invalid miplevel count %u for buffer.\n", desc->MipLevels);
+ return E_INVALIDARG;
+ }
+
+ if (desc->Format != DXGI_FORMAT_UNKNOWN || desc->Layout != D3D12_TEXTURE_LAYOUT_ROW_MAJOR
+ || desc->Height != 1 || desc->DepthOrArraySize != 1
+ || desc->SampleDesc.Count != 1 || desc->SampleDesc.Quality != 0
+ || (desc->Alignment != 0 && desc->Alignment != D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT))
+ {
+ WARN("Invalid parameters for a buffer resource.\n");
+ return E_INVALIDARG;
+ }
+ break;
+
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
+ if (desc->Height != 1)
+ {
+ WARN("1D texture with a height of %u.\n", desc->Height);
+ return E_INVALIDARG;
+ }
+ /* Fall through. */
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
+ if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0)))
+ {
+ WARN("Invalid format %#x.\n", desc->Format);
+ return E_INVALIDARG;
+ }
+
+ if (!d3d12_resource_validate_texture_format(desc, format)
+ || !d3d12_resource_validate_texture_alignment(desc, format))
+ return E_INVALIDARG;
+ break;
+
+ default:
+ WARN("Invalid resource dimension %#x.\n", desc->Dimension);
+ return E_INVALIDARG;
+ }
+
+ d3d12_validate_resource_flags(desc->Flags);
+
+ return S_OK;
+}
+
+static bool d3d12_resource_validate_heap_properties(const struct d3d12_resource *resource,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_RESOURCE_STATES initial_state)
+{
+ if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD
+ || heap_properties->Type == D3D12_HEAP_TYPE_READBACK)
+ {
+ if (d3d12_resource_is_texture(resource))
+ {
+ WARN("Textures cannot be created on upload/readback heaps.\n");
+ return false;
+ }
+
+ if (resource->desc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS))
+ {
+ WARN("Render target and unordered access buffers cannot be created on upload/readback heaps.\n");
+ return false;
+ }
+ }
+
+ if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD && initial_state != D3D12_RESOURCE_STATE_GENERIC_READ)
+ {
+ WARN("For D3D12_HEAP_TYPE_UPLOAD the state must be D3D12_RESOURCE_STATE_GENERIC_READ.\n");
+ return false;
+ }
+ if (heap_properties->Type == D3D12_HEAP_TYPE_READBACK && initial_state != D3D12_RESOURCE_STATE_COPY_DEST)
+ {
+ WARN("For D3D12_HEAP_TYPE_READBACK the state must be D3D12_RESOURCE_STATE_COPY_DEST.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12_device *device,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value)
+{
+ HRESULT hr;
+
+ resource->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
+ resource->refcount = 1;
+ resource->internal_refcount = 1;
+
+ resource->desc = *desc;
+
+ if (heap_properties && !d3d12_resource_validate_heap_properties(resource, heap_properties, initial_state))
+ return E_INVALIDARG;
+
+ if (!is_valid_resource_state(initial_state))
+ {
+ WARN("Invalid initial resource state %#x.\n", initial_state);
+ return E_INVALIDARG;
+ }
+
+ if (optimized_clear_value && d3d12_resource_is_buffer(resource))
+ {
+ WARN("Optimized clear value must be NULL for buffers.\n");
+ return E_INVALIDARG;
+ }
+
+ if (optimized_clear_value)
+ WARN("Ignoring optimized clear value.\n");
+
+ resource->gpu_address = 0;
+ resource->flags = 0;
+
+ if (FAILED(hr = d3d12_resource_validate_desc(&resource->desc, device)))
+ return hr;
+
+ switch (desc->Dimension)
+ {
+ case D3D12_RESOURCE_DIMENSION_BUFFER:
+ if (FAILED(hr = vkd3d_create_buffer(device, heap_properties, heap_flags,
+ &resource->desc, &resource->u.vk_buffer)))
+ return hr;
+ if (!(resource->gpu_address = vkd3d_gpu_va_allocator_allocate(&device->gpu_va_allocator,
+ desc->Alignment ? desc->Alignment : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
+ desc->Width, resource)))
+ {
+ ERR("Failed to allocate GPU VA.\n");
+ d3d12_resource_destroy(resource, device);
+ return E_OUTOFMEMORY;
+ }
+ break;
+
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
+ if (!resource->desc.MipLevels)
+ resource->desc.MipLevels = max_miplevel_count(desc);
+ resource->flags |= VKD3D_RESOURCE_INITIAL_STATE_TRANSITION;
+ if (FAILED(hr = vkd3d_create_image(device, heap_properties, heap_flags,
+ &resource->desc, resource, &resource->u.vk_image)))
+ return hr;
+ break;
+
+ default:
+ WARN("Invalid resource dimension %#x.\n", resource->desc.Dimension);
+ return E_INVALIDARG;
+ }
+
+ resource->map_count = 0;
+
+ resource->initial_state = initial_state;
+
+ resource->heap = NULL;
+ resource->heap_offset = 0;
+
+ if (FAILED(hr = vkd3d_private_store_init(&resource->private_store)))
+ {
+ d3d12_resource_destroy(resource, device);
+ return hr;
+ }
+
+ d3d12_device_add_ref(resource->device = device);
+
+ return S_OK;
+}
+
+static HRESULT d3d12_resource_create(struct d3d12_device *device,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
+{
+ struct d3d12_resource *object;
+ HRESULT hr;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_resource_init(object, device, heap_properties, heap_flags,
+ desc, initial_state, optimized_clear_value)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ *resource = object;
+
+ return hr;
+}
+
+static HRESULT vkd3d_allocate_resource_memory(
+ struct d3d12_device *device, struct d3d12_resource *resource,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags)
+{
+ D3D12_HEAP_DESC heap_desc;
+ HRESULT hr;
+
+ heap_desc.SizeInBytes = 0;
+ heap_desc.Properties = *heap_properties;
+ heap_desc.Alignment = 0;
+ heap_desc.Flags = heap_flags;
+ if (SUCCEEDED(hr = d3d12_heap_create(device, &heap_desc, resource, &resource->heap)))
+ resource->flags |= VKD3D_RESOURCE_DEDICATED_HEAP;
+ return hr;
+}
+
+HRESULT d3d12_committed_resource_create(struct d3d12_device *device,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
+{
+ struct d3d12_resource *object;
+ HRESULT hr;
+
+ if (!heap_properties)
+ {
+ WARN("Heap properties are NULL.\n");
+ return E_INVALIDARG;
+ }
+
+ if (FAILED(hr = d3d12_resource_create(device, heap_properties, heap_flags,
+ desc, initial_state, optimized_clear_value, &object)))
+ return hr;
+
+ if (FAILED(hr = vkd3d_allocate_resource_memory(device, object, heap_properties, heap_flags)))
+ {
+ d3d12_resource_Release(&object->ID3D12Resource_iface);
+ return hr;
+ }
+
+ TRACE("Created committed resource %p.\n", object);
+
+ *resource = object;
+
+ return S_OK;
+}
+
+static HRESULT vkd3d_bind_heap_memory(struct d3d12_device *device,
+ struct d3d12_resource *resource, struct d3d12_heap *heap, uint64_t heap_offset)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkDevice vk_device = device->vk_device;
+ VkMemoryRequirements requirements;
+ VkResult vr;
+
+ if (d3d12_resource_is_buffer(resource))
+ VK_CALL(vkGetBufferMemoryRequirements(vk_device, resource->u.vk_buffer, &requirements));
+ else
+ VK_CALL(vkGetImageMemoryRequirements(vk_device, resource->u.vk_image, &requirements));
+
+ if (heap_offset % requirements.alignment)
+ {
+ FIXME("Invalid heap offset %#"PRIx64" (alignment %#"PRIx64").\n",
+ heap_offset, requirements.alignment);
+ goto allocate_memory;
+ }
+
+ if (!(requirements.memoryTypeBits & (1u << heap->vk_memory_type)))
+ {
+ FIXME("Memory type %u cannot be bound to resource %p (allowed types %#x).\n",
+ heap->vk_memory_type, resource, requirements.memoryTypeBits);
+ goto allocate_memory;
+ }
+
+ if (d3d12_resource_is_buffer(resource))
+ vr = VK_CALL(vkBindBufferMemory(vk_device, resource->u.vk_buffer, heap->vk_memory, heap_offset));
+ else
+ vr = VK_CALL(vkBindImageMemory(vk_device, resource->u.vk_image, heap->vk_memory, heap_offset));
+
+ if (vr == VK_SUCCESS)
+ {
+ resource->heap = heap;
+ resource->heap_offset = heap_offset;
+ }
+ else
+ {
+ WARN("Failed to bind memory, vr %d.\n", vr);
+ }
+
+ return hresult_from_vk_result(vr);
+
+allocate_memory:
+ FIXME("Allocating device memory.\n");
+ return vkd3d_allocate_resource_memory(device, resource, &heap->desc.Properties, heap->desc.Flags);
+}
+
+HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_heap *heap, uint64_t heap_offset,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
+{
+ struct d3d12_resource *object;
+ HRESULT hr;
+
+ if (FAILED(hr = d3d12_resource_create(device, &heap->desc.Properties, heap->desc.Flags,
+ desc, initial_state, optimized_clear_value, &object)))
+ return hr;
+
+ if (FAILED(hr = vkd3d_bind_heap_memory(device, object, heap, heap_offset)))
+ {
+ d3d12_resource_Release(&object->ID3D12Resource_iface);
+ return hr;
+ }
+
+ TRACE("Created placed resource %p.\n", object);
+
+ *resource = object;
+
+ return S_OK;
+}
+
+HRESULT d3d12_reserved_resource_create(struct d3d12_device *device,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
+{
+ struct d3d12_resource *object;
+ HRESULT hr;
+
+ if (FAILED(hr = d3d12_resource_create(device, NULL, 0,
+ desc, initial_state, optimized_clear_value, &object)))
+ return hr;
+
+ TRACE("Created reserved resource %p.\n", object);
+
+ *resource = object;
+
+ return S_OK;
+}
+
+HRESULT vkd3d_create_image_resource(ID3D12Device *device,
+ const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource)
+{
+ struct d3d12_device *d3d12_device = unsafe_impl_from_ID3D12Device(device);
+ struct d3d12_resource *object;
+ HRESULT hr;
+
+ TRACE("device %p, create_info %p, resource %p.\n", device, create_info, resource);
+
+ if (!create_info || !resource)
+ return E_INVALIDARG;
+ if (create_info->type != VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO)
+ {
+ WARN("Invalid structure type %#x.\n", create_info->type);
+ return E_INVALIDARG;
+ }
+ if (create_info->next)
+ WARN("Unhandled next %p.\n", create_info->next);
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ memset(object, 0, sizeof(*object));
+
+ object->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
+ object->refcount = 1;
+ object->internal_refcount = 1;
+ object->desc = create_info->desc;
+ object->u.vk_image = create_info->vk_image;
+ object->flags = VKD3D_RESOURCE_EXTERNAL;
+ object->flags |= create_info->flags & VKD3D_RESOURCE_PUBLIC_FLAGS;
+ object->initial_state = D3D12_RESOURCE_STATE_COMMON;
+ if (create_info->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION)
+ object->present_state = create_info->present_state;
+ else
+ object->present_state = D3D12_RESOURCE_STATE_COMMON;
+
+ if (FAILED(hr = vkd3d_private_store_init(&object->private_store)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ d3d12_device_add_ref(object->device = d3d12_device);
+
+ TRACE("Created resource %p.\n", object);
+
+ *resource = &object->ID3D12Resource_iface;
+
+ return S_OK;
+}
+
+ULONG vkd3d_resource_incref(ID3D12Resource *resource)
+{
+ TRACE("resource %p.\n", resource);
+ return d3d12_resource_incref(impl_from_ID3D12Resource(resource));
+}
+
+ULONG vkd3d_resource_decref(ID3D12Resource *resource)
+{
+ TRACE("resource %p.\n", resource);
+ return d3d12_resource_decref(impl_from_ID3D12Resource(resource));
+}
+
+/* CBVs, SRVs, UAVs */
+static struct vkd3d_view *vkd3d_view_create(enum vkd3d_view_type type)
+{
+ struct vkd3d_view *view;
+
+ if ((view = vkd3d_malloc(sizeof(*view))))
+ {
+ view->refcount = 1;
+ view->type = type;
+ view->vk_counter_view = VK_NULL_HANDLE;
+ }
+ return view;
+}
+
+void vkd3d_view_incref(struct vkd3d_view *view)
+{
+ InterlockedIncrement(&view->refcount);
+}
+
+static void vkd3d_view_destroy(struct vkd3d_view *view, struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ TRACE("Destroying view %p.\n", view);
+
+ switch (view->type)
+ {
+ case VKD3D_VIEW_TYPE_BUFFER:
+ VK_CALL(vkDestroyBufferView(device->vk_device, view->u.vk_buffer_view, NULL));
+ break;
+ case VKD3D_VIEW_TYPE_IMAGE:
+ VK_CALL(vkDestroyImageView(device->vk_device, view->u.vk_image_view, NULL));
+ break;
+ case VKD3D_VIEW_TYPE_SAMPLER:
+ VK_CALL(vkDestroySampler(device->vk_device, view->u.vk_sampler, NULL));
+ break;
+ default:
+ WARN("Unhandled view type %d.\n", view->type);
+ }
+
+ if (view->vk_counter_view)
+ VK_CALL(vkDestroyBufferView(device->vk_device, view->vk_counter_view, NULL));
+
+ vkd3d_free(view);
+}
+
+void vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device)
+{
+ if (!InterlockedDecrement(&view->refcount))
+ vkd3d_view_destroy(view, device);
+}
+
+void d3d12_desc_write_atomic(struct d3d12_desc *dst, const struct d3d12_desc *src,
+ struct d3d12_device *device)
+{
+ struct d3d12_desc destroy_desc;
+ pthread_mutex_t *mutex;
+
+ destroy_desc.u.view = NULL;
+
+ mutex = d3d12_device_get_descriptor_mutex(device, dst);
+ pthread_mutex_lock(mutex);
+
+ /* Nothing to do for VKD3D_DESCRIPTOR_MAGIC_CBV. */
+ if ((dst->magic == VKD3D_DESCRIPTOR_MAGIC_SRV
+ || dst->magic == VKD3D_DESCRIPTOR_MAGIC_UAV
+ || dst->magic == VKD3D_DESCRIPTOR_MAGIC_SAMPLER)
+ && !InterlockedDecrement(&dst->u.view->refcount))
+ destroy_desc = *dst;
+
+ *dst = *src;
+
+ pthread_mutex_unlock(mutex);
+
+ /* Destroy the view after unlocking to reduce wait time. */
+ if (destroy_desc.u.view)
+ vkd3d_view_destroy(destroy_desc.u.view, device);
+}
+
+static void d3d12_desc_destroy(struct d3d12_desc *descriptor, struct d3d12_device *device)
+{
+ static const struct d3d12_desc null_desc = {0};
+
+ d3d12_desc_write_atomic(descriptor, &null_desc, device);
+}
+
+void d3d12_desc_copy(struct d3d12_desc *dst, const struct d3d12_desc *src,
+ struct d3d12_device *device)
+{
+ struct d3d12_desc tmp;
+ pthread_mutex_t *mutex;
+
+ assert(dst != src);
+
+ /* Shadow of the Tomb Raider and possibly other titles sometimes destroy
+ * and rewrite a descriptor in another thread while it is being copied. */
+ mutex = d3d12_device_get_descriptor_mutex(device, src);
+ pthread_mutex_lock(mutex);
+
+ if (src->magic == VKD3D_DESCRIPTOR_MAGIC_SRV
+ || src->magic == VKD3D_DESCRIPTOR_MAGIC_UAV
+ || src->magic == VKD3D_DESCRIPTOR_MAGIC_SAMPLER)
+ {
+ vkd3d_view_incref(src->u.view);
+ }
+
+ tmp = *src;
+
+ pthread_mutex_unlock(mutex);
+
+ d3d12_desc_write_atomic(dst, &tmp, device);
+}
+
+static VkDeviceSize vkd3d_get_required_texel_buffer_alignment(const struct d3d12_device *device,
+ const struct vkd3d_format *format)
+{
+ const VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *properties;
+ const struct vkd3d_vulkan_info *vk_info = &device->vk_info;
+ VkDeviceSize alignment;
+
+ if (vk_info->EXT_texel_buffer_alignment)
+ {
+ properties = &vk_info->texel_buffer_alignment_properties;
+
+ alignment = max(properties->storageTexelBufferOffsetAlignmentBytes,
+ properties->uniformTexelBufferOffsetAlignmentBytes);
+
+ if (properties->storageTexelBufferOffsetSingleTexelAlignment
+ && properties->uniformTexelBufferOffsetSingleTexelAlignment)
+ {
+ assert(!vkd3d_format_is_compressed(format));
+ return min(format->byte_count, alignment);
+ }
+
+ return alignment;
+ }
+
+ return vk_info->device_limits.minTexelBufferOffsetAlignment;
+}
+
+static bool vkd3d_create_vk_buffer_view(struct d3d12_device *device,
+ VkBuffer vk_buffer, const struct vkd3d_format *format,
+ VkDeviceSize offset, VkDeviceSize range, VkBufferView *vk_view)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct VkBufferViewCreateInfo view_desc;
+ VkDeviceSize alignment;
+ VkResult vr;
+
+ if (vkd3d_format_is_compressed(format))
+ {
+ WARN("Invalid format for buffer view %#x.\n", format->dxgi_format);
+ return false;
+ }
+
+ alignment = vkd3d_get_required_texel_buffer_alignment(device, format);
+ if (offset % alignment)
+ FIXME("Offset %#"PRIx64" violates the required alignment %#"PRIx64".\n", offset, alignment);
+
+ view_desc.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
+ view_desc.pNext = NULL;
+ view_desc.flags = 0;
+ view_desc.buffer = vk_buffer;
+ view_desc.format = format->vk_format;
+ view_desc.offset = offset;
+ view_desc.range = range;
+ if ((vr = VK_CALL(vkCreateBufferView(device->vk_device, &view_desc, NULL, vk_view))) < 0)
+ WARN("Failed to create Vulkan buffer view, vr %d.\n", vr);
+ return vr == VK_SUCCESS;
+}
+
+bool vkd3d_create_buffer_view(struct d3d12_device *device, VkBuffer vk_buffer, const struct vkd3d_format *format,
+ VkDeviceSize offset, VkDeviceSize size, struct vkd3d_view **view)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_view *object;
+ VkBufferView vk_view;
+
+ if (!vkd3d_create_vk_buffer_view(device, vk_buffer, format, offset, size, &vk_view))
+ return false;
+
+ if (!(object = vkd3d_view_create(VKD3D_VIEW_TYPE_BUFFER)))
+ {
+ VK_CALL(vkDestroyBufferView(device->vk_device, vk_view, NULL));
+ return false;
+ }
+
+ object->u.vk_buffer_view = vk_view;
+ object->format = format;
+ object->info.buffer.offset = offset;
+ object->info.buffer.size = size;
+ *view = object;
+ return true;
+}
+
+#define VKD3D_VIEW_RAW_BUFFER 0x1
+
+static bool vkd3d_create_buffer_view_for_resource(struct d3d12_device *device,
+ struct d3d12_resource *resource, DXGI_FORMAT view_format,
+ unsigned int offset, unsigned int size, unsigned int structure_stride,
+ unsigned int flags, struct vkd3d_view **view)
+{
+ const struct vkd3d_format *format;
+ VkDeviceSize element_size;
+
+ if (view_format == DXGI_FORMAT_R32_TYPELESS && (flags & VKD3D_VIEW_RAW_BUFFER))
+ {
+ format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
+ element_size = format->byte_count;
+ }
+ else if (view_format == DXGI_FORMAT_UNKNOWN && structure_stride)
+ {
+ format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
+ element_size = structure_stride;
+ }
+ else if ((format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, view_format)))
+ {
+ element_size = format->byte_count;
+ }
+ else
+ {
+ WARN("Failed to find format for %#x.\n", resource->desc.Format);
+ return false;
+ }
+
+ assert(d3d12_resource_is_buffer(resource));
+
+ return vkd3d_create_buffer_view(device, resource->u.vk_buffer,
+ format, offset * element_size, size * element_size, view);
+}
+
+static void vkd3d_set_view_swizzle_for_format(VkComponentMapping *components,
+ const struct vkd3d_format *format, bool allowed_swizzle)
+{
+ components->r = VK_COMPONENT_SWIZZLE_R;
+ components->g = VK_COMPONENT_SWIZZLE_G;
+ components->b = VK_COMPONENT_SWIZZLE_B;
+ components->a = VK_COMPONENT_SWIZZLE_A;
+
+ if (format->vk_aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT)
+ {
+ if (allowed_swizzle)
+ {
+ components->r = VK_COMPONENT_SWIZZLE_ZERO;
+ components->g = VK_COMPONENT_SWIZZLE_R;
+ components->b = VK_COMPONENT_SWIZZLE_ZERO;
+ components->a = VK_COMPONENT_SWIZZLE_ZERO;
+ }
+ else
+ {
+ FIXME("Stencil swizzle is not supported for format %#x.\n",
+ format->dxgi_format);
+ }
+ }
+
+ if (format->dxgi_format == DXGI_FORMAT_A8_UNORM)
+ {
+ if (allowed_swizzle)
+ {
+ components->r = VK_COMPONENT_SWIZZLE_ZERO;
+ components->g = VK_COMPONENT_SWIZZLE_ZERO;
+ components->b = VK_COMPONENT_SWIZZLE_ZERO;
+ components->a = VK_COMPONENT_SWIZZLE_R;
+ }
+ else
+ {
+ FIXME("Alpha swizzle is not supported.\n");
+ }
+ }
+
+ if (format->dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM
+ || format->dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM_SRGB)
+ {
+ if (allowed_swizzle)
+ {
+ components->r = VK_COMPONENT_SWIZZLE_R;
+ components->g = VK_COMPONENT_SWIZZLE_G;
+ components->b = VK_COMPONENT_SWIZZLE_B;
+ components->a = VK_COMPONENT_SWIZZLE_ONE;
+ }
+ else
+ {
+ FIXME("B8G8R8X8 swizzle is not supported.\n");
+ }
+ }
+}
+
+static VkComponentSwizzle vk_component_swizzle_from_d3d12(unsigned int component_mapping,
+ unsigned int component_index)
+{
+ D3D12_SHADER_COMPONENT_MAPPING mapping
+ = D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(component_index, component_mapping);
+
+ switch (mapping)
+ {
+ case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0:
+ return VK_COMPONENT_SWIZZLE_R;
+ case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1:
+ return VK_COMPONENT_SWIZZLE_G;
+ case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2:
+ return VK_COMPONENT_SWIZZLE_B;
+ case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3:
+ return VK_COMPONENT_SWIZZLE_A;
+ case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0:
+ return VK_COMPONENT_SWIZZLE_ZERO;
+ case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1:
+ return VK_COMPONENT_SWIZZLE_ONE;
+ }
+
+ FIXME("Invalid component mapping %#x.\n", mapping);
+ return VK_COMPONENT_SWIZZLE_IDENTITY;
+}
+
+static void vk_component_mapping_from_d3d12(VkComponentMapping *components,
+ unsigned int component_mapping)
+{
+ components->r = vk_component_swizzle_from_d3d12(component_mapping, 0);
+ components->g = vk_component_swizzle_from_d3d12(component_mapping, 1);
+ components->b = vk_component_swizzle_from_d3d12(component_mapping, 2);
+ components->a = vk_component_swizzle_from_d3d12(component_mapping, 3);
+}
+
+static VkComponentSwizzle swizzle_vk_component(const VkComponentMapping *components,
+ VkComponentSwizzle component, VkComponentSwizzle swizzle)
+{
+ switch (swizzle)
+ {
+ case VK_COMPONENT_SWIZZLE_IDENTITY:
+ break;
+
+ case VK_COMPONENT_SWIZZLE_R:
+ component = components->r;
+ break;
+
+ case VK_COMPONENT_SWIZZLE_G:
+ component = components->g;
+ break;
+
+ case VK_COMPONENT_SWIZZLE_B:
+ component = components->b;
+ break;
+
+ case VK_COMPONENT_SWIZZLE_A:
+ component = components->a;
+ break;
+
+ case VK_COMPONENT_SWIZZLE_ONE:
+ case VK_COMPONENT_SWIZZLE_ZERO:
+ component = swizzle;
+ break;
+
+ default:
+ FIXME("Invalid component swizzle %#x.\n", swizzle);
+ break;
+ }
+
+ assert(component != VK_COMPONENT_SWIZZLE_IDENTITY);
+ return component;
+}
+
+static void vk_component_mapping_compose(VkComponentMapping *dst, const VkComponentMapping *b)
+{
+ const VkComponentMapping a = *dst;
+
+ dst->r = swizzle_vk_component(&a, a.r, b->r);
+ dst->g = swizzle_vk_component(&a, a.g, b->g);
+ dst->b = swizzle_vk_component(&a, a.b, b->b);
+ dst->a = swizzle_vk_component(&a, a.a, b->a);
+}
+
+static bool init_default_texture_view_desc(struct vkd3d_texture_view_desc *desc,
+ struct d3d12_resource *resource, DXGI_FORMAT view_format)
+{
+ const struct d3d12_device *device = resource->device;
+
+ if (!(desc->format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, view_format)))
+ {
+ FIXME("Failed to find format (resource format %#x, view format %#x).\n",
+ resource->desc.Format, view_format);
+ return false;
+ }
+
+ desc->miplevel_idx = 0;
+ desc->miplevel_count = 1;
+ desc->layer_idx = 0;
+ desc->layer_count = d3d12_resource_desc_get_layer_count(&resource->desc);
+
+ switch (resource->desc.Dimension)
+ {
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
+ desc->view_type = resource->desc.DepthOrArraySize > 1
+ ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D;
+ break;
+
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
+ desc->view_type = resource->desc.DepthOrArraySize > 1
+ ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
+ break;
+
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
+ desc->view_type = VK_IMAGE_VIEW_TYPE_3D;
+ desc->layer_count = 1;
+ break;
+
+ default:
+ FIXME("Resource dimension %#x not implemented.\n", resource->desc.Dimension);
+ return false;
+ }
+
+ desc->components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
+ desc->components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
+ desc->components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
+ desc->components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+ desc->allowed_swizzle = false;
+ return true;
+}
+
+bool vkd3d_create_texture_view(struct d3d12_device *device, VkImage vk_image,
+ const struct vkd3d_texture_view_desc *desc, struct vkd3d_view **view)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ const struct vkd3d_format *format = desc->format;
+ struct VkImageViewCreateInfo view_desc;
+ struct vkd3d_view *object;
+ VkImageView vk_view;
+ VkResult vr;
+
+ view_desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ view_desc.pNext = NULL;
+ view_desc.flags = 0;
+ view_desc.image = vk_image;
+ view_desc.viewType = desc->view_type;
+ view_desc.format = format->vk_format;
+ vkd3d_set_view_swizzle_for_format(&view_desc.components, format, desc->allowed_swizzle);
+ if (desc->allowed_swizzle)
+ vk_component_mapping_compose(&view_desc.components, &desc->components);
+ view_desc.subresourceRange.aspectMask = format->vk_aspect_mask;
+ view_desc.subresourceRange.baseMipLevel = desc->miplevel_idx;
+ view_desc.subresourceRange.levelCount = desc->miplevel_count;
+ view_desc.subresourceRange.baseArrayLayer = desc->layer_idx;
+ view_desc.subresourceRange.layerCount = desc->layer_count;
+ if ((vr = VK_CALL(vkCreateImageView(device->vk_device, &view_desc, NULL, &vk_view))) < 0)
+ {
+ WARN("Failed to create Vulkan image view, vr %d.\n", vr);
+ return false;
+ }
+
+ if (!(object = vkd3d_view_create(VKD3D_VIEW_TYPE_IMAGE)))
+ {
+ VK_CALL(vkDestroyImageView(device->vk_device, vk_view, NULL));
+ return false;
+ }
+
+ object->u.vk_image_view = vk_view;
+ object->format = format;
+ object->info.texture.vk_view_type = desc->view_type;
+ object->info.texture.miplevel_idx = desc->miplevel_idx;
+ object->info.texture.layer_idx = desc->layer_idx;
+ object->info.texture.layer_count = desc->layer_count;
+ *view = object;
+ return true;
+}
+
+void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
+ struct d3d12_device *device, const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc)
+{
+ struct VkDescriptorBufferInfo *buffer_info;
+ struct d3d12_resource *resource;
+
+ if (!desc)
+ {
+ WARN("Constant buffer desc is NULL.\n");
+ return;
+ }
+
+ if (desc->SizeInBytes & (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1))
+ {
+ WARN("Size is not %u bytes aligned.\n", D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
+ return;
+ }
+
+ buffer_info = &descriptor->u.vk_cbv_info;
+ if (desc->BufferLocation)
+ {
+ resource = vkd3d_gpu_va_allocator_dereference(&device->gpu_va_allocator, desc->BufferLocation);
+ buffer_info->buffer = resource->u.vk_buffer;
+ buffer_info->offset = desc->BufferLocation - resource->gpu_address;
+ buffer_info->range = min(desc->SizeInBytes, resource->desc.Width - buffer_info->offset);
+ }
+ else
+ {
+ /* NULL descriptor */
+ buffer_info->buffer = device->null_resources.vk_buffer;
+ buffer_info->offset = 0;
+ buffer_info->range = VKD3D_NULL_BUFFER_SIZE;
+ }
+
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_CBV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+}
+
+static unsigned int vkd3d_view_flags_from_d3d12_buffer_srv_flags(D3D12_BUFFER_SRV_FLAGS flags)
+{
+ if (flags == D3D12_BUFFER_SRV_FLAG_RAW)
+ return VKD3D_VIEW_RAW_BUFFER;
+ if (flags)
+ FIXME("Unhandled buffer SRV flags %#x.\n", flags);
+ return 0;
+}
+
+static void vkd3d_create_null_srv(struct d3d12_desc *descriptor,
+ struct d3d12_device *device, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc)
+{
+ struct vkd3d_null_resources *null_resources = &device->null_resources;
+ struct vkd3d_texture_view_desc vkd3d_desc;
+ struct vkd3d_view *view;
+ VkImage vk_image;
+
+ if (!desc)
+ {
+ WARN("D3D12_SHADER_RESOURCE_VIEW_DESC is required for NULL view.\n");
+ return;
+ }
+
+ switch (desc->ViewDimension)
+ {
+ case D3D12_SRV_DIMENSION_BUFFER:
+ WARN("Creating NULL buffer SRV %#x.\n", desc->Format);
+
+ if (vkd3d_create_buffer_view(device, null_resources->vk_buffer,
+ vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false),
+ 0, VKD3D_NULL_BUFFER_SIZE, &view))
+ {
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ descriptor->u.view = view;
+ }
+ return;
+
+ case D3D12_SRV_DIMENSION_TEXTURE2D:
+ vk_image = null_resources->vk_2d_image;
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
+ break;
+ case D3D12_SRV_DIMENSION_TEXTURE2DARRAY:
+ vk_image = null_resources->vk_2d_image;
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ break;
+
+ default:
+ FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
+ return;
+ }
+
+ WARN("Creating NULL SRV %#x.\n", desc->ViewDimension);
+
+ vkd3d_desc.format = vkd3d_get_format(device, VKD3D_NULL_VIEW_FORMAT, false);
+ vkd3d_desc.miplevel_idx = 0;
+ vkd3d_desc.miplevel_count = 1;
+ vkd3d_desc.layer_idx = 0;
+ vkd3d_desc.layer_count = 1;
+ vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_ZERO;
+ vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_ZERO;
+ vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_ZERO;
+ vkd3d_desc.components.a = VK_COMPONENT_SWIZZLE_ZERO;
+ vkd3d_desc.allowed_swizzle = true;
+
+ if (!vkd3d_create_texture_view(device, vk_image, &vkd3d_desc, &view))
+ return;
+
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ descriptor->u.view = view;
+}
+
+static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
+ struct d3d12_device *device, struct d3d12_resource *resource,
+ const D3D12_SHADER_RESOURCE_VIEW_DESC *desc)
+{
+ struct vkd3d_view *view;
+ unsigned int flags;
+
+ if (!desc)
+ {
+ FIXME("Default SRV views not supported.\n");
+ return;
+ }
+
+ if (desc->ViewDimension != D3D12_SRV_DIMENSION_BUFFER)
+ {
+ WARN("Unexpected view dimension %#x.\n", desc->ViewDimension);
+ return;
+ }
+
+ flags = vkd3d_view_flags_from_d3d12_buffer_srv_flags(desc->u.Buffer.Flags);
+ if (!vkd3d_create_buffer_view_for_resource(device, resource, desc->Format,
+ desc->u.Buffer.FirstElement, desc->u.Buffer.NumElements,
+ desc->u.Buffer.StructureByteStride, flags, &view))
+ return;
+
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ descriptor->u.view = view;
+}
+
+void d3d12_desc_create_srv(struct d3d12_desc *descriptor,
+ struct d3d12_device *device, struct d3d12_resource *resource,
+ const D3D12_SHADER_RESOURCE_VIEW_DESC *desc)
+{
+ struct vkd3d_texture_view_desc vkd3d_desc;
+ struct vkd3d_view *view;
+
+ if (!resource)
+ {
+ vkd3d_create_null_srv(descriptor, device, desc);
+ return;
+ }
+
+ if (d3d12_resource_is_buffer(resource))
+ {
+ vkd3d_create_buffer_srv(descriptor, device, resource, desc);
+ return;
+ }
+
+ if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
+ return;
+
+ vkd3d_desc.miplevel_count = VK_REMAINING_MIP_LEVELS;
+ vkd3d_desc.allowed_swizzle = true;
+
+ if (desc)
+ {
+ if (desc->Shader4ComponentMapping != D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING)
+ {
+ TRACE("Component mapping %s for format %#x.\n",
+ debug_d3d12_shader_component_mapping(desc->Shader4ComponentMapping), desc->Format);
+
+ vk_component_mapping_from_d3d12(&vkd3d_desc.components, desc->Shader4ComponentMapping);
+ }
+
+ switch (desc->ViewDimension)
+ {
+ case D3D12_SRV_DIMENSION_TEXTURE2D:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
+ vkd3d_desc.miplevel_idx = desc->u.Texture2D.MostDetailedMip;
+ vkd3d_desc.miplevel_count = desc->u.Texture2D.MipLevels;
+ if (desc->u.Texture2D.PlaneSlice)
+ FIXME("Ignoring plane slice %u.\n", desc->u.Texture2D.PlaneSlice);
+ if (desc->u.Texture2D.ResourceMinLODClamp)
+ FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.Texture2D.ResourceMinLODClamp);
+ break;
+ case D3D12_SRV_DIMENSION_TEXTURE2DARRAY:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.miplevel_idx = desc->u.Texture2DArray.MostDetailedMip;
+ vkd3d_desc.miplevel_count = desc->u.Texture2DArray.MipLevels;
+ vkd3d_desc.layer_idx = desc->u.Texture2DArray.FirstArraySlice;
+ vkd3d_desc.layer_count = desc->u.Texture2DArray.ArraySize;
+ if (desc->u.Texture2DArray.PlaneSlice)
+ FIXME("Ignoring plane slice %u.\n", desc->u.Texture2DArray.PlaneSlice);
+ if (desc->u.Texture2DArray.ResourceMinLODClamp)
+ FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.Texture2DArray.ResourceMinLODClamp);
+ break;
+ case D3D12_SRV_DIMENSION_TEXTURE2DMS:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
+ break;
+ case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.layer_idx = desc->u.Texture2DMSArray.FirstArraySlice;
+ vkd3d_desc.layer_count = desc->u.Texture2DMSArray.ArraySize;
+ break;
+ case D3D12_SRV_DIMENSION_TEXTURE3D:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_3D;
+ vkd3d_desc.miplevel_idx = desc->u.Texture3D.MostDetailedMip;
+ vkd3d_desc.miplevel_count = desc->u.Texture3D.MipLevels;
+ if (desc->u.Texture3D.ResourceMinLODClamp)
+ FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.Texture2D.ResourceMinLODClamp);
+ break;
+ case D3D12_SRV_DIMENSION_TEXTURECUBE:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_CUBE;
+ vkd3d_desc.miplevel_idx = desc->u.TextureCube.MostDetailedMip;
+ vkd3d_desc.miplevel_count = desc->u.TextureCube.MipLevels;
+ vkd3d_desc.layer_count = 6;
+ if (desc->u.TextureCube.ResourceMinLODClamp)
+ FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.TextureCube.ResourceMinLODClamp);
+ break;
+ case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+ vkd3d_desc.miplevel_idx = desc->u.TextureCubeArray.MostDetailedMip;
+ vkd3d_desc.miplevel_count = desc->u.TextureCubeArray.MipLevels;
+ vkd3d_desc.layer_idx = desc->u.TextureCubeArray.First2DArrayFace;
+ vkd3d_desc.layer_count = desc->u.TextureCubeArray.NumCubes;
+ if (vkd3d_desc.layer_count != VK_REMAINING_ARRAY_LAYERS)
+ vkd3d_desc.layer_count *= 6;
+ if (desc->u.TextureCubeArray.ResourceMinLODClamp)
+ FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.TextureCubeArray.ResourceMinLODClamp);
+ break;
+ default:
+ FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
+ }
+ }
+
+ if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
+ return;
+
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ descriptor->u.view = view;
+}
+
+static unsigned int vkd3d_view_flags_from_d3d12_buffer_uav_flags(D3D12_BUFFER_UAV_FLAGS flags)
+{
+ if (flags == D3D12_BUFFER_UAV_FLAG_RAW)
+ return VKD3D_VIEW_RAW_BUFFER;
+ if (flags)
+ FIXME("Unhandled buffer UAV flags %#x.\n", flags);
+ return 0;
+}
+
+static void vkd3d_create_null_uav(struct d3d12_desc *descriptor,
+ struct d3d12_device *device, const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
+ struct vkd3d_null_resources *null_resources = &device->null_resources;
+ struct vkd3d_texture_view_desc vkd3d_desc;
+ struct vkd3d_view *view;
+ VkImage vk_image;
+
+ if (!desc)
+ {
+ WARN("View desc is required for NULL view.\n");
+ return;
+ }
+
+ switch (desc->ViewDimension)
+ {
+ case D3D12_UAV_DIMENSION_BUFFER:
+ WARN("Creating NULL buffer UAV %#x.\n", desc->Format);
+
+ if (vkd3d_create_buffer_view(device, null_resources->vk_storage_buffer,
+ vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false),
+ 0, VKD3D_NULL_BUFFER_SIZE, &view))
+ {
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ descriptor->u.view = view;
+ }
+ return;
+
+ case D3D12_UAV_DIMENSION_TEXTURE2D:
+ vk_image = null_resources->vk_2d_storage_image;
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
+ break;
+ case D3D12_UAV_DIMENSION_TEXTURE2DARRAY:
+ vk_image = null_resources->vk_2d_storage_image;
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ break;
+
+ default:
+ FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
+ return;
+ }
+
+ WARN("Creating NULL UAV %#x.\n", desc->ViewDimension);
+
+ vkd3d_desc.format = vkd3d_get_format(device, VKD3D_NULL_VIEW_FORMAT, false);
+ vkd3d_desc.miplevel_idx = 0;
+ vkd3d_desc.miplevel_count = 1;
+ vkd3d_desc.layer_idx = 0;
+ vkd3d_desc.layer_count = 1;
+ vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_R;
+ vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_G;
+ vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_B;
+ vkd3d_desc.components.a = VK_COMPONENT_SWIZZLE_A;
+ vkd3d_desc.allowed_swizzle = false;
+
+ if (!vkd3d_create_texture_view(device, vk_image, &vkd3d_desc, &view))
+ return;
+
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ descriptor->u.view = view;
+}
+
+static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
+ struct d3d12_resource *resource, struct d3d12_resource *counter_resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
+ struct vkd3d_view *view;
+ unsigned int flags;
+
+ if (!desc)
+ {
+ FIXME("Default UAV views not supported.\n");
+ return;
+ }
+
+ if (desc->ViewDimension != D3D12_UAV_DIMENSION_BUFFER)
+ {
+ WARN("Unexpected view dimension %#x.\n", desc->ViewDimension);
+ return;
+ }
+
+ if (desc->u.Buffer.CounterOffsetInBytes)
+ FIXME("Ignoring counter offset %"PRIu64".\n", desc->u.Buffer.CounterOffsetInBytes);
+
+ flags = vkd3d_view_flags_from_d3d12_buffer_uav_flags(desc->u.Buffer.Flags);
+ if (!vkd3d_create_buffer_view_for_resource(device, resource, desc->Format,
+ desc->u.Buffer.FirstElement, desc->u.Buffer.NumElements,
+ desc->u.Buffer.StructureByteStride, flags, &view))
+ return;
+
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ descriptor->u.view = view;
+
+ if (counter_resource)
+ {
+ const struct vkd3d_format *format;
+
+ assert(d3d12_resource_is_buffer(counter_resource));
+ assert(desc->u.Buffer.StructureByteStride);
+
+ format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
+ if (!vkd3d_create_vk_buffer_view(device, counter_resource->u.vk_buffer, format,
+ desc->u.Buffer.CounterOffsetInBytes, sizeof(uint32_t), &view->vk_counter_view))
+ {
+ WARN("Failed to create counter buffer view.\n");
+ view->vk_counter_view = VK_NULL_HANDLE;
+ d3d12_desc_destroy(descriptor, device);
+ }
+ }
+}
+
+static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor,
+ struct d3d12_device *device, struct d3d12_resource *resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
+ struct vkd3d_texture_view_desc vkd3d_desc;
+ struct vkd3d_view *view;
+
+ if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
+ return;
+
+ if (vkd3d_format_is_compressed(vkd3d_desc.format))
+ {
+ WARN("UAVs cannot be created for compressed formats.\n");
+ return;
+ }
+
+ if (desc)
+ {
+ switch (desc->ViewDimension)
+ {
+ case D3D12_UAV_DIMENSION_TEXTURE2D:
+ vkd3d_desc.miplevel_idx = desc->u.Texture2D.MipSlice;
+ if (desc->u.Texture2D.PlaneSlice)
+ FIXME("Ignoring plane slice %u.\n", desc->u.Texture2D.PlaneSlice);
+ break;
+ case D3D12_UAV_DIMENSION_TEXTURE2DARRAY:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.miplevel_idx = desc->u.Texture2DArray.MipSlice;
+ vkd3d_desc.layer_idx = desc->u.Texture2DArray.FirstArraySlice;
+ vkd3d_desc.layer_count = desc->u.Texture2DArray.ArraySize;
+ if (desc->u.Texture2DArray.PlaneSlice)
+ FIXME("Ignoring plane slice %u.\n", desc->u.Texture2DArray.PlaneSlice);
+ break;
+ case D3D12_UAV_DIMENSION_TEXTURE3D:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_3D;
+ vkd3d_desc.miplevel_idx = desc->u.Texture3D.MipSlice;
+ if (desc->u.Texture3D.FirstWSlice || desc->u.Texture3D.WSize != resource->desc.DepthOrArraySize)
+ FIXME("Unhandled depth view %u-%u.\n",
+ desc->u.Texture3D.FirstWSlice, desc->u.Texture3D.WSize);
+ break;
+ default:
+ FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
+ }
+ }
+
+ if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
+ return;
+
+ descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
+ descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ descriptor->u.view = view;
+}
+
+void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
+ struct d3d12_resource *resource, struct d3d12_resource *counter_resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
+ if (!resource)
+ {
+ if (counter_resource)
+ FIXME("Ignoring counter resource %p.\n", counter_resource);
+ vkd3d_create_null_uav(descriptor, device, desc);
+ return;
+ }
+
+ if (d3d12_resource_is_buffer(resource))
+ {
+ vkd3d_create_buffer_uav(descriptor, device, resource, counter_resource, desc);
+ }
+ else
+ {
+ if (counter_resource)
+ FIXME("Unexpected counter resource for texture view.\n");
+ vkd3d_create_texture_uav(descriptor, device, resource, desc);
+ }
+}
+
+bool vkd3d_create_raw_buffer_view(struct d3d12_device *device,
+ D3D12_GPU_VIRTUAL_ADDRESS gpu_address, VkBufferView *vk_buffer_view)
+{
+ const struct vkd3d_format *format;
+ struct d3d12_resource *resource;
+
+ format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
+ resource = vkd3d_gpu_va_allocator_dereference(&device->gpu_va_allocator, gpu_address);
+ assert(d3d12_resource_is_buffer(resource));
+ return vkd3d_create_vk_buffer_view(device, resource->u.vk_buffer, format,
+ gpu_address - resource->gpu_address, VK_WHOLE_SIZE, vk_buffer_view);
+}
+
+/* samplers */
+static VkFilter vk_filter_from_d3d12(D3D12_FILTER_TYPE type)
+{
+ switch (type)
+ {
+ case D3D12_FILTER_TYPE_POINT:
+ return VK_FILTER_NEAREST;
+ case D3D12_FILTER_TYPE_LINEAR:
+ return VK_FILTER_LINEAR;
+ default:
+ FIXME("Unhandled filter type %#x.\n", type);
+ return VK_FILTER_NEAREST;
+ }
+}
+
+static VkSamplerMipmapMode vk_mipmap_mode_from_d3d12(D3D12_FILTER_TYPE type)
+{
+ switch (type)
+ {
+ case D3D12_FILTER_TYPE_POINT:
+ return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ case D3D12_FILTER_TYPE_LINEAR:
+ return VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ default:
+ FIXME("Unhandled filter type %#x.\n", type);
+ return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ }
+}
+
+static VkSamplerAddressMode vk_address_mode_from_d3d12(D3D12_TEXTURE_ADDRESS_MODE mode)
+{
+ switch (mode)
+ {
+ case D3D12_TEXTURE_ADDRESS_MODE_WRAP:
+ return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ case D3D12_TEXTURE_ADDRESS_MODE_MIRROR:
+ return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
+ case D3D12_TEXTURE_ADDRESS_MODE_CLAMP:
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ case D3D12_TEXTURE_ADDRESS_MODE_BORDER:
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+ /* D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE requires VK_KHR_mirror_clamp_to_edge. */
+ default:
+ FIXME("Unhandled address mode %#x.\n", mode);
+ return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ }
+}
+
+static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER filter,
+ D3D12_TEXTURE_ADDRESS_MODE address_u, D3D12_TEXTURE_ADDRESS_MODE address_v,
+ D3D12_TEXTURE_ADDRESS_MODE address_w, float mip_lod_bias, unsigned int max_anisotropy,
+ D3D12_COMPARISON_FUNC comparison_func, float min_lod, float max_lod,
+ VkSampler *vk_sampler)
+{
+ const struct vkd3d_vk_device_procs *vk_procs;
+ struct VkSamplerCreateInfo sampler_desc;
+ VkResult vr;
+
+ vk_procs = &device->vk_procs;
+
+ if (D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MINIMUM
+ || D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MAXIMUM)
+ FIXME("Min/max reduction mode not supported.\n");
+
+ sampler_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ sampler_desc.pNext = NULL;
+ sampler_desc.flags = 0;
+ sampler_desc.magFilter = vk_filter_from_d3d12(D3D12_DECODE_MAG_FILTER(filter));
+ sampler_desc.minFilter = vk_filter_from_d3d12(D3D12_DECODE_MIN_FILTER(filter));
+ sampler_desc.mipmapMode = vk_mipmap_mode_from_d3d12(D3D12_DECODE_MIP_FILTER(filter));
+ sampler_desc.addressModeU = vk_address_mode_from_d3d12(address_u);
+ sampler_desc.addressModeV = vk_address_mode_from_d3d12(address_v);
+ sampler_desc.addressModeW = vk_address_mode_from_d3d12(address_w);
+ sampler_desc.mipLodBias = mip_lod_bias;
+ sampler_desc.anisotropyEnable = D3D12_DECODE_IS_ANISOTROPIC_FILTER(filter);
+ sampler_desc.maxAnisotropy = max_anisotropy;
+ sampler_desc.compareEnable = D3D12_DECODE_IS_COMPARISON_FILTER(filter);
+ sampler_desc.compareOp = sampler_desc.compareEnable ? vk_compare_op_from_d3d12(comparison_func) : 0;
+ sampler_desc.minLod = min_lod;
+ sampler_desc.maxLod = max_lod;
+ sampler_desc.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
+ sampler_desc.unnormalizedCoordinates = VK_FALSE;
+ if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0)
+ WARN("Failed to create Vulkan sampler, vr %d.\n", vr);
+
+ return vr;
+}
+
+void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
+ struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc)
+{
+ struct vkd3d_view *view;
+
+ if (!desc)
+ {
+ WARN("NULL sampler desc.\n");
+ return;
+ }
+
+ if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER
+ || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER
+ || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER)
+ FIXME("Ignoring border color {%.8e, %.8e, %.8e, %.8e}.\n",
+ desc->BorderColor[0], desc->BorderColor[1], desc->BorderColor[2], desc->BorderColor[3]);
+
+ if (!(view = vkd3d_view_create(VKD3D_VIEW_TYPE_SAMPLER)))
+ return;
+
+ if (d3d12_create_sampler(device, desc->Filter, desc->AddressU,
+ desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy,
+ desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, &view->u.vk_sampler) < 0)
+ {
+ vkd3d_free(view);
+ return;
+ }
+
+ sampler->magic = VKD3D_DESCRIPTOR_MAGIC_SAMPLER;
+ sampler->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLER;
+ sampler->u.view = view;
+}
+
+HRESULT vkd3d_create_static_sampler(struct d3d12_device *device,
+ const D3D12_STATIC_SAMPLER_DESC *desc, VkSampler *vk_sampler)
+{
+ VkResult vr;
+
+ if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER
+ || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER
+ || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER)
+ FIXME("Ignoring border %#x.\n", desc->BorderColor);
+
+ vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU,
+ desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy,
+ desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, vk_sampler);
+ return hresult_from_vk_result(vr);
+}
+
+/* RTVs */
+static void d3d12_rtv_desc_destroy(struct d3d12_rtv_desc *rtv, struct d3d12_device *device)
+{
+ if (rtv->magic != VKD3D_DESCRIPTOR_MAGIC_RTV)
+ return;
+
+ vkd3d_view_decref(rtv->view, device);
+ memset(rtv, 0, sizeof(*rtv));
+}
+
+void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_device *device,
+ struct d3d12_resource *resource, const D3D12_RENDER_TARGET_VIEW_DESC *desc)
+{
+ struct vkd3d_texture_view_desc vkd3d_desc;
+ struct vkd3d_view *view;
+
+ d3d12_rtv_desc_destroy(rtv_desc, device);
+
+ if (!resource)
+ {
+ FIXME("NULL resource RTV not implemented.\n");
+ return;
+ }
+
+ if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
+ return;
+
+ if (vkd3d_desc.format->vk_aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT)
+ {
+ WARN("Trying to create RTV for depth/stencil format %#x.\n", vkd3d_desc.format->dxgi_format);
+ return;
+ }
+
+ if (desc)
+ {
+ switch (desc->ViewDimension)
+ {
+ case D3D12_RTV_DIMENSION_TEXTURE2D:
+ vkd3d_desc.miplevel_idx = desc->u.Texture2D.MipSlice;
+ if (desc->u.Texture2D.PlaneSlice)
+ FIXME("Ignoring plane slice %u.\n", desc->u.Texture2D.PlaneSlice);
+ break;
+ case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.miplevel_idx = desc->u.Texture2DArray.MipSlice;
+ vkd3d_desc.layer_idx = desc->u.Texture2DArray.FirstArraySlice;
+ vkd3d_desc.layer_count = desc->u.Texture2DArray.ArraySize;
+ if (desc->u.Texture2DArray.PlaneSlice)
+ FIXME("Ignoring plane slice %u.\n", desc->u.Texture2DArray.PlaneSlice);
+ break;
+ case D3D12_RTV_DIMENSION_TEXTURE2DMS:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
+ break;
+ case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.layer_idx = desc->u.Texture2DMSArray.FirstArraySlice;
+ vkd3d_desc.layer_count = desc->u.Texture2DMSArray.ArraySize;
+ break;
+ case D3D12_RTV_DIMENSION_TEXTURE3D:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.miplevel_idx = desc->u.Texture3D.MipSlice;
+ vkd3d_desc.layer_idx = desc->u.Texture3D.FirstWSlice;
+ vkd3d_desc.layer_count = desc->u.Texture3D.WSize;
+ break;
+ default:
+ FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
+ }
+ }
+ else if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
+ {
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.layer_idx = 0;
+ vkd3d_desc.layer_count = resource->desc.DepthOrArraySize;
+ }
+
+ assert(d3d12_resource_is_texture(resource));
+
+ if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
+ return;
+
+ rtv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_RTV;
+ rtv_desc->sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
+ rtv_desc->format = vkd3d_desc.format;
+ rtv_desc->width = d3d12_resource_desc_get_width(&resource->desc, vkd3d_desc.miplevel_idx);
+ rtv_desc->height = d3d12_resource_desc_get_height(&resource->desc, vkd3d_desc.miplevel_idx);
+ rtv_desc->layer_count = vkd3d_desc.layer_count;
+ rtv_desc->view = view;
+ rtv_desc->resource = resource;
+}
+
+/* DSVs */
+static void d3d12_dsv_desc_destroy(struct d3d12_dsv_desc *dsv, struct d3d12_device *device)
+{
+ if (dsv->magic != VKD3D_DESCRIPTOR_MAGIC_DSV)
+ return;
+
+ vkd3d_view_decref(dsv->view, device);
+ memset(dsv, 0, sizeof(*dsv));
+}
+
+void d3d12_dsv_desc_create_dsv(struct d3d12_dsv_desc *dsv_desc, struct d3d12_device *device,
+ struct d3d12_resource *resource, const D3D12_DEPTH_STENCIL_VIEW_DESC *desc)
+{
+ struct vkd3d_texture_view_desc vkd3d_desc;
+ struct vkd3d_view *view;
+
+ d3d12_dsv_desc_destroy(dsv_desc, device);
+
+ if (!resource)
+ {
+ FIXME("NULL resource DSV not implemented.\n");
+ return;
+ }
+
+ if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
+ {
+ WARN("Cannot create DSV for 3D texture.\n");
+ return;
+ }
+
+ if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
+ return;
+
+ if (!(vkd3d_desc.format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))
+ {
+ WARN("Trying to create DSV for format %#x.\n", vkd3d_desc.format->dxgi_format);
+ return;
+ }
+
+ if (desc)
+ {
+ if (desc->Flags)
+ FIXME("Ignoring flags %#x.\n", desc->Flags);
+
+ switch (desc->ViewDimension)
+ {
+ case D3D12_DSV_DIMENSION_TEXTURE2D:
+ vkd3d_desc.miplevel_idx = desc->u.Texture2D.MipSlice;
+ break;
+ case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.miplevel_idx = desc->u.Texture2DArray.MipSlice;
+ vkd3d_desc.layer_idx = desc->u.Texture2DArray.FirstArraySlice;
+ vkd3d_desc.layer_count = desc->u.Texture2DArray.ArraySize;
+ break;
+ case D3D12_DSV_DIMENSION_TEXTURE2DMS:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
+ break;
+ case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:
+ vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ vkd3d_desc.layer_idx = desc->u.Texture2DMSArray.FirstArraySlice;
+ vkd3d_desc.layer_count = desc->u.Texture2DMSArray.ArraySize;
+ break;
+ default:
+ FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
+ }
+ }
+
+ assert(d3d12_resource_is_texture(resource));
+
+ if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
+ return;
+
+ dsv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_DSV;
+ dsv_desc->sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
+ dsv_desc->format = vkd3d_desc.format;
+ dsv_desc->width = d3d12_resource_desc_get_width(&resource->desc, vkd3d_desc.miplevel_idx);
+ dsv_desc->height = d3d12_resource_desc_get_height(&resource->desc, vkd3d_desc.miplevel_idx);
+ dsv_desc->layer_count = vkd3d_desc.layer_count;
+ dsv_desc->view = view;
+ dsv_desc->resource = resource;
+}
+
+/* ID3D12DescriptorHeap */
+static inline struct d3d12_descriptor_heap *impl_from_ID3D12DescriptorHeap(ID3D12DescriptorHeap *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_descriptor_heap, ID3D12DescriptorHeap_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_QueryInterface(ID3D12DescriptorHeap *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12DescriptorHeap)
+ || IsEqualGUID(riid, &IID_ID3D12Pageable)
+ || IsEqualGUID(riid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12DescriptorHeap_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_AddRef(ID3D12DescriptorHeap *iface)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+ ULONG refcount = InterlockedIncrement(&heap->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", heap, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHeap *iface)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+ ULONG refcount = InterlockedDecrement(&heap->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", heap, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = heap->device;
+ unsigned int i;
+
+ vkd3d_private_store_destroy(&heap->private_store);
+
+ switch (heap->desc.Type)
+ {
+ case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
+ case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
+ {
+ struct d3d12_desc *descriptors = (struct d3d12_desc *)heap->descriptors;
+
+ for (i = 0; i < heap->desc.NumDescriptors; ++i)
+ {
+ d3d12_desc_destroy(&descriptors[i], device);
+ }
+ break;
+ }
+
+ case D3D12_DESCRIPTOR_HEAP_TYPE_RTV:
+ {
+ struct d3d12_rtv_desc *rtvs = (struct d3d12_rtv_desc *)heap->descriptors;
+
+ for (i = 0; i < heap->desc.NumDescriptors; ++i)
+ {
+ d3d12_rtv_desc_destroy(&rtvs[i], device);
+ }
+ break;
+ }
+
+ case D3D12_DESCRIPTOR_HEAP_TYPE_DSV:
+ {
+ struct d3d12_dsv_desc *dsvs = (struct d3d12_dsv_desc *)heap->descriptors;
+
+ for (i = 0; i < heap->desc.NumDescriptors; ++i)
+ {
+ d3d12_dsv_desc_destroy(&dsvs[i], device);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ vkd3d_free(heap);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_GetPrivateData(ID3D12DescriptorHeap *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&heap->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_SetPrivateData(ID3D12DescriptorHeap *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&heap->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_SetPrivateDataInterface(ID3D12DescriptorHeap *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&heap->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_SetName(ID3D12DescriptorHeap *iface, const WCHAR *name)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, heap->device->wchar_size));
+
+ return name ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_GetDevice(ID3D12DescriptorHeap *iface, REFIID iid, void **device)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(heap->device, iid, device);
+}
+
+static D3D12_DESCRIPTOR_HEAP_DESC * STDMETHODCALLTYPE d3d12_descriptor_heap_GetDesc(ID3D12DescriptorHeap *iface,
+ D3D12_DESCRIPTOR_HEAP_DESC *desc)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+
+ TRACE("iface %p, desc %p.\n", iface, desc);
+
+ *desc = heap->desc;
+ return desc;
+}
+
+static D3D12_CPU_DESCRIPTOR_HANDLE * STDMETHODCALLTYPE d3d12_descriptor_heap_GetCPUDescriptorHandleForHeapStart(
+ ID3D12DescriptorHeap *iface, D3D12_CPU_DESCRIPTOR_HANDLE *descriptor)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+
+ TRACE("iface %p, descriptor %p.\n", iface, descriptor);
+
+ descriptor->ptr = (SIZE_T)heap->descriptors;
+
+ return descriptor;
+}
+
+static D3D12_GPU_DESCRIPTOR_HANDLE * STDMETHODCALLTYPE d3d12_descriptor_heap_GetGPUDescriptorHandleForHeapStart(
+ ID3D12DescriptorHeap *iface, D3D12_GPU_DESCRIPTOR_HANDLE *descriptor)
+{
+ struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
+
+ TRACE("iface %p, descriptor %p.\n", iface, descriptor);
+
+ descriptor->ptr = (uint64_t)(intptr_t)heap->descriptors;
+
+ return descriptor;
+}
+
+static const struct ID3D12DescriptorHeapVtbl d3d12_descriptor_heap_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_descriptor_heap_QueryInterface,
+ d3d12_descriptor_heap_AddRef,
+ d3d12_descriptor_heap_Release,
+ /* ID3D12Object methods */
+ d3d12_descriptor_heap_GetPrivateData,
+ d3d12_descriptor_heap_SetPrivateData,
+ d3d12_descriptor_heap_SetPrivateDataInterface,
+ d3d12_descriptor_heap_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_descriptor_heap_GetDevice,
+ /* ID3D12DescriptorHeap methods */
+ d3d12_descriptor_heap_GetDesc,
+ d3d12_descriptor_heap_GetCPUDescriptorHandleForHeapStart,
+ d3d12_descriptor_heap_GetGPUDescriptorHandleForHeapStart,
+};
+
+static HRESULT d3d12_descriptor_heap_init(struct d3d12_descriptor_heap *descriptor_heap,
+ struct d3d12_device *device, const D3D12_DESCRIPTOR_HEAP_DESC *desc)
+{
+ HRESULT hr;
+
+ descriptor_heap->ID3D12DescriptorHeap_iface.lpVtbl = &d3d12_descriptor_heap_vtbl;
+ descriptor_heap->refcount = 1;
+
+ descriptor_heap->desc = *desc;
+
+ if (FAILED(hr = vkd3d_private_store_init(&descriptor_heap->private_store)))
+ return hr;
+
+ d3d12_device_add_ref(descriptor_heap->device = device);
+
+ return S_OK;
+}
+
+HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device,
+ const D3D12_DESCRIPTOR_HEAP_DESC *desc, struct d3d12_descriptor_heap **descriptor_heap)
+{
+ size_t max_descriptor_count, descriptor_size;
+ struct d3d12_descriptor_heap *object;
+ HRESULT hr;
+
+ if (!(descriptor_size = d3d12_device_get_descriptor_handle_increment_size(device, desc->Type)))
+ {
+ WARN("No descriptor size for descriptor type %#x.\n", desc->Type);
+ return E_INVALIDARG;
+ }
+
+ if ((desc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
+ && (desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_RTV || desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_DSV))
+ {
+ WARN("RTV/DSV descriptor heaps cannot be shader visible.\n");
+ return E_INVALIDARG;
+ }
+
+ max_descriptor_count = (~(size_t)0 - sizeof(*object)) / descriptor_size;
+ if (desc->NumDescriptors > max_descriptor_count)
+ {
+ WARN("Invalid descriptor count %u (max %zu).\n", desc->NumDescriptors, max_descriptor_count);
+ return E_OUTOFMEMORY;
+ }
+
+ if (!(object = vkd3d_malloc(offsetof(struct d3d12_descriptor_heap,
+ descriptors[descriptor_size * desc->NumDescriptors]))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_descriptor_heap_init(object, device, desc)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ memset(object->descriptors, 0, descriptor_size * desc->NumDescriptors);
+
+ TRACE("Created descriptor heap %p.\n", object);
+
+ *descriptor_heap = object;
+
+ return S_OK;
+}
+
+/* ID3D12QueryHeap */
+static inline struct d3d12_query_heap *impl_from_ID3D12QueryHeap(ID3D12QueryHeap *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_query_heap, ID3D12QueryHeap_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_query_heap_QueryInterface(ID3D12QueryHeap *iface,
+ REFIID iid, void **out)
+{
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_ID3D12QueryHeap)
+ || IsEqualGUID(iid, &IID_ID3D12Pageable)
+ || IsEqualGUID(iid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(iid, &IID_ID3D12Object)
+ || IsEqualGUID(iid, &IID_IUnknown))
+ {
+ ID3D12QueryHeap_AddRef(iface);
+ *out = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_query_heap_AddRef(ID3D12QueryHeap *iface)
+{
+ struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
+ ULONG refcount = InterlockedIncrement(&heap->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", heap, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_query_heap_Release(ID3D12QueryHeap *iface)
+{
+ struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
+ ULONG refcount = InterlockedDecrement(&heap->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", heap, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = heap->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ vkd3d_private_store_destroy(&heap->private_store);
+
+ VK_CALL(vkDestroyQueryPool(device->vk_device, heap->vk_query_pool, NULL));
+
+ vkd3d_free(heap);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_query_heap_GetPrivateData(ID3D12QueryHeap *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&heap->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_query_heap_SetPrivateData(ID3D12QueryHeap *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&heap->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_query_heap_SetPrivateDataInterface(ID3D12QueryHeap *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&heap->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_query_heap_SetName(ID3D12QueryHeap *iface, const WCHAR *name)
+{
+ struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, heap->device->wchar_size));
+
+ return vkd3d_set_vk_object_name(heap->device, (uint64_t)heap->vk_query_pool,
+ VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, name);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_query_heap_GetDevice(ID3D12QueryHeap *iface, REFIID iid, void **device)
+{
+ struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(heap->device, iid, device);
+}
+
+static const struct ID3D12QueryHeapVtbl d3d12_query_heap_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_query_heap_QueryInterface,
+ d3d12_query_heap_AddRef,
+ d3d12_query_heap_Release,
+ /* ID3D12Object methods */
+ d3d12_query_heap_GetPrivateData,
+ d3d12_query_heap_SetPrivateData,
+ d3d12_query_heap_SetPrivateDataInterface,
+ d3d12_query_heap_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_query_heap_GetDevice,
+};
+
+struct d3d12_query_heap *unsafe_impl_from_ID3D12QueryHeap(ID3D12QueryHeap *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_query_heap_vtbl);
+ return impl_from_ID3D12QueryHeap(iface);
+}
+
+HRESULT d3d12_query_heap_create(struct d3d12_device *device, const D3D12_QUERY_HEAP_DESC *desc,
+ struct d3d12_query_heap **heap)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct d3d12_query_heap *object;
+ VkQueryPoolCreateInfo pool_info;
+ unsigned int element_count;
+ VkResult vr;
+ HRESULT hr;
+
+ element_count = DIV_ROUND_UP(desc->Count, sizeof(*object->availability_mask) * CHAR_BIT);
+ if (!(object = vkd3d_malloc(offsetof(struct d3d12_query_heap, availability_mask[element_count]))))
+ return E_OUTOFMEMORY;
+
+ object->ID3D12QueryHeap_iface.lpVtbl = &d3d12_query_heap_vtbl;
+ object->refcount = 1;
+ object->device = device;
+ memset(object->availability_mask, 0, element_count * sizeof(*object->availability_mask));
+
+ pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
+ pool_info.pNext = NULL;
+ pool_info.flags = 0;
+ pool_info.queryCount = desc->Count;
+
+ switch (desc->Type)
+ {
+ case D3D12_QUERY_HEAP_TYPE_OCCLUSION:
+ pool_info.queryType = VK_QUERY_TYPE_OCCLUSION;
+ pool_info.pipelineStatistics = 0;
+ break;
+
+ case D3D12_QUERY_HEAP_TYPE_TIMESTAMP:
+ pool_info.queryType = VK_QUERY_TYPE_TIMESTAMP;
+ pool_info.pipelineStatistics = 0;
+ break;
+
+ case D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS:
+ pool_info.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS;
+ pool_info.pipelineStatistics = VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT
+ | VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
+ break;
+
+ case D3D12_QUERY_HEAP_TYPE_SO_STATISTICS:
+ if (!device->vk_info.transform_feedback_queries)
+ {
+ FIXME("Transform feedback queries are not supported by Vulkan implementation.\n");
+ vkd3d_free(object);
+ return E_NOTIMPL;
+ }
+
+ pool_info.queryType = VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT;
+ pool_info.pipelineStatistics = 0;
+ break;
+
+ default:
+ WARN("Invalid query heap type %u.\n", desc->Type);
+ vkd3d_free(object);
+ return E_INVALIDARG;
+ }
+
+ if (FAILED(hr = vkd3d_private_store_init(&object->private_store)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ if ((vr = VK_CALL(vkCreateQueryPool(device->vk_device, &pool_info, NULL, &object->vk_query_pool))) < 0)
+ {
+ WARN("Failed to create Vulkan query pool, vr %d.\n", vr);
+ vkd3d_private_store_destroy(&object->private_store);
+ vkd3d_free(object);
+ return hresult_from_vk_result(vr);
+ }
+
+ d3d12_device_add_ref(device);
+
+ TRACE("Created query heap %p.\n", object);
+
+ *heap = object;
+
+ return S_OK;
+}
+
+static HRESULT vkd3d_init_null_resources_data(struct vkd3d_null_resources *null_resource,
+ struct d3d12_device *device)
+{
+ const bool use_sparse_resources = device->vk_info.sparse_properties.residencyNonResidentStrict;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ static const VkClearColorValue clear_color = {{0}};
+ VkCommandBufferAllocateInfo command_buffer_info;
+ VkCommandPool vk_command_pool = VK_NULL_HANDLE;
+ VkCommandPoolCreateInfo command_pool_info;
+ VkDevice vk_device = device->vk_device;
+ VkCommandBufferBeginInfo begin_info;
+ VkCommandBuffer vk_command_buffer;
+ VkFence vk_fence = VK_NULL_HANDLE;
+ VkImageSubresourceRange range;
+ VkImageMemoryBarrier barrier;
+ VkFenceCreateInfo fence_info;
+ struct vkd3d_queue *queue;
+ VkSubmitInfo submit_info;
+ VkQueue vk_queue;
+ VkResult vr;
+
+ queue = d3d12_device_get_vkd3d_queue(device, D3D12_COMMAND_LIST_TYPE_DIRECT);
+
+ command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ command_pool_info.pNext = NULL;
+ command_pool_info.flags = 0;
+ command_pool_info.queueFamilyIndex = queue->vk_family_index;
+
+ if ((vr = VK_CALL(vkCreateCommandPool(vk_device, &command_pool_info, NULL, &vk_command_pool))) < 0)
+ {
+ WARN("Failed to create Vulkan command pool, vr %d.\n", vr);
+ goto done;
+ }
+
+ command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ command_buffer_info.pNext = NULL;
+ command_buffer_info.commandPool = vk_command_pool;
+ command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ command_buffer_info.commandBufferCount = 1;
+
+ if ((vr = VK_CALL(vkAllocateCommandBuffers(vk_device, &command_buffer_info, &vk_command_buffer))) < 0)
+ {
+ WARN("Failed to allocate Vulkan command buffer, vr %d.\n", vr);
+ goto done;
+ }
+
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.pNext = NULL;
+ begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ begin_info.pInheritanceInfo = NULL;
+
+ if ((vr = VK_CALL(vkBeginCommandBuffer(vk_command_buffer, &begin_info))) < 0)
+ {
+ WARN("Failed to begin command buffer, vr %d.\n", vr);
+ goto done;
+ }
+
+ /* fill buffer */
+ VK_CALL(vkCmdFillBuffer(vk_command_buffer, null_resource->vk_buffer, 0, VK_WHOLE_SIZE, 0x00000000));
+
+ if (use_sparse_resources)
+ {
+ /* transition 2D UAV image */
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.pNext = NULL;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = 0;
+ barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = null_resource->vk_2d_storage_image;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+
+ VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
+ 0, NULL, 0, NULL, 1, &barrier));
+ }
+ else
+ {
+ /* fill UAV buffer */
+ VK_CALL(vkCmdFillBuffer(vk_command_buffer,
+ null_resource->vk_storage_buffer, 0, VK_WHOLE_SIZE, 0x00000000));
+
+ /* clear 2D UAV image */
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.pNext = NULL;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = null_resource->vk_2d_storage_image;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+
+ VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
+ 0, NULL, 0, NULL, 1, &barrier));
+
+ range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ range.baseMipLevel = 0;
+ range.levelCount = 1;
+ range.baseArrayLayer = 0;
+ range.layerCount = 1;
+
+ VK_CALL(vkCmdClearColorImage(vk_command_buffer,
+ null_resource->vk_2d_storage_image, VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range));
+ }
+
+ /* transition 2D SRV image */
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.pNext = NULL;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = 0;
+ barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = null_resource->vk_2d_image;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+
+ VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
+ 0, NULL, 0, NULL, 1, &barrier));
+
+ if ((vr = VK_CALL(vkEndCommandBuffer(vk_command_buffer))) < 0)
+ {
+ WARN("Failed to end command buffer, vr %d.\n", vr);
+ goto done;
+ }
+
+ fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fence_info.pNext = NULL;
+ fence_info.flags = 0;
+
+ if ((vr = VK_CALL(vkCreateFence(device->vk_device, &fence_info, NULL, &vk_fence))) < 0)
+ {
+ WARN("Failed to create Vulkan fence, vr %d.\n", vr);
+ goto done;
+ }
+
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.pNext = NULL;
+ submit_info.waitSemaphoreCount = 0;
+ submit_info.pWaitSemaphores = NULL;
+ submit_info.pWaitDstStageMask = NULL;
+ submit_info.commandBufferCount = 1;
+ submit_info.pCommandBuffers = &vk_command_buffer;
+ submit_info.signalSemaphoreCount = 0;
+ submit_info.pSignalSemaphores = NULL;
+
+ if (!(vk_queue = vkd3d_queue_acquire(queue)))
+ {
+ WARN("Failed to acquire queue %p.\n", queue);
+ goto done;
+ }
+
+ if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_info, vk_fence))) < 0)
+ ERR("Failed to submit, vr %d.\n", vr);
+
+ vkd3d_queue_release(queue);
+
+ vr = VK_CALL(vkWaitForFences(device->vk_device, 1, &vk_fence, VK_FALSE, ~(uint64_t)0));
+ if (vr != VK_SUCCESS)
+ WARN("Failed to wait for fence, vr %d.\n", vr);
+
+done:
+ VK_CALL(vkDestroyCommandPool(vk_device, vk_command_pool, NULL));
+ VK_CALL(vkDestroyFence(vk_device, vk_fence, NULL));
+
+ return hresult_from_vk_result(vr);
+}
+
+HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources,
+ struct d3d12_device *device)
+{
+ const bool use_sparse_resources = device->vk_info.sparse_properties.residencyNonResidentStrict;
+ D3D12_HEAP_PROPERTIES heap_properties;
+ D3D12_RESOURCE_DESC resource_desc;
+ HRESULT hr;
+
+ TRACE("Creating resources for NULL views.\n");
+
+ memset(null_resources, 0, sizeof(*null_resources));
+
+ memset(&heap_properties, 0, sizeof(heap_properties));
+ heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
+
+ /* buffer */
+ resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ resource_desc.Alignment = 0;
+ resource_desc.Width = VKD3D_NULL_BUFFER_SIZE;
+ resource_desc.Height = 1;
+ resource_desc.DepthOrArraySize = 1;
+ resource_desc.MipLevels = 1;
+ resource_desc.Format = DXGI_FORMAT_UNKNOWN;
+ resource_desc.SampleDesc.Count = 1;
+ resource_desc.SampleDesc.Quality = 0;
+ resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ if (FAILED(hr = vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
+ &resource_desc, &null_resources->vk_buffer)))
+ goto fail;
+ if (FAILED(hr = vkd3d_allocate_buffer_memory(device, null_resources->vk_buffer,
+ &heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_buffer_memory, NULL, NULL)))
+ goto fail;
+
+ /* buffer UAV */
+ resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ if (FAILED(hr = vkd3d_create_buffer(device, use_sparse_resources ? NULL : &heap_properties, D3D12_HEAP_FLAG_NONE,
+ &resource_desc, &null_resources->vk_storage_buffer)))
+ goto fail;
+ if (!use_sparse_resources && FAILED(hr = vkd3d_allocate_buffer_memory(device, null_resources->vk_storage_buffer,
+ &heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_storage_buffer_memory, NULL, NULL)))
+ goto fail;
+
+ /* 2D SRV */
+ resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resource_desc.Alignment = 0;
+ resource_desc.Width = 1;
+ resource_desc.Height = 1;
+ resource_desc.DepthOrArraySize = 1;
+ resource_desc.MipLevels = 1;
+ resource_desc.Format = VKD3D_NULL_VIEW_FORMAT;
+ resource_desc.SampleDesc.Count = 1;
+ resource_desc.SampleDesc.Quality = 0;
+ resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ if (FAILED(hr = vkd3d_create_image(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
+ &resource_desc, NULL, &null_resources->vk_2d_image)))
+ goto fail;
+ if (FAILED(hr = vkd3d_allocate_image_memory(device, null_resources->vk_2d_image,
+ &heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_2d_image_memory, NULL, NULL)))
+ goto fail;
+
+ /* 2D UAV */
+ resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resource_desc.Alignment = 0;
+ resource_desc.Width = 1;
+ resource_desc.Height = 1;
+ resource_desc.DepthOrArraySize = 1;
+ resource_desc.MipLevels = 1;
+ resource_desc.Format = VKD3D_NULL_VIEW_FORMAT;
+ resource_desc.SampleDesc.Count = 1;
+ resource_desc.SampleDesc.Quality = 0;
+ resource_desc.Layout = use_sparse_resources
+ ? D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE : D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ if (FAILED(hr = vkd3d_create_image(device, use_sparse_resources ? NULL : &heap_properties, D3D12_HEAP_FLAG_NONE,
+ &resource_desc, NULL, &null_resources->vk_2d_storage_image)))
+ goto fail;
+ if (!use_sparse_resources && FAILED(hr = vkd3d_allocate_image_memory(device, null_resources->vk_2d_storage_image,
+ &heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_2d_storage_image_memory, NULL, NULL)))
+ goto fail;
+
+ /* set Vulkan object names */
+ vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_buffer,
+ VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "NULL buffer");
+ vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_buffer_memory,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, "NULL memory");
+ vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_storage_buffer,
+ VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "NULL UAV buffer");
+ vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_2d_image,
+ VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "NULL 2D SRV image");
+ vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_2d_image_memory,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, "NULL 2D SRV memory");
+ vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_2d_storage_image,
+ VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "NULL 2D UAV image");
+ if (!use_sparse_resources)
+ {
+ vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_storage_buffer_memory,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, "NULL UAV buffer memory");
+ vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_2d_storage_image_memory,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, "NULL 2D UAV memory");
+ }
+
+ return vkd3d_init_null_resources_data(null_resources, device);
+
+fail:
+ ERR("Failed to initialize NULL resources, hr %#x.\n", hr);
+ vkd3d_destroy_null_resources(null_resources, device);
+ return hr;
+}
+
+void vkd3d_destroy_null_resources(struct vkd3d_null_resources *null_resources,
+ struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ VK_CALL(vkDestroyBuffer(device->vk_device, null_resources->vk_buffer, NULL));
+ VK_CALL(vkFreeMemory(device->vk_device, null_resources->vk_buffer_memory, NULL));
+
+ VK_CALL(vkDestroyBuffer(device->vk_device, null_resources->vk_storage_buffer, NULL));
+ VK_CALL(vkFreeMemory(device->vk_device, null_resources->vk_storage_buffer_memory, NULL));
+
+ VK_CALL(vkDestroyImage(device->vk_device, null_resources->vk_2d_image, NULL));
+ VK_CALL(vkFreeMemory(device->vk_device, null_resources->vk_2d_image_memory, NULL));
+
+ VK_CALL(vkDestroyImage(device->vk_device, null_resources->vk_2d_storage_image, NULL));
+ VK_CALL(vkFreeMemory(device->vk_device, null_resources->vk_2d_storage_image_memory, NULL));
+
+ memset(null_resources, 0, sizeof(*null_resources));
+}
diff --git a/dlls/vkd3d/libs/vkd3d/state.c b/dlls/vkd3d/libs/vkd3d/state.c
new file mode 100644
index 00000000000..81f33435eb5
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/state.c
@@ -0,0 +1,3020 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ * Copyright 2016 Henri Verbeet for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_private.h"
+#include "vkd3d_shaders.h"
+
+/* ID3D12RootSignature */
+static inline struct d3d12_root_signature *impl_from_ID3D12RootSignature(ID3D12RootSignature *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_root_signature, ID3D12RootSignature_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_root_signature_QueryInterface(ID3D12RootSignature *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12RootSignature)
+ || IsEqualGUID(riid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12RootSignature_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_root_signature_AddRef(ID3D12RootSignature *iface)
+{
+ struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface);
+ ULONG refcount = InterlockedIncrement(&root_signature->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", root_signature, refcount);
+
+ return refcount;
+}
+
+static void d3d12_root_signature_cleanup(struct d3d12_root_signature *root_signature,
+ struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ unsigned int i;
+
+ if (root_signature->vk_pipeline_layout)
+ VK_CALL(vkDestroyPipelineLayout(device->vk_device, root_signature->vk_pipeline_layout, NULL));
+ if (root_signature->vk_set_layout)
+ VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, root_signature->vk_set_layout, NULL));
+ if (root_signature->vk_push_set_layout)
+ VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, root_signature->vk_push_set_layout, NULL));
+
+ if (root_signature->parameters)
+ {
+ for (i = 0; i < root_signature->parameter_count; ++i)
+ {
+ if (root_signature->parameters[i].parameter_type == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
+ vkd3d_free(root_signature->parameters[i].u.descriptor_table.ranges);
+ }
+ vkd3d_free(root_signature->parameters);
+ }
+
+ if (root_signature->descriptor_mapping)
+ vkd3d_free(root_signature->descriptor_mapping);
+ if (root_signature->root_constants)
+ vkd3d_free(root_signature->root_constants);
+
+ for (i = 0; i < root_signature->static_sampler_count; ++i)
+ {
+ if (root_signature->static_samplers[i])
+ VK_CALL(vkDestroySampler(device->vk_device, root_signature->static_samplers[i], NULL));
+ }
+ if (root_signature->static_samplers)
+ vkd3d_free(root_signature->static_samplers);
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_root_signature_Release(ID3D12RootSignature *iface)
+{
+ struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface);
+ ULONG refcount = InterlockedDecrement(&root_signature->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", root_signature, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = root_signature->device;
+ vkd3d_private_store_destroy(&root_signature->private_store);
+ d3d12_root_signature_cleanup(root_signature, device);
+ vkd3d_free(root_signature);
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_root_signature_GetPrivateData(ID3D12RootSignature *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&root_signature->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_root_signature_SetPrivateData(ID3D12RootSignature *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&root_signature->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_root_signature_SetPrivateDataInterface(ID3D12RootSignature *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&root_signature->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_root_signature_SetName(ID3D12RootSignature *iface, const WCHAR *name)
+{
+ struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, root_signature->device->wchar_size));
+
+ return name ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_root_signature_GetDevice(ID3D12RootSignature *iface,
+ REFIID iid, void **device)
+{
+ struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(root_signature->device, iid, device);
+}
+
+static const struct ID3D12RootSignatureVtbl d3d12_root_signature_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_root_signature_QueryInterface,
+ d3d12_root_signature_AddRef,
+ d3d12_root_signature_Release,
+ /* ID3D12Object methods */
+ d3d12_root_signature_GetPrivateData,
+ d3d12_root_signature_SetPrivateData,
+ d3d12_root_signature_SetPrivateDataInterface,
+ d3d12_root_signature_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_root_signature_GetDevice,
+};
+
+struct d3d12_root_signature *unsafe_impl_from_ID3D12RootSignature(ID3D12RootSignature *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_root_signature_vtbl);
+ return impl_from_ID3D12RootSignature(iface);
+}
+
+static VkShaderStageFlags stage_flags_from_visibility(D3D12_SHADER_VISIBILITY visibility)
+{
+ switch (visibility)
+ {
+ case D3D12_SHADER_VISIBILITY_ALL:
+ return VK_SHADER_STAGE_ALL;
+ case D3D12_SHADER_VISIBILITY_VERTEX:
+ return VK_SHADER_STAGE_VERTEX_BIT;
+ case D3D12_SHADER_VISIBILITY_HULL:
+ return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+ case D3D12_SHADER_VISIBILITY_DOMAIN:
+ return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+ case D3D12_SHADER_VISIBILITY_GEOMETRY:
+ return VK_SHADER_STAGE_GEOMETRY_BIT;
+ case D3D12_SHADER_VISIBILITY_PIXEL:
+ return VK_SHADER_STAGE_FRAGMENT_BIT;
+ default:
+ return 0;
+ }
+}
+
+static enum vkd3d_shader_visibility vkd3d_shader_visibility_from_d3d12(D3D12_SHADER_VISIBILITY visibility)
+{
+ switch (visibility)
+ {
+ case D3D12_SHADER_VISIBILITY_ALL:
+ return VKD3D_SHADER_VISIBILITY_ALL;
+ case D3D12_SHADER_VISIBILITY_VERTEX:
+ return VKD3D_SHADER_VISIBILITY_VERTEX;
+ case D3D12_SHADER_VISIBILITY_HULL:
+ return VKD3D_SHADER_VISIBILITY_HULL;
+ case D3D12_SHADER_VISIBILITY_DOMAIN:
+ return VKD3D_SHADER_VISIBILITY_DOMAIN;
+ case D3D12_SHADER_VISIBILITY_GEOMETRY:
+ return VKD3D_SHADER_VISIBILITY_GEOMETRY;
+ case D3D12_SHADER_VISIBILITY_PIXEL:
+ return VKD3D_SHADER_VISIBILITY_PIXEL;
+ default:
+ FIXME("Unhandled visibility %#x.\n", visibility);
+ return VKD3D_SHADER_VISIBILITY_ALL;
+ }
+}
+
+static VkDescriptorType vk_descriptor_type_from_d3d12_range_type(D3D12_DESCRIPTOR_RANGE_TYPE type,
+ bool is_buffer)
+{
+ switch (type)
+ {
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
+ return is_buffer ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
+ return is_buffer ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
+ return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER:
+ return VK_DESCRIPTOR_TYPE_SAMPLER;
+ default:
+ FIXME("Unhandled descriptor range type type %#x.\n", type);
+ return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ }
+}
+
+static VkDescriptorType vk_descriptor_type_from_d3d12_root_parameter(D3D12_ROOT_PARAMETER_TYPE type)
+{
+ switch (type)
+ {
+ /* SRV and UAV root parameters are buffer views. */
+ case D3D12_ROOT_PARAMETER_TYPE_SRV:
+ return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ case D3D12_ROOT_PARAMETER_TYPE_UAV:
+ return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ case D3D12_ROOT_PARAMETER_TYPE_CBV:
+ return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ default:
+ FIXME("Unhandled descriptor root parameter type %#x.\n", type);
+ return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ }
+}
+
+static enum vkd3d_shader_descriptor_type vkd3d_descriptor_type_from_d3d12_range_type(
+ D3D12_DESCRIPTOR_RANGE_TYPE type)
+{
+ switch (type)
+ {
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_CBV;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER:
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER;
+ default:
+ FIXME("Unhandled descriptor range type type %#x.\n", type);
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
+ }
+}
+
+static enum vkd3d_shader_descriptor_type vkd3d_descriptor_type_from_d3d12_root_parameter_type(
+ D3D12_ROOT_PARAMETER_TYPE type)
+{
+ switch (type)
+ {
+ case D3D12_ROOT_PARAMETER_TYPE_SRV:
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
+ case D3D12_ROOT_PARAMETER_TYPE_UAV:
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
+ case D3D12_ROOT_PARAMETER_TYPE_CBV:
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_CBV;
+ default:
+ FIXME("Unhandled descriptor root parameter type %#x.\n", type);
+ return VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
+ }
+}
+
+static bool vk_binding_from_d3d12_descriptor_range(struct VkDescriptorSetLayoutBinding *binding_desc,
+ const D3D12_DESCRIPTOR_RANGE *descriptor_range, D3D12_SHADER_VISIBILITY shader_visibility,
+ bool is_buffer, uint32_t vk_binding)
+{
+ binding_desc->binding = vk_binding;
+ binding_desc->descriptorType
+ = vk_descriptor_type_from_d3d12_range_type(descriptor_range->RangeType, is_buffer);
+ binding_desc->descriptorCount = 1;
+ binding_desc->stageFlags = stage_flags_from_visibility(shader_visibility);
+ binding_desc->pImmutableSamplers = NULL;
+
+ return true;
+}
+
+struct d3d12_root_signature_info
+{
+ size_t cbv_count;
+ size_t buffer_uav_count;
+ size_t uav_count;
+ size_t buffer_srv_count;
+ size_t srv_count;
+ size_t sampler_count;
+
+ size_t descriptor_count;
+
+ size_t root_constant_count;
+ size_t root_descriptor_count;
+
+ size_t cost;
+};
+
+static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_signature_info *info,
+ const D3D12_DESCRIPTOR_RANGE *range)
+{
+ if (range->NumDescriptors == 0xffffffff)
+ {
+ FIXME("Unhandled unbound descriptor range.\n");
+ return E_NOTIMPL;
+ }
+
+ switch (range->RangeType)
+ {
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
+ info->srv_count += range->NumDescriptors;
+ break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
+ info->uav_count += range->NumDescriptors;
+ break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
+ info->cbv_count += range->NumDescriptors;
+ break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER:
+ info->sampler_count += range->NumDescriptors;
+ break;
+ default:
+ FIXME("Unhandled descriptor type %#x.\n", range->RangeType);
+ return E_NOTIMPL;
+ }
+
+ info->descriptor_count += range->NumDescriptors;
+
+ return S_OK;
+}
+
+static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_info *info,
+ const D3D12_ROOT_SIGNATURE_DESC *desc)
+{
+ unsigned int i, j;
+ HRESULT hr;
+
+ memset(info, 0, sizeof(*info));
+
+ for (i = 0; i < desc->NumParameters; ++i)
+ {
+ const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i];
+
+ switch (p->ParameterType)
+ {
+ case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
+ for (j = 0; j < p->u.DescriptorTable.NumDescriptorRanges; ++j)
+ if (FAILED(hr = d3d12_root_signature_info_count_descriptors(info,
+ &p->u.DescriptorTable.pDescriptorRanges[j])))
+ return hr;
+ ++info->cost;
+ break;
+
+ case D3D12_ROOT_PARAMETER_TYPE_CBV:
+ ++info->root_descriptor_count;
+ ++info->cbv_count;
+ ++info->descriptor_count;
+ info->cost += 2;
+ break;
+ case D3D12_ROOT_PARAMETER_TYPE_SRV:
+ ++info->root_descriptor_count;
+ ++info->buffer_srv_count;
+ ++info->descriptor_count;
+ info->cost += 2;
+ break;
+ case D3D12_ROOT_PARAMETER_TYPE_UAV:
+ ++info->root_descriptor_count;
+ ++info->buffer_uav_count;
+ ++info->descriptor_count;
+ info->cost += 2;
+ break;
+
+ case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
+ ++info->root_constant_count;
+ info->cost += p->u.Constants.Num32BitValues;
+ break;
+
+ default:
+ FIXME("Unhandled type %#x for parameter %u.\n", p->ParameterType, i);
+ return E_NOTIMPL;
+ }
+ }
+
+ info->sampler_count += desc->NumStaticSamplers;
+ info->descriptor_count += desc->NumStaticSamplers;
+
+ return S_OK;
+}
+
+static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signature *root_signature,
+ const D3D12_ROOT_SIGNATURE_DESC *desc, const struct d3d12_root_signature_info *info,
+ struct VkPushConstantRange push_constants[D3D12_SHADER_VISIBILITY_PIXEL + 1],
+ uint32_t *push_constant_range_count)
+{
+ uint32_t push_constants_offset[D3D12_SHADER_VISIBILITY_PIXEL + 1];
+ unsigned int i, j, push_constant_count;
+ uint32_t offset;
+
+ memset(push_constants, 0, (D3D12_SHADER_VISIBILITY_PIXEL + 1) * sizeof(*push_constants));
+ memset(push_constants_offset, 0, sizeof(push_constants_offset));
+ for (i = 0; i < desc->NumParameters; ++i)
+ {
+ const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i];
+ if (p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS)
+ continue;
+
+ assert(p->ShaderVisibility <= D3D12_SHADER_VISIBILITY_PIXEL);
+ push_constants[p->ShaderVisibility].stageFlags = stage_flags_from_visibility(p->ShaderVisibility);
+ push_constants[p->ShaderVisibility].size += p->u.Constants.Num32BitValues * sizeof(uint32_t);
+ }
+ if (push_constants[D3D12_SHADER_VISIBILITY_ALL].size)
+ {
+ /* When D3D12_SHADER_VISIBILITY_ALL is used we use a single push
+ * constants range because the Vulkan spec states:
+ *
+ * "Any two elements of pPushConstantRanges must not include the same
+ * stage in stageFlags".
+ */
+ push_constant_count = 1;
+ for (i = 0; i <= D3D12_SHADER_VISIBILITY_PIXEL; ++i)
+ {
+ if (i == D3D12_SHADER_VISIBILITY_ALL)
+ continue;
+
+ push_constants[D3D12_SHADER_VISIBILITY_ALL].size += push_constants[i].size;
+ push_constants[i].size = 0;
+ }
+ }
+ else
+ {
+ /* Move non-empty push constants ranges to front and compute offsets. */
+ offset = 0;
+ for (i = 0, j = 0; i <= D3D12_SHADER_VISIBILITY_PIXEL; ++i)
+ {
+ if (push_constants[i].size)
+ {
+ push_constants[j] = push_constants[i];
+ push_constants[j].offset = offset;
+ push_constants_offset[i] = offset;
+ offset += push_constants[j].size;
+ ++j;
+ }
+ }
+ push_constant_count = j;
+ }
+
+ for (i = 0, j = 0; i < desc->NumParameters; ++i)
+ {
+ struct d3d12_root_constant *root_constant = &root_signature->parameters[i].u.constant;
+ const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i];
+ unsigned int idx;
+
+ if (p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS)
+ continue;
+
+ idx = push_constant_count == 1 ? 0 : p->ShaderVisibility;
+ offset = push_constants_offset[idx];
+ push_constants_offset[idx] += p->u.Constants.Num32BitValues * sizeof(uint32_t);
+
+ root_signature->parameters[i].parameter_type = p->ParameterType;
+ root_constant->stage_flags = push_constant_count == 1
+ ? push_constants[0].stageFlags : stage_flags_from_visibility(p->ShaderVisibility);
+ root_constant->offset = offset;
+
+ root_signature->root_constants[j].register_space = p->u.Constants.RegisterSpace;
+ root_signature->root_constants[j].register_index = p->u.Constants.ShaderRegister;
+ root_signature->root_constants[j].shader_visibility
+ = vkd3d_shader_visibility_from_d3d12(p->ShaderVisibility);
+ root_signature->root_constants[j].offset = offset;
+ root_signature->root_constants[j].size = p->u.Constants.Num32BitValues * sizeof(uint32_t);
+
+ ++j;
+ }
+
+ *push_constant_range_count = push_constant_count;
+
+ return S_OK;
+}
+
+struct vkd3d_descriptor_set_context
+{
+ VkDescriptorSetLayoutBinding *current_binding;
+ unsigned int descriptor_index;
+ uint32_t set_index;
+ uint32_t descriptor_binding;
+};
+
+static void d3d12_root_signature_append_vk_binding(struct d3d12_root_signature *root_signature,
+ enum vkd3d_shader_descriptor_type descriptor_type, unsigned int register_space, unsigned int register_idx,
+ bool buffer_descriptor, enum vkd3d_shader_visibility shader_visibility,
+ struct vkd3d_descriptor_set_context *context)
+{
+ struct vkd3d_shader_resource_binding *mapping
+ = &root_signature->descriptor_mapping[context->descriptor_index++];
+
+ mapping->type = descriptor_type;
+ mapping->register_space = register_space;
+ mapping->register_index = register_idx;
+ mapping->shader_visibility = shader_visibility;
+ mapping->flags = buffer_descriptor ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE;
+ mapping->binding.set = context->set_index;
+ mapping->binding.binding = context->descriptor_binding++;
+ mapping->binding.count = 1;
+}
+
+static uint32_t d3d12_root_signature_assign_vk_bindings(struct d3d12_root_signature *root_signature,
+ enum vkd3d_shader_descriptor_type descriptor_type, unsigned int register_space, unsigned int base_register_idx,
+ unsigned int binding_count, bool is_buffer_descriptor, bool duplicate_descriptors,
+ enum vkd3d_shader_visibility shader_visibility, struct vkd3d_descriptor_set_context *context)
+{
+ uint32_t first_binding;
+ unsigned int i;
+
+ is_buffer_descriptor |= descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV;
+ duplicate_descriptors = (descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV
+ || descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV)
+ && duplicate_descriptors;
+
+ first_binding = context->descriptor_binding;
+ for (i = 0; i < binding_count; ++i)
+ {
+ if (duplicate_descriptors)
+ d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, register_space,
+ base_register_idx + i, true, shader_visibility, context);
+
+ d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, register_space,
+ base_register_idx + i, is_buffer_descriptor, shader_visibility, context);
+ }
+ return first_binding;
+}
+
+static uint32_t vkd3d_descriptor_magic_from_d3d12(D3D12_DESCRIPTOR_RANGE_TYPE type)
+{
+ switch (type)
+ {
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
+ return VKD3D_DESCRIPTOR_MAGIC_SRV;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
+ return VKD3D_DESCRIPTOR_MAGIC_UAV;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
+ return VKD3D_DESCRIPTOR_MAGIC_CBV;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER:
+ return VKD3D_DESCRIPTOR_MAGIC_SAMPLER;
+ default:
+ ERR("Invalid range type %#x.\n", type);
+ return VKD3D_DESCRIPTOR_MAGIC_FREE;
+ }
+}
+
+static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_root_signature *root_signature,
+ const D3D12_ROOT_SIGNATURE_DESC *desc, struct vkd3d_descriptor_set_context *context)
+{
+ VkDescriptorSetLayoutBinding *cur_binding = context->current_binding;
+ struct d3d12_root_descriptor_table *table;
+ const D3D12_DESCRIPTOR_RANGE *range;
+ unsigned int i, j, k, range_count;
+ uint32_t vk_binding;
+
+ root_signature->descriptor_table_mask = 0;
+
+ for (i = 0; i < desc->NumParameters; ++i)
+ {
+ const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i];
+ if (p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
+ continue;
+
+ root_signature->descriptor_table_mask |= 1ull << i;
+
+ table = &root_signature->parameters[i].u.descriptor_table;
+ range_count = p->u.DescriptorTable.NumDescriptorRanges;
+
+ root_signature->parameters[i].parameter_type = p->ParameterType;
+ table->range_count = range_count;
+ if (!(table->ranges = vkd3d_calloc(table->range_count, sizeof(*table->ranges))))
+ return E_OUTOFMEMORY;
+
+ for (j = 0; j < range_count; ++j)
+ {
+ range = &p->u.DescriptorTable.pDescriptorRanges[j];
+
+ vk_binding = d3d12_root_signature_assign_vk_bindings(root_signature,
+ vkd3d_descriptor_type_from_d3d12_range_type(range->RangeType),
+ range->RegisterSpace, range->BaseShaderRegister, range->NumDescriptors, false, true,
+ vkd3d_shader_visibility_from_d3d12(p->ShaderVisibility), context);
+
+ /* Unroll descriptor range. */
+ for (k = 0; k < range->NumDescriptors; ++k)
+ {
+ uint32_t vk_current_binding = vk_binding + k;
+
+ if (range->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV
+ || range->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV)
+ {
+ vk_current_binding = vk_binding + 2 * k;
+
+ /* Assign binding for image view. */
+ if (!vk_binding_from_d3d12_descriptor_range(cur_binding,
+ range, p->ShaderVisibility, false, vk_current_binding + 1))
+ return E_NOTIMPL;
+
+ ++cur_binding;
+ }
+
+ if (!vk_binding_from_d3d12_descriptor_range(cur_binding,
+ range, p->ShaderVisibility, true, vk_current_binding))
+ return E_NOTIMPL;
+
+ ++cur_binding;
+ }
+
+ table->ranges[j].offset = range->OffsetInDescriptorsFromTableStart;
+ table->ranges[j].descriptor_count = range->NumDescriptors;
+ table->ranges[j].binding = vk_binding;
+ table->ranges[j].descriptor_magic = vkd3d_descriptor_magic_from_d3d12(range->RangeType);
+ table->ranges[j].register_space = range->RegisterSpace;
+ table->ranges[j].base_register_idx = range->BaseShaderRegister;
+ }
+ }
+
+ context->current_binding = cur_binding;
+ return S_OK;
+}
+
+static HRESULT d3d12_root_signature_init_root_descriptors(struct d3d12_root_signature *root_signature,
+ const D3D12_ROOT_SIGNATURE_DESC *desc, struct vkd3d_descriptor_set_context *context)
+{
+ VkDescriptorSetLayoutBinding *cur_binding = context->current_binding;
+ unsigned int i;
+
+ root_signature->push_descriptor_mask = 0;
+
+ for (i = 0; i < desc->NumParameters; ++i)
+ {
+ const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i];
+ if (p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_CBV
+ && p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_SRV
+ && p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_UAV)
+ continue;
+
+ root_signature->push_descriptor_mask |= 1u << i;
+
+ cur_binding->binding = d3d12_root_signature_assign_vk_bindings(root_signature,
+ vkd3d_descriptor_type_from_d3d12_root_parameter_type(p->ParameterType),
+ p->u.Descriptor.RegisterSpace, p->u.Descriptor.ShaderRegister, 1, true, false,
+ vkd3d_shader_visibility_from_d3d12(p->ShaderVisibility), context);
+ cur_binding->descriptorType = vk_descriptor_type_from_d3d12_root_parameter(p->ParameterType);
+ cur_binding->descriptorCount = 1;
+ cur_binding->stageFlags = stage_flags_from_visibility(p->ShaderVisibility);
+ cur_binding->pImmutableSamplers = NULL;
+
+ root_signature->parameters[i].parameter_type = p->ParameterType;
+ root_signature->parameters[i].u.descriptor.binding = cur_binding->binding;
+
+ ++cur_binding;
+ }
+
+ context->current_binding = cur_binding;
+ return S_OK;
+}
+
+static HRESULT d3d12_root_signature_init_static_samplers(struct d3d12_root_signature *root_signature,
+ struct d3d12_device *device, const D3D12_ROOT_SIGNATURE_DESC *desc,
+ struct vkd3d_descriptor_set_context *context)
+{
+ VkDescriptorSetLayoutBinding *cur_binding = context->current_binding;
+ unsigned int i;
+ HRESULT hr;
+
+ assert(root_signature->static_sampler_count == desc->NumStaticSamplers);
+ for (i = 0; i < desc->NumStaticSamplers; ++i)
+ {
+ const D3D12_STATIC_SAMPLER_DESC *s = &desc->pStaticSamplers[i];
+
+ if (FAILED(hr = vkd3d_create_static_sampler(device, s, &root_signature->static_samplers[i])))
+ return hr;
+
+ cur_binding->binding = d3d12_root_signature_assign_vk_bindings(root_signature,
+ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, s->RegisterSpace, s->ShaderRegister, 1, false, false,
+ vkd3d_shader_visibility_from_d3d12(s->ShaderVisibility), context);
+ cur_binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
+ cur_binding->descriptorCount = 1;
+ cur_binding->stageFlags = stage_flags_from_visibility(s->ShaderVisibility);
+ cur_binding->pImmutableSamplers = &root_signature->static_samplers[i];
+
+ ++cur_binding;
+ }
+
+ context->current_binding = cur_binding;
+ return S_OK;
+}
+
+static HRESULT vkd3d_create_descriptor_set_layout(struct d3d12_device *device,
+ VkDescriptorSetLayoutCreateFlags flags, unsigned int binding_count,
+ const VkDescriptorSetLayoutBinding *bindings, VkDescriptorSetLayout *set_layout)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkDescriptorSetLayoutCreateInfo set_desc;
+ VkResult vr;
+
+ set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ set_desc.pNext = NULL;
+ set_desc.flags = flags;
+ set_desc.bindingCount = binding_count;
+ set_desc.pBindings = bindings;
+ if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device->vk_device, &set_desc, NULL, set_layout))) < 0)
+ {
+ WARN("Failed to create Vulkan descriptor set layout, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ return S_OK;
+}
+
+static HRESULT vkd3d_create_pipeline_layout(struct d3d12_device *device,
+ unsigned int set_layout_count, const VkDescriptorSetLayout *set_layouts,
+ unsigned int push_constant_count, const VkPushConstantRange *push_constants,
+ VkPipelineLayout *pipeline_layout)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct VkPipelineLayoutCreateInfo pipeline_layout_info;
+ VkResult vr;
+
+ pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipeline_layout_info.pNext = NULL;
+ pipeline_layout_info.flags = 0;
+ pipeline_layout_info.setLayoutCount = set_layout_count;
+ pipeline_layout_info.pSetLayouts = set_layouts;
+ pipeline_layout_info.pushConstantRangeCount = push_constant_count;
+ pipeline_layout_info.pPushConstantRanges = push_constants;
+ if ((vr = VK_CALL(vkCreatePipelineLayout(device->vk_device,
+ &pipeline_layout_info, NULL, pipeline_layout))) < 0)
+ {
+ WARN("Failed to create Vulkan pipeline layout, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ return S_OK;
+}
+
+static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signature,
+ struct d3d12_device *device, const D3D12_ROOT_SIGNATURE_DESC *desc)
+{
+ const struct vkd3d_vulkan_info *vk_info = &device->vk_info;
+ struct vkd3d_descriptor_set_context context;
+ VkDescriptorSetLayoutBinding *binding_desc;
+ struct d3d12_root_signature_info info;
+ VkDescriptorSetLayout set_layouts[2];
+ HRESULT hr;
+
+ memset(&context, 0, sizeof(context));
+ binding_desc = NULL;
+
+ root_signature->ID3D12RootSignature_iface.lpVtbl = &d3d12_root_signature_vtbl;
+ root_signature->refcount = 1;
+
+ root_signature->vk_pipeline_layout = VK_NULL_HANDLE;
+ root_signature->vk_push_set_layout = VK_NULL_HANDLE;
+ root_signature->vk_set_layout = VK_NULL_HANDLE;
+ root_signature->parameters = NULL;
+ root_signature->flags = desc->Flags;
+ root_signature->descriptor_mapping = NULL;
+ root_signature->static_sampler_count = 0;
+ root_signature->static_samplers = NULL;
+
+ if (desc->Flags & ~(D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT
+ | D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT))
+ FIXME("Ignoring root signature flags %#x.\n", desc->Flags);
+
+ if (FAILED(hr = d3d12_root_signature_info_from_desc(&info, desc)))
+ return hr;
+ if (info.cost > D3D12_MAX_ROOT_COST)
+ {
+ WARN("Root signature cost %zu exceeds maximum allowed cost.\n", info.cost);
+ return E_INVALIDARG;
+ }
+
+ /* XXX: Vulkan buffer and image descriptors have different types. In order
+ * to preserve compatibility between Vulkan resource bindings for the same
+ * root signature, we create descriptor set layouts with two bindings for
+ * each SRV and UAV. */
+ info.descriptor_count += info.srv_count + info.uav_count;
+
+ root_signature->descriptor_count = info.descriptor_count;
+ root_signature->static_sampler_count = desc->NumStaticSamplers;
+ root_signature->root_descriptor_count = info.root_descriptor_count;
+
+ hr = E_OUTOFMEMORY;
+ root_signature->parameter_count = desc->NumParameters;
+ if (!(root_signature->parameters = vkd3d_calloc(root_signature->parameter_count,
+ sizeof(*root_signature->parameters))))
+ goto fail;
+ if (!(root_signature->descriptor_mapping = vkd3d_calloc(root_signature->descriptor_count,
+ sizeof(*root_signature->descriptor_mapping))))
+ goto fail;
+ root_signature->root_constant_count = info.root_constant_count;
+ if (!(root_signature->root_constants = vkd3d_calloc(root_signature->root_constant_count,
+ sizeof(*root_signature->root_constants))))
+ goto fail;
+ if (!(root_signature->static_samplers = vkd3d_calloc(root_signature->static_sampler_count,
+ sizeof(*root_signature->static_samplers))))
+ goto fail;
+
+ if (!(binding_desc = vkd3d_calloc(info.descriptor_count, sizeof(*binding_desc))))
+ goto fail;
+ context.current_binding = binding_desc;
+
+ if (FAILED(hr = d3d12_root_signature_init_root_descriptors(root_signature, desc, &context)))
+ goto fail;
+
+ /* We use KHR_push_descriptor for root descriptor parameters. */
+ if (vk_info->KHR_push_descriptor && context.descriptor_binding)
+ {
+ if (FAILED(hr = vkd3d_create_descriptor_set_layout(device,
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
+ context.descriptor_binding, binding_desc, &root_signature->vk_push_set_layout)))
+ goto fail;
+
+ set_layouts[context.set_index++] = root_signature->vk_push_set_layout;
+ context.current_binding = binding_desc;
+ context.descriptor_binding = 0;
+ }
+
+ if (FAILED(hr = d3d12_root_signature_init_push_constants(root_signature, desc, &info,
+ root_signature->push_constant_ranges, &root_signature->push_constant_range_count)))
+ goto fail;
+ if (FAILED(hr = d3d12_root_signature_init_root_descriptor_tables(root_signature, desc, &context)))
+ goto fail;
+ if (FAILED(hr = d3d12_root_signature_init_static_samplers(root_signature, device, desc, &context)))
+ goto fail;
+
+ root_signature->main_set = context.set_index;
+ if (context.descriptor_binding)
+ {
+ if (FAILED(hr = vkd3d_create_descriptor_set_layout(device,
+ 0, context.descriptor_binding, binding_desc, &root_signature->vk_set_layout)))
+ goto fail;
+
+ set_layouts[context.set_index++] = root_signature->vk_set_layout;
+ }
+ vkd3d_free(binding_desc);
+ binding_desc = NULL;
+
+ if (FAILED(hr = vkd3d_create_pipeline_layout(device, context.set_index, set_layouts,
+ root_signature->push_constant_range_count, root_signature->push_constant_ranges,
+ &root_signature->vk_pipeline_layout)))
+ goto fail;
+
+ if (FAILED(hr = vkd3d_private_store_init(&root_signature->private_store)))
+ goto fail;
+
+ d3d12_device_add_ref(root_signature->device = device);
+
+ return S_OK;
+
+fail:
+ vkd3d_free(binding_desc);
+ d3d12_root_signature_cleanup(root_signature, device);
+ return hr;
+}
+
+HRESULT d3d12_root_signature_create(struct d3d12_device *device,
+ const void *bytecode, size_t bytecode_length, struct d3d12_root_signature **root_signature)
+{
+ const struct vkd3d_shader_code dxbc = {bytecode, bytecode_length};
+ union
+ {
+ D3D12_VERSIONED_ROOT_SIGNATURE_DESC d3d12;
+ struct vkd3d_shader_versioned_root_signature_desc vkd3d;
+ } root_signature_desc;
+ struct d3d12_root_signature *object;
+ HRESULT hr;
+ int ret;
+
+ if ((ret = vkd3d_parse_root_signature_v_1_0(&dxbc, &root_signature_desc.vkd3d)) < 0)
+ {
+ WARN("Failed to parse root signature, vkd3d result %d.\n", ret);
+ return hresult_from_vkd3d_result(ret);
+ }
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ {
+ vkd3d_shader_free_root_signature(&root_signature_desc.vkd3d);
+ return E_OUTOFMEMORY;
+ }
+
+ hr = d3d12_root_signature_init(object, device, &root_signature_desc.d3d12.u.Desc_1_0);
+ vkd3d_shader_free_root_signature(&root_signature_desc.vkd3d);
+ if (FAILED(hr))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created root signature %p.\n", object);
+
+ *root_signature = object;
+
+ return S_OK;
+}
+
+/* vkd3d_render_pass_cache */
+struct vkd3d_render_pass_entry
+{
+ struct vkd3d_render_pass_key key;
+ VkRenderPass vk_render_pass;
+};
+
+STATIC_ASSERT(sizeof(struct vkd3d_render_pass_key) == 48);
+
+static HRESULT vkd3d_render_pass_cache_create_pass_locked(struct vkd3d_render_pass_cache *cache,
+ struct d3d12_device *device, const struct vkd3d_render_pass_key *key, VkRenderPass *vk_render_pass)
+{
+ VkAttachmentReference attachment_references[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT + 1];
+ VkAttachmentDescription attachments[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT + 1];
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_render_pass_entry *entry;
+ unsigned int index, attachment_index;
+ VkSubpassDescription sub_pass_desc;
+ VkRenderPassCreateInfo pass_info;
+ bool have_depth_stencil;
+ unsigned int rt_count;
+ VkResult vr;
+
+ if (!vkd3d_array_reserve((void **)&cache->render_passes, &cache->render_passes_size,
+ cache->render_pass_count + 1, sizeof(*cache->render_passes)))
+ {
+ *vk_render_pass = VK_NULL_HANDLE;
+ return E_OUTOFMEMORY;
+ }
+
+ entry = &cache->render_passes[cache->render_pass_count];
+
+ entry->key = *key;
+
+ have_depth_stencil = key->depth_enable || key->stencil_enable;
+ rt_count = have_depth_stencil ? key->attachment_count - 1 : key->attachment_count;
+ assert(rt_count <= D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT);
+
+ for (index = 0, attachment_index = 0; index < rt_count; ++index)
+ {
+ if (!key->vk_formats[index])
+ {
+ attachment_references[index].attachment = VK_ATTACHMENT_UNUSED;
+ attachment_references[index].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ continue;
+ }
+
+ attachments[attachment_index].flags = 0;
+ attachments[attachment_index].format = key->vk_formats[index];
+ attachments[attachment_index].samples = key->sample_count;
+ attachments[attachment_index].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ attachments[attachment_index].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachments[attachment_index].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachments[attachment_index].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachments[attachment_index].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attachments[attachment_index].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ attachment_references[index].attachment = attachment_index;
+ attachment_references[index].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ ++attachment_index;
+ }
+
+ if (have_depth_stencil)
+ {
+ VkImageLayout depth_layout = key->depth_stencil_write
+ ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
+ : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
+
+ attachments[attachment_index].flags = 0;
+ attachments[attachment_index].format = key->vk_formats[index];
+ attachments[attachment_index].samples = key->sample_count;
+
+ if (key->depth_enable)
+ {
+ attachments[attachment_index].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ attachments[attachment_index].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ }
+ else
+ {
+ attachments[attachment_index].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachments[attachment_index].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ }
+ if (key->stencil_enable)
+ {
+ attachments[attachment_index].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ attachments[attachment_index].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+ }
+ else
+ {
+ attachments[attachment_index].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachments[attachment_index].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ }
+ attachments[attachment_index].initialLayout = depth_layout;
+ attachments[attachment_index].finalLayout = depth_layout;
+
+ attachment_references[index].attachment = attachment_index;
+ attachment_references[index].layout = depth_layout;
+
+ attachment_index++;
+ }
+
+ sub_pass_desc.flags = 0;
+ sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ sub_pass_desc.inputAttachmentCount = 0;
+ sub_pass_desc.pInputAttachments = NULL;
+ sub_pass_desc.colorAttachmentCount = rt_count;
+ sub_pass_desc.pColorAttachments = attachment_references;
+ sub_pass_desc.pResolveAttachments = NULL;
+ if (have_depth_stencil)
+ sub_pass_desc.pDepthStencilAttachment = &attachment_references[rt_count];
+ else
+ sub_pass_desc.pDepthStencilAttachment = NULL;
+ sub_pass_desc.preserveAttachmentCount = 0;
+ sub_pass_desc.pPreserveAttachments = NULL;
+
+ pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ pass_info.pNext = NULL;
+ pass_info.flags = 0;
+ pass_info.attachmentCount = attachment_index;
+ pass_info.pAttachments = attachments;
+ pass_info.subpassCount = 1;
+ pass_info.pSubpasses = &sub_pass_desc;
+ pass_info.dependencyCount = 0;
+ pass_info.pDependencies = NULL;
+ if ((vr = VK_CALL(vkCreateRenderPass(device->vk_device, &pass_info, NULL, vk_render_pass))) >= 0)
+ {
+ entry->vk_render_pass = *vk_render_pass;
+ ++cache->render_pass_count;
+ }
+ else
+ {
+ WARN("Failed to create Vulkan render pass, vr %d.\n", vr);
+ *vk_render_pass = VK_NULL_HANDLE;
+ }
+
+ return hresult_from_vk_result(vr);
+}
+
+HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache,
+ struct d3d12_device *device, const struct vkd3d_render_pass_key *key, VkRenderPass *vk_render_pass)
+{
+ bool found = false;
+ HRESULT hr = S_OK;
+ unsigned int i;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&device->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ *vk_render_pass = VK_NULL_HANDLE;
+ return hresult_from_errno(rc);
+ }
+
+ for (i = 0; i < cache->render_pass_count; ++i)
+ {
+ struct vkd3d_render_pass_entry *current = &cache->render_passes[i];
+
+ if (!memcmp(¤t->key, key, sizeof(*key)))
+ {
+ *vk_render_pass = current->vk_render_pass;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ hr = vkd3d_render_pass_cache_create_pass_locked(cache, device, key, vk_render_pass);
+
+ pthread_mutex_unlock(&device->mutex);
+
+ return hr;
+}
+
+void vkd3d_render_pass_cache_init(struct vkd3d_render_pass_cache *cache)
+{
+ cache->render_passes = NULL;
+ cache->render_pass_count = 0;
+ cache->render_passes_size = 0;
+}
+
+void vkd3d_render_pass_cache_cleanup(struct vkd3d_render_pass_cache *cache,
+ struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ unsigned int i;
+
+ for (i = 0; i < cache->render_pass_count; ++i)
+ {
+ struct vkd3d_render_pass_entry *current = &cache->render_passes[i];
+ VK_CALL(vkDestroyRenderPass(device->vk_device, current->vk_render_pass, NULL));
+ }
+
+ vkd3d_free(cache->render_passes);
+ cache->render_passes = NULL;
+}
+
+struct vkd3d_pipeline_key
+{
+ D3D12_PRIMITIVE_TOPOLOGY topology;
+ uint32_t strides[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ VkFormat dsv_format;
+};
+
+struct vkd3d_compiled_pipeline
+{
+ struct list entry;
+ struct vkd3d_pipeline_key key;
+ VkPipeline vk_pipeline;
+ VkRenderPass vk_render_pass;
+};
+
+/* ID3D12PipelineState */
+static inline struct d3d12_pipeline_state *impl_from_ID3D12PipelineState(ID3D12PipelineState *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_pipeline_state, ID3D12PipelineState_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_pipeline_state_QueryInterface(ID3D12PipelineState *iface,
+ REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3D12PipelineState)
+ || IsEqualGUID(riid, &IID_ID3D12Pageable)
+ || IsEqualGUID(riid, &IID_ID3D12DeviceChild)
+ || IsEqualGUID(riid, &IID_ID3D12Object)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D12PipelineState_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_pipeline_state_AddRef(ID3D12PipelineState *iface)
+{
+ struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface);
+ ULONG refcount = InterlockedIncrement(&state->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", state, refcount);
+
+ return refcount;
+}
+
+static void d3d12_pipeline_state_destroy_graphics(struct d3d12_pipeline_state *state,
+ struct d3d12_device *device)
+{
+ struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_compiled_pipeline *current, *e;
+ unsigned int i;
+
+ for (i = 0; i < graphics->stage_count; ++i)
+ {
+ VK_CALL(vkDestroyShaderModule(device->vk_device, graphics->stages[i].module, NULL));
+ }
+
+ LIST_FOR_EACH_ENTRY_SAFE(current, e, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry)
+ {
+ VK_CALL(vkDestroyPipeline(device->vk_device, current->vk_pipeline, NULL));
+ vkd3d_free(current);
+ }
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_pipeline_state_Release(ID3D12PipelineState *iface)
+{
+ struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface);
+ ULONG refcount = InterlockedDecrement(&state->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", state, refcount);
+
+ if (!refcount)
+ {
+ struct d3d12_device *device = state->device;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ vkd3d_private_store_destroy(&state->private_store);
+
+ if (d3d12_pipeline_state_is_graphics(state))
+ d3d12_pipeline_state_destroy_graphics(state, device);
+ else if (d3d12_pipeline_state_is_compute(state))
+ VK_CALL(vkDestroyPipeline(device->vk_device, state->u.compute.vk_pipeline, NULL));
+
+ if (state->vk_set_layout)
+ VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, state->vk_set_layout, NULL));
+ if (state->vk_pipeline_layout)
+ VK_CALL(vkDestroyPipelineLayout(device->vk_device, state->vk_pipeline_layout, NULL));
+
+ vkd3d_free(state->uav_counters);
+
+ vkd3d_free(state);
+
+ d3d12_device_release(device);
+ }
+
+ return refcount;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_pipeline_state_GetPrivateData(ID3D12PipelineState *iface,
+ REFGUID guid, UINT *data_size, void *data)
+{
+ struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface);
+
+ TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_get_private_data(&state->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_pipeline_state_SetPrivateData(ID3D12PipelineState *iface,
+ REFGUID guid, UINT data_size, const void *data)
+{
+ struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface);
+
+ TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+ return vkd3d_set_private_data(&state->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_pipeline_state_SetPrivateDataInterface(ID3D12PipelineState *iface,
+ REFGUID guid, const IUnknown *data)
+{
+ struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface);
+
+ TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+ return vkd3d_set_private_data_interface(&state->private_store, guid, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_pipeline_state_SetName(ID3D12PipelineState *iface, const WCHAR *name)
+{
+ struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface);
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, state->device->wchar_size));
+
+ if (d3d12_pipeline_state_is_compute(state))
+ {
+ return vkd3d_set_vk_object_name(state->device, (uint64_t)state->u.compute.vk_pipeline,
+ VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, name);
+ }
+
+ return name ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_pipeline_state_GetDevice(ID3D12PipelineState *iface,
+ REFIID iid, void **device)
+{
+ struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface);
+
+ TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
+
+ return d3d12_device_query_interface(state->device, iid, device);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_pipeline_state_GetCachedBlob(ID3D12PipelineState *iface,
+ ID3DBlob **blob)
+{
+ FIXME("iface %p, blob %p stub!\n", iface, blob);
+
+ return E_NOTIMPL;
+}
+
+static const struct ID3D12PipelineStateVtbl d3d12_pipeline_state_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_pipeline_state_QueryInterface,
+ d3d12_pipeline_state_AddRef,
+ d3d12_pipeline_state_Release,
+ /* ID3D12Object methods */
+ d3d12_pipeline_state_GetPrivateData,
+ d3d12_pipeline_state_SetPrivateData,
+ d3d12_pipeline_state_SetPrivateDataInterface,
+ d3d12_pipeline_state_SetName,
+ /* ID3D12DeviceChild methods */
+ d3d12_pipeline_state_GetDevice,
+ /* ID3D12PipelineState methods */
+ d3d12_pipeline_state_GetCachedBlob,
+};
+
+struct d3d12_pipeline_state *unsafe_impl_from_ID3D12PipelineState(ID3D12PipelineState *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d3d12_pipeline_state_vtbl);
+ return impl_from_ID3D12PipelineState(iface);
+}
+
+static HRESULT create_shader_stage(struct d3d12_device *device,
+ struct VkPipelineShaderStageCreateInfo *stage_desc, enum VkShaderStageFlagBits stage,
+ const D3D12_SHADER_BYTECODE *code, const struct vkd3d_shader_interface_info *shader_interface)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_shader_compile_info compile_info;
+ struct VkShaderModuleCreateInfo shader_desc;
+ struct vkd3d_shader_code spirv = {0};
+ VkResult vr;
+ int ret;
+
+ stage_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ stage_desc->pNext = NULL;
+ stage_desc->flags = 0;
+ stage_desc->stage = stage;
+ stage_desc->pName = "main";
+ stage_desc->pSpecializationInfo = NULL;
+
+ shader_desc.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shader_desc.pNext = NULL;
+ shader_desc.flags = 0;
+
+ compile_info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;
+ compile_info.next = shader_interface;
+ compile_info.source.code = code->pShaderBytecode;
+ compile_info.source.size = code->BytecodeLength;
+ compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF;
+ compile_info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY;
+ compile_info.options = NULL;
+ compile_info.option_count = 0;
+ compile_info.log_level = VKD3D_SHADER_LOG_NONE;
+ compile_info.source_name = NULL;
+
+ if ((ret = vkd3d_shader_compile(&compile_info, &spirv, NULL)) < 0)
+ {
+ WARN("Failed to compile shader, vkd3d result %d.\n", ret);
+ return hresult_from_vkd3d_result(ret);
+ }
+ shader_desc.codeSize = spirv.size;
+ shader_desc.pCode = spirv.code;
+
+ vr = VK_CALL(vkCreateShaderModule(device->vk_device, &shader_desc, NULL, &stage_desc->module));
+ vkd3d_shader_free_shader_code(&spirv);
+ if (vr < 0)
+ {
+ WARN("Failed to create Vulkan shader module, vr %d.\n", vr);
+ return hresult_from_vk_result(vr);
+ }
+
+ return S_OK;
+}
+
+static int vkd3d_scan_dxbc(const D3D12_SHADER_BYTECODE *code,
+ struct vkd3d_shader_scan_descriptor_info *descriptor_info)
+{
+ struct vkd3d_shader_compile_info compile_info;
+
+ compile_info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;
+ compile_info.next = descriptor_info;
+ compile_info.source.code = code->pShaderBytecode;
+ compile_info.source.size = code->BytecodeLength;
+ compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF;
+ compile_info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY;
+ compile_info.options = NULL;
+ compile_info.option_count = 0;
+ compile_info.log_level = VKD3D_SHADER_LOG_NONE;
+ compile_info.source_name = NULL;
+
+ return vkd3d_shader_scan(&compile_info, NULL);
+}
+
+static HRESULT vkd3d_create_compute_pipeline(struct d3d12_device *device,
+ const D3D12_SHADER_BYTECODE *code, const struct vkd3d_shader_interface_info *shader_interface,
+ VkPipelineLayout vk_pipeline_layout, VkPipeline *vk_pipeline)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkComputePipelineCreateInfo pipeline_info;
+ VkResult vr;
+ HRESULT hr;
+
+ pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
+ pipeline_info.pNext = NULL;
+ pipeline_info.flags = 0;
+ if (FAILED(hr = create_shader_stage(device, &pipeline_info.stage,
+ VK_SHADER_STAGE_COMPUTE_BIT, code, shader_interface)))
+ return hr;
+ pipeline_info.layout = vk_pipeline_layout;
+ pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
+ pipeline_info.basePipelineIndex = -1;
+
+ vr = VK_CALL(vkCreateComputePipelines(device->vk_device,
+ VK_NULL_HANDLE, 1, &pipeline_info, NULL, vk_pipeline));
+ VK_CALL(vkDestroyShaderModule(device->vk_device, pipeline_info.stage.module, NULL));
+ if (vr < 0)
+ {
+ WARN("Failed to create Vulkan compute pipeline, hr %#x.", hr);
+ return hresult_from_vk_result(vr);
+ }
+
+ return S_OK;
+}
+
+static HRESULT d3d12_pipeline_state_init_compute_uav_counters(struct d3d12_pipeline_state *state,
+ struct d3d12_device *device, const struct d3d12_root_signature *root_signature,
+ const struct vkd3d_shader_scan_descriptor_info *shader_info)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_descriptor_set_context context;
+ VkDescriptorSetLayoutBinding *binding_desc;
+ VkDescriptorSetLayout set_layouts[3];
+ unsigned int uav_counter_count = 0;
+ unsigned int i, j;
+ HRESULT hr;
+
+ for (i = 0; i < shader_info->descriptor_count; ++i)
+ {
+ const struct vkd3d_shader_descriptor_info *d = &shader_info->descriptors[i];
+
+ if (d->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV
+ && (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER))
+ ++uav_counter_count;
+ }
+
+ if (!uav_counter_count)
+ return S_OK;
+
+ if (!(binding_desc = vkd3d_calloc(uav_counter_count, sizeof(*binding_desc))))
+ return E_OUTOFMEMORY;
+ if (!(state->uav_counters = vkd3d_calloc(uav_counter_count, sizeof(*state->uav_counters))))
+ {
+ vkd3d_free(binding_desc);
+ return E_OUTOFMEMORY;
+ }
+ state->uav_counter_count = uav_counter_count;
+
+ memset(&context, 0, sizeof(context));
+ if (root_signature->vk_push_set_layout)
+ set_layouts[context.set_index++] = root_signature->vk_push_set_layout;
+ if (root_signature->vk_set_layout)
+ set_layouts[context.set_index++] = root_signature->vk_set_layout;
+
+ for (i = 0, j = 0; i < shader_info->descriptor_count; ++i)
+ {
+ const struct vkd3d_shader_descriptor_info *d = &shader_info->descriptors[i];
+
+ if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_UAV
+ || !(d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER))
+ continue;
+
+ state->uav_counters[j].register_space = d->register_space;
+ state->uav_counters[j].register_index = d->register_index;
+ state->uav_counters[j].shader_visibility = VKD3D_SHADER_VISIBILITY_COMPUTE;
+ state->uav_counters[j].binding.set = context.set_index;
+ state->uav_counters[j].binding.binding = context.descriptor_binding;
+ state->uav_counters[j].binding.count = 1;
+
+ /* FIXME: For the graphics pipeline we have to take the shader
+ * visibility into account. */
+ binding_desc[j].binding = context.descriptor_binding;
+ binding_desc[j].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ binding_desc[j].descriptorCount = 1;
+ binding_desc[j].stageFlags = VK_SHADER_STAGE_ALL;
+ binding_desc[j].pImmutableSamplers = NULL;
+
+ ++context.descriptor_binding;
+ ++j;
+ }
+
+ /* Create a descriptor set layout for UAV counters. */
+ hr = vkd3d_create_descriptor_set_layout(device,
+ 0, context.descriptor_binding, binding_desc, &state->vk_set_layout);
+ vkd3d_free(binding_desc);
+ if (FAILED(hr))
+ {
+ vkd3d_free(state->uav_counters);
+ return hr;
+ }
+
+ /* Create a pipeline layout which is compatible for all other descriptor
+ * sets with the root signature's pipeline layout.
+ */
+ state->set_index = context.set_index;
+ set_layouts[context.set_index++] = state->vk_set_layout;
+ if (FAILED(hr = vkd3d_create_pipeline_layout(device, context.set_index, set_layouts,
+ root_signature->push_constant_range_count, root_signature->push_constant_ranges,
+ &state->vk_pipeline_layout)))
+ {
+ VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, state->vk_set_layout, NULL));
+ vkd3d_free(state->uav_counters);
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *state,
+ struct d3d12_device *device, const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_shader_scan_descriptor_info shader_info;
+ struct vkd3d_shader_interface_info shader_interface;
+ const struct d3d12_root_signature *root_signature;
+ VkPipelineLayout vk_pipeline_layout;
+ HRESULT hr;
+ int ret;
+
+ state->ID3D12PipelineState_iface.lpVtbl = &d3d12_pipeline_state_vtbl;
+ state->refcount = 1;
+
+ state->vk_pipeline_layout = VK_NULL_HANDLE;
+ state->vk_set_layout = VK_NULL_HANDLE;
+ state->uav_counters = NULL;
+ state->uav_counter_count = 0;
+
+ if (!(root_signature = unsafe_impl_from_ID3D12RootSignature(desc->pRootSignature)))
+ {
+ WARN("Root signature is NULL.\n");
+ return E_INVALIDARG;
+ }
+
+ shader_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO;
+ shader_info.next = NULL;
+ if ((ret = vkd3d_scan_dxbc(&desc->CS, &shader_info)) < 0)
+ {
+ WARN("Failed to scan shader bytecode, vkd3d result %d.\n", ret);
+ return hresult_from_vkd3d_result(ret);
+ }
+
+ if (FAILED(hr = d3d12_pipeline_state_init_compute_uav_counters(state,
+ device, root_signature, &shader_info)))
+ {
+ WARN("Failed to create descriptor set layout for UAV counters, hr %#x.\n", hr);
+ return hr;
+ }
+ vkd3d_shader_free_scan_descriptor_info(&shader_info);
+
+ shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
+ shader_interface.next = NULL;
+ shader_interface.bindings = root_signature->descriptor_mapping;
+ shader_interface.binding_count = root_signature->descriptor_count;
+ shader_interface.push_constant_buffers = root_signature->root_constants;
+ shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
+ shader_interface.combined_samplers = NULL;
+ shader_interface.combined_sampler_count = 0;
+ shader_interface.uav_counters = state->uav_counters;
+ shader_interface.uav_counter_count = state->uav_counter_count;
+
+ vk_pipeline_layout = state->vk_pipeline_layout
+ ? state->vk_pipeline_layout : root_signature->vk_pipeline_layout;
+ if (FAILED(hr = vkd3d_create_compute_pipeline(device, &desc->CS, &shader_interface,
+ vk_pipeline_layout, &state->u.compute.vk_pipeline)))
+ {
+ WARN("Failed to create Vulkan compute pipeline, hr %#x.\n", hr);
+ if (state->vk_set_layout)
+ VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, state->vk_set_layout, NULL));
+ if (state->vk_pipeline_layout)
+ VK_CALL(vkDestroyPipelineLayout(device->vk_device, state->vk_pipeline_layout, NULL));
+ vkd3d_free(state->uav_counters);
+ return hr;
+ }
+
+ if (FAILED(hr = vkd3d_private_store_init(&state->private_store)))
+ {
+ VK_CALL(vkDestroyPipeline(device->vk_device, state->u.compute.vk_pipeline, NULL));
+ if (state->vk_set_layout)
+ VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, state->vk_set_layout, NULL));
+ if (state->vk_pipeline_layout)
+ VK_CALL(vkDestroyPipelineLayout(device->vk_device, state->vk_pipeline_layout, NULL));
+ vkd3d_free(state->uav_counters);
+ return hr;
+ }
+
+ state->vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
+ d3d12_device_add_ref(state->device = device);
+
+ return S_OK;
+}
+
+HRESULT d3d12_pipeline_state_create_compute(struct d3d12_device *device,
+ const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state)
+{
+ struct d3d12_pipeline_state *object;
+ HRESULT hr;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_pipeline_state_init_compute(object, device, desc)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created compute pipeline state %p.\n", object);
+
+ *state = object;
+
+ return S_OK;
+}
+
+static enum VkPolygonMode vk_polygon_mode_from_d3d12(D3D12_FILL_MODE mode)
+{
+ switch (mode)
+ {
+ case D3D12_FILL_MODE_WIREFRAME:
+ return VK_POLYGON_MODE_LINE;
+ case D3D12_FILL_MODE_SOLID:
+ return VK_POLYGON_MODE_FILL;
+ default:
+ FIXME("Unhandled fill mode %#x.\n", mode);
+ return VK_POLYGON_MODE_FILL;
+ }
+}
+
+static enum VkCullModeFlagBits vk_cull_mode_from_d3d12(D3D12_CULL_MODE mode)
+{
+ switch (mode)
+ {
+ case D3D12_CULL_MODE_NONE:
+ return VK_CULL_MODE_NONE;
+ case D3D12_CULL_MODE_FRONT:
+ return VK_CULL_MODE_FRONT_BIT;
+ case D3D12_CULL_MODE_BACK:
+ return VK_CULL_MODE_BACK_BIT;
+ default:
+ FIXME("Unhandled cull mode %#x.\n", mode);
+ return VK_CULL_MODE_NONE;
+ }
+}
+
+static void rs_desc_from_d3d12(VkPipelineRasterizationStateCreateInfo *vk_desc,
+ const D3D12_RASTERIZER_DESC *d3d12_desc)
+{
+ vk_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ vk_desc->pNext = NULL;
+ vk_desc->flags = 0;
+ vk_desc->depthClampEnable = !d3d12_desc->DepthClipEnable;
+ vk_desc->rasterizerDiscardEnable = VK_FALSE;
+ vk_desc->polygonMode = vk_polygon_mode_from_d3d12(d3d12_desc->FillMode);
+ vk_desc->cullMode = vk_cull_mode_from_d3d12(d3d12_desc->CullMode);
+ vk_desc->frontFace = d3d12_desc->FrontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
+ vk_desc->depthBiasEnable = d3d12_desc->DepthBias || d3d12_desc->SlopeScaledDepthBias;
+ vk_desc->depthBiasConstantFactor = d3d12_desc->DepthBias;
+ vk_desc->depthBiasClamp = d3d12_desc->DepthBiasClamp;
+ vk_desc->depthBiasSlopeFactor = d3d12_desc->SlopeScaledDepthBias;
+ vk_desc->lineWidth = 1.0f;
+
+ if (d3d12_desc->MultisampleEnable)
+ FIXME_ONCE("Ignoring MultisampleEnable %#x.\n", d3d12_desc->MultisampleEnable);
+ if (d3d12_desc->AntialiasedLineEnable)
+ FIXME_ONCE("Ignoring AntialiasedLineEnable %#x.\n", d3d12_desc->AntialiasedLineEnable);
+ if (d3d12_desc->ForcedSampleCount)
+ FIXME("Ignoring ForcedSampleCount %#x.\n", d3d12_desc->ForcedSampleCount);
+ if (d3d12_desc->ConservativeRaster)
+ FIXME("Ignoring ConservativeRaster %#x.\n", d3d12_desc->ConservativeRaster);
+}
+
+static void rs_depth_clip_info_from_d3d12(VkPipelineRasterizationDepthClipStateCreateInfoEXT *depth_clip_info,
+ VkPipelineRasterizationStateCreateInfo *vk_rs_desc, const D3D12_RASTERIZER_DESC *d3d12_desc)
+{
+ vk_rs_desc->depthClampEnable = VK_TRUE;
+
+ depth_clip_info->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT;
+ depth_clip_info->pNext = NULL;
+ depth_clip_info->flags = 0;
+ depth_clip_info->depthClipEnable = d3d12_desc->DepthClipEnable;
+
+ vk_prepend_struct(vk_rs_desc, depth_clip_info);
+}
+
+static void rs_stream_info_from_d3d12(VkPipelineRasterizationStateStreamCreateInfoEXT *stream_info,
+ VkPipelineRasterizationStateCreateInfo *vk_rs_desc, const D3D12_STREAM_OUTPUT_DESC *so_desc,
+ const struct vkd3d_vulkan_info *vk_info)
+{
+ if (!so_desc->RasterizedStream || so_desc->RasterizedStream == D3D12_SO_NO_RASTERIZED_STREAM)
+ return;
+
+ if (!vk_info->rasterization_stream)
+ {
+ FIXME("Rasterization stream select is not supported by Vulkan implementation.\n");
+ return;
+ }
+
+ stream_info->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT;
+ stream_info->pNext = NULL;
+ stream_info->flags = 0;
+ stream_info->rasterizationStream = so_desc->RasterizedStream;
+
+ vk_prepend_struct(vk_rs_desc, stream_info);
+}
+
+static enum VkStencilOp vk_stencil_op_from_d3d12(D3D12_STENCIL_OP op)
+{
+ switch (op)
+ {
+ case D3D12_STENCIL_OP_KEEP:
+ return VK_STENCIL_OP_KEEP;
+ case D3D12_STENCIL_OP_ZERO:
+ return VK_STENCIL_OP_ZERO;
+ case D3D12_STENCIL_OP_REPLACE:
+ return VK_STENCIL_OP_REPLACE;
+ case D3D12_STENCIL_OP_INCR_SAT:
+ return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
+ case D3D12_STENCIL_OP_DECR_SAT:
+ return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
+ case D3D12_STENCIL_OP_INVERT:
+ return VK_STENCIL_OP_INVERT;
+ case D3D12_STENCIL_OP_INCR:
+ return VK_STENCIL_OP_INCREMENT_AND_WRAP;
+ case D3D12_STENCIL_OP_DECR:
+ return VK_STENCIL_OP_DECREMENT_AND_WRAP;
+ default:
+ FIXME("Unhandled stencil op %#x.\n", op);
+ return VK_STENCIL_OP_KEEP;
+ }
+}
+
+enum VkCompareOp vk_compare_op_from_d3d12(D3D12_COMPARISON_FUNC op)
+{
+ switch (op)
+ {
+ case D3D12_COMPARISON_FUNC_NEVER:
+ return VK_COMPARE_OP_NEVER;
+ case D3D12_COMPARISON_FUNC_LESS:
+ return VK_COMPARE_OP_LESS;
+ case D3D12_COMPARISON_FUNC_EQUAL:
+ return VK_COMPARE_OP_EQUAL;
+ case D3D12_COMPARISON_FUNC_LESS_EQUAL:
+ return VK_COMPARE_OP_LESS_OR_EQUAL;
+ case D3D12_COMPARISON_FUNC_GREATER:
+ return VK_COMPARE_OP_GREATER;
+ case D3D12_COMPARISON_FUNC_NOT_EQUAL:
+ return VK_COMPARE_OP_NOT_EQUAL;
+ case D3D12_COMPARISON_FUNC_GREATER_EQUAL:
+ return VK_COMPARE_OP_GREATER_OR_EQUAL;
+ case D3D12_COMPARISON_FUNC_ALWAYS:
+ return VK_COMPARE_OP_ALWAYS;
+ default:
+ FIXME("Unhandled compare op %#x.\n", op);
+ return VK_COMPARE_OP_NEVER;
+ }
+}
+
+static void vk_stencil_op_state_from_d3d12(struct VkStencilOpState *vk_desc,
+ const D3D12_DEPTH_STENCILOP_DESC *d3d12_desc, uint32_t compare_mask, uint32_t write_mask)
+{
+ vk_desc->failOp = vk_stencil_op_from_d3d12(d3d12_desc->StencilFailOp);
+ vk_desc->passOp = vk_stencil_op_from_d3d12(d3d12_desc->StencilPassOp);
+ vk_desc->depthFailOp = vk_stencil_op_from_d3d12(d3d12_desc->StencilDepthFailOp);
+ vk_desc->compareOp = vk_compare_op_from_d3d12(d3d12_desc->StencilFunc);
+ vk_desc->compareMask = compare_mask;
+ vk_desc->writeMask = write_mask;
+ /* The stencil reference value is a dynamic state. Set by OMSetStencilRef(). */
+ vk_desc->reference = 0;
+}
+
+static void ds_desc_from_d3d12(struct VkPipelineDepthStencilStateCreateInfo *vk_desc,
+ const D3D12_DEPTH_STENCIL_DESC *d3d12_desc)
+{
+ memset(vk_desc, 0, sizeof(*vk_desc));
+ vk_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ vk_desc->pNext = NULL;
+ vk_desc->flags = 0;
+ if ((vk_desc->depthTestEnable = d3d12_desc->DepthEnable))
+ {
+ vk_desc->depthWriteEnable = d3d12_desc->DepthWriteMask & D3D12_DEPTH_WRITE_MASK_ALL;
+ vk_desc->depthCompareOp = vk_compare_op_from_d3d12(d3d12_desc->DepthFunc);
+ }
+ else
+ {
+ vk_desc->depthWriteEnable = VK_FALSE;
+ vk_desc->depthCompareOp = VK_COMPARE_OP_NEVER;
+ }
+ vk_desc->depthBoundsTestEnable = VK_FALSE;
+ if ((vk_desc->stencilTestEnable = d3d12_desc->StencilEnable))
+ {
+ vk_stencil_op_state_from_d3d12(&vk_desc->front, &d3d12_desc->FrontFace,
+ d3d12_desc->StencilReadMask, d3d12_desc->StencilWriteMask);
+ vk_stencil_op_state_from_d3d12(&vk_desc->back, &d3d12_desc->BackFace,
+ d3d12_desc->StencilReadMask, d3d12_desc->StencilWriteMask);
+ }
+ else
+ {
+ memset(&vk_desc->front, 0, sizeof(vk_desc->front));
+ memset(&vk_desc->back, 0, sizeof(vk_desc->back));
+ }
+ vk_desc->minDepthBounds = 0.0f;
+ vk_desc->maxDepthBounds = 1.0f;
+}
+
+static enum VkBlendFactor vk_blend_factor_from_d3d12(D3D12_BLEND blend, bool alpha)
+{
+ switch (blend)
+ {
+ case D3D12_BLEND_ZERO:
+ return VK_BLEND_FACTOR_ZERO;
+ case D3D12_BLEND_ONE:
+ return VK_BLEND_FACTOR_ONE;
+ case D3D12_BLEND_SRC_COLOR:
+ return VK_BLEND_FACTOR_SRC_COLOR;
+ case D3D12_BLEND_INV_SRC_COLOR:
+ return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ case D3D12_BLEND_SRC_ALPHA:
+ return VK_BLEND_FACTOR_SRC_ALPHA;
+ case D3D12_BLEND_INV_SRC_ALPHA:
+ return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ case D3D12_BLEND_DEST_ALPHA:
+ return VK_BLEND_FACTOR_DST_ALPHA;
+ case D3D12_BLEND_INV_DEST_ALPHA:
+ return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
+ case D3D12_BLEND_DEST_COLOR:
+ return VK_BLEND_FACTOR_DST_COLOR;
+ case D3D12_BLEND_INV_DEST_COLOR:
+ return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
+ case D3D12_BLEND_SRC_ALPHA_SAT:
+ return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
+ case D3D12_BLEND_BLEND_FACTOR:
+ if (alpha)
+ return VK_BLEND_FACTOR_CONSTANT_ALPHA;
+ return VK_BLEND_FACTOR_CONSTANT_COLOR;
+ case D3D12_BLEND_INV_BLEND_FACTOR:
+ if (alpha)
+ return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
+ return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
+ case D3D12_BLEND_SRC1_COLOR:
+ return VK_BLEND_FACTOR_SRC1_COLOR;
+ case D3D12_BLEND_INV_SRC1_COLOR:
+ return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
+ case D3D12_BLEND_SRC1_ALPHA:
+ return VK_BLEND_FACTOR_SRC1_ALPHA;
+ case D3D12_BLEND_INV_SRC1_ALPHA:
+ return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
+ default:
+ FIXME("Unhandled blend %#x.\n", blend);
+ return VK_BLEND_FACTOR_ZERO;
+ }
+}
+
+static enum VkBlendOp vk_blend_op_from_d3d12(D3D12_BLEND_OP op)
+{
+ switch (op)
+ {
+ case D3D12_BLEND_OP_ADD:
+ return VK_BLEND_OP_ADD;
+ case D3D12_BLEND_OP_SUBTRACT:
+ return VK_BLEND_OP_SUBTRACT;
+ case D3D12_BLEND_OP_REV_SUBTRACT:
+ return VK_BLEND_OP_REVERSE_SUBTRACT;
+ case D3D12_BLEND_OP_MIN:
+ return VK_BLEND_OP_MIN;
+ case D3D12_BLEND_OP_MAX:
+ return VK_BLEND_OP_MAX;
+ default:
+ FIXME("Unhandled blend op %#x.\n", op);
+ return VK_BLEND_OP_ADD;
+ }
+}
+
+static void blend_attachment_from_d3d12(struct VkPipelineColorBlendAttachmentState *vk_desc,
+ const D3D12_RENDER_TARGET_BLEND_DESC *d3d12_desc)
+{
+ if (d3d12_desc->BlendEnable)
+ {
+ vk_desc->blendEnable = VK_TRUE;
+ vk_desc->srcColorBlendFactor = vk_blend_factor_from_d3d12(d3d12_desc->SrcBlend, false);
+ vk_desc->dstColorBlendFactor = vk_blend_factor_from_d3d12(d3d12_desc->DestBlend, false);
+ vk_desc->colorBlendOp = vk_blend_op_from_d3d12(d3d12_desc->BlendOp);
+ vk_desc->srcAlphaBlendFactor = vk_blend_factor_from_d3d12(d3d12_desc->SrcBlendAlpha, true);
+ vk_desc->dstAlphaBlendFactor = vk_blend_factor_from_d3d12(d3d12_desc->DestBlendAlpha, true);
+ vk_desc->alphaBlendOp = vk_blend_op_from_d3d12(d3d12_desc->BlendOpAlpha);
+ }
+ else
+ {
+ memset(vk_desc, 0, sizeof(*vk_desc));
+ }
+ vk_desc->colorWriteMask = 0;
+ if (d3d12_desc->RenderTargetWriteMask & D3D12_COLOR_WRITE_ENABLE_RED)
+ vk_desc->colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;
+ if (d3d12_desc->RenderTargetWriteMask & D3D12_COLOR_WRITE_ENABLE_GREEN)
+ vk_desc->colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;
+ if (d3d12_desc->RenderTargetWriteMask & D3D12_COLOR_WRITE_ENABLE_BLUE)
+ vk_desc->colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;
+ if (d3d12_desc->RenderTargetWriteMask & D3D12_COLOR_WRITE_ENABLE_ALPHA)
+ vk_desc->colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
+
+ if (d3d12_desc->LogicOpEnable)
+ FIXME("Ignoring LogicOpEnable %#x.\n", d3d12_desc->LogicOpEnable);
+}
+
+static bool is_dual_source_blending_blend(D3D12_BLEND b)
+{
+ return b == D3D12_BLEND_SRC1_COLOR || b == D3D12_BLEND_INV_SRC1_COLOR
+ || b == D3D12_BLEND_SRC1_ALPHA || b == D3D12_BLEND_INV_SRC1_ALPHA;
+}
+
+static bool is_dual_source_blending(const D3D12_RENDER_TARGET_BLEND_DESC *desc)
+{
+ return desc->BlendEnable
+ && (is_dual_source_blending_blend(desc->SrcBlend)
+ || is_dual_source_blending_blend(desc->DestBlend)
+ || is_dual_source_blending_blend(desc->SrcBlendAlpha)
+ || is_dual_source_blending_blend(desc->DestBlendAlpha));
+}
+
+static HRESULT compute_input_layout_offsets(const struct d3d12_device *device,
+ const D3D12_INPUT_LAYOUT_DESC *input_layout_desc, uint32_t *offsets)
+{
+ uint32_t input_slot_offsets[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT] = {0};
+ const D3D12_INPUT_ELEMENT_DESC *e;
+ const struct vkd3d_format *format;
+ unsigned int i;
+
+ if (input_layout_desc->NumElements > D3D12_VS_INPUT_REGISTER_COUNT)
+ {
+ FIXME("InputLayout.NumElements %u > %u, ignoring extra elements.\n",
+ input_layout_desc->NumElements, D3D12_VS_INPUT_REGISTER_COUNT);
+ }
+
+ for (i = 0; i < min(input_layout_desc->NumElements, D3D12_VS_INPUT_REGISTER_COUNT); ++i)
+ {
+ e = &input_layout_desc->pInputElementDescs[i];
+
+ if (e->InputSlot >= ARRAY_SIZE(input_slot_offsets))
+ {
+ WARN("Invalid input slot %#x.\n", e->InputSlot);
+ return E_INVALIDARG;
+ }
+
+ if (!(format = vkd3d_get_format(device, e->Format, false)))
+ {
+ WARN("Invalid input element format %#x.\n", e->Format);
+ return E_INVALIDARG;
+ }
+
+ if (e->AlignedByteOffset != D3D12_APPEND_ALIGNED_ELEMENT)
+ offsets[i] = e->AlignedByteOffset;
+ else
+ offsets[i] = input_slot_offsets[e->InputSlot];
+
+ input_slot_offsets[e->InputSlot] = align(offsets[i] + format->byte_count, 4);
+ }
+
+ return S_OK;
+}
+
+static unsigned int vkd3d_get_rt_format_swizzle(const struct vkd3d_format *format)
+{
+ if (format->dxgi_format == DXGI_FORMAT_A8_UNORM)
+ return VKD3D_SHADER_SWIZZLE(W, X, Y, Z);
+
+ return VKD3D_SHADER_NO_SWIZZLE;
+}
+
+STATIC_ASSERT(sizeof(struct vkd3d_shader_transform_feedback_element) == sizeof(D3D12_SO_DECLARATION_ENTRY));
+
+static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
+ struct d3d12_graphics_pipeline_state *graphics, struct d3d12_device *device,
+ VkFormat dynamic_dsv_format, VkRenderPass *vk_render_pass)
+{
+ struct vkd3d_render_pass_key key;
+ VkFormat dsv_format;
+ unsigned int i;
+
+ memcpy(key.vk_formats, graphics->rtv_formats, sizeof(graphics->rtv_formats));
+ key.attachment_count = graphics->rt_count;
+
+ if (!(dsv_format = graphics->dsv_format) && (graphics->null_attachment_mask & dsv_attachment_mask(graphics)))
+ dsv_format = dynamic_dsv_format;
+
+ if (dsv_format)
+ {
+ assert(graphics->ds_desc.front.writeMask == graphics->ds_desc.back.writeMask);
+ key.depth_enable = graphics->ds_desc.depthTestEnable;
+ key.stencil_enable = graphics->ds_desc.stencilTestEnable;
+ key.depth_stencil_write = graphics->ds_desc.depthWriteEnable
+ || graphics->ds_desc.front.writeMask;
+ key.vk_formats[key.attachment_count++] = dsv_format;
+ }
+ else
+ {
+ key.depth_enable = false;
+ key.stencil_enable = false;
+ key.depth_stencil_write = false;
+ }
+
+ if (key.attachment_count != ARRAY_SIZE(key.vk_formats))
+ key.vk_formats[ARRAY_SIZE(key.vk_formats) - 1] = VK_FORMAT_UNDEFINED;
+ for (i = key.attachment_count; i < ARRAY_SIZE(key.vk_formats); ++i)
+ assert(key.vk_formats[i] == VK_FORMAT_UNDEFINED);
+
+ key.padding = 0;
+ key.sample_count = graphics->ms_desc.rasterizationSamples;
+
+ return vkd3d_render_pass_cache_find(&device->render_pass_cache, device, &key, vk_render_pass);
+}
+
+static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *state,
+ struct d3d12_device *device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc)
+{
+ unsigned int ps_output_swizzle[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
+ struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics;
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ const D3D12_STREAM_OUTPUT_DESC *so_desc = &desc->StreamOutput;
+ VkVertexInputBindingDivisorDescriptionEXT *binding_divisor;
+ const struct vkd3d_vulkan_info *vk_info = &device->vk_info;
+ uint32_t instance_divisors[D3D12_VS_INPUT_REGISTER_COUNT];
+ uint32_t aligned_offsets[D3D12_VS_INPUT_REGISTER_COUNT];
+ struct vkd3d_shader_parameter ps_shader_parameters[1];
+ struct vkd3d_shader_transform_feedback_info xfb_info;
+ struct vkd3d_shader_spirv_target_info ps_target_info;
+ struct vkd3d_shader_interface_info shader_interface;
+ struct vkd3d_shader_spirv_target_info *target_info;
+ const struct d3d12_root_signature *root_signature;
+ struct vkd3d_shader_signature input_signature;
+ bool have_attachment, is_dsv_format_unknown;
+ VkShaderStageFlagBits xfb_stage = 0;
+ VkSampleCountFlagBits sample_count;
+ const struct vkd3d_format *format;
+ unsigned int instance_divisor;
+ VkVertexInputRate input_rate;
+ unsigned int i, j;
+ size_t rt_count;
+ uint32_t mask;
+ HRESULT hr;
+ int ret;
+
+ static const DWORD default_ps_code[] =
+ {
+#if 0
+ ps_4_0
+ ret
+#endif
+ 0x43425844, 0x19cbf606, 0x18f562b9, 0xdaeed4db, 0xc324aa46, 0x00000001, 0x00000060, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x52444853, 0x0000000c, 0x00000040, 0x00000003, 0x0100003e,
+ };
+ static const D3D12_SHADER_BYTECODE default_ps = {default_ps_code, sizeof(default_ps_code)};
+ static const struct
+ {
+ enum VkShaderStageFlagBits stage;
+ ptrdiff_t offset;
+ }
+ shader_stages[] =
+ {
+ {VK_SHADER_STAGE_VERTEX_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, VS)},
+ {VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, HS)},
+ {VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, DS)},
+ {VK_SHADER_STAGE_GEOMETRY_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, GS)},
+ {VK_SHADER_STAGE_FRAGMENT_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, PS)},
+ };
+
+ state->ID3D12PipelineState_iface.lpVtbl = &d3d12_pipeline_state_vtbl;
+ state->refcount = 1;
+
+ state->vk_pipeline_layout = VK_NULL_HANDLE;
+ state->vk_set_layout = VK_NULL_HANDLE;
+ state->uav_counters = NULL;
+ state->uav_counter_count = 0;
+ graphics->stage_count = 0;
+
+ memset(&input_signature, 0, sizeof(input_signature));
+
+ for (i = desc->NumRenderTargets; i < ARRAY_SIZE(desc->RTVFormats); ++i)
+ {
+ if (desc->RTVFormats[i] != DXGI_FORMAT_UNKNOWN)
+ {
+ WARN("Format must be set to DXGI_FORMAT_UNKNOWN for inactive render targets.\n");
+ return E_INVALIDARG;
+ }
+ }
+
+ if (!(root_signature = unsafe_impl_from_ID3D12RootSignature(desc->pRootSignature)))
+ {
+ WARN("Root signature is NULL.\n");
+ return E_INVALIDARG;
+ }
+
+ sample_count = vk_samples_from_dxgi_sample_desc(&desc->SampleDesc);
+ if (desc->SampleDesc.Count != 1 && desc->SampleDesc.Quality)
+ WARN("Ignoring sample quality %u.\n", desc->SampleDesc.Quality);
+
+ rt_count = desc->NumRenderTargets;
+ if (rt_count > ARRAY_SIZE(graphics->blend_attachments))
+ {
+ FIXME("NumRenderTargets %zu > %zu, ignoring extra formats.\n",
+ rt_count, ARRAY_SIZE(graphics->blend_attachments));
+ rt_count = ARRAY_SIZE(graphics->blend_attachments);
+ }
+
+ graphics->null_attachment_mask = 0;
+ for (i = 0; i < rt_count; ++i)
+ {
+ const D3D12_RENDER_TARGET_BLEND_DESC *rt_desc;
+
+ if (desc->RTVFormats[i] == DXGI_FORMAT_UNKNOWN)
+ {
+ graphics->null_attachment_mask |= 1u << i;
+ ps_output_swizzle[i] = VKD3D_SHADER_NO_SWIZZLE;
+ graphics->rtv_formats[i] = VK_FORMAT_UNDEFINED;
+ }
+ else if ((format = vkd3d_get_format(device, desc->RTVFormats[i], false)))
+ {
+ ps_output_swizzle[i] = vkd3d_get_rt_format_swizzle(format);
+ graphics->rtv_formats[i] = format->vk_format;
+ }
+ else
+ {
+ WARN("Invalid RTV format %#x.\n", desc->RTVFormats[i]);
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ rt_desc = &desc->BlendState.RenderTarget[desc->BlendState.IndependentBlendEnable ? i : 0];
+ if (desc->BlendState.IndependentBlendEnable && rt_desc->LogicOpEnable)
+ {
+ WARN("IndependentBlendEnable must be FALSE when logic operations are enabled.\n");
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+ if (rt_desc->BlendEnable && rt_desc->LogicOpEnable)
+ {
+ WARN("Only one of BlendEnable or LogicOpEnable can be set to TRUE.");
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ blend_attachment_from_d3d12(&graphics->blend_attachments[i], rt_desc);
+ }
+ for (i = rt_count; i < ARRAY_SIZE(graphics->rtv_formats); ++i)
+ graphics->rtv_formats[i] = VK_FORMAT_UNDEFINED;
+ graphics->rt_count = rt_count;
+
+ ds_desc_from_d3d12(&graphics->ds_desc, &desc->DepthStencilState);
+ if (desc->DSVFormat == DXGI_FORMAT_UNKNOWN
+ && graphics->ds_desc.depthTestEnable && !graphics->ds_desc.depthWriteEnable
+ && graphics->ds_desc.depthCompareOp == VK_COMPARE_OP_ALWAYS && !graphics->ds_desc.stencilTestEnable)
+ {
+ TRACE("Disabling depth test.\n");
+ graphics->ds_desc.depthTestEnable = VK_FALSE;
+ }
+
+ graphics->dsv_format = VK_FORMAT_UNDEFINED;
+ if (graphics->ds_desc.depthTestEnable || graphics->ds_desc.stencilTestEnable)
+ {
+ if (desc->DSVFormat == DXGI_FORMAT_UNKNOWN)
+ {
+ WARN("DSV format is DXGI_FORMAT_UNKNOWN.\n");
+ graphics->dsv_format = VK_FORMAT_UNDEFINED;
+ graphics->null_attachment_mask |= dsv_attachment_mask(graphics);
+ }
+ else if ((format = vkd3d_get_format(device, desc->DSVFormat, true)))
+ {
+ if (!(format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))
+ FIXME("Format %#x is not depth/stencil format.\n", format->dxgi_format);
+
+ graphics->dsv_format = format->vk_format;
+ }
+ else
+ {
+ WARN("Invalid DSV format %#x.\n", desc->DSVFormat);
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ if (!desc->PS.pShaderBytecode)
+ {
+ if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count],
+ VK_SHADER_STAGE_FRAGMENT_BIT, &default_ps, NULL)))
+ goto fail;
+
+ ++graphics->stage_count;
+ }
+ }
+
+ ps_shader_parameters[0].name = VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT;
+ ps_shader_parameters[0].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
+ ps_shader_parameters[0].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
+ ps_shader_parameters[0].u.immediate_constant.u.u32 = sample_count;
+
+ ps_target_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO;
+ ps_target_info.next = NULL;
+ ps_target_info.entry_point = "main";
+ ps_target_info.environment = VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0;
+ ps_target_info.extensions = vk_info->shader_extensions;
+ ps_target_info.extension_count = vk_info->shader_extension_count;
+ ps_target_info.parameters = ps_shader_parameters;
+ ps_target_info.parameter_count = ARRAY_SIZE(ps_shader_parameters);
+ ps_target_info.dual_source_blending = is_dual_source_blending(&desc->BlendState.RenderTarget[0]);
+ ps_target_info.output_swizzles = ps_output_swizzle;
+ ps_target_info.output_swizzle_count = rt_count;
+
+ if (ps_target_info.dual_source_blending && rt_count > 1)
+ {
+ WARN("Only one render target is allowed when dual source blending is used.\n");
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+ if (ps_target_info.dual_source_blending && desc->BlendState.IndependentBlendEnable)
+ {
+ for (i = 1; i < ARRAY_SIZE(desc->BlendState.RenderTarget); ++i)
+ {
+ if (desc->BlendState.RenderTarget[i].BlendEnable)
+ {
+ WARN("Blend enable cannot be set for render target %u when dual source blending is used.\n", i);
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+ }
+ }
+
+ graphics->xfb_enabled = false;
+ if (so_desc->NumEntries)
+ {
+ if (!(root_signature->flags & D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT))
+ {
+ WARN("Stream output is used without D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT.\n");
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ if (!vk_info->EXT_transform_feedback)
+ {
+ FIXME("Transform feedback is not supported by Vulkan implementation.\n");
+ hr = E_NOTIMPL;
+ goto fail;
+ }
+
+ graphics->xfb_enabled = true;
+
+ xfb_info.type = VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO;
+ xfb_info.next = NULL;
+
+ xfb_info.elements = (const struct vkd3d_shader_transform_feedback_element *)so_desc->pSODeclaration;
+ xfb_info.element_count = so_desc->NumEntries;
+ xfb_info.buffer_strides = so_desc->pBufferStrides;
+ xfb_info.buffer_stride_count = so_desc->NumStrides;
+
+ if (desc->GS.pShaderBytecode)
+ xfb_stage = VK_SHADER_STAGE_GEOMETRY_BIT;
+ else if (desc->DS.pShaderBytecode)
+ xfb_stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+ else
+ xfb_stage = VK_SHADER_STAGE_VERTEX_BIT;
+ }
+
+ shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
+ shader_interface.next = NULL;
+ shader_interface.bindings = root_signature->descriptor_mapping;
+ shader_interface.binding_count = root_signature->descriptor_count;
+ shader_interface.push_constant_buffers = root_signature->root_constants;
+ shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
+ shader_interface.combined_samplers = NULL;
+ shader_interface.combined_sampler_count = 0;
+ shader_interface.uav_counters = NULL;
+ shader_interface.uav_counter_count = 0;
+
+ for (i = 0; i < ARRAY_SIZE(shader_stages); ++i)
+ {
+ struct vkd3d_shader_scan_descriptor_info shader_info =
+ {
+ .type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO,
+ };
+ const D3D12_SHADER_BYTECODE *b = (const void *)((uintptr_t)desc + shader_stages[i].offset);
+ const struct vkd3d_shader_code dxbc = {b->pShaderBytecode, b->BytecodeLength};
+
+ if (!b->pShaderBytecode)
+ continue;
+
+ if ((ret = vkd3d_scan_dxbc(b, &shader_info)) < 0)
+ {
+ WARN("Failed to scan shader bytecode, stage %#x, vkd3d result %d.\n",
+ shader_stages[i].stage, ret);
+ hr = hresult_from_vkd3d_result(ret);
+ goto fail;
+ }
+ for (j = 0; j < shader_info.descriptor_count; ++j)
+ {
+ const struct vkd3d_shader_descriptor_info *d = &shader_info.descriptors[j];
+
+ if (d->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV
+ && (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER))
+ {
+ FIXME("UAV counters not implemented for graphics pipelines.\n");
+ break;
+ }
+ }
+ vkd3d_shader_free_scan_descriptor_info(&shader_info);
+
+ target_info = NULL;
+ switch (shader_stages[i].stage)
+ {
+ case VK_SHADER_STAGE_VERTEX_BIT:
+ if ((ret = vkd3d_shader_parse_input_signature(&dxbc, &input_signature, NULL)) < 0)
+ {
+ hr = hresult_from_vkd3d_result(ret);
+ goto fail;
+ }
+ break;
+
+ case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
+ case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
+ if (desc->PrimitiveTopologyType != D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH)
+ {
+ WARN("D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH must be used with tessellation shaders.\n");
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+ break;
+
+ case VK_SHADER_STAGE_GEOMETRY_BIT:
+ break;
+
+ case VK_SHADER_STAGE_FRAGMENT_BIT:
+ target_info = &ps_target_info;
+ break;
+
+ default:
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ shader_interface.next = shader_stages[i].stage == xfb_stage ? &xfb_info : NULL;
+ if (target_info)
+ {
+ target_info->next = shader_interface.next;
+ shader_interface.next = target_info;
+ }
+
+ if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count],
+ shader_stages[i].stage, b, &shader_interface)))
+ goto fail;
+
+ ++graphics->stage_count;
+ }
+
+ graphics->attribute_count = desc->InputLayout.NumElements;
+ if (graphics->attribute_count > ARRAY_SIZE(graphics->attributes))
+ {
+ FIXME("InputLayout.NumElements %zu > %zu, ignoring extra elements.\n",
+ graphics->attribute_count, ARRAY_SIZE(graphics->attributes));
+ graphics->attribute_count = ARRAY_SIZE(graphics->attributes);
+ }
+
+ if (graphics->attribute_count
+ && !(root_signature->flags & D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT))
+ {
+ WARN("Input layout is used without D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT.\n");
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ if (FAILED(hr = compute_input_layout_offsets(device, &desc->InputLayout, aligned_offsets)))
+ goto fail;
+
+ graphics->instance_divisor_count = 0;
+ for (i = 0, j = 0, mask = 0; i < graphics->attribute_count; ++i)
+ {
+ const D3D12_INPUT_ELEMENT_DESC *e = &desc->InputLayout.pInputElementDescs[i];
+ const struct vkd3d_shader_signature_element *signature_element;
+
+ if (!(format = vkd3d_get_format(device, e->Format, false)))
+ {
+ WARN("Invalid input element format %#x.\n", e->Format);
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ if (e->InputSlot >= ARRAY_SIZE(graphics->input_rates)
+ || e->InputSlot >= ARRAY_SIZE(instance_divisors))
+ {
+ WARN("Invalid input slot %#x.\n", e->InputSlot);
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ if (!(signature_element = vkd3d_shader_find_signature_element(&input_signature,
+ e->SemanticName, e->SemanticIndex, 0)))
+ {
+ WARN("Unused input element %u.\n", i);
+ continue;
+ }
+
+ graphics->attributes[j].location = signature_element->register_index;
+ graphics->attributes[j].binding = e->InputSlot;
+ graphics->attributes[j].format = format->vk_format;
+ if (e->AlignedByteOffset != D3D12_APPEND_ALIGNED_ELEMENT)
+ graphics->attributes[j].offset = e->AlignedByteOffset;
+ else
+ graphics->attributes[j].offset = aligned_offsets[i];
+ ++j;
+
+ switch (e->InputSlotClass)
+ {
+ case D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA:
+ input_rate = VK_VERTEX_INPUT_RATE_VERTEX;
+ instance_divisor = 1;
+ break;
+
+ case D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA:
+ input_rate = VK_VERTEX_INPUT_RATE_INSTANCE;
+ instance_divisor = e->InstanceDataStepRate;
+ if (instance_divisor > vk_info->max_vertex_attrib_divisor
+ || (!instance_divisor && !vk_info->vertex_attrib_zero_divisor))
+ {
+ FIXME("Instance divisor %u not supported by Vulkan implementation.\n", instance_divisor);
+ instance_divisor = 1;
+ }
+ break;
+
+ default:
+ FIXME("Unhandled input slot class %#x on input element %u.\n", e->InputSlotClass, i);
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ if (mask & (1u << e->InputSlot) && (graphics->input_rates[e->InputSlot] != input_rate
+ || instance_divisors[e->InputSlot] != instance_divisor))
+ {
+ FIXME("Input slot rate %#x, instance divisor %u on input element %u conflicts "
+ "with earlier input slot rate %#x, instance divisor %u.\n",
+ input_rate, instance_divisor, e->InputSlot,
+ graphics->input_rates[e->InputSlot], instance_divisors[e->InputSlot]);
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ graphics->input_rates[e->InputSlot] = input_rate;
+ instance_divisors[e->InputSlot] = instance_divisor;
+ if (instance_divisor != 1 && !(mask & (1u << e->InputSlot)))
+ {
+ binding_divisor = &graphics->instance_divisors[graphics->instance_divisor_count++];
+ binding_divisor->binding = e->InputSlot;
+ binding_divisor->divisor = instance_divisor;
+ }
+ mask |= 1u << e->InputSlot;
+ }
+ graphics->attribute_count = j;
+ vkd3d_shader_free_shader_signature(&input_signature);
+
+ switch (desc->IBStripCutValue)
+ {
+ case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED:
+ case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF:
+ case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF:
+ graphics->index_buffer_strip_cut_value = desc->IBStripCutValue;
+ break;
+ default:
+ WARN("Invalid index buffer strip cut value %#x.\n", desc->IBStripCutValue);
+ hr = E_INVALIDARG;
+ goto fail;
+ }
+
+ is_dsv_format_unknown = graphics->null_attachment_mask & dsv_attachment_mask(graphics);
+
+ rs_desc_from_d3d12(&graphics->rs_desc, &desc->RasterizerState);
+ have_attachment = graphics->rt_count || graphics->dsv_format || is_dsv_format_unknown;
+ if ((!have_attachment && !(desc->PS.pShaderBytecode && desc->PS.BytecodeLength))
+ || so_desc->RasterizedStream == D3D12_SO_NO_RASTERIZED_STREAM)
+ graphics->rs_desc.rasterizerDiscardEnable = VK_TRUE;
+
+ rs_stream_info_from_d3d12(&graphics->rs_stream_info, &graphics->rs_desc, so_desc, vk_info);
+ if (vk_info->EXT_depth_clip_enable)
+ rs_depth_clip_info_from_d3d12(&graphics->rs_depth_clip_info, &graphics->rs_desc, &desc->RasterizerState);
+
+ graphics->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ graphics->ms_desc.pNext = NULL;
+ graphics->ms_desc.flags = 0;
+ graphics->ms_desc.rasterizationSamples = sample_count;
+ graphics->ms_desc.sampleShadingEnable = VK_FALSE;
+ graphics->ms_desc.minSampleShading = 0.0f;
+ graphics->ms_desc.pSampleMask = NULL;
+ if (desc->SampleMask != ~0u)
+ {
+ assert(DIV_ROUND_UP(sample_count, 32) <= ARRAY_SIZE(graphics->sample_mask));
+ graphics->sample_mask[0] = desc->SampleMask;
+ graphics->sample_mask[1] = 0xffffffffu;
+ graphics->ms_desc.pSampleMask = graphics->sample_mask;
+ }
+ graphics->ms_desc.alphaToCoverageEnable = desc->BlendState.AlphaToCoverageEnable;
+ graphics->ms_desc.alphaToOneEnable = VK_FALSE;
+
+ /* We defer creating the render pass for pipelines wth DSVFormat equal to
+ * DXGI_FORMAT_UNKNOWN. We take the actual DSV format from the bound DSV. */
+ if (is_dsv_format_unknown)
+ graphics->render_pass = VK_NULL_HANDLE;
+ else if (FAILED(hr = d3d12_graphics_pipeline_state_create_render_pass(graphics,
+ device, 0, &graphics->render_pass)))
+ goto fail;
+
+ graphics->root_signature = root_signature;
+
+ list_init(&graphics->compiled_pipelines);
+
+ if (FAILED(hr = vkd3d_private_store_init(&state->private_store)))
+ goto fail;
+
+ state->vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ d3d12_device_add_ref(state->device = device);
+
+ return S_OK;
+
+fail:
+ for (i = 0; i < graphics->stage_count; ++i)
+ {
+ VK_CALL(vkDestroyShaderModule(device->vk_device, state->u.graphics.stages[i].module, NULL));
+ }
+ vkd3d_shader_free_shader_signature(&input_signature);
+
+ return hr;
+}
+
+HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device,
+ const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state)
+{
+ struct d3d12_pipeline_state *object;
+ HRESULT hr;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_pipeline_state_init_graphics(object, device, desc)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ TRACE("Created graphics pipeline state %p.\n", object);
+
+ *state = object;
+
+ return S_OK;
+}
+
+static enum VkPrimitiveTopology vk_topology_from_d3d12_topology(D3D12_PRIMITIVE_TOPOLOGY topology)
+{
+ switch (topology)
+ {
+ case D3D_PRIMITIVE_TOPOLOGY_POINTLIST:
+ return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+ case D3D_PRIMITIVE_TOPOLOGY_LINELIST:
+ return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
+ case D3D_PRIMITIVE_TOPOLOGY_LINESTRIP:
+ return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
+ case D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST:
+ return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ case D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP:
+ return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ case D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST:
+ case D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST:
+ return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
+ default:
+ FIXME("Unhandled primitive topology %#x.\n", topology);
+ return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+ }
+}
+
+static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12_pipeline_state *state,
+ const struct vkd3d_pipeline_key *key, VkRenderPass *vk_render_pass)
+{
+ const struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics;
+ struct d3d12_device *device = state->device;
+ VkPipeline vk_pipeline = VK_NULL_HANDLE;
+ struct vkd3d_compiled_pipeline *current;
+ int rc;
+
+ *vk_render_pass = VK_NULL_HANDLE;
+
+ if (!(rc = pthread_mutex_lock(&device->mutex)))
+ {
+ LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry)
+ {
+ if (!memcmp(¤t->key, key, sizeof(*key)))
+ {
+ vk_pipeline = current->vk_pipeline;
+ *vk_render_pass = current->vk_render_pass;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&device->mutex);
+ }
+ else
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ }
+
+ return vk_pipeline;
+}
+
+static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_state *state,
+ const struct vkd3d_pipeline_key *key, VkPipeline vk_pipeline, VkRenderPass vk_render_pass)
+{
+ struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics;
+ struct vkd3d_compiled_pipeline *compiled_pipeline, *current;
+ struct d3d12_device *device = state->device;
+ int rc;
+
+ if (!(compiled_pipeline = vkd3d_malloc(sizeof(*compiled_pipeline))))
+ return false;
+
+ compiled_pipeline->key = *key;
+ compiled_pipeline->vk_pipeline = vk_pipeline;
+ compiled_pipeline->vk_render_pass = vk_render_pass;
+
+ if ((rc = pthread_mutex_lock(&device->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ vkd3d_free(compiled_pipeline);
+ return false;
+ }
+
+ LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry)
+ {
+ if (!memcmp(¤t->key, key, sizeof(*key)))
+ {
+ vkd3d_free(compiled_pipeline);
+ compiled_pipeline = NULL;
+ break;
+ }
+ }
+
+ if (compiled_pipeline)
+ list_add_tail(&graphics->compiled_pipelines, &compiled_pipeline->entry);
+
+ pthread_mutex_unlock(&device->mutex);
+ return compiled_pipeline;
+}
+
+VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state,
+ D3D12_PRIMITIVE_TOPOLOGY topology, const uint32_t *strides, VkFormat dsv_format,
+ VkRenderPass *vk_render_pass)
+{
+ VkVertexInputBindingDescription bindings[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ const struct vkd3d_vk_device_procs *vk_procs = &state->device->vk_procs;
+ struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics;
+ VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_info;
+ VkPipelineTessellationStateCreateInfo tessellation_info;
+ VkPipelineVertexInputStateCreateInfo input_desc;
+ VkPipelineInputAssemblyStateCreateInfo ia_desc;
+ VkPipelineColorBlendStateCreateInfo blend_desc;
+ struct d3d12_device *device = state->device;
+ VkGraphicsPipelineCreateInfo pipeline_desc;
+ struct vkd3d_pipeline_key pipeline_key;
+ size_t binding_count = 0;
+ VkPipeline vk_pipeline;
+ unsigned int i;
+ uint32_t mask;
+ VkResult vr;
+ HRESULT hr;
+
+ static const VkPipelineViewportStateCreateInfo vp_desc =
+ {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ .pNext = NULL,
+ .flags = 0,
+ .viewportCount = 1,
+ .pViewports = NULL,
+ .scissorCount = 1,
+ .pScissors = NULL,
+ };
+ static const VkDynamicState dynamic_states[] =
+ {
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR,
+ VK_DYNAMIC_STATE_BLEND_CONSTANTS,
+ VK_DYNAMIC_STATE_STENCIL_REFERENCE,
+ };
+ static const VkPipelineDynamicStateCreateInfo dynamic_desc =
+ {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ .pNext = NULL,
+ .flags = 0,
+ .dynamicStateCount = ARRAY_SIZE(dynamic_states),
+ .pDynamicStates = dynamic_states,
+ };
+
+ assert(d3d12_pipeline_state_is_graphics(state));
+
+ memset(&pipeline_key, 0, sizeof(pipeline_key));
+ pipeline_key.topology = topology;
+
+ for (i = 0, mask = 0; i < graphics->attribute_count; ++i)
+ {
+ struct VkVertexInputBindingDescription *b;
+ uint32_t binding;
+
+ binding = graphics->attributes[i].binding;
+ if (mask & (1u << binding))
+ continue;
+
+ if (binding_count == ARRAY_SIZE(bindings))
+ {
+ FIXME("Maximum binding count exceeded.\n");
+ break;
+ }
+
+ mask |= 1u << binding;
+ b = &bindings[binding_count];
+ b->binding = binding;
+ b->stride = strides[binding];
+ b->inputRate = graphics->input_rates[binding];
+
+ pipeline_key.strides[binding_count] = strides[binding];
+
+ ++binding_count;
+ }
+
+ pipeline_key.dsv_format = dsv_format;
+
+ if ((vk_pipeline = d3d12_pipeline_state_find_compiled_pipeline(state, &pipeline_key, vk_render_pass)))
+ return vk_pipeline;
+
+ input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ input_desc.pNext = NULL;
+ input_desc.flags = 0;
+ input_desc.vertexBindingDescriptionCount = binding_count;
+ input_desc.pVertexBindingDescriptions = bindings;
+ input_desc.vertexAttributeDescriptionCount = graphics->attribute_count;
+ input_desc.pVertexAttributeDescriptions = graphics->attributes;
+
+ if (graphics->instance_divisor_count)
+ {
+ input_desc.pNext = &input_divisor_info;
+ input_divisor_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
+ input_divisor_info.pNext = NULL;
+ input_divisor_info.vertexBindingDivisorCount = graphics->instance_divisor_count;
+ input_divisor_info.pVertexBindingDivisors = graphics->instance_divisors;
+ }
+
+ ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia_desc.pNext = NULL;
+ ia_desc.flags = 0;
+ ia_desc.topology = vk_topology_from_d3d12_topology(topology);
+ ia_desc.primitiveRestartEnable = !!graphics->index_buffer_strip_cut_value;
+
+ tessellation_info.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
+ tessellation_info.pNext = NULL;
+ tessellation_info.flags = 0;
+ tessellation_info.patchControlPoints
+ = max(topology - D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + 1, 1);
+
+ blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ blend_desc.pNext = NULL;
+ blend_desc.flags = 0;
+ blend_desc.logicOpEnable = VK_FALSE;
+ blend_desc.logicOp = VK_LOGIC_OP_COPY;
+ blend_desc.attachmentCount = graphics->rt_count;
+ blend_desc.pAttachments = graphics->blend_attachments;
+ blend_desc.blendConstants[0] = D3D12_DEFAULT_BLEND_FACTOR_RED;
+ blend_desc.blendConstants[1] = D3D12_DEFAULT_BLEND_FACTOR_GREEN;
+ blend_desc.blendConstants[2] = D3D12_DEFAULT_BLEND_FACTOR_BLUE;
+ blend_desc.blendConstants[3] = D3D12_DEFAULT_BLEND_FACTOR_ALPHA;
+
+ pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ pipeline_desc.pNext = NULL;
+ pipeline_desc.flags = 0;
+ pipeline_desc.stageCount = graphics->stage_count;
+ pipeline_desc.pStages = graphics->stages;
+ pipeline_desc.pVertexInputState = &input_desc;
+ pipeline_desc.pInputAssemblyState = &ia_desc;
+ pipeline_desc.pTessellationState = &tessellation_info;
+ pipeline_desc.pViewportState = &vp_desc;
+ pipeline_desc.pRasterizationState = &graphics->rs_desc;
+ pipeline_desc.pMultisampleState = &graphics->ms_desc;
+ pipeline_desc.pDepthStencilState = &graphics->ds_desc;
+ pipeline_desc.pColorBlendState = &blend_desc;
+ pipeline_desc.pDynamicState = &dynamic_desc;
+ pipeline_desc.layout = graphics->root_signature->vk_pipeline_layout;
+ pipeline_desc.subpass = 0;
+ pipeline_desc.basePipelineHandle = VK_NULL_HANDLE;
+ pipeline_desc.basePipelineIndex = -1;
+
+ /* Create a render pass for pipelines with DXGI_FORMAT_UNKNOWN. */
+ if (!(pipeline_desc.renderPass = graphics->render_pass))
+ {
+ if (graphics->null_attachment_mask & dsv_attachment_mask(graphics))
+ TRACE("Compiling %p with DSV format %#x.\n", state, dsv_format);
+
+ if (FAILED(hr = d3d12_graphics_pipeline_state_create_render_pass(graphics, device, dsv_format,
+ &pipeline_desc.renderPass)))
+ return VK_NULL_HANDLE;
+ }
+
+ *vk_render_pass = pipeline_desc.renderPass;
+
+ if ((vr = VK_CALL(vkCreateGraphicsPipelines(device->vk_device, device->vk_pipeline_cache,
+ 1, &pipeline_desc, NULL, &vk_pipeline))) < 0)
+ {
+ WARN("Failed to create Vulkan graphics pipeline, vr %d.\n", vr);
+ return VK_NULL_HANDLE;
+ }
+
+ if (d3d12_pipeline_state_put_pipeline_to_cache(state, &pipeline_key, vk_pipeline, pipeline_desc.renderPass))
+ return vk_pipeline;
+
+ /* Other thread compiled the pipeline before us. */
+ VK_CALL(vkDestroyPipeline(device->vk_device, vk_pipeline, NULL));
+ vk_pipeline = d3d12_pipeline_state_find_compiled_pipeline(state, &pipeline_key, vk_render_pass);
+ if (!vk_pipeline)
+ ERR("Could not get the pipeline compiled by other thread from the cache.\n");
+ return vk_pipeline;
+}
+
+static void vkd3d_uav_clear_pipelines_cleanup(struct vkd3d_uav_clear_pipelines *pipelines,
+ struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ VK_CALL(vkDestroyPipeline(device->vk_device, pipelines->image_3d, NULL));
+ VK_CALL(vkDestroyPipeline(device->vk_device, pipelines->image_2d_array, NULL));
+ VK_CALL(vkDestroyPipeline(device->vk_device, pipelines->image_2d, NULL));
+ VK_CALL(vkDestroyPipeline(device->vk_device, pipelines->image_1d_array, NULL));
+ VK_CALL(vkDestroyPipeline(device->vk_device, pipelines->image_1d, NULL));
+ VK_CALL(vkDestroyPipeline(device->vk_device, pipelines->buffer, NULL));
+}
+
+void vkd3d_uav_clear_state_cleanup(struct vkd3d_uav_clear_state *state, struct d3d12_device *device)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ vkd3d_uav_clear_pipelines_cleanup(&state->pipelines_uint, device);
+ vkd3d_uav_clear_pipelines_cleanup(&state->pipelines_float, device);
+
+ VK_CALL(vkDestroyPipelineLayout(device->vk_device, state->vk_pipeline_layout_image, NULL));
+ VK_CALL(vkDestroyPipelineLayout(device->vk_device, state->vk_pipeline_layout_buffer, NULL));
+
+ VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, state->vk_set_layout_image, NULL));
+ VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, state->vk_set_layout_buffer, NULL));
+}
+
+HRESULT vkd3d_uav_clear_state_init(struct vkd3d_uav_clear_state *state, struct d3d12_device *device)
+{
+ struct vkd3d_shader_push_constant_buffer push_constant;
+ struct vkd3d_shader_interface_info shader_interface;
+ struct vkd3d_shader_resource_binding binding;
+ VkDescriptorSetLayoutBinding set_binding;
+ VkPushConstantRange push_constant_range;
+ unsigned int i;
+ HRESULT hr;
+
+ const struct
+ {
+ VkDescriptorSetLayout *set_layout;
+ VkPipelineLayout *pipeline_layout;
+ VkDescriptorType descriptor_type;
+ }
+ set_layouts[] =
+ {
+ {&state->vk_set_layout_buffer, &state->vk_pipeline_layout_buffer, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER},
+ {&state->vk_set_layout_image, &state->vk_pipeline_layout_image, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE},
+ };
+
+ const struct
+ {
+ VkPipeline *pipeline;
+ VkPipelineLayout *pipeline_layout;
+ D3D12_SHADER_BYTECODE code;
+ }
+ pipelines[] =
+ {
+#define SHADER_CODE(name) {name, sizeof(name)}
+ {&state->pipelines_float.buffer, &state->vk_pipeline_layout_buffer,
+ SHADER_CODE(cs_uav_clear_buffer_float_code)},
+ {&state->pipelines_float.image_1d, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_1d_float_code)},
+ {&state->pipelines_float.image_1d_array, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_1d_array_float_code)},
+ {&state->pipelines_float.image_2d, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_2d_float_code)},
+ {&state->pipelines_float.image_2d_array, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_2d_array_float_code)},
+ {&state->pipelines_float.image_3d, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_3d_float_code)},
+
+ {&state->pipelines_uint.buffer, &state->vk_pipeline_layout_buffer,
+ SHADER_CODE(cs_uav_clear_buffer_uint_code)},
+ {&state->pipelines_uint.image_1d, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_1d_uint_code)},
+ {&state->pipelines_uint.image_1d_array, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_1d_array_uint_code)},
+ {&state->pipelines_uint.image_2d, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_2d_uint_code)},
+ {&state->pipelines_uint.image_2d_array, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_2d_array_uint_code)},
+ {&state->pipelines_uint.image_3d, &state->vk_pipeline_layout_image,
+ SHADER_CODE(cs_uav_clear_3d_uint_code)},
+#undef SHADER_CODE
+ };
+
+ memset(state, 0, sizeof(*state));
+
+ set_binding.binding = 0;
+ set_binding.descriptorCount = 1;
+ set_binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+ set_binding.pImmutableSamplers = NULL;
+
+ binding.type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
+ binding.register_space = 0;
+ binding.register_index = 0;
+ binding.shader_visibility = VKD3D_SHADER_VISIBILITY_COMPUTE;
+ binding.binding.set = 0;
+ binding.binding.binding = 0;
+ binding.binding.count = 1;
+
+ push_constant_range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+ push_constant_range.offset = 0;
+ push_constant_range.size = sizeof(struct vkd3d_uav_clear_args);
+
+ push_constant.register_space = 0;
+ push_constant.register_index = 0;
+ push_constant.shader_visibility = VKD3D_SHADER_VISIBILITY_COMPUTE;
+ push_constant.offset = 0;
+ push_constant.size = sizeof(struct vkd3d_uav_clear_args);
+
+ for (i = 0; i < ARRAY_SIZE(set_layouts); ++i)
+ {
+ set_binding.descriptorType = set_layouts[i].descriptor_type;
+
+ if (FAILED(hr = vkd3d_create_descriptor_set_layout(device, 0, 1, &set_binding, set_layouts[i].set_layout)))
+ {
+ ERR("Failed to create descriptor set layout %u, hr %#x.\n", i, hr);
+ goto fail;
+ }
+
+ if (FAILED(hr = vkd3d_create_pipeline_layout(device, 1, set_layouts[i].set_layout,
+ 1, &push_constant_range, set_layouts[i].pipeline_layout)))
+ {
+ ERR("Failed to create pipeline layout %u, hr %#x.\n", i, hr);
+ goto fail;
+ }
+ }
+
+ shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
+ shader_interface.next = NULL;
+ shader_interface.bindings = &binding;
+ shader_interface.binding_count = 1;
+ shader_interface.push_constant_buffers = &push_constant;
+ shader_interface.push_constant_buffer_count = 1;
+ shader_interface.combined_samplers = NULL;
+ shader_interface.combined_sampler_count = 0;
+ shader_interface.uav_counters = NULL;
+ shader_interface.uav_counter_count = 0;
+
+ for (i = 0; i < ARRAY_SIZE(pipelines); ++i)
+ {
+ if (pipelines[i].pipeline_layout == &state->vk_pipeline_layout_buffer)
+ binding.flags = VKD3D_SHADER_BINDING_FLAG_BUFFER;
+ else
+ binding.flags = VKD3D_SHADER_BINDING_FLAG_IMAGE;
+
+ if (FAILED(hr = vkd3d_create_compute_pipeline(device, &pipelines[i].code, &shader_interface,
+ *pipelines[i].pipeline_layout, pipelines[i].pipeline)))
+ {
+ ERR("Failed to create compute pipeline %u, hr %#x.\n", i, hr);
+ goto fail;
+ }
+ }
+
+ return S_OK;
+
+fail:
+ vkd3d_uav_clear_state_cleanup(state, device);
+ return hr;
+}
diff --git a/dlls/vkd3d/libs/vkd3d/utils.c b/dlls/vkd3d/libs/vkd3d/utils.c
new file mode 100644
index 00000000000..f9f26635892
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/utils.c
@@ -0,0 +1,1080 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_private.h"
+
+#include <errno.h>
+
+#define COLOR (VK_IMAGE_ASPECT_COLOR_BIT)
+#define DEPTH (VK_IMAGE_ASPECT_DEPTH_BIT)
+#define STENCIL (VK_IMAGE_ASPECT_STENCIL_BIT)
+#define DEPTH_STENCIL (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)
+#define TYPELESS VKD3D_FORMAT_TYPE_TYPELESS
+#define SINT VKD3D_FORMAT_TYPE_SINT
+#define UINT VKD3D_FORMAT_TYPE_UINT
+static const struct vkd3d_format vkd3d_formats[] =
+{
+ {DXGI_FORMAT_R32G32B32A32_TYPELESS, VK_FORMAT_R32G32B32A32_SFLOAT, 16, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R32G32B32A32_FLOAT, VK_FORMAT_R32G32B32A32_SFLOAT, 16, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_UINT, 16, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SINT, 16, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R32G32B32_TYPELESS, VK_FORMAT_R32G32B32_SFLOAT, 12, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R32G32B32_FLOAT, VK_FORMAT_R32G32B32_SFLOAT, 12, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32_UINT, 12, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R32G32B32_SINT, VK_FORMAT_R32G32B32_SINT, 12, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R16G16B16A16_TYPELESS, VK_FORMAT_R16G16B16A16_SFLOAT, 8, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R16G16B16A16_FLOAT, VK_FORMAT_R16G16B16A16_SFLOAT, 8, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_UNORM, 8, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_UINT, 8, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_SNORM, 8, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SINT, 8, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R32G32_TYPELESS, VK_FORMAT_R32G32_SFLOAT, 8, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R32G32_FLOAT, VK_FORMAT_R32G32_SFLOAT, 8, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_UINT, 8, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R32G32_SINT, VK_FORMAT_R32G32_SINT, 8, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R10G10B10A2_TYPELESS, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R10G10B10A2_UNORM, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R10G10B10A2_UINT, VK_FORMAT_A2B10G10R10_UINT_PACK32, 4, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R11G11B10_FLOAT, VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R8G8_TYPELESS, VK_FORMAT_R8G8_UNORM, 2, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_UNORM, 2, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R8G8_UINT, VK_FORMAT_R8G8_UINT, 2, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8_SNORM, 2, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R8G8_SINT, VK_FORMAT_R8G8_SINT, 2, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R8G8B8A8_TYPELESS, VK_FORMAT_R8G8B8A8_UNORM, 4, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, VK_FORMAT_R8G8B8A8_SRGB, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_UINT, 4, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_R8G8B8A8_SNORM, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R8G8B8A8_SINT, VK_FORMAT_R8G8B8A8_SINT, 4, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R16G16_TYPELESS, VK_FORMAT_R16G16_SFLOAT, 4, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R16G16_FLOAT, VK_FORMAT_R16G16_SFLOAT, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16_UNORM, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R16G16_UINT, VK_FORMAT_R16G16_UINT, 4, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16_SNORM, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R16G16_SINT, VK_FORMAT_R16G16_SINT, 4, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R32_TYPELESS, VK_FORMAT_R32_UINT, 4, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_D32_FLOAT, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1},
+ {DXGI_FORMAT_R32_FLOAT, VK_FORMAT_R32_SFLOAT, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R32_UINT, VK_FORMAT_R32_UINT, 4, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R32_SINT, VK_FORMAT_R32_SINT, 4, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R16_TYPELESS, VK_FORMAT_R16_UINT, 2, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R16_FLOAT, VK_FORMAT_R16_SFLOAT, 2, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_D16_UNORM, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1},
+ {DXGI_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, 2, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R16_UINT, VK_FORMAT_R16_UINT, 2, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R16_SNORM, VK_FORMAT_R16_SNORM, 2, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R16_SINT, VK_FORMAT_R16_SINT, 2, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_R8_TYPELESS, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R8_UINT, VK_FORMAT_R8_UINT, 1, 1, 1, 1, COLOR, 1, UINT},
+ {DXGI_FORMAT_R8_SNORM, VK_FORMAT_R8_SNORM, 1, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_R8_SINT, VK_FORMAT_R8_SINT, 1, 1, 1, 1, COLOR, 1, SINT},
+ {DXGI_FORMAT_A8_UNORM, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_B8G8R8X8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_B8G8R8A8_TYPELESS, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, VK_FORMAT_B8G8R8A8_SRGB, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_B8G8R8X8_TYPELESS, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, VK_FORMAT_B8G8R8A8_SRGB, 4, 1, 1, 1, COLOR, 1},
+ {DXGI_FORMAT_BC1_TYPELESS, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_BC1_UNORM, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1},
+ {DXGI_FORMAT_BC1_UNORM_SRGB, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, 1, 4, 4, 8, COLOR, 1},
+ {DXGI_FORMAT_BC2_TYPELESS, VK_FORMAT_BC2_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_BC2_UNORM, VK_FORMAT_BC2_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC2_UNORM_SRGB, VK_FORMAT_BC2_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC3_TYPELESS, VK_FORMAT_BC3_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_BC3_UNORM, VK_FORMAT_BC3_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC3_UNORM_SRGB, VK_FORMAT_BC3_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC4_TYPELESS, VK_FORMAT_BC4_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_BC4_UNORM, VK_FORMAT_BC4_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1},
+ {DXGI_FORMAT_BC4_SNORM, VK_FORMAT_BC4_SNORM_BLOCK, 1, 4, 4, 8, COLOR, 1},
+ {DXGI_FORMAT_BC5_TYPELESS, VK_FORMAT_BC5_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_BC5_UNORM, VK_FORMAT_BC5_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC5_SNORM, VK_FORMAT_BC5_SNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC6H_TYPELESS, VK_FORMAT_BC6H_UFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_BC6H_UF16, VK_FORMAT_BC6H_UFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC6H_SF16, VK_FORMAT_BC6H_SFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC7_TYPELESS, VK_FORMAT_BC7_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
+ {DXGI_FORMAT_BC7_UNORM, VK_FORMAT_BC7_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
+ {DXGI_FORMAT_BC7_UNORM_SRGB, VK_FORMAT_BC7_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1},
+};
+
+/* Each depth/stencil format is only compatible with itself in Vulkan. */
+static const struct vkd3d_format vkd3d_depth_stencil_formats[] =
+{
+ {DXGI_FORMAT_R32G8X24_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH_STENCIL, 2, TYPELESS},
+ {DXGI_FORMAT_D32_FLOAT_S8X24_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH_STENCIL, 2},
+ {DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH, 2},
+ {DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, STENCIL, 2},
+ {DXGI_FORMAT_R32_TYPELESS, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1, TYPELESS},
+ {DXGI_FORMAT_R32_FLOAT, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1},
+ {DXGI_FORMAT_R24G8_TYPELESS, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH_STENCIL, 2, TYPELESS},
+ {DXGI_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH_STENCIL, 2},
+ {DXGI_FORMAT_R24_UNORM_X8_TYPELESS, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH, 2},
+ {DXGI_FORMAT_X24_TYPELESS_G8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, STENCIL, 2},
+ {DXGI_FORMAT_R16_TYPELESS, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1, TYPELESS},
+ {DXGI_FORMAT_R16_UNORM, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1},
+};
+#undef COLOR
+#undef DEPTH
+#undef STENCIL
+#undef DEPTH_STENCIL
+#undef TYPELESS
+#undef SINT
+#undef UINT
+
+static const struct vkd3d_format_compatibility_info
+{
+ DXGI_FORMAT format;
+ DXGI_FORMAT typeless_format;
+}
+vkd3d_format_compatibility_info[] =
+{
+ /* DXGI_FORMAT_R32G32B32A32_TYPELESS */
+ {DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
+ {DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
+ {DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
+ /* DXGI_FORMAT_R32G32B32_TYPELESS */
+ {DXGI_FORMAT_R32G32B32_UINT, DXGI_FORMAT_R32G32B32_TYPELESS},
+ {DXGI_FORMAT_R32G32B32_SINT, DXGI_FORMAT_R32G32B32_TYPELESS},
+ {DXGI_FORMAT_R32G32B32_FLOAT, DXGI_FORMAT_R32G32B32_TYPELESS},
+ /* DXGI_FORMAT_R16G16B16A16_TYPELESS */
+ {DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_TYPELESS},
+ {DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_TYPELESS},
+ {DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
+ {DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
+ {DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
+ /* DXGI_FORMAT_R32G32_TYPELESS */
+ {DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_TYPELESS},
+ {DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_TYPELESS},
+ {DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_TYPELESS},
+ /* DXGI_FORMAT_R32G8X24_TYPELESS */
+ {DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_R32G8X24_TYPELESS},
+ {DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS},
+ {DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS},
+ /* DXGI_FORMAT_R10G10B10A2_TYPELESS */
+ {DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_TYPELESS},
+ {DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_TYPELESS},
+ /* DXGI_FORMAT_R8G8B8A8_TYPELESS */
+ {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_TYPELESS},
+ {DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS},
+ {DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS},
+ {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_TYPELESS},
+ {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS},
+ /* DXGI_FORMAT_R16G16_TYPELESS */
+ {DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_TYPELESS},
+ {DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_TYPELESS},
+ {DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_TYPELESS},
+ {DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_TYPELESS},
+ {DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_TYPELESS},
+ /* DXGI_FORMAT_R32_TYPELESS */
+ {DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_TYPELESS},
+ {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS},
+ {DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_TYPELESS},
+ {DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_TYPELESS},
+ /* DXGI_FORMAT_R24G8_TYPELESS */
+ {DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_R24G8_TYPELESS},
+ {DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_R24G8_TYPELESS},
+ {DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_R24G8_TYPELESS},
+ /* DXGI_FORMAT_R8G8_TYPELESS */
+ {DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_TYPELESS},
+ {DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_TYPELESS},
+ {DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_TYPELESS},
+ {DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_TYPELESS},
+ /* DXGI_FORMAT_R16_TYPELESS */
+ {DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_R16_TYPELESS},
+ {DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_TYPELESS},
+ {DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_TYPELESS},
+ {DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_TYPELESS},
+ {DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_TYPELESS},
+ {DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS},
+ /* DXGI_FORMAT_R8_TYPELESS */
+ {DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_TYPELESS},
+ {DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_TYPELESS},
+ {DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_TYPELESS},
+ {DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_TYPELESS},
+ /* DXGI_FORMAT_BC1_TYPELESS */
+ {DXGI_FORMAT_BC1_UNORM_SRGB, DXGI_FORMAT_BC1_TYPELESS},
+ {DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_TYPELESS},
+ /* DXGI_FORMAT_BC2_TYPELESS */
+ {DXGI_FORMAT_BC2_UNORM_SRGB, DXGI_FORMAT_BC2_TYPELESS},
+ {DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_TYPELESS},
+ /* DXGI_FORMAT_BC3_TYPELESS */
+ {DXGI_FORMAT_BC3_UNORM_SRGB, DXGI_FORMAT_BC3_TYPELESS},
+ {DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_TYPELESS},
+ /* DXGI_FORMAT_BC4_TYPELESS */
+ {DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_TYPELESS},
+ {DXGI_FORMAT_BC4_SNORM, DXGI_FORMAT_BC4_TYPELESS},
+ /* DXGI_FORMAT_BC5_TYPELESS */
+ {DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_TYPELESS},
+ {DXGI_FORMAT_BC5_SNORM, DXGI_FORMAT_BC5_TYPELESS},
+ /* DXGI_FORMAT_BC6H_TYPELESS */
+ {DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_TYPELESS},
+ {DXGI_FORMAT_BC6H_SF16, DXGI_FORMAT_BC6H_TYPELESS},
+ /* DXGI_FORMAT_BC7_TYPELESS */
+ {DXGI_FORMAT_BC7_UNORM_SRGB, DXGI_FORMAT_BC7_TYPELESS},
+ {DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_TYPELESS},
+ /* DXGI_FORMAT_B8G8R8A8_TYPELESS */
+ {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_TYPELESS},
+ {DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_TYPELESS},
+ /* DXGI_FORMAT_B8G8R8X8_TYPELESS */
+ {DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, DXGI_FORMAT_B8G8R8X8_TYPELESS},
+ {DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_TYPELESS},
+};
+
+static bool dxgi_format_is_depth_stencil(DXGI_FORMAT dxgi_format)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i)
+ {
+ const struct vkd3d_format *current = &vkd3d_formats[i];
+
+ if (current->dxgi_format == dxgi_format)
+ return current->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_depth_stencil_formats); ++i)
+ {
+ if (vkd3d_depth_stencil_formats[i].dxgi_format == dxgi_format)
+ return true;
+ }
+
+ return false;
+}
+
+/* FIXME: This table should be generated at compile-time. */
+static HRESULT vkd3d_init_format_compatibility_lists(struct d3d12_device *device)
+{
+ struct vkd3d_format_compatibility_list *lists, *current_list;
+ const struct vkd3d_format_compatibility_info *current;
+ DXGI_FORMAT dxgi_format;
+ VkFormat vk_format;
+ unsigned int count;
+ unsigned int i, j;
+
+ device->format_compatibility_list_count = 0;
+ device->format_compatibility_lists = NULL;
+
+ if (!device->vk_info.KHR_image_format_list)
+ return S_OK;
+
+ count = 1;
+ dxgi_format = vkd3d_format_compatibility_info[0].typeless_format;
+ for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
+ {
+ DXGI_FORMAT typeless_format = vkd3d_format_compatibility_info[i].typeless_format;
+
+ if (dxgi_format != typeless_format)
+ {
+ ++count;
+ dxgi_format = typeless_format;
+ }
+ }
+
+ if (!(lists = vkd3d_calloc(count, sizeof(*lists))))
+ return E_OUTOFMEMORY;
+
+ count = 0;
+ current_list = lists;
+ current_list->typeless_format = vkd3d_format_compatibility_info[0].typeless_format;
+ for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
+ {
+ current = &vkd3d_format_compatibility_info[i];
+
+ if (current_list->typeless_format != current->typeless_format)
+ {
+ /* Avoid empty format lists. */
+ if (current_list->format_count)
+ {
+ ++current_list;
+ ++count;
+ }
+
+ current_list->typeless_format = current->typeless_format;
+ }
+
+ /* In Vulkan, each depth-stencil format is only compatible with itself. */
+ if (dxgi_format_is_depth_stencil(current->format))
+ continue;
+
+ if (!(vk_format = vkd3d_get_vk_format(current->format)))
+ continue;
+
+ for (j = 0; j < current_list->format_count; ++j)
+ {
+ if (current_list->vk_formats[j] == vk_format)
+ break;
+ }
+
+ if (j >= current_list->format_count)
+ {
+ assert(current_list->format_count < VKD3D_MAX_COMPATIBLE_FORMAT_COUNT);
+ current_list->vk_formats[current_list->format_count++] = vk_format;
+ }
+ }
+ if (current_list->format_count)
+ ++count;
+
+ device->format_compatibility_list_count = count;
+ device->format_compatibility_lists = lists;
+ return S_OK;
+}
+
+static void vkd3d_cleanup_format_compatibility_lists(struct d3d12_device *device)
+{
+ vkd3d_free((void *)device->format_compatibility_lists);
+
+ device->format_compatibility_lists = NULL;
+ device->format_compatibility_list_count = 0;
+}
+
+static HRESULT vkd3d_init_depth_stencil_formats(struct d3d12_device *device)
+{
+ const unsigned int count = ARRAY_SIZE(vkd3d_depth_stencil_formats);
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkFormatProperties properties;
+ struct vkd3d_format *formats;
+ unsigned int i;
+
+ VK_CALL(vkGetPhysicalDeviceFormatProperties(device->vk_physical_device,
+ VK_FORMAT_D24_UNORM_S8_UINT, &properties));
+
+ if (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
+ {
+ device->depth_stencil_formats = vkd3d_depth_stencil_formats;
+ }
+ else
+ {
+ /* AMD doesn't support VK_FORMAT_D24_UNORM_S8_UINT. */
+ WARN("Mapping VK_FORMAT_D24_UNORM_S8_UINT to VK_FORMAT_D32_SFLOAT_S8_UINT.\n");
+
+ if (!(formats = vkd3d_calloc(count, sizeof(*formats))))
+ return E_OUTOFMEMORY;
+
+ memcpy(formats, vkd3d_depth_stencil_formats, sizeof(vkd3d_depth_stencil_formats));
+ for (i = 0; i < count; ++i)
+ {
+ if (formats[i].vk_format == VK_FORMAT_D24_UNORM_S8_UINT)
+ {
+ formats[i].vk_format = VK_FORMAT_D32_SFLOAT_S8_UINT;
+ formats[i].is_emulated = true;
+ }
+ }
+
+ device->depth_stencil_formats = formats;
+ }
+
+ return S_OK;
+}
+
+static void vkd3d_cleanup_depth_stencil_formats(struct d3d12_device *device)
+{
+ if (vkd3d_depth_stencil_formats != device->depth_stencil_formats)
+ vkd3d_free((void *)device->depth_stencil_formats);
+
+ device->depth_stencil_formats = NULL;
+}
+
+HRESULT vkd3d_init_format_info(struct d3d12_device *device)
+{
+ HRESULT hr;
+
+ if (FAILED(hr = vkd3d_init_depth_stencil_formats(device)))
+ return hr;
+
+ if FAILED(hr = vkd3d_init_format_compatibility_lists(device))
+ vkd3d_cleanup_depth_stencil_formats(device);
+
+ return hr;
+}
+
+void vkd3d_cleanup_format_info(struct d3d12_device *device)
+{
+ vkd3d_cleanup_depth_stencil_formats(device);
+ vkd3d_cleanup_format_compatibility_lists(device);
+}
+
+/* We use overrides for depth/stencil formats. This is required in order to
+ * properly support typeless formats because depth/stencil formats are only
+ * compatible with themselves in Vulkan.
+ */
+static const struct vkd3d_format *vkd3d_get_depth_stencil_format(const struct d3d12_device *device,
+ DXGI_FORMAT dxgi_format)
+{
+ const struct vkd3d_format *formats;
+ unsigned int i;
+
+ assert(device);
+ formats = device->depth_stencil_formats;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_depth_stencil_formats); ++i)
+ {
+ if (formats[i].dxgi_format == dxgi_format)
+ return &formats[i];
+ }
+
+ return NULL;
+}
+
+const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device,
+ DXGI_FORMAT dxgi_format, bool depth_stencil)
+{
+ const struct vkd3d_format *format;
+ unsigned int i;
+
+ if (depth_stencil && (format = vkd3d_get_depth_stencil_format(device, dxgi_format)))
+ return format;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i)
+ {
+ if (vkd3d_formats[i].dxgi_format == dxgi_format)
+ return &vkd3d_formats[i];
+ }
+
+ return NULL;
+}
+
+const struct vkd3d_format *vkd3d_find_uint_format(const struct d3d12_device *device, DXGI_FORMAT dxgi_format)
+{
+ DXGI_FORMAT typeless_format = DXGI_FORMAT_UNKNOWN;
+ const struct vkd3d_format *vkd3d_format;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
+ {
+ if (vkd3d_format_compatibility_info[i].format == dxgi_format)
+ {
+ typeless_format = vkd3d_format_compatibility_info[i].typeless_format;
+ break;
+ }
+ }
+
+ if (!typeless_format)
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
+ {
+ if (vkd3d_format_compatibility_info[i].typeless_format != typeless_format)
+ continue;
+
+ vkd3d_format = vkd3d_get_format(device, vkd3d_format_compatibility_info[i].format, false);
+ if (vkd3d_format->type == VKD3D_FORMAT_TYPE_UINT)
+ return vkd3d_format;
+ }
+
+ return NULL;
+}
+
+void vkd3d_format_copy_data(const struct vkd3d_format *format, const uint8_t *src,
+ unsigned int src_row_pitch, unsigned int src_slice_pitch, uint8_t *dst, unsigned int dst_row_pitch,
+ unsigned int dst_slice_pitch, unsigned int w, unsigned int h, unsigned int d)
+{
+ unsigned int row_block_count, row_count, row_size, slice, row;
+ unsigned int slice_count = d;
+ const uint8_t *src_row;
+ uint8_t *dst_row;
+
+ row_block_count = (w + format->block_width - 1) / format->block_width;
+ row_count = (h + format->block_height - 1) / format->block_height;
+ row_size = row_block_count * format->byte_count * format->block_byte_count;
+
+ for (slice = 0; slice < slice_count; ++slice)
+ {
+ for (row = 0; row < row_count; ++row)
+ {
+ src_row = &src[slice * src_slice_pitch + row * src_row_pitch];
+ dst_row = &dst[slice * dst_slice_pitch + row * dst_row_pitch];
+ memcpy(dst_row, src_row, row_size);
+ }
+ }
+}
+
+VkFormat vkd3d_get_vk_format(DXGI_FORMAT format)
+{
+ const struct vkd3d_format *vkd3d_format;
+
+ if (!(vkd3d_format = vkd3d_get_format(NULL, format, false)))
+ return VK_FORMAT_UNDEFINED;
+
+ return vkd3d_format->vk_format;
+}
+
+DXGI_FORMAT vkd3d_get_dxgi_format(VkFormat format)
+{
+ DXGI_FORMAT dxgi_format;
+ VkFormat vk_format;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i)
+ {
+ vk_format = vkd3d_formats[i].vk_format;
+ dxgi_format = vkd3d_formats[i].dxgi_format;
+ if (vk_format == format && vkd3d_formats[i].type != VKD3D_FORMAT_TYPE_TYPELESS)
+ return dxgi_format;
+ }
+
+ FIXME("Unhandled Vulkan format %#x.\n", format);
+ return DXGI_FORMAT_UNKNOWN;
+}
+
+bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level)
+{
+ static const D3D_FEATURE_LEVEL valid_feature_levels[] =
+ {
+ D3D_FEATURE_LEVEL_12_1,
+ D3D_FEATURE_LEVEL_12_0,
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1,
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(valid_feature_levels); ++i)
+ {
+ if (valid_feature_levels[i] == feature_level)
+ return true;
+ }
+
+ return false;
+}
+
+bool is_write_resource_state(D3D12_RESOURCE_STATES state)
+{
+ return state & (D3D12_RESOURCE_STATE_RENDER_TARGET
+ | D3D12_RESOURCE_STATE_UNORDERED_ACCESS
+ | D3D12_RESOURCE_STATE_DEPTH_WRITE
+ | D3D12_RESOURCE_STATE_STREAM_OUT
+ | D3D12_RESOURCE_STATE_COPY_DEST
+ | D3D12_RESOURCE_STATE_RESOLVE_DEST);
+}
+
+static bool is_power_of_two(unsigned int x)
+{
+ return x && !(x & (x -1));
+}
+
+bool is_valid_resource_state(D3D12_RESOURCE_STATES state)
+{
+ const D3D12_RESOURCE_STATES valid_states =
+ D3D12_RESOURCE_STATE_COMMON |
+ D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER |
+ D3D12_RESOURCE_STATE_INDEX_BUFFER |
+ D3D12_RESOURCE_STATE_RENDER_TARGET |
+ D3D12_RESOURCE_STATE_UNORDERED_ACCESS |
+ D3D12_RESOURCE_STATE_DEPTH_WRITE |
+ D3D12_RESOURCE_STATE_DEPTH_READ |
+ D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
+ D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
+ D3D12_RESOURCE_STATE_STREAM_OUT |
+ D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT |
+ D3D12_RESOURCE_STATE_COPY_DEST |
+ D3D12_RESOURCE_STATE_COPY_SOURCE |
+ D3D12_RESOURCE_STATE_RESOLVE_DEST |
+ D3D12_RESOURCE_STATE_RESOLVE_SOURCE |
+ D3D12_RESOURCE_STATE_GENERIC_READ |
+ D3D12_RESOURCE_STATE_PRESENT |
+ D3D12_RESOURCE_STATE_PREDICATION;
+
+ if (state & ~valid_states)
+ {
+ WARN("Invalid resource states %#x.\n", state & ~valid_states);
+ return false;
+ }
+
+ /* Exactly one bit must be set for write states. */
+ if (is_write_resource_state(state) && !is_power_of_two(state))
+ {
+ WARN("Write state cannot be mixed with other states: %#x.\n", state);
+ return false;
+ }
+
+ return true;
+}
+
+HRESULT return_interface(void *iface, REFIID iface_iid,
+ REFIID requested_iid, void **object)
+{
+ IUnknown *unknown = iface;
+ HRESULT hr;
+
+ if (IsEqualGUID(iface_iid, requested_iid))
+ {
+ *object = unknown;
+ return S_OK;
+ }
+
+ hr = IUnknown_QueryInterface(unknown, requested_iid, object);
+ IUnknown_Release(unknown);
+ return hr;
+}
+
+const char *debug_d3d12_box(const D3D12_BOX *box)
+{
+ if (!box)
+ return "(null)";
+
+ return vkd3d_dbg_sprintf("(%u, %u, %u)-(%u, %u, %u)",
+ box->left, box->top, box->front,
+ box->right, box->bottom, box->back);
+}
+
+static const char *debug_d3d12_shader_component(D3D12_SHADER_COMPONENT_MAPPING component)
+{
+ switch (component)
+ {
+ case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0:
+ return "r";
+ case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1:
+ return "g";
+ case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2:
+ return "b";
+ case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3:
+ return "a";
+ case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0:
+ return "0";
+ case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1:
+ return "1";
+ }
+
+ FIXME("Invalid component mapping %#x.\n", component);
+ return "invalid";
+}
+
+const char *debug_d3d12_shader_component_mapping(unsigned int mapping)
+{
+ return vkd3d_dbg_sprintf("{%s, %s, %s, %s}",
+ debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(0, mapping)),
+ debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(1, mapping)),
+ debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(2, mapping)),
+ debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(3, mapping)));
+}
+
+const char *debug_vk_extent_3d(VkExtent3D extent)
+{
+ return vkd3d_dbg_sprintf("(%u, %u, %u)",
+ (unsigned int)extent.width,
+ (unsigned int)extent.height,
+ (unsigned int)extent.depth);
+}
+
+const char *debug_vk_queue_flags(VkQueueFlags flags)
+{
+ char buffer[120];
+
+ buffer[0] = '\0';
+#define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; }
+ FLAG_TO_STR(VK_QUEUE_GRAPHICS_BIT)
+ FLAG_TO_STR(VK_QUEUE_COMPUTE_BIT)
+ FLAG_TO_STR(VK_QUEUE_TRANSFER_BIT)
+ FLAG_TO_STR(VK_QUEUE_SPARSE_BINDING_BIT)
+#undef FLAG_TO_STR
+ if (flags)
+ FIXME("Unrecognized flag(s) %#x.\n", flags);
+
+ if (!buffer[0])
+ return "0";
+ return vkd3d_dbg_sprintf("%s", &buffer[3]);
+}
+
+const char *debug_vk_memory_heap_flags(VkMemoryHeapFlags flags)
+{
+ char buffer[80];
+
+ buffer[0] = '\0';
+#define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; }
+ FLAG_TO_STR(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
+ FLAG_TO_STR(VK_MEMORY_HEAP_MULTI_INSTANCE_BIT)
+#undef FLAG_TO_STR
+ if (flags)
+ FIXME("Unrecognized flag(s) %#x.\n", flags);
+
+ if (!buffer[0])
+ return "0";
+ return vkd3d_dbg_sprintf("%s", &buffer[3]);
+}
+
+const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags)
+{
+ char buffer[200];
+
+ buffer[0] = '\0';
+#define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; }
+ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
+ FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
+ FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
+ FLAG_TO_STR(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
+#undef FLAG_TO_STR
+ if (flags)
+ FIXME("Unrecognized flag(s) %#x.\n", flags);
+
+ if (!buffer[0])
+ return "0";
+ return vkd3d_dbg_sprintf("%s", &buffer[3]);
+}
+
+HRESULT hresult_from_errno(int rc)
+{
+ switch (rc)
+ {
+ case 0:
+ return S_OK;
+ case ENOMEM:
+ return E_OUTOFMEMORY;
+ case EINVAL:
+ return E_INVALIDARG;
+ default:
+ FIXME("Unhandled errno %d.\n", rc);
+ return E_FAIL;
+ }
+}
+
+HRESULT hresult_from_vk_result(VkResult vr)
+{
+ switch (vr)
+ {
+ case VK_SUCCESS:
+ return S_OK;
+ case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+ WARN("Out of device memory.\n");
+ /* fall-through */
+ case VK_ERROR_OUT_OF_HOST_MEMORY:
+ return E_OUTOFMEMORY;
+ default:
+ FIXME("Unhandled VkResult %d.\n", vr);
+ /* fall-through */
+ case VK_ERROR_DEVICE_LOST:
+ case VK_ERROR_EXTENSION_NOT_PRESENT:
+ return E_FAIL;
+ }
+}
+
+HRESULT hresult_from_vkd3d_result(int vkd3d_result)
+{
+ switch (vkd3d_result)
+ {
+ case VKD3D_OK:
+ return S_OK;
+ case VKD3D_ERROR_INVALID_SHADER:
+ WARN("Invalid shader bytecode.\n");
+ /* fall-through */
+ case VKD3D_ERROR:
+ return E_FAIL;
+ case VKD3D_ERROR_OUT_OF_MEMORY:
+ return E_OUTOFMEMORY;
+ case VKD3D_ERROR_INVALID_ARGUMENT:
+ return E_INVALIDARG;
+ case VKD3D_ERROR_NOT_IMPLEMENTED:
+ return E_NOTIMPL;
+ default:
+ FIXME("Unhandled vkd3d result %d.\n", vkd3d_result);
+ return E_FAIL;
+ }
+}
+
+#define LOAD_GLOBAL_PFN(name) \
+ if (!(procs->name = (void *)vkGetInstanceProcAddr(NULL, #name))) \
+ { \
+ ERR("Could not get global proc addr for '" #name "'.\n"); \
+ return E_FAIL; \
+ }
+
+HRESULT vkd3d_load_vk_global_procs(struct vkd3d_vk_global_procs *procs,
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr)
+{
+ memset(procs, 0, sizeof(*procs));
+
+ procs->vkGetInstanceProcAddr = vkGetInstanceProcAddr;
+
+ LOAD_GLOBAL_PFN(vkCreateInstance)
+ LOAD_GLOBAL_PFN(vkEnumerateInstanceExtensionProperties)
+
+ TRACE("Loaded global Vulkan procs.\n");
+ return S_OK;
+}
+
+#define LOAD_INSTANCE_PFN(name) \
+ if (!(procs->name = (void *)global_procs->vkGetInstanceProcAddr(instance, #name))) \
+ { \
+ ERR("Could not get instance proc addr for '" #name "'.\n"); \
+ return E_FAIL; \
+ }
+#define LOAD_INSTANCE_OPTIONAL_PFN(name) \
+ procs->name = (void *)global_procs->vkGetInstanceProcAddr(instance, #name);
+
+HRESULT vkd3d_load_vk_instance_procs(struct vkd3d_vk_instance_procs *procs,
+ const struct vkd3d_vk_global_procs *global_procs, VkInstance instance)
+{
+ memset(procs, 0, sizeof(*procs));
+
+#define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
+#define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPTIONAL_PFN
+#include "vulkan_procs.h"
+
+ TRACE("Loaded procs for VkInstance %p.\n", instance);
+ return S_OK;
+}
+
+#define COPY_PARENT_PFN(name) procs->name = parent_procs->name;
+#define LOAD_DEVICE_PFN(name) \
+ if (!(procs->name = (void *)procs->vkGetDeviceProcAddr(device, #name))) \
+ { \
+ ERR("Could not get device proc addr for '" #name "'.\n"); \
+ return E_FAIL; \
+ }
+#define LOAD_DEVICE_OPTIONAL_PFN(name) \
+ procs->name = (void *)procs->vkGetDeviceProcAddr(device, #name);
+
+HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs,
+ const struct vkd3d_vk_instance_procs *parent_procs, VkDevice device)
+{
+ memset(procs, 0, sizeof(*procs));
+
+#define VK_INSTANCE_PFN COPY_PARENT_PFN
+#define VK_DEVICE_PFN LOAD_DEVICE_PFN
+#define VK_DEVICE_EXT_PFN LOAD_DEVICE_OPTIONAL_PFN
+#include "vulkan_procs.h"
+
+ TRACE("Loaded procs for VkDevice %p.\n", device);
+ return S_OK;
+}
+
+#if HAVE_DECL_PROGRAM_INVOCATION_NAME
+
+bool vkd3d_get_program_name(char program_name[PATH_MAX])
+{
+ char *name, *p, *real_path = NULL;
+
+ if ((name = strrchr(program_invocation_name, '/')))
+ {
+ real_path = realpath("/proc/self/exe", NULL);
+
+ /* Try to strip command line arguments. */
+ if (real_path && (p = strrchr(real_path, '/'))
+ && !strncmp(real_path, program_invocation_name, strlen(real_path)))
+ {
+ name = p;
+ }
+
+ ++name;
+ }
+ else if ((name = strrchr(program_invocation_name, '\\')))
+ {
+ ++name;
+ }
+ else
+ {
+ name = program_invocation_name;
+ }
+
+ strncpy(program_name, name, PATH_MAX);
+ program_name[PATH_MAX - 1] = '\0';
+ free(real_path);
+ return true;
+}
+
+#else
+
+bool vkd3d_get_program_name(char program_name[PATH_MAX])
+{
+ *program_name = '\0';
+ return false;
+}
+
+#endif /* HAVE_DECL_PROGRAM_INVOCATION_NAME */
+
+static struct vkd3d_private_data *vkd3d_private_store_get_private_data(
+ const struct vkd3d_private_store *store, const GUID *tag)
+{
+ struct vkd3d_private_data *data;
+
+ LIST_FOR_EACH_ENTRY(data, &store->content, struct vkd3d_private_data, entry)
+ {
+ if (IsEqualGUID(&data->tag, tag))
+ return data;
+ }
+
+ return NULL;
+}
+
+static HRESULT vkd3d_private_store_set_private_data(struct vkd3d_private_store *store,
+ const GUID *tag, const void *data, unsigned int data_size, bool is_object)
+{
+ struct vkd3d_private_data *d, *old_data;
+ const void *ptr = data;
+
+ if (!data)
+ {
+ if ((d = vkd3d_private_store_get_private_data(store, tag)))
+ {
+ vkd3d_private_data_destroy(d);
+ return S_OK;
+ }
+
+ return S_FALSE;
+ }
+
+ if (is_object)
+ {
+ if (data_size != sizeof(IUnknown *))
+ return E_INVALIDARG;
+ ptr = &data;
+ }
+
+ if (!(d = vkd3d_malloc(offsetof(struct vkd3d_private_data, u.data[data_size]))))
+ return E_OUTOFMEMORY;
+
+ d->tag = *tag;
+ d->size = data_size;
+ d->is_object = is_object;
+ memcpy(d->u.data, ptr, data_size);
+ if (is_object)
+ IUnknown_AddRef(d->u.object);
+
+ if ((old_data = vkd3d_private_store_get_private_data(store, tag)))
+ vkd3d_private_data_destroy(old_data);
+ list_add_tail(&store->content, &d->entry);
+
+ return S_OK;
+}
+
+HRESULT vkd3d_get_private_data(struct vkd3d_private_store *store,
+ const GUID *tag, unsigned int *out_size, void *out)
+{
+ const struct vkd3d_private_data *data;
+ HRESULT hr = S_OK;
+ unsigned int size;
+ int rc;
+
+ if (!out_size)
+ return E_INVALIDARG;
+
+ if ((rc = pthread_mutex_lock(&store->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ if (!(data = vkd3d_private_store_get_private_data(store, tag)))
+ {
+ *out_size = 0;
+ hr = DXGI_ERROR_NOT_FOUND;
+ goto done;
+ }
+
+ size = *out_size;
+ *out_size = data->size;
+ if (!out)
+ goto done;
+
+ if (size < data->size)
+ {
+ hr = DXGI_ERROR_MORE_DATA;
+ goto done;
+ }
+
+ if (data->is_object)
+ IUnknown_AddRef(data->u.object);
+ memcpy(out, data->u.data, data->size);
+
+done:
+ pthread_mutex_unlock(&store->mutex);
+ return hr;
+}
+
+HRESULT vkd3d_set_private_data(struct vkd3d_private_store *store,
+ const GUID *tag, unsigned int data_size, const void *data)
+{
+ HRESULT hr;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&store->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ hr = vkd3d_private_store_set_private_data(store, tag, data, data_size, false);
+
+ pthread_mutex_unlock(&store->mutex);
+ return hr;
+}
+
+HRESULT vkd3d_set_private_data_interface(struct vkd3d_private_store *store,
+ const GUID *tag, const IUnknown *object)
+{
+ const void *data = object ? object : (void *)&object;
+ HRESULT hr;
+ int rc;
+
+ if ((rc = pthread_mutex_lock(&store->mutex)))
+ {
+ ERR("Failed to lock mutex, error %d.\n", rc);
+ return hresult_from_errno(rc);
+ }
+
+ hr = vkd3d_private_store_set_private_data(store, tag, data, sizeof(object), !!object);
+
+ pthread_mutex_unlock(&store->mutex);
+ return hr;
+}
+
+VkResult vkd3d_set_vk_object_name_utf8(struct d3d12_device *device, uint64_t vk_object,
+ VkDebugReportObjectTypeEXT vk_object_type, const char *name)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkDebugMarkerObjectNameInfoEXT info;
+
+ if (!device->vk_info.EXT_debug_marker)
+ return VK_SUCCESS;
+
+ info.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
+ info.pNext = NULL;
+ info.objectType = vk_object_type;
+ info.object = vk_object;
+ info.pObjectName = name;
+ return VK_CALL(vkDebugMarkerSetObjectNameEXT(device->vk_device, &info));
+}
+
+HRESULT vkd3d_set_vk_object_name(struct d3d12_device *device, uint64_t vk_object,
+ VkDebugReportObjectTypeEXT vk_object_type, const WCHAR *name)
+{
+ char *name_utf8;
+ VkResult vr;
+
+ if (!name)
+ return E_INVALIDARG;
+
+ if (!device->vk_info.EXT_debug_marker)
+ return S_OK;
+
+ if (!(name_utf8 = vkd3d_strdup_w_utf8(name, device->wchar_size)))
+ return E_OUTOFMEMORY;
+
+ vr = vkd3d_set_vk_object_name_utf8(device, vk_object, vk_object_type, name_utf8);
+
+ vkd3d_free(name_utf8);
+
+ return hresult_from_vk_result(vr);
+}
diff --git a/dlls/vkd3d/libs/vkd3d/vkd3d.map b/dlls/vkd3d/libs/vkd3d/vkd3d.map
new file mode 100644
index 00000000000..6f1f376113e
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/vkd3d.map
@@ -0,0 +1,27 @@
+VKD3D_1_0
+{
+global:
+ vkd3d_acquire_vk_queue;
+ vkd3d_create_device;
+ vkd3d_create_image_resource;
+ vkd3d_create_instance;
+ vkd3d_create_root_signature_deserializer;
+ vkd3d_create_versioned_root_signature_deserializer;
+ vkd3d_get_device_parent;
+ vkd3d_get_dxgi_format;
+ vkd3d_get_vk_device;
+ vkd3d_get_vk_format;
+ vkd3d_get_vk_physical_device;
+ vkd3d_get_vk_queue_family_index;
+ vkd3d_instance_decref;
+ vkd3d_instance_from_device;
+ vkd3d_instance_get_vk_instance;
+ vkd3d_instance_incref;
+ vkd3d_release_vk_queue;
+ vkd3d_resource_decref;
+ vkd3d_resource_incref;
+ vkd3d_serialize_root_signature;
+ vkd3d_serialize_versioned_root_signature;
+
+local: *;
+};
diff --git a/dlls/vkd3d/libs/vkd3d/vkd3d_main.c b/dlls/vkd3d/libs/vkd3d/vkd3d_main.c
new file mode 100644
index 00000000000..327cdf882fa
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/vkd3d_main.c
@@ -0,0 +1,641 @@
+/*
+ * Copyright 2016-2017 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define INITGUID
+#include "vkd3d_private.h"
+
+VKD3D_DEBUG_ENV_NAME("VKD3D_DEBUG");
+
+HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
+ REFIID iid, void **device)
+{
+ struct vkd3d_instance *instance;
+ struct d3d12_device *object;
+ HRESULT hr;
+
+ TRACE("create_info %p, iid %s, device %p.\n", create_info, debugstr_guid(iid), device);
+
+ if (!create_info)
+ return E_INVALIDARG;
+ if (create_info->type != VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
+ {
+ WARN("Invalid structure type %#x.\n", create_info->type);
+ return E_INVALIDARG;
+ }
+ if (!create_info->instance && !create_info->instance_create_info)
+ {
+ ERR("Instance or instance create info is required.\n");
+ return E_INVALIDARG;
+ }
+ if (create_info->instance && create_info->instance_create_info)
+ {
+ ERR("Instance and instance create info are mutually exclusive parameters.\n");
+ return E_INVALIDARG;
+ }
+
+ if (create_info->minimum_feature_level < D3D_FEATURE_LEVEL_11_0
+ || !is_valid_feature_level(create_info->minimum_feature_level))
+ {
+ WARN("Invalid feature level %#x.\n", create_info->minimum_feature_level);
+ return E_INVALIDARG;
+ }
+
+ if ((instance = create_info->instance))
+ {
+ vkd3d_instance_incref(instance);
+ }
+ else if (FAILED(hr = vkd3d_create_instance(create_info->instance_create_info, &instance)))
+ {
+ WARN("Failed to create instance, hr %#x.\n", hr);
+ return E_FAIL;
+ }
+
+ hr = d3d12_device_create(instance, create_info, &object);
+ vkd3d_instance_decref(instance);
+ if (FAILED(hr))
+ return hr;
+
+ if (!device)
+ {
+ ID3D12Device_Release(&object->ID3D12Device_iface);
+ return S_FALSE;
+ }
+
+ return return_interface(&object->ID3D12Device_iface, &IID_ID3D12Device, iid, device);
+}
+
+/* ID3D12RootSignatureDeserializer */
+struct d3d12_root_signature_deserializer
+{
+ ID3D12RootSignatureDeserializer ID3D12RootSignatureDeserializer_iface;
+ LONG refcount;
+
+ union
+ {
+ D3D12_VERSIONED_ROOT_SIGNATURE_DESC d3d12;
+ struct vkd3d_shader_versioned_root_signature_desc vkd3d;
+ } desc;
+};
+
+STATIC_ASSERT(sizeof(D3D12_ROOT_SIGNATURE_DESC) == sizeof(struct vkd3d_shader_root_signature_desc));
+
+static struct d3d12_root_signature_deserializer *impl_from_ID3D12RootSignatureDeserializer(
+ ID3D12RootSignatureDeserializer *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_root_signature_deserializer, ID3D12RootSignatureDeserializer_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_root_signature_deserializer_QueryInterface(
+ ID3D12RootSignatureDeserializer *iface, REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ /* QueryInterface() implementation is broken, E_NOINTERFACE is returned for
+ * IUnknown.
+ */
+ if (IsEqualGUID(riid, &IID_ID3D12RootSignatureDeserializer))
+ {
+ ID3D12RootSignatureDeserializer_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_AddRef(ID3D12RootSignatureDeserializer *iface)
+{
+ struct d3d12_root_signature_deserializer *deserializer = impl_from_ID3D12RootSignatureDeserializer(iface);
+ ULONG refcount = InterlockedIncrement(&deserializer->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", deserializer, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_Release(ID3D12RootSignatureDeserializer *iface)
+{
+ struct d3d12_root_signature_deserializer *deserializer = impl_from_ID3D12RootSignatureDeserializer(iface);
+ ULONG refcount = InterlockedDecrement(&deserializer->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", deserializer, refcount);
+
+ if (!refcount)
+ {
+ vkd3d_shader_free_root_signature(&deserializer->desc.vkd3d);
+ vkd3d_free(deserializer);
+ }
+
+ return refcount;
+}
+
+static const D3D12_ROOT_SIGNATURE_DESC * STDMETHODCALLTYPE d3d12_root_signature_deserializer_GetRootSignatureDesc(
+ ID3D12RootSignatureDeserializer *iface)
+{
+ struct d3d12_root_signature_deserializer *deserializer = impl_from_ID3D12RootSignatureDeserializer(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ assert(deserializer->desc.d3d12.Version == D3D_ROOT_SIGNATURE_VERSION_1_0);
+ return &deserializer->desc.d3d12.u.Desc_1_0;
+}
+
+static const struct ID3D12RootSignatureDeserializerVtbl d3d12_root_signature_deserializer_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_root_signature_deserializer_QueryInterface,
+ d3d12_root_signature_deserializer_AddRef,
+ d3d12_root_signature_deserializer_Release,
+ /* ID3D12RootSignatureDeserializer methods */
+ d3d12_root_signature_deserializer_GetRootSignatureDesc,
+};
+
+int vkd3d_parse_root_signature_v_1_0(const struct vkd3d_shader_code *dxbc,
+ struct vkd3d_shader_versioned_root_signature_desc *out_desc)
+{
+ struct vkd3d_shader_versioned_root_signature_desc desc, converted_desc;
+ int ret;
+
+ if ((ret = vkd3d_shader_parse_root_signature(dxbc, &desc, NULL)) < 0)
+ {
+ WARN("Failed to parse root signature, vkd3d result %d.\n", ret);
+ return ret;
+ }
+
+ if (desc.version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
+ {
+ *out_desc = desc;
+ }
+ else
+ {
+ enum vkd3d_shader_root_signature_version version = desc.version;
+
+ ret = vkd3d_shader_convert_root_signature(&converted_desc, VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0, &desc);
+ vkd3d_shader_free_root_signature(&desc);
+ if (ret < 0)
+ {
+ WARN("Failed to convert from version %#x, vkd3d result %d.\n", version, ret);
+ return ret;
+ }
+
+ *out_desc = converted_desc;
+ }
+
+ return ret;
+}
+
+static HRESULT d3d12_root_signature_deserializer_init(struct d3d12_root_signature_deserializer *deserializer,
+ const struct vkd3d_shader_code *dxbc)
+{
+ int ret;
+
+ deserializer->ID3D12RootSignatureDeserializer_iface.lpVtbl = &d3d12_root_signature_deserializer_vtbl;
+ deserializer->refcount = 1;
+
+ if ((ret = vkd3d_parse_root_signature_v_1_0(dxbc, &deserializer->desc.vkd3d)) < 0)
+ return hresult_from_vkd3d_result(ret);
+
+ return S_OK;
+}
+
+HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_size,
+ REFIID iid, void **deserializer)
+{
+ struct vkd3d_shader_code dxbc = {data, data_size};
+ struct d3d12_root_signature_deserializer *object;
+ HRESULT hr;
+
+ TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
+ data, data_size, debugstr_guid(iid), deserializer);
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_root_signature_deserializer_init(object, &dxbc)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ return return_interface(&object->ID3D12RootSignatureDeserializer_iface,
+ &IID_ID3D12RootSignatureDeserializer, iid, deserializer);
+}
+
+/* ID3D12VersionedRootSignatureDeserializer */
+struct d3d12_versioned_root_signature_deserializer
+{
+ ID3D12VersionedRootSignatureDeserializer ID3D12VersionedRootSignatureDeserializer_iface;
+ LONG refcount;
+
+ union
+ {
+ D3D12_VERSIONED_ROOT_SIGNATURE_DESC d3d12;
+ struct vkd3d_shader_versioned_root_signature_desc vkd3d;
+ } desc, other_desc;
+};
+
+STATIC_ASSERT(sizeof(D3D12_VERSIONED_ROOT_SIGNATURE_DESC) == sizeof(struct vkd3d_shader_versioned_root_signature_desc));
+
+static struct d3d12_versioned_root_signature_deserializer *impl_from_ID3D12VersionedRootSignatureDeserializer(
+ ID3D12VersionedRootSignatureDeserializer *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_versioned_root_signature_deserializer,
+ ID3D12VersionedRootSignatureDeserializer_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_QueryInterface(
+ ID3D12VersionedRootSignatureDeserializer *iface, REFIID iid, void **object)
+{
+ TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
+
+ /* QueryInterface() implementation is broken, E_NOINTERFACE is returned for
+ * IUnknown.
+ */
+ if (IsEqualGUID(iid, &IID_ID3D12VersionedRootSignatureDeserializer))
+ {
+ ID3D12VersionedRootSignatureDeserializer_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_AddRef(ID3D12VersionedRootSignatureDeserializer *iface)
+{
+ struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface);
+ ULONG refcount = InterlockedIncrement(&deserializer->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", deserializer, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_Release(ID3D12VersionedRootSignatureDeserializer *iface)
+{
+ struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface);
+ ULONG refcount = InterlockedDecrement(&deserializer->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", deserializer, refcount);
+
+ if (!refcount)
+ {
+ vkd3d_shader_free_root_signature(&deserializer->desc.vkd3d);
+ vkd3d_shader_free_root_signature(&deserializer->other_desc.vkd3d);
+ vkd3d_free(deserializer);
+ }
+
+ return refcount;
+}
+
+static enum vkd3d_shader_root_signature_version vkd3d_root_signature_version_from_d3d12(
+ D3D_ROOT_SIGNATURE_VERSION version)
+{
+ switch (version)
+ {
+ case D3D_ROOT_SIGNATURE_VERSION_1_0:
+ return VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0;
+ case D3D_ROOT_SIGNATURE_VERSION_1_1:
+ return VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1;
+ default:
+ WARN("Unknown root signature version %#x.\n", version);
+ return 0;
+ }
+}
+
+static HRESULT STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_GetRootSignatureDescAtVersion(
+ ID3D12VersionedRootSignatureDeserializer *iface, D3D_ROOT_SIGNATURE_VERSION version,
+ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC **desc)
+{
+ struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface);
+ int ret;
+
+ TRACE("iface %p, version %#x, desc %p.\n", iface, version, desc);
+
+ if (version != D3D_ROOT_SIGNATURE_VERSION_1_0 && version != D3D_ROOT_SIGNATURE_VERSION_1_1)
+ {
+ WARN("Root signature version %#x not supported.\n", version);
+ return E_INVALIDARG;
+ }
+
+ if (deserializer->desc.d3d12.Version == version)
+ {
+ *desc = &deserializer->desc.d3d12;
+ return S_OK;
+ }
+
+ if (!deserializer->other_desc.d3d12.Version)
+ {
+ if ((ret = vkd3d_shader_convert_root_signature(&deserializer->other_desc.vkd3d,
+ vkd3d_root_signature_version_from_d3d12(version), &deserializer->desc.vkd3d)) < 0)
+ {
+ WARN("Failed to convert versioned root signature, vkd3d result %d.\n", ret);
+ return hresult_from_vkd3d_result(ret);
+ }
+ }
+
+ assert(deserializer->other_desc.d3d12.Version == version);
+ *desc = &deserializer->other_desc.d3d12;
+ return S_OK;
+}
+
+static const D3D12_VERSIONED_ROOT_SIGNATURE_DESC * STDMETHODCALLTYPE
+d3d12_versioned_root_signature_deserializer_GetUnconvertedRootSignatureDesc(ID3D12VersionedRootSignatureDeserializer *iface)
+{
+ struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ return &deserializer->desc.d3d12;
+}
+
+static const struct ID3D12VersionedRootSignatureDeserializerVtbl d3d12_versioned_root_signature_deserializer_vtbl =
+{
+ /* IUnknown methods */
+ d3d12_versioned_root_signature_deserializer_QueryInterface,
+ d3d12_versioned_root_signature_deserializer_AddRef,
+ d3d12_versioned_root_signature_deserializer_Release,
+ /* ID3D12VersionedRootSignatureDeserializer methods */
+ d3d12_versioned_root_signature_deserializer_GetRootSignatureDescAtVersion,
+ d3d12_versioned_root_signature_deserializer_GetUnconvertedRootSignatureDesc,
+};
+
+static HRESULT d3d12_versioned_root_signature_deserializer_init(struct d3d12_versioned_root_signature_deserializer *deserializer,
+ const struct vkd3d_shader_code *dxbc)
+{
+ int ret;
+
+ deserializer->ID3D12VersionedRootSignatureDeserializer_iface.lpVtbl = &d3d12_versioned_root_signature_deserializer_vtbl;
+ deserializer->refcount = 1;
+
+ if ((ret = vkd3d_shader_parse_root_signature(dxbc, &deserializer->desc.vkd3d, NULL)) < 0)
+ {
+ WARN("Failed to parse root signature, vkd3d result %d.\n", ret);
+ return hresult_from_vkd3d_result(ret);
+ }
+
+ memset(&deserializer->other_desc, 0, sizeof(deserializer->other_desc));
+
+ return S_OK;
+}
+
+HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZE_T data_size,
+ REFIID iid, void **deserializer)
+{
+ struct d3d12_versioned_root_signature_deserializer *object;
+ struct vkd3d_shader_code dxbc = {data, data_size};
+ HRESULT hr;
+
+ TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
+ data, data_size, debugstr_guid(iid), deserializer);
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d3d12_versioned_root_signature_deserializer_init(object, &dxbc)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
+
+ return return_interface(&object->ID3D12VersionedRootSignatureDeserializer_iface,
+ &IID_ID3D12VersionedRootSignatureDeserializer, iid, deserializer);
+}
+
+/* ID3DBlob */
+struct d3d_blob
+{
+ ID3D10Blob ID3DBlob_iface;
+ LONG refcount;
+
+ void *buffer;
+ SIZE_T size;
+};
+
+static struct d3d_blob *impl_from_ID3DBlob(ID3DBlob *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d_blob, ID3DBlob_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d_blob_QueryInterface(ID3DBlob *iface, REFIID riid, void **object)
+{
+ TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
+
+ if (IsEqualGUID(riid, &IID_ID3DBlob)
+ || IsEqualGUID(riid, &IID_IUnknown))
+ {
+ ID3D10Blob_AddRef(iface);
+ *object = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d_blob_AddRef(ID3DBlob *iface)
+{
+ struct d3d_blob *blob = impl_from_ID3DBlob(iface);
+ ULONG refcount = InterlockedIncrement(&blob->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", blob, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d_blob_Release(ID3DBlob *iface)
+{
+ struct d3d_blob *blob = impl_from_ID3DBlob(iface);
+ ULONG refcount = InterlockedDecrement(&blob->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", blob, refcount);
+
+ if (!refcount)
+ {
+ vkd3d_free(blob->buffer);
+
+ vkd3d_free(blob);
+ }
+
+ return refcount;
+}
+
+static void * STDMETHODCALLTYPE d3d_blob_GetBufferPointer(ID3DBlob *iface)
+{
+ struct d3d_blob *blob = impl_from_ID3DBlob(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ return blob->buffer;
+}
+
+static SIZE_T STDMETHODCALLTYPE d3d_blob_GetBufferSize(ID3DBlob *iface)
+{
+ struct d3d_blob *blob = impl_from_ID3DBlob(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ return blob->size;
+}
+
+static const struct ID3D10BlobVtbl d3d_blob_vtbl =
+{
+ /* IUnknown methods */
+ d3d_blob_QueryInterface,
+ d3d_blob_AddRef,
+ d3d_blob_Release,
+ /* ID3DBlob methods */
+ d3d_blob_GetBufferPointer,
+ d3d_blob_GetBufferSize
+};
+
+static void d3d_blob_init(struct d3d_blob *blob, void *buffer, SIZE_T size)
+{
+ blob->ID3DBlob_iface.lpVtbl = &d3d_blob_vtbl;
+ blob->refcount = 1;
+
+ blob->buffer = buffer;
+ blob->size = size;
+}
+
+static HRESULT d3d_blob_create(void *buffer, SIZE_T size, struct d3d_blob **blob)
+{
+ struct d3d_blob *object;
+
+ if (!(object = vkd3d_malloc(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ d3d_blob_init(object, buffer, size);
+
+ TRACE("Created blob object %p.\n", object);
+
+ *blob = object;
+
+ return S_OK;
+}
+
+HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc,
+ D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob)
+{
+ struct vkd3d_shader_versioned_root_signature_desc vkd3d_desc;
+ struct vkd3d_shader_code dxbc;
+ struct d3d_blob *blob_object;
+ char *messages;
+ HRESULT hr;
+ int ret;
+
+ TRACE("desc %p, version %#x, blob %p, error_blob %p.\n", desc, version, blob, error_blob);
+
+ if (version != D3D_ROOT_SIGNATURE_VERSION_1_0)
+ {
+ WARN("Unexpected Root signature version %#x.\n", version);
+ return E_INVALIDARG;
+ }
+
+ if (!blob)
+ {
+ WARN("Invalid blob parameter.\n");
+ return E_INVALIDARG;
+ }
+
+ if (error_blob)
+ *error_blob = NULL;
+
+ vkd3d_desc.version = VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0;
+ vkd3d_desc.u.v_1_0 = *(const struct vkd3d_shader_root_signature_desc *)desc;
+ if ((ret = vkd3d_shader_serialize_root_signature(&vkd3d_desc, &dxbc, &messages)) < 0)
+ {
+ WARN("Failed to serialize root signature, vkd3d result %d.\n", ret);
+ if (error_blob && messages)
+ {
+ if (FAILED(hr = d3d_blob_create(messages, strlen(messages), &blob_object)))
+ ERR("Failed to create error blob, hr %#x.\n", hr);
+ else
+ *error_blob = &blob_object->ID3DBlob_iface;
+ }
+ return hresult_from_vkd3d_result(ret);
+ }
+ vkd3d_shader_free_messages(messages);
+
+ if (FAILED(hr = d3d_blob_create((void *)dxbc.code, dxbc.size, &blob_object)))
+ {
+ WARN("Failed to create blob object, hr %#x.\n", hr);
+ vkd3d_shader_free_shader_code(&dxbc);
+ return hr;
+ }
+
+ *blob = &blob_object->ID3DBlob_iface;
+
+ return S_OK;
+}
+
+HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
+ ID3DBlob **blob, ID3DBlob **error_blob)
+{
+ const struct vkd3d_shader_versioned_root_signature_desc *vkd3d_desc;
+ struct vkd3d_shader_code dxbc;
+ struct d3d_blob *blob_object;
+ char *messages;
+ HRESULT hr;
+ int ret;
+
+ TRACE("desc %p, blob %p, error_blob %p.\n", desc, blob, error_blob);
+
+ if (!blob)
+ {
+ WARN("Invalid blob parameter.\n");
+ return E_INVALIDARG;
+ }
+
+ if (error_blob)
+ *error_blob = NULL;
+
+ vkd3d_desc = (const struct vkd3d_shader_versioned_root_signature_desc *)desc;
+ if ((ret = vkd3d_shader_serialize_root_signature(vkd3d_desc, &dxbc, &messages)) < 0)
+ {
+ WARN("Failed to serialize root signature, vkd3d result %d.\n", ret);
+ if (error_blob && messages)
+ {
+ if (FAILED(hr = d3d_blob_create(messages, strlen(messages), &blob_object)))
+ ERR("Failed to create error blob, hr %#x.\n", hr);
+ else
+ *error_blob = &blob_object->ID3DBlob_iface;
+ }
+ return hresult_from_vkd3d_result(ret);
+ }
+ vkd3d_shader_free_messages(messages);
+
+ if (FAILED(hr = d3d_blob_create((void *)dxbc.code, dxbc.size, &blob_object)))
+ {
+ WARN("Failed to create blob object, hr %#x.\n", hr);
+ vkd3d_shader_free_shader_code(&dxbc);
+ return hr;
+ }
+
+ *blob = &blob_object->ID3DBlob_iface;
+
+ return S_OK;
+}
diff --git a/dlls/vkd3d/libs/vkd3d/vkd3d_private.h b/dlls/vkd3d/libs/vkd3d/vkd3d_private.h
new file mode 100644
index 00000000000..9f0982df05f
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/vkd3d_private.h
@@ -0,0 +1,1372 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_PRIVATE_H
+#define __VKD3D_PRIVATE_H
+
+#define COBJMACROS
+#define NONAMELESSUNION
+#define VK_NO_PROTOTYPES
+
+#include "vkd3d_common.h"
+#include "vkd3d_memory.h"
+#include "vkd3d_utf8.h"
+#include "list.h"
+#include "rbtree.h"
+
+#include "vkd3d.h"
+#include "vkd3d_shader.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdbool.h>
+
+#define VK_CALL(f) (vk_procs->f)
+
+#define VKD3D_DESCRIPTOR_MAGIC_FREE 0x00000000u
+#define VKD3D_DESCRIPTOR_MAGIC_CBV 0x00564243u
+#define VKD3D_DESCRIPTOR_MAGIC_SRV 0x00565253u
+#define VKD3D_DESCRIPTOR_MAGIC_UAV 0x00564155u
+#define VKD3D_DESCRIPTOR_MAGIC_SAMPLER 0x504d4153u
+#define VKD3D_DESCRIPTOR_MAGIC_DSV 0x00565344u
+#define VKD3D_DESCRIPTOR_MAGIC_RTV 0x00565452u
+
+#define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u
+#define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u
+#define VKD3D_MAX_SHADER_EXTENSIONS 1u
+#define VKD3D_MAX_SHADER_STAGES 5u
+#define VKD3D_MAX_VK_SYNC_OBJECTS 4u
+
+struct d3d12_command_list;
+struct d3d12_device;
+struct d3d12_resource;
+
+struct vkd3d_vk_global_procs
+{
+ PFN_vkCreateInstance vkCreateInstance;
+ PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+};
+
+#define DECLARE_VK_PFN(name) PFN_##name name;
+struct vkd3d_vk_instance_procs
+{
+#define VK_INSTANCE_PFN DECLARE_VK_PFN
+#define VK_INSTANCE_EXT_PFN DECLARE_VK_PFN
+#include "vulkan_procs.h"
+};
+
+struct vkd3d_vk_device_procs
+{
+#define VK_INSTANCE_PFN DECLARE_VK_PFN
+#define VK_DEVICE_PFN DECLARE_VK_PFN
+#define VK_DEVICE_EXT_PFN DECLARE_VK_PFN
+#include "vulkan_procs.h"
+};
+#undef DECLARE_VK_PFN
+
+HRESULT hresult_from_errno(int rc) DECLSPEC_HIDDEN;
+HRESULT hresult_from_vk_result(VkResult vr) DECLSPEC_HIDDEN;
+HRESULT hresult_from_vkd3d_result(int vkd3d_result) DECLSPEC_HIDDEN;
+
+struct vkd3d_vulkan_info
+{
+ /* KHR instance extensions */
+ bool KHR_get_physical_device_properties2;
+ /* EXT instance extensions */
+ bool EXT_debug_report;
+
+ /* KHR device extensions */
+ bool KHR_dedicated_allocation;
+ bool KHR_draw_indirect_count;
+ bool KHR_get_memory_requirements2;
+ bool KHR_image_format_list;
+ bool KHR_maintenance3;
+ bool KHR_push_descriptor;
+ /* EXT device extensions */
+ bool EXT_conditional_rendering;
+ bool EXT_debug_marker;
+ bool EXT_depth_clip_enable;
+ bool EXT_descriptor_indexing;
+ bool EXT_shader_demote_to_helper_invocation;
+ bool EXT_texel_buffer_alignment;
+ bool EXT_transform_feedback;
+ bool EXT_vertex_attribute_divisor;
+
+ bool rasterization_stream;
+ bool transform_feedback_queries;
+
+ bool vertex_attrib_zero_divisor;
+ unsigned int max_vertex_attrib_divisor;
+
+ VkPhysicalDeviceLimits device_limits;
+ VkPhysicalDeviceSparseProperties sparse_properties;
+
+ VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties;
+
+ unsigned int shader_extension_count;
+ enum vkd3d_shader_spirv_extension shader_extensions[VKD3D_MAX_SHADER_EXTENSIONS];
+
+ D3D_FEATURE_LEVEL max_feature_level;
+};
+
+enum vkd3d_config_flags
+{
+ VKD3D_CONFIG_FLAG_VULKAN_DEBUG = 0x00000001,
+};
+
+struct vkd3d_instance
+{
+ VkInstance vk_instance;
+ struct vkd3d_vk_instance_procs vk_procs;
+
+ PFN_vkd3d_signal_event signal_event;
+ PFN_vkd3d_create_thread create_thread;
+ PFN_vkd3d_join_thread join_thread;
+ size_t wchar_size;
+
+ struct vkd3d_vulkan_info vk_info;
+ struct vkd3d_vk_global_procs vk_global_procs;
+ void *libvulkan;
+
+ uint64_t config_flags;
+ enum vkd3d_api_version api_version;
+
+ VkDebugReportCallbackEXT vk_debug_callback;
+
+ LONG refcount;
+};
+
+union vkd3d_thread_handle
+{
+ pthread_t pthread;
+ void *handle;
+};
+
+HRESULT vkd3d_create_thread(struct vkd3d_instance *instance,
+ PFN_vkd3d_thread thread_main, void *data, union vkd3d_thread_handle *thread) DECLSPEC_HIDDEN;
+HRESULT vkd3d_join_thread(struct vkd3d_instance *instance, union vkd3d_thread_handle *thread) DECLSPEC_HIDDEN;
+
+struct vkd3d_waiting_fence
+{
+ struct d3d12_fence *fence;
+ uint64_t value;
+ struct vkd3d_queue *queue;
+ uint64_t queue_sequence_number;
+};
+
+struct vkd3d_fence_worker
+{
+ union vkd3d_thread_handle thread;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ pthread_cond_t fence_destruction_cond;
+ bool should_exit;
+ bool pending_fence_destruction;
+
+ size_t enqueued_fence_count;
+ struct vkd3d_enqueued_fence
+ {
+ VkFence vk_fence;
+ struct vkd3d_waiting_fence waiting_fence;
+ } *enqueued_fences;
+ size_t enqueued_fences_size;
+
+ size_t fence_count;
+ VkFence *vk_fences;
+ size_t vk_fences_size;
+ struct vkd3d_waiting_fence *fences;
+ size_t fences_size;
+
+ struct d3d12_device *device;
+};
+
+HRESULT vkd3d_fence_worker_start(struct vkd3d_fence_worker *worker,
+ struct d3d12_device *device) DECLSPEC_HIDDEN;
+HRESULT vkd3d_fence_worker_stop(struct vkd3d_fence_worker *worker,
+ struct d3d12_device *device) DECLSPEC_HIDDEN;
+
+struct vkd3d_gpu_va_allocation
+{
+ D3D12_GPU_VIRTUAL_ADDRESS base;
+ size_t size;
+ void *ptr;
+};
+
+struct vkd3d_gpu_va_slab
+{
+ size_t size;
+ void *ptr;
+};
+
+struct vkd3d_gpu_va_allocator
+{
+ pthread_mutex_t mutex;
+
+ D3D12_GPU_VIRTUAL_ADDRESS fallback_floor;
+ struct vkd3d_gpu_va_allocation *fallback_allocations;
+ size_t fallback_allocations_size;
+ size_t fallback_allocation_count;
+
+ struct vkd3d_gpu_va_slab *slabs;
+ struct vkd3d_gpu_va_slab *free_slab;
+};
+
+D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator,
+ size_t alignment, size_t size, void *ptr) DECLSPEC_HIDDEN;
+void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocator,
+ D3D12_GPU_VIRTUAL_ADDRESS address) DECLSPEC_HIDDEN;
+void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator,
+ D3D12_GPU_VIRTUAL_ADDRESS address) DECLSPEC_HIDDEN;
+
+struct vkd3d_render_pass_key
+{
+ unsigned int attachment_count;
+ bool depth_enable;
+ bool stencil_enable;
+ bool depth_stencil_write;
+ bool padding;
+ unsigned int sample_count;
+ VkFormat vk_formats[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT + 1];
+};
+
+struct vkd3d_render_pass_entry;
+
+struct vkd3d_render_pass_cache
+{
+ struct vkd3d_render_pass_entry *render_passes;
+ size_t render_pass_count;
+ size_t render_passes_size;
+};
+
+void vkd3d_render_pass_cache_cleanup(struct vkd3d_render_pass_cache *cache,
+ struct d3d12_device *device) DECLSPEC_HIDDEN;
+HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache,
+ struct d3d12_device *device, const struct vkd3d_render_pass_key *key,
+ VkRenderPass *vk_render_pass) DECLSPEC_HIDDEN;
+void vkd3d_render_pass_cache_init(struct vkd3d_render_pass_cache *cache) DECLSPEC_HIDDEN;
+
+struct vkd3d_private_store
+{
+ pthread_mutex_t mutex;
+
+ struct list content;
+};
+
+struct vkd3d_private_data
+{
+ struct list entry;
+
+ GUID tag;
+ unsigned int size;
+ bool is_object;
+ union
+ {
+ BYTE data[1];
+ IUnknown *object;
+ } u;
+};
+
+static inline void vkd3d_private_data_destroy(struct vkd3d_private_data *data)
+{
+ if (data->is_object)
+ IUnknown_Release(data->u.object);
+ list_remove(&data->entry);
+ vkd3d_free(data);
+}
+
+static inline HRESULT vkd3d_private_store_init(struct vkd3d_private_store *store)
+{
+ int rc;
+
+ list_init(&store->content);
+
+ if ((rc = pthread_mutex_init(&store->mutex, NULL)))
+ ERR("Failed to initialize mutex, error %d.\n", rc);
+
+ return hresult_from_errno(rc);
+}
+
+static inline void vkd3d_private_store_destroy(struct vkd3d_private_store *store)
+{
+ struct vkd3d_private_data *data, *cursor;
+
+ LIST_FOR_EACH_ENTRY_SAFE(data, cursor, &store->content, struct vkd3d_private_data, entry)
+ {
+ vkd3d_private_data_destroy(data);
+ }
+
+ pthread_mutex_destroy(&store->mutex);
+}
+
+HRESULT vkd3d_get_private_data(struct vkd3d_private_store *store,
+ const GUID *tag, unsigned int *out_size, void *out) DECLSPEC_HIDDEN;
+HRESULT vkd3d_set_private_data(struct vkd3d_private_store *store,
+ const GUID *tag, unsigned int data_size, const void *data) DECLSPEC_HIDDEN;
+HRESULT vkd3d_set_private_data_interface(struct vkd3d_private_store *store,
+ const GUID *tag, const IUnknown *object) DECLSPEC_HIDDEN;
+
+struct vkd3d_signaled_semaphore
+{
+ struct list entry;
+ uint64_t value;
+ VkSemaphore vk_semaphore;
+ VkFence vk_fence;
+ bool is_acquired;
+};
+
+/* ID3D12Fence */
+struct d3d12_fence
+{
+ ID3D12Fence ID3D12Fence_iface;
+ LONG refcount;
+
+ uint64_t value;
+ pthread_mutex_t mutex;
+
+ struct vkd3d_waiting_event
+ {
+ uint64_t value;
+ HANDLE event;
+ } *events;
+ size_t events_size;
+ size_t event_count;
+
+ struct list semaphores;
+ unsigned int semaphore_count;
+
+ LONG pending_worker_operation_count;
+
+ VkFence old_vk_fences[VKD3D_MAX_VK_SYNC_OBJECTS];
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+HRESULT d3d12_fence_create(struct d3d12_device *device,
+ uint64_t initial_value, D3D12_FENCE_FLAGS flags, struct d3d12_fence **fence) DECLSPEC_HIDDEN;
+
+/* ID3D12Heap */
+struct d3d12_heap
+{
+ ID3D12Heap ID3D12Heap_iface;
+ LONG refcount;
+
+ bool is_private;
+ D3D12_HEAP_DESC desc;
+
+ pthread_mutex_t mutex;
+
+ VkDeviceMemory vk_memory;
+ void *map_ptr;
+ unsigned int map_count;
+ uint32_t vk_memory_type;
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+HRESULT d3d12_heap_create(struct d3d12_device *device, const D3D12_HEAP_DESC *desc,
+ const struct d3d12_resource *resource, struct d3d12_heap **heap) DECLSPEC_HIDDEN;
+struct d3d12_heap *unsafe_impl_from_ID3D12Heap(ID3D12Heap *iface) DECLSPEC_HIDDEN;
+
+#define VKD3D_RESOURCE_PUBLIC_FLAGS \
+ (VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION)
+#define VKD3D_RESOURCE_EXTERNAL 0x00000004
+#define VKD3D_RESOURCE_DEDICATED_HEAP 0x00000008
+#define VKD3D_RESOURCE_LINEAR_TILING 0x00000010
+
+/* ID3D12Resource */
+struct d3d12_resource
+{
+ ID3D12Resource ID3D12Resource_iface;
+ LONG refcount;
+ LONG internal_refcount;
+
+ D3D12_RESOURCE_DESC desc;
+
+ D3D12_GPU_VIRTUAL_ADDRESS gpu_address;
+ union
+ {
+ VkBuffer vk_buffer;
+ VkImage vk_image;
+ } u;
+ unsigned int flags;
+
+ unsigned int map_count;
+
+ struct d3d12_heap *heap;
+ uint64_t heap_offset;
+
+ D3D12_RESOURCE_STATES initial_state;
+ D3D12_RESOURCE_STATES present_state;
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+static inline bool d3d12_resource_is_buffer(const struct d3d12_resource *resource)
+{
+ return resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER;
+}
+
+static inline bool d3d12_resource_is_texture(const struct d3d12_resource *resource)
+{
+ return resource->desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER;
+}
+
+bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource) DECLSPEC_HIDDEN;
+HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device) DECLSPEC_HIDDEN;
+
+HRESULT d3d12_committed_resource_create(struct d3d12_device *device,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource) DECLSPEC_HIDDEN;
+HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_heap *heap, uint64_t heap_offset,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource) DECLSPEC_HIDDEN;
+HRESULT d3d12_reserved_resource_create(struct d3d12_device *device,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
+ const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource) DECLSPEC_HIDDEN;
+struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface) DECLSPEC_HIDDEN;
+
+HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_buffer,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ VkDeviceMemory *vk_memory, uint32_t *vk_memory_type, VkDeviceSize *vk_memory_size) DECLSPEC_HIDDEN;
+HRESULT vkd3d_create_buffer(struct d3d12_device *device,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
+ const D3D12_RESOURCE_DESC *desc, VkBuffer *vk_buffer) DECLSPEC_HIDDEN;
+HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device,
+ const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_ALLOCATION_INFO *allocation_info) DECLSPEC_HIDDEN;
+
+enum vkd3d_view_type
+{
+ VKD3D_VIEW_TYPE_BUFFER,
+ VKD3D_VIEW_TYPE_IMAGE,
+ VKD3D_VIEW_TYPE_SAMPLER,
+};
+
+struct vkd3d_view
+{
+ LONG refcount;
+ enum vkd3d_view_type type;
+ union
+ {
+ VkBufferView vk_buffer_view;
+ VkImageView vk_image_view;
+ VkSampler vk_sampler;
+ } u;
+ VkBufferView vk_counter_view;
+ const struct vkd3d_format *format;
+ union
+ {
+ struct
+ {
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ } buffer;
+ struct
+ {
+ VkImageViewType vk_view_type;
+ unsigned int miplevel_idx;
+ unsigned int layer_idx;
+ unsigned int layer_count;
+ } texture;
+ } info;
+};
+
+void vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device) DECLSPEC_HIDDEN;
+void vkd3d_view_incref(struct vkd3d_view *view) DECLSPEC_HIDDEN;
+
+struct vkd3d_texture_view_desc
+{
+ VkImageViewType view_type;
+ const struct vkd3d_format *format;
+ unsigned int miplevel_idx;
+ unsigned int miplevel_count;
+ unsigned int layer_idx;
+ unsigned int layer_count;
+ VkComponentMapping components;
+ bool allowed_swizzle;
+};
+
+bool vkd3d_create_buffer_view(struct d3d12_device *device, VkBuffer vk_buffer, const struct vkd3d_format *format,
+ VkDeviceSize offset, VkDeviceSize size, struct vkd3d_view **view) DECLSPEC_HIDDEN;
+bool vkd3d_create_texture_view(struct d3d12_device *device, VkImage vk_image,
+ const struct vkd3d_texture_view_desc *desc, struct vkd3d_view **view) DECLSPEC_HIDDEN;
+
+struct d3d12_desc
+{
+ uint32_t magic;
+ VkDescriptorType vk_descriptor_type;
+ union
+ {
+ VkDescriptorBufferInfo vk_cbv_info;
+ struct vkd3d_view *view;
+ } u;
+};
+
+static inline struct d3d12_desc *d3d12_desc_from_cpu_handle(D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle)
+{
+ return (struct d3d12_desc *)cpu_handle.ptr;
+}
+
+static inline struct d3d12_desc *d3d12_desc_from_gpu_handle(D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle)
+{
+ return (struct d3d12_desc *)(intptr_t)gpu_handle.ptr;
+}
+
+void d3d12_desc_copy(struct d3d12_desc *dst, const struct d3d12_desc *src,
+ struct d3d12_device *device) DECLSPEC_HIDDEN;
+void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
+ struct d3d12_device *device, const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc) DECLSPEC_HIDDEN;
+void d3d12_desc_create_srv(struct d3d12_desc *descriptor,
+ struct d3d12_device *device, struct d3d12_resource *resource,
+ const D3D12_SHADER_RESOURCE_VIEW_DESC *desc) DECLSPEC_HIDDEN;
+void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
+ struct d3d12_resource *resource, struct d3d12_resource *counter_resource,
+ const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc) DECLSPEC_HIDDEN;
+void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
+ struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc) DECLSPEC_HIDDEN;
+void d3d12_desc_write_atomic(struct d3d12_desc *dst, const struct d3d12_desc *src,
+ struct d3d12_device *device) DECLSPEC_HIDDEN;
+
+bool vkd3d_create_raw_buffer_view(struct d3d12_device *device,
+ D3D12_GPU_VIRTUAL_ADDRESS gpu_address, VkBufferView *vk_buffer_view) DECLSPEC_HIDDEN;
+HRESULT vkd3d_create_static_sampler(struct d3d12_device *device,
+ const D3D12_STATIC_SAMPLER_DESC *desc, VkSampler *vk_sampler) DECLSPEC_HIDDEN;
+
+struct d3d12_rtv_desc
+{
+ uint32_t magic;
+ VkSampleCountFlagBits sample_count;
+ const struct vkd3d_format *format;
+ uint64_t width;
+ unsigned int height;
+ unsigned int layer_count;
+ struct vkd3d_view *view;
+ struct d3d12_resource *resource;
+};
+
+static inline struct d3d12_rtv_desc *d3d12_rtv_desc_from_cpu_handle(D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle)
+{
+ return (struct d3d12_rtv_desc *)cpu_handle.ptr;
+}
+
+void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_device *device,
+ struct d3d12_resource *resource, const D3D12_RENDER_TARGET_VIEW_DESC *desc) DECLSPEC_HIDDEN;
+
+struct d3d12_dsv_desc
+{
+ uint32_t magic;
+ VkSampleCountFlagBits sample_count;
+ const struct vkd3d_format *format;
+ uint64_t width;
+ unsigned int height;
+ unsigned int layer_count;
+ struct vkd3d_view *view;
+ struct d3d12_resource *resource;
+};
+
+static inline struct d3d12_dsv_desc *d3d12_dsv_desc_from_cpu_handle(D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle)
+{
+ return (struct d3d12_dsv_desc *)cpu_handle.ptr;
+}
+
+void d3d12_dsv_desc_create_dsv(struct d3d12_dsv_desc *dsv_desc, struct d3d12_device *device,
+ struct d3d12_resource *resource, const D3D12_DEPTH_STENCIL_VIEW_DESC *desc) DECLSPEC_HIDDEN;
+
+/* ID3D12DescriptorHeap */
+struct d3d12_descriptor_heap
+{
+ ID3D12DescriptorHeap ID3D12DescriptorHeap_iface;
+ LONG refcount;
+
+ D3D12_DESCRIPTOR_HEAP_DESC desc;
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+
+ BYTE descriptors[];
+};
+
+HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device,
+ const D3D12_DESCRIPTOR_HEAP_DESC *desc, struct d3d12_descriptor_heap **descriptor_heap) DECLSPEC_HIDDEN;
+
+/* ID3D12QueryHeap */
+struct d3d12_query_heap
+{
+ ID3D12QueryHeap ID3D12QueryHeap_iface;
+ LONG refcount;
+
+ VkQueryPool vk_query_pool;
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+
+ uint64_t availability_mask[];
+};
+
+HRESULT d3d12_query_heap_create(struct d3d12_device *device, const D3D12_QUERY_HEAP_DESC *desc,
+ struct d3d12_query_heap **heap) DECLSPEC_HIDDEN;
+struct d3d12_query_heap *unsafe_impl_from_ID3D12QueryHeap(ID3D12QueryHeap *iface) DECLSPEC_HIDDEN;
+
+/* A Vulkan query has to be issued at least one time before the result is
+ * available. In D3D12 it is legal to get query reults for not issued queries.
+ */
+static inline bool d3d12_query_heap_is_result_available(const struct d3d12_query_heap *heap,
+ unsigned int query_index)
+{
+ unsigned int index = query_index / (sizeof(*heap->availability_mask) * CHAR_BIT);
+ unsigned int shift = query_index % (sizeof(*heap->availability_mask) * CHAR_BIT);
+ return heap->availability_mask[index] & ((uint64_t)1 << shift);
+}
+
+static inline void d3d12_query_heap_mark_result_as_available(struct d3d12_query_heap *heap,
+ unsigned int query_index)
+{
+ unsigned int index = query_index / (sizeof(*heap->availability_mask) * CHAR_BIT);
+ unsigned int shift = query_index % (sizeof(*heap->availability_mask) * CHAR_BIT);
+ heap->availability_mask[index] |= (uint64_t)1 << shift;
+}
+
+struct d3d12_root_descriptor_table_range
+{
+ unsigned int offset;
+ unsigned int descriptor_count;
+ uint32_t binding;
+
+ uint32_t descriptor_magic;
+ unsigned int register_space;
+ unsigned int base_register_idx;
+};
+
+struct d3d12_root_descriptor_table
+{
+ unsigned int range_count;
+ struct d3d12_root_descriptor_table_range *ranges;
+};
+
+struct d3d12_root_constant
+{
+ VkShaderStageFlags stage_flags;
+ uint32_t offset;
+};
+
+struct d3d12_root_descriptor
+{
+ uint32_t binding;
+};
+
+struct d3d12_root_parameter
+{
+ D3D12_ROOT_PARAMETER_TYPE parameter_type;
+ union
+ {
+ struct d3d12_root_constant constant;
+ struct d3d12_root_descriptor descriptor;
+ struct d3d12_root_descriptor_table descriptor_table;
+ } u;
+};
+
+/* ID3D12RootSignature */
+struct d3d12_root_signature
+{
+ ID3D12RootSignature ID3D12RootSignature_iface;
+ LONG refcount;
+
+ VkPipelineLayout vk_pipeline_layout;
+ VkDescriptorSetLayout vk_push_set_layout;
+ VkDescriptorSetLayout vk_set_layout;
+
+ struct d3d12_root_parameter *parameters;
+ unsigned int parameter_count;
+ uint32_t main_set;
+
+ uint64_t descriptor_table_mask;
+ uint32_t push_descriptor_mask;
+
+ D3D12_ROOT_SIGNATURE_FLAGS flags;
+
+ unsigned int descriptor_count;
+ struct vkd3d_shader_resource_binding *descriptor_mapping;
+
+ unsigned int root_constant_count;
+ struct vkd3d_shader_push_constant_buffer *root_constants;
+
+ unsigned int root_descriptor_count;
+
+ unsigned int push_constant_range_count;
+ /* Only a single push constant range may include the same stage in Vulkan. */
+ VkPushConstantRange push_constant_ranges[D3D12_SHADER_VISIBILITY_PIXEL + 1];
+
+ unsigned int static_sampler_count;
+ VkSampler *static_samplers;
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+HRESULT d3d12_root_signature_create(struct d3d12_device *device, const void *bytecode,
+ size_t bytecode_length, struct d3d12_root_signature **root_signature) DECLSPEC_HIDDEN;
+struct d3d12_root_signature *unsafe_impl_from_ID3D12RootSignature(ID3D12RootSignature *iface) DECLSPEC_HIDDEN;
+
+int vkd3d_parse_root_signature_v_1_0(const struct vkd3d_shader_code *dxbc,
+ struct vkd3d_shader_versioned_root_signature_desc *desc) DECLSPEC_HIDDEN;
+
+struct d3d12_graphics_pipeline_state
+{
+ VkPipelineShaderStageCreateInfo stages[VKD3D_MAX_SHADER_STAGES];
+ size_t stage_count;
+
+ VkVertexInputAttributeDescription attributes[D3D12_VS_INPUT_REGISTER_COUNT];
+ VkVertexInputRate input_rates[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ VkVertexInputBindingDivisorDescriptionEXT instance_divisors[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ size_t instance_divisor_count;
+ size_t attribute_count;
+
+ VkPipelineColorBlendAttachmentState blend_attachments[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
+ unsigned int rt_count;
+ unsigned int null_attachment_mask;
+ VkFormat dsv_format;
+ VkFormat rtv_formats[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
+ VkRenderPass render_pass;
+
+ D3D12_INDEX_BUFFER_STRIP_CUT_VALUE index_buffer_strip_cut_value;
+ VkPipelineRasterizationStateCreateInfo rs_desc;
+ VkPipelineMultisampleStateCreateInfo ms_desc;
+ VkPipelineDepthStencilStateCreateInfo ds_desc;
+
+ VkSampleMask sample_mask[2];
+ VkPipelineRasterizationDepthClipStateCreateInfoEXT rs_depth_clip_info;
+ VkPipelineRasterizationStateStreamCreateInfoEXT rs_stream_info;
+
+ const struct d3d12_root_signature *root_signature;
+
+ struct list compiled_pipelines;
+
+ bool xfb_enabled;
+};
+
+static inline unsigned int dsv_attachment_mask(const struct d3d12_graphics_pipeline_state *graphics)
+{
+ return 1u << graphics->rt_count;
+}
+
+struct d3d12_compute_pipeline_state
+{
+ VkPipeline vk_pipeline;
+};
+
+/* ID3D12PipelineState */
+struct d3d12_pipeline_state
+{
+ ID3D12PipelineState ID3D12PipelineState_iface;
+ LONG refcount;
+
+ union
+ {
+ struct d3d12_graphics_pipeline_state graphics;
+ struct d3d12_compute_pipeline_state compute;
+ } u;
+ VkPipelineBindPoint vk_bind_point;
+
+ VkPipelineLayout vk_pipeline_layout;
+ VkDescriptorSetLayout vk_set_layout;
+ uint32_t set_index;
+
+ struct vkd3d_shader_uav_counter_binding *uav_counters;
+ unsigned int uav_counter_count;
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+static inline bool d3d12_pipeline_state_is_compute(const struct d3d12_pipeline_state *state)
+{
+ return state && state->vk_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE;
+}
+
+static inline bool d3d12_pipeline_state_is_graphics(const struct d3d12_pipeline_state *state)
+{
+ return state && state->vk_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS;
+}
+
+static inline bool d3d12_pipeline_state_has_unknown_dsv_format(struct d3d12_pipeline_state *state)
+{
+ if (d3d12_pipeline_state_is_graphics(state))
+ {
+ struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics;
+
+ return graphics->null_attachment_mask & dsv_attachment_mask(graphics);
+ }
+
+ return false;
+}
+
+HRESULT d3d12_pipeline_state_create_compute(struct d3d12_device *device,
+ const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state) DECLSPEC_HIDDEN;
+HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device,
+ const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state) DECLSPEC_HIDDEN;
+VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state,
+ D3D12_PRIMITIVE_TOPOLOGY topology, const uint32_t *strides, VkFormat dsv_format,
+ VkRenderPass *vk_render_pass) DECLSPEC_HIDDEN;
+struct d3d12_pipeline_state *unsafe_impl_from_ID3D12PipelineState(ID3D12PipelineState *iface) DECLSPEC_HIDDEN;
+
+struct vkd3d_buffer
+{
+ VkBuffer vk_buffer;
+ VkDeviceMemory vk_memory;
+};
+
+/* ID3D12CommandAllocator */
+struct d3d12_command_allocator
+{
+ ID3D12CommandAllocator ID3D12CommandAllocator_iface;
+ LONG refcount;
+
+ D3D12_COMMAND_LIST_TYPE type;
+ VkQueueFlags vk_queue_flags;
+
+ VkCommandPool vk_command_pool;
+
+ VkDescriptorPool vk_descriptor_pool;
+
+ VkDescriptorPool *free_descriptor_pools;
+ size_t free_descriptor_pools_size;
+ size_t free_descriptor_pool_count;
+
+ VkRenderPass *passes;
+ size_t passes_size;
+ size_t pass_count;
+
+ VkFramebuffer *framebuffers;
+ size_t framebuffers_size;
+ size_t framebuffer_count;
+
+ VkDescriptorPool *descriptor_pools;
+ size_t descriptor_pools_size;
+ size_t descriptor_pool_count;
+
+ struct vkd3d_view **views;
+ size_t views_size;
+ size_t view_count;
+
+ VkBufferView *buffer_views;
+ size_t buffer_views_size;
+ size_t buffer_view_count;
+
+ struct vkd3d_buffer *transfer_buffers;
+ size_t transfer_buffers_size;
+ size_t transfer_buffer_count;
+
+ VkCommandBuffer *command_buffers;
+ size_t command_buffers_size;
+ size_t command_buffer_count;
+
+ struct d3d12_command_list *current_command_list;
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+HRESULT d3d12_command_allocator_create(struct d3d12_device *device,
+ D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_allocator **allocator) DECLSPEC_HIDDEN;
+
+struct vkd3d_push_descriptor
+{
+ union
+ {
+ VkBufferView vk_buffer_view;
+ struct
+ {
+ VkBuffer vk_buffer;
+ VkDeviceSize offset;
+ } cbv;
+ } u;
+};
+
+struct vkd3d_pipeline_bindings
+{
+ const struct d3d12_root_signature *root_signature;
+
+ VkPipelineBindPoint vk_bind_point;
+ VkDescriptorSet descriptor_set;
+ bool in_use;
+
+ D3D12_GPU_DESCRIPTOR_HANDLE descriptor_tables[D3D12_MAX_ROOT_COST];
+ uint64_t descriptor_table_dirty_mask;
+ uint64_t descriptor_table_active_mask;
+
+ VkBufferView *vk_uav_counter_views;
+ size_t vk_uav_counter_views_size;
+ bool uav_counters_dirty;
+
+ /* Needed when VK_KHR_push_descriptor is not available. */
+ struct vkd3d_push_descriptor push_descriptors[D3D12_MAX_ROOT_COST / 2];
+ uint32_t push_descriptor_dirty_mask;
+ uint32_t push_descriptor_active_mask;
+};
+
+enum vkd3d_pipeline_bind_point
+{
+ VKD3D_PIPELINE_BIND_POINT_GRAPHICS = 0x0,
+ VKD3D_PIPELINE_BIND_POINT_COMPUTE = 0x1,
+ VKD3D_PIPELINE_BIND_POINT_COUNT = 0x2,
+};
+
+/* ID3D12CommandList */
+struct d3d12_command_list
+{
+ ID3D12GraphicsCommandList2 ID3D12GraphicsCommandList2_iface;
+ LONG refcount;
+
+ D3D12_COMMAND_LIST_TYPE type;
+ VkQueueFlags vk_queue_flags;
+
+ bool is_recording;
+ bool is_valid;
+ VkCommandBuffer vk_command_buffer;
+
+ uint32_t strides[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ D3D12_PRIMITIVE_TOPOLOGY primitive_topology;
+
+ DXGI_FORMAT index_buffer_format;
+
+ VkImageView rtvs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
+ VkImageView dsv;
+ unsigned int fb_width;
+ unsigned int fb_height;
+ unsigned int fb_layer_count;
+ VkFormat dsv_format;
+
+ bool xfb_enabled;
+
+ bool is_predicated;
+
+ VkFramebuffer current_framebuffer;
+ VkPipeline current_pipeline;
+ VkRenderPass pso_render_pass;
+ VkRenderPass current_render_pass;
+ struct vkd3d_pipeline_bindings pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COUNT];
+
+ struct d3d12_pipeline_state *state;
+
+ struct d3d12_command_allocator *allocator;
+ struct d3d12_device *device;
+
+ VkBuffer so_counter_buffers[D3D12_SO_BUFFER_SLOT_COUNT];
+ VkDeviceSize so_counter_buffer_offsets[D3D12_SO_BUFFER_SLOT_COUNT];
+
+ struct vkd3d_private_store private_store;
+};
+
+HRESULT d3d12_command_list_create(struct d3d12_device *device,
+ UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface,
+ ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list) DECLSPEC_HIDDEN;
+
+struct vkd3d_queue
+{
+ /* Access to VkQueue must be externally synchronized. */
+ pthread_mutex_t mutex;
+
+ VkQueue vk_queue;
+
+ uint64_t completed_sequence_number;
+ uint64_t submitted_sequence_number;
+
+ uint32_t vk_family_index;
+ VkQueueFlags vk_queue_flags;
+ uint32_t timestamp_bits;
+
+ struct
+ {
+ VkSemaphore vk_semaphore;
+ uint64_t sequence_number;
+ } *semaphores;
+ size_t semaphores_size;
+ size_t semaphore_count;
+
+ VkSemaphore old_vk_semaphores[VKD3D_MAX_VK_SYNC_OBJECTS];
+};
+
+VkQueue vkd3d_queue_acquire(struct vkd3d_queue *queue) DECLSPEC_HIDDEN;
+HRESULT vkd3d_queue_create(struct d3d12_device *device,
+ uint32_t family_index, const VkQueueFamilyProperties *properties,
+ struct vkd3d_queue **queue) DECLSPEC_HIDDEN;
+void vkd3d_queue_destroy(struct vkd3d_queue *queue, struct d3d12_device *device) DECLSPEC_HIDDEN;
+void vkd3d_queue_release(struct vkd3d_queue *queue) DECLSPEC_HIDDEN;
+
+/* ID3D12CommandQueue */
+struct d3d12_command_queue
+{
+ ID3D12CommandQueue ID3D12CommandQueue_iface;
+ LONG refcount;
+
+ D3D12_COMMAND_QUEUE_DESC desc;
+
+ struct vkd3d_queue *vkd3d_queue;
+
+ const struct d3d12_fence *last_waited_fence;
+ uint64_t last_waited_fence_value;
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+HRESULT d3d12_command_queue_create(struct d3d12_device *device,
+ const D3D12_COMMAND_QUEUE_DESC *desc, struct d3d12_command_queue **queue) DECLSPEC_HIDDEN;
+
+/* ID3D12CommandSignature */
+struct d3d12_command_signature
+{
+ ID3D12CommandSignature ID3D12CommandSignature_iface;
+ LONG refcount;
+
+ D3D12_COMMAND_SIGNATURE_DESC desc;
+
+ struct d3d12_device *device;
+
+ struct vkd3d_private_store private_store;
+};
+
+HRESULT d3d12_command_signature_create(struct d3d12_device *device, const D3D12_COMMAND_SIGNATURE_DESC *desc,
+ struct d3d12_command_signature **signature) DECLSPEC_HIDDEN;
+struct d3d12_command_signature *unsafe_impl_from_ID3D12CommandSignature(ID3D12CommandSignature *iface) DECLSPEC_HIDDEN;
+
+/* NULL resources */
+struct vkd3d_null_resources
+{
+ VkBuffer vk_buffer;
+ VkDeviceMemory vk_buffer_memory;
+
+ VkBuffer vk_storage_buffer;
+ VkDeviceMemory vk_storage_buffer_memory;
+
+ VkImage vk_2d_image;
+ VkDeviceMemory vk_2d_image_memory;
+
+ VkImage vk_2d_storage_image;
+ VkDeviceMemory vk_2d_storage_image_memory;
+};
+
+HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources,
+ struct d3d12_device *device) DECLSPEC_HIDDEN;
+void vkd3d_destroy_null_resources(struct vkd3d_null_resources *null_resources,
+ struct d3d12_device *device) DECLSPEC_HIDDEN;
+
+struct vkd3d_format_compatibility_list
+{
+ DXGI_FORMAT typeless_format;
+ unsigned int format_count;
+ VkFormat vk_formats[VKD3D_MAX_COMPATIBLE_FORMAT_COUNT];
+};
+
+struct vkd3d_uav_clear_args
+{
+ VkClearColorValue colour;
+ VkOffset2D offset;
+ VkExtent2D extent;
+};
+
+struct vkd3d_uav_clear_pipelines
+{
+ VkPipeline buffer;
+ VkPipeline image_1d;
+ VkPipeline image_1d_array;
+ VkPipeline image_2d;
+ VkPipeline image_2d_array;
+ VkPipeline image_3d;
+};
+
+struct vkd3d_uav_clear_state
+{
+ VkDescriptorSetLayout vk_set_layout_buffer;
+ VkDescriptorSetLayout vk_set_layout_image;
+
+ VkPipelineLayout vk_pipeline_layout_buffer;
+ VkPipelineLayout vk_pipeline_layout_image;
+
+ struct vkd3d_uav_clear_pipelines pipelines_float;
+ struct vkd3d_uav_clear_pipelines pipelines_uint;
+};
+
+HRESULT vkd3d_uav_clear_state_init(struct vkd3d_uav_clear_state *state, struct d3d12_device *device) DECLSPEC_HIDDEN;
+void vkd3d_uav_clear_state_cleanup(struct vkd3d_uav_clear_state *state, struct d3d12_device *device) DECLSPEC_HIDDEN;
+
+/* ID3D12Device */
+struct d3d12_device
+{
+ ID3D12Device ID3D12Device_iface;
+ LONG refcount;
+
+ VkDevice vk_device;
+ VkPhysicalDevice vk_physical_device;
+ struct vkd3d_vk_device_procs vk_procs;
+ PFN_vkd3d_signal_event signal_event;
+ size_t wchar_size;
+
+ struct vkd3d_gpu_va_allocator gpu_va_allocator;
+ struct vkd3d_fence_worker fence_worker;
+
+ pthread_mutex_t mutex;
+ pthread_mutex_t desc_mutex[8];
+ struct vkd3d_render_pass_cache render_pass_cache;
+ VkPipelineCache vk_pipeline_cache;
+
+ VkPhysicalDeviceMemoryProperties memory_properties;
+
+ D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options;
+ D3D12_FEATURE_DATA_D3D12_OPTIONS1 feature_options1;
+ D3D12_FEATURE_DATA_D3D12_OPTIONS2 feature_options2;
+ D3D12_FEATURE_DATA_D3D12_OPTIONS3 feature_options3;
+ D3D12_FEATURE_DATA_D3D12_OPTIONS4 feature_options4;
+ D3D12_FEATURE_DATA_D3D12_OPTIONS5 feature_options5;
+
+ struct vkd3d_vulkan_info vk_info;
+
+ struct vkd3d_queue *direct_queue;
+ struct vkd3d_queue *compute_queue;
+ struct vkd3d_queue *copy_queue;
+ uint32_t queue_family_indices[VKD3D_MAX_QUEUE_FAMILY_COUNT];
+ unsigned int queue_family_count;
+
+ struct vkd3d_instance *vkd3d_instance;
+
+ IUnknown *parent;
+ LUID adapter_luid;
+
+ struct vkd3d_private_store private_store;
+
+ HRESULT removed_reason;
+
+ const struct vkd3d_format *depth_stencil_formats;
+ unsigned int format_compatibility_list_count;
+ const struct vkd3d_format_compatibility_list *format_compatibility_lists;
+ struct vkd3d_null_resources null_resources;
+ struct vkd3d_uav_clear_state uav_clear_state;
+};
+
+HRESULT d3d12_device_create(struct vkd3d_instance *instance,
+ const struct vkd3d_device_create_info *create_info, struct d3d12_device **device) DECLSPEC_HIDDEN;
+struct vkd3d_queue *d3d12_device_get_vkd3d_queue(struct d3d12_device *device,
+ D3D12_COMMAND_LIST_TYPE type) DECLSPEC_HIDDEN;
+bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent) DECLSPEC_HIDDEN;
+void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason,
+ const char *message, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN;
+struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface) DECLSPEC_HIDDEN;
+
+static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object)
+{
+ return ID3D12Device_QueryInterface(&device->ID3D12Device_iface, iid, object);
+}
+
+static inline ULONG d3d12_device_add_ref(struct d3d12_device *device)
+{
+ return ID3D12Device_AddRef(&device->ID3D12Device_iface);
+}
+
+static inline ULONG d3d12_device_release(struct d3d12_device *device)
+{
+ return ID3D12Device_Release(&device->ID3D12Device_iface);
+}
+
+static inline unsigned int d3d12_device_get_descriptor_handle_increment_size(struct d3d12_device *device,
+ D3D12_DESCRIPTOR_HEAP_TYPE descriptor_type)
+{
+ return ID3D12Device_GetDescriptorHandleIncrementSize(&device->ID3D12Device_iface, descriptor_type);
+}
+
+static inline pthread_mutex_t *d3d12_device_get_descriptor_mutex(struct d3d12_device *device,
+ const struct d3d12_desc *descriptor)
+{
+ STATIC_ASSERT(!(ARRAY_SIZE(device->desc_mutex) & (ARRAY_SIZE(device->desc_mutex) - 1)));
+ uintptr_t idx = (uintptr_t)descriptor;
+
+ idx ^= idx >> 12;
+ idx ^= idx >> 6;
+ idx ^= idx >> 3;
+
+ return &device->desc_mutex[idx & (ARRAY_SIZE(device->desc_mutex) - 1)];
+}
+
+/* utils */
+enum vkd3d_format_type
+{
+ VKD3D_FORMAT_TYPE_OTHER,
+ VKD3D_FORMAT_TYPE_TYPELESS,
+ VKD3D_FORMAT_TYPE_SINT,
+ VKD3D_FORMAT_TYPE_UINT,
+};
+
+struct vkd3d_format
+{
+ DXGI_FORMAT dxgi_format;
+ VkFormat vk_format;
+ size_t byte_count;
+ size_t block_width;
+ size_t block_height;
+ size_t block_byte_count;
+ VkImageAspectFlags vk_aspect_mask;
+ unsigned int plane_count;
+ enum vkd3d_format_type type;
+ bool is_emulated;
+};
+
+static inline size_t vkd3d_format_get_data_offset(const struct vkd3d_format *format,
+ unsigned int row_pitch, unsigned int slice_pitch,
+ unsigned int x, unsigned int y, unsigned int z)
+{
+ return z * slice_pitch
+ + (y / format->block_height) * row_pitch
+ + (x / format->block_width) * format->byte_count * format->block_byte_count;
+}
+
+static inline bool vkd3d_format_is_compressed(const struct vkd3d_format *format)
+{
+ return format->block_byte_count != 1;
+}
+
+void vkd3d_format_copy_data(const struct vkd3d_format *format, const uint8_t *src,
+ unsigned int src_row_pitch, unsigned int src_slice_pitch, uint8_t *dst, unsigned int dst_row_pitch,
+ unsigned int dst_slice_pitch, unsigned int w, unsigned int h, unsigned int d) DECLSPEC_HIDDEN;
+
+const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device,
+ DXGI_FORMAT dxgi_format, bool depth_stencil) DECLSPEC_HIDDEN;
+const struct vkd3d_format *vkd3d_find_uint_format(const struct d3d12_device *device,
+ DXGI_FORMAT dxgi_format) DECLSPEC_HIDDEN;
+
+HRESULT vkd3d_init_format_info(struct d3d12_device *device) DECLSPEC_HIDDEN;
+void vkd3d_cleanup_format_info(struct d3d12_device *device) DECLSPEC_HIDDEN;
+
+static inline const struct vkd3d_format *vkd3d_format_from_d3d12_resource_desc(
+ const struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc, DXGI_FORMAT view_format)
+{
+ return vkd3d_get_format(device, view_format ? view_format : desc->Format,
+ desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);
+}
+
+static inline bool d3d12_box_is_empty(const D3D12_BOX *box)
+{
+ return box->right <= box->left || box->bottom <= box->top || box->back <= box->front;
+}
+
+static inline unsigned int d3d12_resource_desc_get_width(const D3D12_RESOURCE_DESC *desc,
+ unsigned int miplevel_idx)
+{
+ return max(1, desc->Width >> miplevel_idx);
+}
+
+static inline unsigned int d3d12_resource_desc_get_height(const D3D12_RESOURCE_DESC *desc,
+ unsigned int miplevel_idx)
+{
+ return max(1, desc->Height >> miplevel_idx);
+}
+
+static inline unsigned int d3d12_resource_desc_get_depth(const D3D12_RESOURCE_DESC *desc,
+ unsigned int miplevel_idx)
+{
+ unsigned int d = desc->Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? 1 : desc->DepthOrArraySize;
+ return max(1, d >> miplevel_idx);
+}
+
+static inline unsigned int d3d12_resource_desc_get_layer_count(const D3D12_RESOURCE_DESC *desc)
+{
+ return desc->Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? desc->DepthOrArraySize : 1;
+}
+
+static inline unsigned int d3d12_resource_desc_get_sub_resource_count(const D3D12_RESOURCE_DESC *desc)
+{
+ return d3d12_resource_desc_get_layer_count(desc) * desc->MipLevels;
+}
+
+static inline unsigned int vkd3d_compute_workgroup_count(unsigned int thread_count, unsigned int workgroup_size)
+{
+ return (thread_count + workgroup_size - 1) / workgroup_size;
+}
+
+VkCompareOp vk_compare_op_from_d3d12(D3D12_COMPARISON_FUNC op) DECLSPEC_HIDDEN;
+VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_DESC *desc) DECLSPEC_HIDDEN;
+VkSampleCountFlagBits vk_samples_from_sample_count(unsigned int sample_count) DECLSPEC_HIDDEN;
+
+bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) DECLSPEC_HIDDEN;
+
+bool is_valid_resource_state(D3D12_RESOURCE_STATES state) DECLSPEC_HIDDEN;
+bool is_write_resource_state(D3D12_RESOURCE_STATES state) DECLSPEC_HIDDEN;
+
+HRESULT return_interface(void *iface, REFIID iface_iid,
+ REFIID requested_iid, void **object) DECLSPEC_HIDDEN;
+
+const char *debug_d3d12_box(const D3D12_BOX *box) DECLSPEC_HIDDEN;
+const char *debug_d3d12_shader_component_mapping(unsigned int mapping) DECLSPEC_HIDDEN;
+const char *debug_vk_extent_3d(VkExtent3D extent) DECLSPEC_HIDDEN;
+const char *debug_vk_memory_heap_flags(VkMemoryHeapFlags flags) DECLSPEC_HIDDEN;
+const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags) DECLSPEC_HIDDEN;
+const char *debug_vk_queue_flags(VkQueueFlags flags) DECLSPEC_HIDDEN;
+
+static inline void debug_ignored_node_mask(unsigned int mask)
+{
+ if (mask && mask != 1)
+ FIXME("Ignoring node mask 0x%08x.\n", mask);
+}
+
+HRESULT vkd3d_load_vk_global_procs(struct vkd3d_vk_global_procs *procs,
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr) DECLSPEC_HIDDEN;
+HRESULT vkd3d_load_vk_instance_procs(struct vkd3d_vk_instance_procs *procs,
+ const struct vkd3d_vk_global_procs *global_procs, VkInstance instance) DECLSPEC_HIDDEN;
+HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs,
+ const struct vkd3d_vk_instance_procs *parent_procs, VkDevice device) DECLSPEC_HIDDEN;
+
+extern const char vkd3d_build[];
+
+bool vkd3d_get_program_name(char program_name[PATH_MAX]) DECLSPEC_HIDDEN;
+
+static inline void vkd3d_set_thread_name(const char *name)
+{
+#if defined(HAVE_PTHREAD_SETNAME_NP_2)
+ pthread_setname_np(pthread_self(), name);
+#elif defined(HAVE_PTHREAD_SETNAME_NP_1)
+ pthread_setname_np(name);
+#endif
+}
+
+VkResult vkd3d_set_vk_object_name_utf8(struct d3d12_device *device, uint64_t vk_object,
+ VkDebugReportObjectTypeEXT vk_object_type, const char *name) DECLSPEC_HIDDEN;
+HRESULT vkd3d_set_vk_object_name(struct d3d12_device *device, uint64_t vk_object,
+ VkDebugReportObjectTypeEXT vk_object_type, const WCHAR *name) DECLSPEC_HIDDEN;
+
+static inline void vk_prepend_struct(void *header, void *structure)
+{
+ VkBaseOutStructure *vk_header = header, *vk_structure = structure;
+
+ assert(!vk_structure->pNext);
+ vk_structure->pNext = vk_header->pNext;
+ vk_header->pNext = vk_structure;
+}
+
+#endif /* __VKD3D_PRIVATE_H */
diff --git a/dlls/vkd3d/libs/vkd3d/vkd3d_shaders.h b/dlls/vkd3d/libs/vkd3d/vkd3d_shaders.h
new file mode 100644
index 00000000000..b2a90cdbf3c
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/vkd3d_shaders.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2019 Philip Rebohle
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_SHADERS_H
+#define __VKD3D_SHADERS_H
+
+static const uint32_t cs_uav_clear_buffer_float_code[] =
+{
+#if 0
+ RWBuffer<float4> dst;
+
+ struct
+ {
+ float4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(128, 1, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (thread_id.x < u_info.dst_extent.x)
+ dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0xe114ba61, 0xff6a0d0b, 0x7b25c8f4, 0xfcf7cf22, 0x00000001, 0x0000010c, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400089c, 0x0011e000, 0x00000000, 0x00005555,
+ 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000080, 0x00000001, 0x00000001,
+ 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
+ 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
+ 0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
+ 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_buffer_uint_code[] =
+{
+#if 0
+ RWBuffer<uint4> dst;
+
+ struct
+ {
+ uint4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(128, 1, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (thread_id.x < u_info.dst_extent.x)
+ dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x3afd0cfd, 0x5145c166, 0x5b9f76b8, 0xa73775cd, 0x00000001, 0x0000010c, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400089c, 0x0011e000, 0x00000000, 0x00004444,
+ 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000080, 0x00000001, 0x00000001,
+ 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
+ 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
+ 0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
+ 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_1d_array_float_code[] =
+{
+#if 0
+ RWTexture1DArray<float4> dst;
+
+ struct
+ {
+ float4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(64, 1, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (thread_id.x < u_info.dst_extent.x)
+ dst[int2(u_info.dst_offset.x + thread_id.x, thread_id.y)] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x3d73bc2d, 0x2b635f3d, 0x6bf98e92, 0xbe0aa5d9, 0x00000001, 0x0000011c, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000c8, 0x00050050, 0x00000032, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400389c, 0x0011e000, 0x00000000, 0x00005555,
+ 0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
+ 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
+ 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
+ 0x00000001, 0x04000036, 0x001000e2, 0x00000000, 0x00020556, 0x080000a4, 0x0011e0f2, 0x00000000,
+ 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_1d_array_uint_code[] =
+{
+#if 0
+ RWTexture1DArray<uint4> dst;
+
+ struct
+ {
+ uint4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(64, 1, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (thread_id.x < u_info.dst_extent.x)
+ dst[int2(u_info.dst_offset.x + thread_id.x, thread_id.y)] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x2f0ca457, 0x72068b34, 0xd9dadc2b, 0xd3178c3e, 0x00000001, 0x0000011c, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000c8, 0x00050050, 0x00000032, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400389c, 0x0011e000, 0x00000000, 0x00004444,
+ 0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
+ 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
+ 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
+ 0x00000001, 0x04000036, 0x001000e2, 0x00000000, 0x00020556, 0x080000a4, 0x0011e0f2, 0x00000000,
+ 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_1d_float_code[] =
+{
+#if 0
+ RWTexture1D<float4> dst;
+
+ struct
+ {
+ float4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(64, 1, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (thread_id.x < u_info.dst_extent.x)
+ dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x05266503, 0x4b97006f, 0x01a5cc63, 0xe617d0a1, 0x00000001, 0x0000010c, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400109c, 0x0011e000, 0x00000000, 0x00005555,
+ 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
+ 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
+ 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
+ 0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
+ 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_1d_uint_code[] =
+{
+#if 0
+ RWTexture1D<uint4> dst;
+
+ struct
+ {
+ uint4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(64, 1, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (thread_id.x < u_info.dst_extent.x)
+ dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x19d5c8f2, 0x3ca4ac24, 0x9e258499, 0xf0463fd6, 0x00000001, 0x0000010c, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400109c, 0x0011e000, 0x00000000, 0x00004444,
+ 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
+ 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
+ 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
+ 0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
+ 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_2d_array_float_code[] =
+{
+#if 0
+ RWTexture2DArray<float4> dst;
+
+ struct
+ {
+ float4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(8, 8, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (all(thread_id.xy < u_info.dst_extent.xy))
+ dst[int3(u_info.dst_offset.xy + thread_id.xy, thread_id.z)] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x924d2d2c, 0xb9166376, 0x99f83871, 0x8ef65025, 0x00000001, 0x00000138, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400409c, 0x0011e000, 0x00000000, 0x00005555,
+ 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
+ 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
+ 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
+ 0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
+ 0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
+ 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_2d_array_uint_code[] =
+{
+#if 0
+ RWTexture2DArray<uint4> dst;
+
+ struct
+ {
+ uint4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(8, 8, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (all(thread_id.xy < u_info.dst_extent.xy))
+ dst[int3(u_info.dst_offset.xy + thread_id.xy, thread_id.z)] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0xa92219d4, 0xa2c5e47d, 0x0d308500, 0xf32197b4, 0x00000001, 0x00000138, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400409c, 0x0011e000, 0x00000000, 0x00004444,
+ 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
+ 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
+ 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
+ 0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
+ 0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
+ 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_2d_float_code[] =
+{
+#if 0
+ RWTexture2D<float4> dst;
+
+ struct
+ {
+ float4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(8, 8, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (all(thread_id.xy < u_info.dst_extent.xy))
+ dst[u_info.dst_offset.xy + thread_id.xy] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x6e735b3f, 0x7348c4fa, 0xb3634e42, 0x50e2d99b, 0x00000001, 0x00000128, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000d4, 0x00050050, 0x00000035, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555,
+ 0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
+ 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
+ 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
+ 0x00000000, 0x0700001e, 0x001000f2, 0x00000000, 0x00020546, 0x00208546, 0x00000000, 0x00000001,
+ 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000,
+ 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_2d_uint_code[] =
+{
+#if 0
+ RWTexture2D<uint4> dst;
+
+ struct
+ {
+ uint4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(8, 8, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (all(thread_id.xy < u_info.dst_extent.xy))
+ dst[u_info.dst_offset.xy + thread_id.xy] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0xf01db5dd, 0xc7dc5e55, 0xb017c1a8, 0x55abd52d, 0x00000001, 0x00000128, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000d4, 0x00050050, 0x00000035, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400189c, 0x0011e000, 0x00000000, 0x00004444,
+ 0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
+ 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
+ 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
+ 0x00000000, 0x0700001e, 0x001000f2, 0x00000000, 0x00020546, 0x00208546, 0x00000000, 0x00000001,
+ 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000,
+ 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_3d_float_code[] =
+{
+#if 0
+ RWTexture3D<float4> dst;
+
+ struct
+ {
+ float4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(8, 8, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (all(thread_id.xy < u_info.dst_extent.xy))
+ dst[int3(u_info.dst_offset.xy, 0) + thread_id.xyz] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x5d8f36a0, 0x30fa86a5, 0xfec7f2ef, 0xdfd76cbb, 0x00000001, 0x00000138, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400289c, 0x0011e000, 0x00000000, 0x00005555,
+ 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
+ 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
+ 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
+ 0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
+ 0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
+ 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
+};
+
+static const uint32_t cs_uav_clear_3d_uint_code[] =
+{
+#if 0
+ RWTexture3D<uint4> dst;
+
+ struct
+ {
+ uint4 clear_value;
+ int2 dst_offset;
+ int2 dst_extent;
+ } u_info;
+
+ [numthreads(8, 8, 1)]
+ void main(int3 thread_id : SV_DispatchThreadID)
+ {
+ if (all(thread_id.xy < u_info.dst_extent.xy))
+ dst[int3(u_info.dst_offset.xy, 0) + thread_id.xyz] = u_info.clear_value;
+ }
+#endif
+ 0x43425844, 0x5b9c95b1, 0xc9bde4e3, 0x9aaff806, 0x24a1d264, 0x00000001, 0x00000138, 0x00000003,
+ 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
+ 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
+ 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400289c, 0x0011e000, 0x00000000, 0x00004444,
+ 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
+ 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
+ 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
+ 0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
+ 0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
+ 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
+};
+
+#endif /* __VKD3D_SHADERS_H */
diff --git a/dlls/vkd3d/libs/vkd3d/vulkan_procs.h b/dlls/vkd3d/libs/vkd3d/vulkan_procs.h
new file mode 100644
index 00000000000..ec29eb45302
--- /dev/null
+++ b/dlls/vkd3d/libs/vkd3d/vulkan_procs.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2016 Józef Kucia for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef VK_INSTANCE_PFN
+# define VK_INSTANCE_PFN(x)
+#endif
+
+#ifndef VK_INSTANCE_EXT_PFN
+# define VK_INSTANCE_EXT_PFN(x)
+#endif
+
+#ifndef VK_DEVICE_PFN
+# define VK_DEVICE_PFN(x)
+#endif
+
+#ifndef VK_DEVICE_EXT_PFN
+# define VK_DEVICE_EXT_PFN(x)
+#endif
+
+/* Instance functions (obtained by vkGetInstanceProcAddr). */
+VK_INSTANCE_PFN(vkDestroyInstance) /* Load vkDestroyInstance() first. */
+VK_INSTANCE_PFN(vkCreateDevice)
+VK_INSTANCE_PFN(vkEnumerateDeviceExtensionProperties)
+VK_INSTANCE_PFN(vkEnumerateDeviceLayerProperties)
+VK_INSTANCE_PFN(vkEnumeratePhysicalDevices)
+VK_INSTANCE_PFN(vkGetDeviceProcAddr)
+VK_INSTANCE_PFN(vkGetPhysicalDeviceFeatures)
+VK_INSTANCE_PFN(vkGetPhysicalDeviceFormatProperties)
+VK_INSTANCE_PFN(vkGetPhysicalDeviceImageFormatProperties)
+VK_INSTANCE_PFN(vkGetPhysicalDeviceMemoryProperties)
+VK_INSTANCE_PFN(vkGetPhysicalDeviceProperties)
+VK_INSTANCE_PFN(vkGetPhysicalDeviceQueueFamilyProperties)
+VK_INSTANCE_PFN(vkGetPhysicalDeviceSparseImageFormatProperties)
+
+/* VK_KHR_get_physical_device_properties2 */
+VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceFeatures2KHR)
+VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2KHR)
+
+/* VK_EXT_debug_report */
+VK_INSTANCE_EXT_PFN(vkCreateDebugReportCallbackEXT)
+VK_INSTANCE_EXT_PFN(vkDestroyDebugReportCallbackEXT)
+
+/* Device functions (obtained by vkGetDeviceProcAddr). */
+VK_DEVICE_PFN(vkDestroyDevice) /* Load vkDestroyDevice() first. */
+VK_DEVICE_PFN(vkAllocateCommandBuffers)
+VK_DEVICE_PFN(vkAllocateDescriptorSets)
+VK_DEVICE_PFN(vkAllocateMemory)
+VK_DEVICE_PFN(vkBeginCommandBuffer)
+VK_DEVICE_PFN(vkBindBufferMemory)
+VK_DEVICE_PFN(vkBindImageMemory)
+VK_DEVICE_PFN(vkCmdBeginQuery)
+VK_DEVICE_PFN(vkCmdBeginRenderPass)
+VK_DEVICE_PFN(vkCmdBindDescriptorSets)
+VK_DEVICE_PFN(vkCmdBindIndexBuffer)
+VK_DEVICE_PFN(vkCmdBindPipeline)
+VK_DEVICE_PFN(vkCmdBindVertexBuffers)
+VK_DEVICE_PFN(vkCmdBlitImage)
+VK_DEVICE_PFN(vkCmdClearAttachments)
+VK_DEVICE_PFN(vkCmdClearColorImage)
+VK_DEVICE_PFN(vkCmdClearDepthStencilImage)
+VK_DEVICE_PFN(vkCmdCopyBuffer)
+VK_DEVICE_PFN(vkCmdCopyBufferToImage)
+VK_DEVICE_PFN(vkCmdCopyImage)
+VK_DEVICE_PFN(vkCmdCopyImageToBuffer)
+VK_DEVICE_PFN(vkCmdCopyQueryPoolResults)
+VK_DEVICE_PFN(vkCmdDispatch)
+VK_DEVICE_PFN(vkCmdDispatchIndirect)
+VK_DEVICE_PFN(vkCmdDraw)
+VK_DEVICE_PFN(vkCmdDrawIndexed)
+VK_DEVICE_PFN(vkCmdDrawIndexedIndirect)
+VK_DEVICE_PFN(vkCmdDrawIndirect)
+VK_DEVICE_PFN(vkCmdEndQuery)
+VK_DEVICE_PFN(vkCmdEndRenderPass)
+VK_DEVICE_PFN(vkCmdExecuteCommands)
+VK_DEVICE_PFN(vkCmdFillBuffer)
+VK_DEVICE_PFN(vkCmdNextSubpass)
+VK_DEVICE_PFN(vkCmdPipelineBarrier)
+VK_DEVICE_PFN(vkCmdPushConstants)
+VK_DEVICE_PFN(vkCmdResetEvent)
+VK_DEVICE_PFN(vkCmdResetQueryPool)
+VK_DEVICE_PFN(vkCmdResolveImage)
+VK_DEVICE_PFN(vkCmdSetBlendConstants)
+VK_DEVICE_PFN(vkCmdSetDepthBias)
+VK_DEVICE_PFN(vkCmdSetDepthBounds)
+VK_DEVICE_PFN(vkCmdSetEvent)
+VK_DEVICE_PFN(vkCmdSetLineWidth)
+VK_DEVICE_PFN(vkCmdSetScissor)
+VK_DEVICE_PFN(vkCmdSetStencilCompareMask)
+VK_DEVICE_PFN(vkCmdSetStencilReference)
+VK_DEVICE_PFN(vkCmdSetStencilWriteMask)
+VK_DEVICE_PFN(vkCmdSetViewport)
+VK_DEVICE_PFN(vkCmdUpdateBuffer)
+VK_DEVICE_PFN(vkCmdWaitEvents)
+VK_DEVICE_PFN(vkCmdWriteTimestamp)
+VK_DEVICE_PFN(vkCreateBuffer)
+VK_DEVICE_PFN(vkCreateBufferView)
+VK_DEVICE_PFN(vkCreateCommandPool)
+VK_DEVICE_PFN(vkCreateComputePipelines)
+VK_DEVICE_PFN(vkCreateDescriptorPool)
+VK_DEVICE_PFN(vkCreateDescriptorSetLayout)
+VK_DEVICE_PFN(vkCreateEvent)
+VK_DEVICE_PFN(vkCreateFence)
+VK_DEVICE_PFN(vkCreateFramebuffer)
+VK_DEVICE_PFN(vkCreateGraphicsPipelines)
+VK_DEVICE_PFN(vkCreateImage)
+VK_DEVICE_PFN(vkCreateImageView)
+VK_DEVICE_PFN(vkCreatePipelineCache)
+VK_DEVICE_PFN(vkCreatePipelineLayout)
+VK_DEVICE_PFN(vkCreateQueryPool)
+VK_DEVICE_PFN(vkCreateRenderPass)
+VK_DEVICE_PFN(vkCreateSampler)
+VK_DEVICE_PFN(vkCreateSemaphore)
+VK_DEVICE_PFN(vkCreateShaderModule)
+VK_DEVICE_PFN(vkDestroyBuffer)
+VK_DEVICE_PFN(vkDestroyBufferView)
+VK_DEVICE_PFN(vkDestroyCommandPool)
+VK_DEVICE_PFN(vkDestroyDescriptorPool)
+VK_DEVICE_PFN(vkDestroyDescriptorSetLayout)
+VK_DEVICE_PFN(vkDestroyEvent)
+VK_DEVICE_PFN(vkDestroyFence)
+VK_DEVICE_PFN(vkDestroyFramebuffer)
+VK_DEVICE_PFN(vkDestroyImage)
+VK_DEVICE_PFN(vkDestroyImageView)
+VK_DEVICE_PFN(vkDestroyPipeline)
+VK_DEVICE_PFN(vkDestroyPipelineCache)
+VK_DEVICE_PFN(vkDestroyPipelineLayout)
+VK_DEVICE_PFN(vkDestroyQueryPool)
+VK_DEVICE_PFN(vkDestroyRenderPass)
+VK_DEVICE_PFN(vkDestroySampler)
+VK_DEVICE_PFN(vkDestroySemaphore)
+VK_DEVICE_PFN(vkDestroyShaderModule)
+VK_DEVICE_PFN(vkDeviceWaitIdle)
+VK_DEVICE_PFN(vkEndCommandBuffer)
+VK_DEVICE_PFN(vkFlushMappedMemoryRanges)
+VK_DEVICE_PFN(vkFreeCommandBuffers)
+VK_DEVICE_PFN(vkFreeDescriptorSets)
+VK_DEVICE_PFN(vkFreeMemory)
+VK_DEVICE_PFN(vkGetBufferMemoryRequirements)
+VK_DEVICE_PFN(vkGetDeviceMemoryCommitment)
+VK_DEVICE_PFN(vkGetDeviceQueue)
+VK_DEVICE_PFN(vkGetEventStatus)
+VK_DEVICE_PFN(vkGetFenceStatus)
+VK_DEVICE_PFN(vkGetImageMemoryRequirements)
+VK_DEVICE_PFN(vkGetImageSparseMemoryRequirements)
+VK_DEVICE_PFN(vkGetImageSubresourceLayout)
+VK_DEVICE_PFN(vkGetPipelineCacheData)
+VK_DEVICE_PFN(vkGetQueryPoolResults)
+VK_DEVICE_PFN(vkGetRenderAreaGranularity)
+VK_DEVICE_PFN(vkInvalidateMappedMemoryRanges)
+VK_DEVICE_PFN(vkMapMemory)
+VK_DEVICE_PFN(vkMergePipelineCaches)
+VK_DEVICE_PFN(vkQueueBindSparse)
+VK_DEVICE_PFN(vkQueueSubmit)
+VK_DEVICE_PFN(vkQueueWaitIdle)
+VK_DEVICE_PFN(vkResetCommandBuffer)
+VK_DEVICE_PFN(vkResetCommandPool)
+VK_DEVICE_PFN(vkResetDescriptorPool)
+VK_DEVICE_PFN(vkResetEvent)
+VK_DEVICE_PFN(vkResetFences)
+VK_DEVICE_PFN(vkSetEvent)
+VK_DEVICE_PFN(vkUnmapMemory)
+VK_DEVICE_PFN(vkUpdateDescriptorSets)
+VK_DEVICE_PFN(vkWaitForFences)
+
+/* VK_KHR_draw_indirect_count */
+VK_DEVICE_EXT_PFN(vkCmdDrawIndirectCountKHR)
+VK_DEVICE_EXT_PFN(vkCmdDrawIndexedIndirectCountKHR)
+
+/* VK_KHR_get_memory_requirements2 */
+VK_DEVICE_EXT_PFN(vkGetBufferMemoryRequirements2KHR)
+VK_DEVICE_EXT_PFN(vkGetImageMemoryRequirements2KHR)
+VK_DEVICE_EXT_PFN(vkGetImageSparseMemoryRequirements2KHR)
+
+/* VK_KHR_maintenance3 */
+VK_DEVICE_EXT_PFN(vkGetDescriptorSetLayoutSupportKHR)
+
+/* VK_KHR_push_descriptor */
+VK_DEVICE_EXT_PFN(vkCmdPushDescriptorSetKHR)
+
+/* VK_EXT_conditional_rendering */
+VK_DEVICE_EXT_PFN(vkCmdBeginConditionalRenderingEXT)
+VK_DEVICE_EXT_PFN(vkCmdEndConditionalRenderingEXT)
+
+/* VK_EXT_debug_marker */
+VK_DEVICE_EXT_PFN(vkDebugMarkerSetObjectNameEXT)
+
+/* VK_EXT_transform_feedback */
+VK_DEVICE_EXT_PFN(vkCmdBeginQueryIndexedEXT)
+VK_DEVICE_EXT_PFN(vkCmdBeginTransformFeedbackEXT)
+VK_DEVICE_EXT_PFN(vkCmdBindTransformFeedbackBuffersEXT)
+VK_DEVICE_EXT_PFN(vkCmdEndQueryIndexedEXT)
+VK_DEVICE_EXT_PFN(vkCmdEndTransformFeedbackEXT)
+
+#undef VK_INSTANCE_PFN
+#undef VK_INSTANCE_EXT_PFN
+#undef VK_DEVICE_PFN
+#undef VK_DEVICE_EXT_PFN
diff --git a/dlls/vkd3d/libvkd3d-wine.spec b/dlls/vkd3d/libvkd3d-wine.spec
new file mode 100644
index 00000000000..93efc2fbb7c
--- /dev/null
+++ b/dlls/vkd3d/libvkd3d-wine.spec
@@ -0,0 +1,20 @@
+@ cdecl vkd3d_acquire_vk_queue(ptr)
+@ cdecl vkd3d_create_device(ptr ptr ptr)
+@ cdecl vkd3d_create_image_resource(ptr ptr ptr)
+@ cdecl vkd3d_create_instance(ptr ptr)
+@ cdecl vkd3d_create_root_signature_deserializer(ptr long ptr ptr)
+@ cdecl vkd3d_create_versioned_root_signature_deserializer(ptr long ptr ptr)
+@ cdecl vkd3d_get_device_parent(ptr)
+@ cdecl vkd3d_get_vk_device(ptr)
+@ cdecl vkd3d_get_vk_format(long)
+@ cdecl vkd3d_get_vk_physical_device(ptr)
+@ cdecl vkd3d_get_vk_queue_family_index(ptr)
+@ cdecl vkd3d_instance_decref(ptr)
+@ cdecl vkd3d_instance_from_device(ptr)
+@ cdecl vkd3d_instance_get_vk_instance(ptr)
+@ cdecl vkd3d_instance_incref(ptr)
+@ cdecl vkd3d_release_vk_queue(ptr)
+@ cdecl vkd3d_resource_decref(ptr)
+@ cdecl vkd3d_resource_incref(ptr)
+@ cdecl vkd3d_serialize_root_signature(ptr long ptr ptr)
+@ cdecl vkd3d_serialize_versioned_root_signature(ptr long ptr ptr)
--
2.34.0
More information about the wine-devel
mailing list