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@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)