wine-staging/patches/vkd3d-latest/0001-Updated-vkd3d-to-ca05e57e67306e9b97eb22a35cd77728e3e.patch

3863 lines
137 KiB
Diff
Raw Normal View History

2023-10-12 15:57:25 -07:00
From b7cf024c15c33db9f98f4c23e6ed0c151e61de9a Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Wed, 17 May 2023 08:35:40 +1000
2023-10-12 15:57:25 -07:00
Subject: [PATCH] Updated vkd3d to ca05e57e67306e9b97eb22a35cd77728e3e91db9
---
libs/vkd3d/include/list.h | 270 +++++++++++
libs/vkd3d/include/private/list.h | 270 +++++++++++
libs/vkd3d/include/private/rbtree.h | 378 +++++++++++++++
libs/vkd3d/include/private/vkd3d_common.h | 2 +-
libs/vkd3d/include/private/vkd3d_test.h | 432 ++++++++++++++++++
libs/vkd3d/include/vkd3d_d3d9types.h | 237 ++++++++++
libs/vkd3d/include/vkd3d_d3dcompiler.h | 74 +++
libs/vkd3d/include/vkd3d_utils.h | 108 +++++
libs/vkd3d/include/vkd3d_windows.h | 289 ++++++++++++
libs/vkd3d/libs/vkd3d-common/blob.c | 1 +
libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 2 +-
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 30 +-
libs/vkd3d/libs/vkd3d-shader/dxil.c | 10 +-
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 2 +-
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 35 +-
.../libs/vkd3d-shader/hlsl_constant_ops.c | 187 +++++++-
libs/vkd3d/libs/vkd3d-shader/ir.c | 150 +++++-
libs/vkd3d/libs/vkd3d-shader/preproc.h | 2 +-
libs/vkd3d/libs/vkd3d-shader/spirv.c | 2 +-
libs/vkd3d/libs/vkd3d-shader/tpf.c | 14 +-
.../libs/vkd3d-shader/vkd3d_shader_main.c | 22 +
.../libs/vkd3d-shader/vkd3d_shader_private.h | 35 +-
libs/vkd3d/libs/vkd3d/command.c | 1 +
libs/vkd3d/libs/vkd3d/device.c | 199 ++++----
libs/vkd3d/libs/vkd3d/resource.c | 2 +-
libs/vkd3d/libs/vkd3d/vkd3d_main.c | 4 +-
libs/vkd3d/libs/vkd3d/vkd3d_private.h | 16 +-
27 files changed, 2597 insertions(+), 177 deletions(-)
create mode 100644 libs/vkd3d/include/list.h
create mode 100644 libs/vkd3d/include/private/list.h
create mode 100644 libs/vkd3d/include/private/rbtree.h
create mode 100644 libs/vkd3d/include/private/vkd3d_test.h
create mode 100644 libs/vkd3d/include/vkd3d_d3d9types.h
create mode 100644 libs/vkd3d/include/vkd3d_d3dcompiler.h
create mode 100644 libs/vkd3d/include/vkd3d_utils.h
create mode 100644 libs/vkd3d/include/vkd3d_windows.h
diff --git a/libs/vkd3d/include/list.h b/libs/vkd3d/include/list.h
new file mode 100644
index 00000000000..2e1d95f3fd4
--- /dev/null
+++ b/libs/vkd3d/include/list.h
@@ -0,0 +1,270 @@
+/*
+ * 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 before the specified element */
+static inline void list_move_before( 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 after the specified element */
+static inline void list_move_after( 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);
+}
+
+/* move all elements from src to the head of dst */
+static inline void list_move_head( struct list *dst, struct list *src )
+{
+ list_move_after( dst, src );
+}
+
+/* move all elements from src to the tail of dst */
+static inline void list_move_tail( struct list *dst, struct list *src )
+{
+ list_move_before( dst, src );
+}
+
+/* move the slice of elements from begin to end inclusive to the head of dst */
+static inline void list_move_slice_head( struct list *dst, struct list *begin, struct list *end )
+{
+ struct list *dst_next = dst->next;
+ begin->prev->next = end->next;
+ end->next->prev = begin->prev;
+ dst->next = begin;
+ dst_next->prev = end;
+ begin->prev = dst;
+ end->next = dst_next;
+}
+
+/* move the slice of elements from begin to end inclusive to the tail of dst */
+static inline void list_move_slice_tail( struct list *dst, struct list *begin, struct list *end )
+{
+ struct list *dst_prev = dst->prev;
+ begin->prev->next = end->next;
+ end->next->prev = begin->prev;
+ dst_prev->next = begin;
+ dst->prev = end;
+ begin->prev = dst_prev;
+ end->next = dst;
+}
+
+/* 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/libs/vkd3d/include/private/list.h b/libs/vkd3d/include/private/list.h
new file mode 100644
index 00000000000..2e1d95f3fd4
--- /dev/null
+++ b/libs/vkd3d/include/private/list.h
@@ -0,0 +1,270 @@
+/*
+ * 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 before the specified element */
+static inline void list_move_before( 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 after the specified element */
+static inline void list_move_after( 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);
+}
+
+/* move all elements from src to the head of dst */
+static inline void list_move_head( struct list *dst, struct list *src )
+{
+ list_move_after( dst, src );
+}
+
+/* move all elements from src to the tail of dst */
+static inline void list_move_tail( struct list *dst, struct list *src )
+{
+ list_move_before( dst, src );
+}
+
+/* move the slice of elements from begin to end inclusive to the head of dst */
+static inline void list_move_slice_head( struct list *dst, struct list *begin, struct list *end )
+{
+ struct list *dst_next = dst->next;
+ begin->prev->next = end->next;
+ end->next->prev = begin->prev;
+ dst->next = begin;
+ dst_next->prev = end;
+ begin->prev = dst;
+ end->next = dst_next;
+}
+
+/* move the slice of elements from begin to end inclusive to the tail of dst */
+static inline void list_move_slice_tail( struct list *dst, struct list *begin, struct list *end )
+{
+ struct list *dst_prev = dst->prev;
+ begin->prev->next = end->next;
+ end->next->prev = begin->prev;
+ dst_prev->next = begin;
+ dst->prev = end;
+ begin->prev = dst_prev;
+ end->next = dst;
+}
+
+/* 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/libs/vkd3d/include/private/rbtree.h b/libs/vkd3d/include/private/rbtree.h
new file mode 100644
index 00000000000..b5d38bca54c
--- /dev/null
+++ b/libs/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) != RB_ENTRY_VALUE(0, type, 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) != WINE_RB_ENTRY_VALUE(0, type, 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/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h
index ee733ee0d76..f7d98f327f1 100644
--- a/libs/vkd3d/include/private/vkd3d_common.h
+++ b/libs/vkd3d/include/private/vkd3d_common.h
@@ -86,7 +86,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v)
{
#ifdef _MSC_VER
return __popcnt(v);
-#elif defined(__MINGW32__)
+#elif defined(HAVE_BUILTIN_POPCOUNT)
return __builtin_popcount(v);
#else
v -= (v >> 1) & 0x55555555;
diff --git a/libs/vkd3d/include/private/vkd3d_test.h b/libs/vkd3d/include/private/vkd3d_test.h
new file mode 100644
index 00000000000..081443c4fa6
--- /dev/null
+++ b/libs/vkd3d/include/private/vkd3d_test.h
@@ -0,0 +1,432 @@
+/*
+ * 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>
+
+extern const char *vkd3d_test_name;
+extern const char *vkd3d_test_platform;
+
+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) \
+ 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)
+
+struct vkd3d_test_state
+{
+ 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[8][128];
+ unsigned int context_count;
+};
+extern struct vkd3d_test_state 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_printf(unsigned int line, const char *msg)
+{
+ unsigned int i;
+
+ printf("%s:%u: ", vkd3d_test_name, line);
+ for (i = 0; i < vkd3d_test_state.context_count; ++i)
+ printf("%s: ", vkd3d_test_state.context[i]);
+ printf("%s", msg);
+}
+
+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)
+ vkd3d_test_printf(line, "Test succeeded.\n");
+ }
+ else
+ {
+ InterlockedIncrement(&vkd3d_test_state.failure_count);
+ vkd3d_test_printf(line, "Test failed: ");
+ 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)
+ vkd3d_test_printf(line, "Fixed bug: ");
+ else
+ vkd3d_test_printf(line, "Bug: ");
+ vprintf(fmt, args);
+ }
+ else if (is_todo)
+ {
+ if (result)
+ {
+ InterlockedIncrement(&vkd3d_test_state.todo_success_count);
+ vkd3d_test_printf(line, "Todo succeeded: ");
+ }
+ else
+ {
+ InterlockedIncrement(&vkd3d_test_state.todo_count);
+ vkd3d_test_printf(line, "Todo: ");
+ }
+ 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);
+ vkd3d_test_printf(line, "Test skipped: ");
+ 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);
+ vkd3d_test_printf(line, "");
+ 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);
+}
+
+#ifndef VKD3D_TEST_NO_DEFS
+const char *vkd3d_test_platform = "other";
+struct vkd3d_test_state vkd3d_test_state;
+
+static void vkd3d_test_main(int argc, char **argv);
+
+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 */
+#endif /* VKD3D_TEST_NO_DEFS */
+
+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_push_context(const char *fmt, ...)
+{
+ va_list args;
+
+ if (vkd3d_test_state.context_count < ARRAY_SIZE(vkd3d_test_state.context))
+ {
+ va_start(args, fmt);
+ vsnprintf(vkd3d_test_state.context[vkd3d_test_state.context_count],
+ sizeof(vkd3d_test_state.context), fmt, args);
+ va_end(args);
+ vkd3d_test_state.context[vkd3d_test_state.context_count][sizeof(vkd3d_test_state.context[0]) - 1] = '\0';
+ }
+ ++vkd3d_test_state.context_count;
+}
+
+static inline void vkd3d_test_pop_context(void)
+{
+ if (vkd3d_test_state.context_count)
+ --vkd3d_test_state.context_count;
+}
+
+#define run_test(test_pfn) \
+ vkd3d_run_test(#test_pfn, test_pfn)
+
+#endif /* __VKD3D_TEST_H */
diff --git a/libs/vkd3d/include/vkd3d_d3d9types.h b/libs/vkd3d/include/vkd3d_d3d9types.h
new file mode 100644
index 00000000000..75d0461409d
--- /dev/null
+++ b/libs/vkd3d/include/vkd3d_d3d9types.h
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2002-2003 Jason Edmeades
+ * Copyright 2002-2003 Raphael Junqueira
+ *
+ * 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_D3D9TYPES_H
+#define __VKD3D_D3D9TYPES_H
+#ifndef _d3d9TYPES_H_
+
+#ifndef MAKEFOURCC
+#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
+ ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
+#endif
+
+#define D3DSI_INSTLENGTH_SHIFT 24
+
+#define D3DSP_DCL_USAGE_SHIFT 0
+#define D3DSP_DCL_USAGEINDEX_SHIFT 16
+#define D3DSP_DSTMOD_SHIFT 20
+
+#define D3DSP_SRCMOD_SHIFT 24
+
+#define D3DSP_REGTYPE_SHIFT 28
+#define D3DSP_REGTYPE_SHIFT2 8
+#define D3DSP_REGTYPE_MASK (0x7 << D3DSP_REGTYPE_SHIFT)
+#define D3DSP_REGTYPE_MASK2 0x00001800
+
+#define D3DSP_WRITEMASK_0 0x00010000
+#define D3DSP_WRITEMASK_1 0x00020000
+#define D3DSP_WRITEMASK_2 0x00040000
+#define D3DSP_WRITEMASK_3 0x00080000
+#define D3DSP_WRITEMASK_ALL 0x000f0000
+
+#define D3DPS_VERSION(major, minor) (0xffff0000 | ((major) << 8) | (minor))
+#define D3DVS_VERSION(major, minor) (0xfffe0000 | ((major) << 8) | (minor))
+
+typedef enum _D3DDECLUSAGE
+{
+ D3DDECLUSAGE_POSITION = 0x0,
+ D3DDECLUSAGE_BLENDWEIGHT = 0x1,
+ D3DDECLUSAGE_BLENDINDICES = 0x2,
+ D3DDECLUSAGE_NORMAL = 0x3,
+ D3DDECLUSAGE_PSIZE = 0x4,
+ D3DDECLUSAGE_TEXCOORD = 0x5,
+ D3DDECLUSAGE_TANGENT = 0x6,
+ D3DDECLUSAGE_BINORMAL = 0x7,
+ D3DDECLUSAGE_TESSFACTOR = 0x8,
+ D3DDECLUSAGE_POSITIONT = 0x9,
+ D3DDECLUSAGE_COLOR = 0xa,
+ D3DDECLUSAGE_FOG = 0xb,
+ D3DDECLUSAGE_DEPTH = 0xc,
+ D3DDECLUSAGE_SAMPLE = 0xd,
+} D3DDECLUSAGE;
+
+typedef enum _D3DSHADER_INSTRUCTION_OPCODE_TYPE
+{
+ D3DSIO_NOP = 0x00,
+ D3DSIO_MOV = 0x01,
+ D3DSIO_ADD = 0x02,
+ D3DSIO_SUB = 0x03,
+ D3DSIO_MAD = 0x04,
+ D3DSIO_MUL = 0x05,
+ D3DSIO_RCP = 0x06,
+ D3DSIO_RSQ = 0x07,
+ D3DSIO_DP3 = 0x08,
+ D3DSIO_DP4 = 0x09,
+ D3DSIO_MIN = 0x0a,
+ D3DSIO_MAX = 0x0b,
+ D3DSIO_SLT = 0x0c,
+ D3DSIO_SGE = 0x0d,
+ D3DSIO_EXP = 0x0e,
+ D3DSIO_LOG = 0x0f,
+ D3DSIO_LIT = 0x10,
+ D3DSIO_DST = 0x11,
+ D3DSIO_LRP = 0x12,
+ D3DSIO_FRC = 0x13,
+ D3DSIO_M4x4 = 0x14,
+ D3DSIO_M4x3 = 0x15,
+ D3DSIO_M3x4 = 0x16,
+ D3DSIO_M3x3 = 0x17,
+ D3DSIO_M3x2 = 0x18,
+ D3DSIO_CALL = 0x19,
+ D3DSIO_CALLNZ = 0x1a,
+ D3DSIO_LOOP = 0x1b,
+ D3DSIO_RET = 0x1c,
+ D3DSIO_ENDLOOP = 0x1d,
+ D3DSIO_LABEL = 0x1e,
+ D3DSIO_DCL = 0x1f,
+ D3DSIO_POW = 0x20,
+ D3DSIO_CRS = 0x21,
+ D3DSIO_SGN = 0x22,
+ D3DSIO_ABS = 0x23,
+ D3DSIO_NRM = 0x24,
+ D3DSIO_SINCOS = 0x25,
+ D3DSIO_REP = 0x26,
+ D3DSIO_ENDREP = 0x27,
+ D3DSIO_IF = 0x28,
+ D3DSIO_IFC = 0x29,
+ D3DSIO_ELSE = 0x2a,
+ D3DSIO_ENDIF = 0x2b,
+ D3DSIO_BREAK = 0x2c,
+ D3DSIO_BREAKC = 0x2d,
+ D3DSIO_MOVA = 0x2e,
+ D3DSIO_DEFB = 0x2f,
+ D3DSIO_DEFI = 0x30,
+
+ D3DSIO_TEXCOORD = 0x40,
+ D3DSIO_TEXKILL = 0x41,
+ D3DSIO_TEX = 0x42,
+ D3DSIO_TEXBEM = 0x43,
+ D3DSIO_TEXBEML = 0x44,
+ D3DSIO_TEXREG2AR = 0x45,
+ D3DSIO_TEXREG2GB = 0x46,
+ D3DSIO_TEXM3x2PAD = 0x47,
+ D3DSIO_TEXM3x2TEX = 0x48,
+ D3DSIO_TEXM3x3PAD = 0x49,
+ D3DSIO_TEXM3x3TEX = 0x4a,
+ D3DSIO_TEXM3x3DIFF = 0x4b,
+ D3DSIO_TEXM3x3SPEC = 0x4c,
+ D3DSIO_TEXM3x3VSPEC = 0x4d,
+ D3DSIO_EXPP = 0x4e,
+ D3DSIO_LOGP = 0x4f,
+ D3DSIO_CND = 0x50,
+ D3DSIO_DEF = 0x51,
+ D3DSIO_TEXREG2RGB = 0x52,
+ D3DSIO_TEXDP3TEX = 0x53,
+ D3DSIO_TEXM3x2DEPTH = 0x54,
+ D3DSIO_TEXDP3 = 0x55,
+ D3DSIO_TEXM3x3 = 0x56,
+ D3DSIO_TEXDEPTH = 0x57,
+ D3DSIO_CMP = 0x58,
+ D3DSIO_BEM = 0x59,
+ D3DSIO_DP2ADD = 0x5a,
+ D3DSIO_DSX = 0x5b,
+ D3DSIO_DSY = 0x5c,
+ D3DSIO_TEXLDD = 0x5d,
+ D3DSIO_SETP = 0x5e,
+ D3DSIO_TEXLDL = 0x5f,
+ D3DSIO_BREAKP = 0x60,
+
+ D3DSIO_PHASE = 0xfffd,
+ D3DSIO_COMMENT = 0xfffe,
+ D3DSIO_END = 0xffff,
+
+ D3DSIO_FORCE_DWORD = 0x7fffffff,
+} D3DSHADER_INSTRUCTION_OPCODE_TYPE;
+
+typedef enum _D3DSHADER_PARAM_DSTMOD_TYPE
+{
+ D3DSPDM_NONE = 0 << D3DSP_DSTMOD_SHIFT,
+ D3DSPDM_SATURATE = 1 << D3DSP_DSTMOD_SHIFT,
+ D3DSPDM_PARTIALPRECISION = 2 << D3DSP_DSTMOD_SHIFT,
+ D3DSPDM_MSAMPCENTROID = 4 << D3DSP_DSTMOD_SHIFT,
+
+ D3DSPDM_FORCE_DWORD = 0x7fffffff,
+} D3DSHADER_PARAM_DSTMOD_TYPE;
+
+typedef enum _D3DSHADER_PARAM_REGISTER_TYPE
+{
+ D3DSPR_TEMP = 0x00,
+ D3DSPR_INPUT = 0x01,
+ D3DSPR_CONST = 0x02,
+ D3DSPR_ADDR = 0x03,
+ D3DSPR_TEXTURE = 0x03,
+ D3DSPR_RASTOUT = 0x04,
+ D3DSPR_ATTROUT = 0x05,
+ D3DSPR_TEXCRDOUT = 0x06,
+ D3DSPR_OUTPUT = 0x06,
+ D3DSPR_CONSTINT = 0x07,
+ D3DSPR_COLOROUT = 0x08,
+ D3DSPR_DEPTHOUT = 0x09,
+ D3DSPR_SAMPLER = 0x0a,
+ D3DSPR_CONST2 = 0x0b,
+ D3DSPR_CONST3 = 0x0c,
+ D3DSPR_CONST4 = 0x0d,
+ D3DSPR_CONSTBOOL = 0x0e,
+ D3DSPR_LOOP = 0x0f,
+ D3DSPR_TEMPFLOAT16 = 0x10,
+ D3DSPR_MISCTYPE = 0x11,
+ D3DSPR_LABEL = 0x12,
+ D3DSPR_PREDICATE = 0x13,
+
+ D3DSPR_FORCE_DWORD = 0x7fffffff,
+} D3DSHADER_PARAM_REGISTER_TYPE;
+
+typedef enum _D3DSHADER_PARAM_SRCMOD_TYPE
+{
+ D3DSPSM_NONE = 0x0 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_NEG = 0x1 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_BIAS = 0x2 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_BIASNEG = 0x3 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_SIGN = 0x4 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_SIGNNEG = 0x5 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_COMP = 0x6 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_X2 = 0x7 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_X2NEG = 0x8 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_DZ = 0x9 << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_DW = 0xa << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_ABS = 0xb << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_ABSNEG = 0xc << D3DSP_SRCMOD_SHIFT,
+ D3DSPSM_NOT = 0xd << D3DSP_SRCMOD_SHIFT,
+
+ D3DSPSM_FORCE_DWORD = 0x7fffffff,
+} D3DSHADER_PARAM_SRCMOD_TYPE;
+
+typedef enum _D3DSHADER_MISCTYPE_OFFSETS
+{
+ D3DSMO_POSITION = 0x0,
+ D3DSMO_FACE = 0x1,
+} D3DSHADER_MISCTYPE_OFFSETS;
+
+typedef enum _D3DVS_RASTOUT_OFFSETS
+{
+ D3DSRO_POSITION = 0x0,
+ D3DSRO_FOG = 0x1,
+ D3DSRO_POINT_SIZE = 0x2,
+
+ D3DSRO_FORCE_DWORD = 0x7fffffff,
+} D3DVS_RASTOUT_OFFSETS;
+
+#endif /* _d3d9TYPES_H_ */
+#endif /* __VKD3D_D3D9TYPES_H */
diff --git a/libs/vkd3d/include/vkd3d_d3dcompiler.h b/libs/vkd3d/include/vkd3d_d3dcompiler.h
new file mode 100644
index 00000000000..c934835dc0a
--- /dev/null
+++ b/libs/vkd3d/include/vkd3d_d3dcompiler.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010 Matteo Bruni 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_D3DCOMPILER_H
+#define __VKD3D_D3DCOMPILER_H
+#ifndef __D3DCOMPILER_H__
+
+#define D3DCOMPILE_DEBUG 0x00000001
+#define D3DCOMPILE_SKIP_VALIDATION 0x00000002
+#define D3DCOMPILE_SKIP_OPTIMIZATION 0x00000004
+#define D3DCOMPILE_PACK_MATRIX_ROW_MAJOR 0x00000008
+#define D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR 0x00000010
+#define D3DCOMPILE_PARTIAL_PRECISION 0x00000020
+#define D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT 0x00000040
+#define D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT 0x00000080
+#define D3DCOMPILE_NO_PRESHADER 0x00000100
+#define D3DCOMPILE_AVOID_FLOW_CONTROL 0x00000200
+#define D3DCOMPILE_PREFER_FLOW_CONTROL 0x00000400
+#define D3DCOMPILE_ENABLE_STRICTNESS 0x00000800
+#define D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY 0x00001000
+#define D3DCOMPILE_IEEE_STRICTNESS 0x00002000
+#define D3DCOMPILE_OPTIMIZATION_LEVEL0 0x00004000
+#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0x00000000
+#define D3DCOMPILE_OPTIMIZATION_LEVEL2 0x0000c000
+#define D3DCOMPILE_OPTIMIZATION_LEVEL3 0x00008000
+#define D3DCOMPILE_RESERVED16 0x00010000
+#define D3DCOMPILE_RESERVED17 0x00020000
+#define D3DCOMPILE_WARNINGS_ARE_ERRORS 0x00040000
+#define D3DCOMPILE_RESOURCES_MAY_ALIAS 0x00080000
+#define D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES 0x00100000
+#define D3DCOMPILE_ALL_RESOURCES_BOUND 0x00200000
+#define D3DCOMPILE_DEBUG_NAME_FOR_SOURCE 0x00400000
+#define D3DCOMPILE_DEBUG_NAME_FOR_BINARY 0x00800000
+
+#define D3DCOMPILE_EFFECT_CHILD_EFFECT 0x00000001
+#define D3DCOMPILE_EFFECT_ALLOW_SLOW_OPS 0x00000002
+
+#define D3DCOMPILE_FLAGS2_FORCE_ROOT_SIGNATURE_LATEST 0x00000000
+#define D3DCOMPILE_FLAGS2_FORCE_ROOT_SIGNATURE_1_0 0x00000010
+#define D3DCOMPILE_FLAGS2_FORCE_ROOT_SIGNATURE_1_1 0x00000020
+
+#define D3DCOMPILE_SECDATA_MERGE_UAV_SLOTS 0x00000001
+#define D3DCOMPILE_SECDATA_PRESERVE_TEMPLATE_SLOTS 0x00000002
+#define D3DCOMPILE_SECDATA_REQUIRE_TEMPLATE_MATCH 0x00000004
+
+HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename,
+ const D3D_SHADER_MACRO *macros, ID3DInclude *include, const char *entrypoint,
+ const char *profile, UINT flags, UINT effect_flags, ID3DBlob **shader, ID3DBlob **error_messages);
+HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filename,
+ const D3D_SHADER_MACRO *macros, ID3DInclude *include, const char *entrypoint,
+ const char *profile, UINT flags, UINT effect_flags, UINT secondary_flags,
+ const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader,
+ ID3DBlob **error_messages);
+HRESULT WINAPI D3DCreateBlob(SIZE_T size, ID3DBlob **blob);
+HRESULT WINAPI D3DPreprocess(const void *data, SIZE_T size, const char *filename, const D3D_SHADER_MACRO *macros,
+ ID3DInclude *include, ID3DBlob **shader, ID3DBlob **error_messages);
+
+#endif /* __D3DCOMPILER_H__ */
+#endif /* __VKD3D_D3DCOMPILER_H */
diff --git a/libs/vkd3d/include/vkd3d_utils.h b/libs/vkd3d/include/vkd3d_utils.h
new file mode 100644
index 00000000000..e8462563576
--- /dev/null
+++ b/libs/vkd3d/include/vkd3d_utils.h
@@ -0,0 +1,108 @@
+/*
+ * 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 */
+
+/**
+ * \file vkd3d_utils.h
+ *
+ * This file contains definitions for the vkd3d-utils library.
+ *
+ * The vkd3d-utils library is a collections of routines to ease the
+ * porting of a Direct3D 12 application to vkd3d.
+ *
+ * \since 1.0
+ */
+
+#define VKD3D_WAIT_OBJECT_0 (0)
+#define VKD3D_WAIT_TIMEOUT (1)
+#define VKD3D_WAIT_FAILED (~0u)
+#define VKD3D_INFINITE (~0u)
+
+#ifdef LIBVKD3D_UTILS_SOURCE
+# define VKD3D_UTILS_API VKD3D_EXPORT
+#else
+# define VKD3D_UTILS_API VKD3D_IMPORT
+#endif
+
+/* 1.0 */
+VKD3D_UTILS_API HANDLE vkd3d_create_event(void);
+VKD3D_UTILS_API HRESULT vkd3d_signal_event(HANDLE event);
+VKD3D_UTILS_API unsigned int vkd3d_wait_event(HANDLE event, unsigned int milliseconds);
+VKD3D_UTILS_API void vkd3d_destroy_event(HANDLE event);
+
+#define D3D12CreateDevice(a, b, c, d) D3D12CreateDeviceVKD3D(a, b, c, d, VKD3D_UTILS_API_VERSION)
+VKD3D_UTILS_API HRESULT WINAPI D3D12CreateRootSignatureDeserializer(
+ const void *data, SIZE_T data_size, REFIID iid, void **deserializer);
+VKD3D_UTILS_API HRESULT WINAPI D3D12GetDebugInterface(REFIID iid, void **debug);
+VKD3D_UTILS_API HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *desc,
+ D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
+
+/* 1.2 */
+VKD3D_UTILS_API HRESULT WINAPI D3D12CreateDeviceVKD3D(IUnknown *adapter, D3D_FEATURE_LEVEL feature_level,
+ REFIID iid, void **device, enum vkd3d_api_version api_version);
+VKD3D_UTILS_API HRESULT WINAPI D3D12CreateVersionedRootSignatureDeserializer(const void *data,
+ SIZE_T data_size, REFIID iid, void **deserializer);
+VKD3D_UTILS_API HRESULT WINAPI D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
+ ID3DBlob **blob, ID3DBlob **error_blob);
+
+/* 1.3 */
+VKD3D_UTILS_API HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename,
+ const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
+ const char *target, UINT flags, UINT effect_flags, ID3DBlob **shader, ID3DBlob **error_messages);
+VKD3D_UTILS_API HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filename,
+ const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
+ const char *target, UINT flags, UINT effect_flags, UINT secondary_flags,
+ const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader,
+ ID3DBlob **error_messages);
+VKD3D_UTILS_API HRESULT WINAPI D3DCreateBlob(SIZE_T data_size, ID3DBlob **blob);
+VKD3D_UTILS_API HRESULT WINAPI D3DPreprocess(const void *data, SIZE_T size, const char *filename,
+ const D3D_SHADER_MACRO *defines, ID3DInclude *include,
+ ID3DBlob **shader, ID3DBlob **error_messages);
+
+/**
+ * Set a callback to be called when vkd3d-utils outputs debug logging.
+ *
+ * If NULL, or if this function has not been called, libvkd3d-utils will print
+ * all enabled log output to stderr.
+ *
+ * Calling this function will also set the log callback for libvkd3d and
+ * libvkd3d-shader.
+ *
+ * \param callback Callback function to set.
+ *
+ * \since 1.4
+ */
+VKD3D_UTILS_API void vkd3d_utils_set_log_callback(PFN_vkd3d_log callback);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __VKD3D_UTILS_H */
diff --git a/libs/vkd3d/include/vkd3d_windows.h b/libs/vkd3d/include/vkd3d_windows.h
new file mode 100644
index 00000000000..7b0e972d828
--- /dev/null
+++ b/libs/vkd3d/include/vkd3d_windows.h
@@ -0,0 +1,289 @@
+/*
+ * 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)
+# define DXGI_ERROR_UNSUPPORTED _HRESULT_TYPEDEF_(0x887a0004)
+
+# define D3DERR_INVALIDCALL _HRESULT_TYPEDEF_(0x8876086c)
+
+/* 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 INT64 LONG64;
+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;
+typedef GUID CLSID;
+typedef GUID UUID;
+
+# 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 &
+# define REFCLSID const CLSID &
+# else
+# define REFIID const IID * const
+# define REFGUID const GUID * const
+# define REFCLSID const CLSID * 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/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c
index 30205088b1b..ce00e536d39 100644
--- a/libs/vkd3d/libs/vkd3d-common/blob.c
+++ b/libs/vkd3d/libs/vkd3d-common/blob.c
@@ -17,6 +17,7 @@
*/
#define COBJMACROS
+
#include "vkd3d.h"
#include "vkd3d_blob.h"
#include "vkd3d_debug.h"
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
index f0c386f1b3a..2c5108095d5 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
@@ -1374,7 +1374,7 @@ static void shader_dump_ins_modifiers(struct vkd3d_d3d_asm_compiler *compiler,
if (mmask & VKD3DSPDM_PARTIALPRECISION) shader_addline(buffer, "_pp");
if (mmask & VKD3DSPDM_MSAMPCENTROID) shader_addline(buffer, "_centroid");
- mmask &= ~(VKD3DSPDM_SATURATE | VKD3DSPDM_PARTIALPRECISION | VKD3DSPDM_MSAMPCENTROID);
+ mmask &= ~VKD3DSPDM_MASK;
if (mmask) FIXME("Unrecognised modifier %#x.\n", mmask);
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
index 1fd5ab2446d..0d2b8d248d1 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
@@ -261,7 +261,7 @@ static const struct vkd3d_sm1_opcode_info vs_opcode_table[] =
{VKD3D_SM1_OP_M3x3, 1, 2, VKD3DSIH_M3x3},
{VKD3D_SM1_OP_M3x2, 1, 2, VKD3DSIH_M3x2},
/* Declarations */
- {VKD3D_SM1_OP_DCL, 0, 2, VKD3DSIH_DCL},
+ {VKD3D_SM1_OP_DCL, 0, 0, VKD3DSIH_DCL},
/* Constant definitions */
{VKD3D_SM1_OP_DEF, 1, 1, VKD3DSIH_DEF},
{VKD3D_SM1_OP_DEFB, 1, 1, VKD3DSIH_DEFB},
@@ -328,7 +328,7 @@ static const struct vkd3d_sm1_opcode_info ps_opcode_table[] =
{VKD3D_SM1_OP_M3x3, 1, 2, VKD3DSIH_M3x3},
{VKD3D_SM1_OP_M3x2, 1, 2, VKD3DSIH_M3x2},
/* Declarations */
- {VKD3D_SM1_OP_DCL, 0, 2, VKD3DSIH_DCL},
+ {VKD3D_SM1_OP_DCL, 0, 0, VKD3DSIH_DCL},
/* Constant definitions */
{VKD3D_SM1_OP_DEF, 1, 1, VKD3DSIH_DEF},
{VKD3D_SM1_OP_DEFB, 1, 1, VKD3DSIH_DEFB},
@@ -853,6 +853,14 @@ static void shader_sm1_skip_opcode(const struct vkd3d_shader_sm1_parser *sm1, co
return;
}
+ /* DCL instructions do not have sources or destinations, but they
+ * read two tokens to a semantic. See
+ * shader_sm1_read_semantic(). */
+ if (opcode_info->vkd3d_opcode == VKD3DSIH_DCL)
+ {
+ *ptr += 2;
+ }
+
*ptr += (opcode_info->dst_count + opcode_info->src_count);
}
@@ -1090,7 +1098,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
goto fail;
}
- ins->handler_idx = opcode_info->vkd3d_opcode;
+ vsir_instruction_init(ins, &sm1->p.location, opcode_info->vkd3d_opcode);
ins->flags = (opcode_token & VKD3D_SM1_INSTRUCTION_FLAGS_MASK) >> VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT;
ins->coissue = opcode_token & VKD3D_SM1_COISSUE;
ins->raw = false;
@@ -1333,12 +1341,22 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi
++instructions->count;
}
- *parser = &sm1->p;
-
for (i = 0; i < ARRAY_SIZE(sm1->p.shader_desc.flat_constant_count); ++i)
sm1->p.shader_desc.flat_constant_count[i].external = get_external_constant_count(sm1, i);
- return sm1->p.failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK;
+ if (!sm1->p.failed)
+ vsir_validate(&sm1->p);
+
+ if (sm1->p.failed)
+ {
+ WARN("Failed to parse shader.\n");
+ shader_sm1_destroy(&sm1->p);
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ *parser = &sm1->p;
+
+ return VKD3D_OK;
}
bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
index b78c78d34a7..b778f6abed3 100644
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
@@ -1999,7 +1999,7 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa
{
struct vkd3d_shader_instruction *ins = sm6_parser_require_space(sm6, 1);
assert(ins);
- shader_instruction_init(ins, handler_idx);
+ vsir_instruction_init(ins, &sm6->p.location, handler_idx);
++sm6->p.instructions.count;
return ins;
}
@@ -2190,7 +2190,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b
return;
}
- shader_instruction_init(ins, VKD3DSIH_MOV);
+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV);
if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6)))
return;
@@ -2955,6 +2955,12 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi
compile_info->source_name, message_context);
vkd3d_free(byte_code);
+ if (!sm6->p.failed && ret >= 0)
+ vsir_validate(&sm6->p);
+
+ if (sm6->p.failed && ret >= 0)
+ ret = VKD3D_ERROR_INVALID_SHADER;
+
if (ret < 0)
{
WARN("Failed to initialise shader parser.\n");
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
index 743a746f2bf..2cde5d58eba 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
@@ -21,7 +21,7 @@
#define __VKD3D_SHADER_HLSL_H
#include "vkd3d_shader_private.h"
-#include "wine/rbtree.h"
+#include "rbtree.h"
#include "d3dcommon.h"
#include "d3dx9shader.h"
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
index be024842164..ed31efc3f0b 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
@@ -2523,36 +2523,19 @@ static bool lower_casts_to_bool(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr
struct hlsl_ir_node *hlsl_add_conditional(struct hlsl_ctx *ctx, struct hlsl_block *instrs,
struct hlsl_ir_node *condition, struct hlsl_ir_node *if_true, struct hlsl_ir_node *if_false)
{
- struct hlsl_block then_block, else_block;
- struct hlsl_ir_node *iff, *store;
- struct hlsl_ir_load *load;
- struct hlsl_ir_var *var;
+ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS];
+ struct hlsl_ir_node *cond;
assert(hlsl_types_are_equal(if_true->data_type, if_false->data_type));
- if (!(var = hlsl_new_synthetic_var(ctx, "conditional", if_true->data_type, &condition->loc)))
- return NULL;
-
- hlsl_block_init(&then_block);
- hlsl_block_init(&else_block);
-
- if (!(store = hlsl_new_simple_store(ctx, var, if_true)))
- return NULL;
- hlsl_block_add_instr(&then_block, store);
-
- if (!(store = hlsl_new_simple_store(ctx, var, if_false)))
- return NULL;
- hlsl_block_add_instr(&else_block, store);
-
- if (!(iff = hlsl_new_if(ctx, condition, &then_block, &else_block, &condition->loc)))
- return NULL;
- hlsl_block_add_instr(instrs, iff);
-
- if (!(load = hlsl_new_var_load(ctx, var, &condition->loc)))
- return NULL;
- hlsl_block_add_instr(instrs, &load->node);
+ operands[0] = condition;
+ operands[1] = if_true;
+ operands[2] = if_false;
+ if (!(cond = hlsl_new_expr(ctx, HLSL_OP3_TERNARY, operands, if_true->data_type, &condition->loc)))
+ return false;
+ hlsl_block_add_instr(instrs, cond);
- return &load->node;
+ return cond;
}
static bool lower_int_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
index 41a72ab6c0d..cff0ba31efb 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
@@ -63,6 +63,56 @@ static bool fold_abs(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
return true;
}
+static uint32_t float_to_uint(float x)
+{
+ if (isnan(x) || x <= 0)
+ return 0;
+
+ if (x >= 4294967296.0f)
+ return UINT32_MAX;
+
+ return x;
+}
+
+static int32_t float_to_int(float x)
+{
+ if (isnan(x))
+ return 0;
+
+ if (x <= -2147483648.0f)
+ return INT32_MIN;
+
+ if (x >= 2147483648.0f)
+ return INT32_MAX;
+
+ return x;
+}
+
+static uint32_t double_to_uint(double x)
+{
+ if (isnan(x) || x <= 0)
+ return 0;
+
+ if (x >= 4294967296.0)
+ return UINT32_MAX;
+
+ return x;
+}
+
+static int32_t double_to_int(double x)
+{
+ if (isnan(x))
+ return 0;
+
+ if (x <= -2147483648.0)
+ return INT32_MIN;
+
+ if (x >= 2147483648.0)
+ return INT32_MAX;
+
+ return x;
+}
+
static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
@@ -86,15 +136,15 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
- u = src->value.u[k].f;
- i = src->value.u[k].f;
+ u = float_to_uint(src->value.u[k].f);
+ i = float_to_int(src->value.u[k].f);
f = src->value.u[k].f;
d = src->value.u[k].f;
break;
case HLSL_TYPE_DOUBLE:
- u = src->value.u[k].d;
- i = src->value.u[k].d;
+ u = double_to_uint(src->value.u[k].d);
+ i = double_to_int(src->value.u[k].d);
f = src->value.u[k].d;
d = src->value.u[k].d;
break;
@@ -152,6 +202,59 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
return true;
}
+static bool fold_exp2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
+ const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
+{
+ enum hlsl_base_type type = dst_type->base_type;
+ unsigned int k;
+
+ assert(type == src->node.data_type->base_type);
+
+ for (k = 0; k < dst_type->dimx; ++k)
+ {
+ switch (type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->u[k].f = exp2f(src->value.u[k].f);
+ break;
+
+ default:
+ FIXME("Fold 'exp2' for type %s.\n", debug_hlsl_type(ctx, dst_type));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool fold_fract(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
+ const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
+{
+ enum hlsl_base_type type = dst_type->base_type;
+ unsigned int k;
+ float i;
+
+ assert(type == src->node.data_type->base_type);
+
+ for (k = 0; k < dst_type->dimx; ++k)
+ {
+ switch (type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->u[k].f = modff(src->value.u[k].f, &i);
+ break;
+
+ default:
+ FIXME("Fold 'fract' for type %s.\n", debug_hlsl_type(ctx, dst_type));
+ return false;
+ }
+ }
+
+ return true;
+}
+
static bool fold_log2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc)
{
@@ -276,6 +379,32 @@ static bool fold_rcp(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
return true;
}
+static bool fold_sat(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
+ const struct hlsl_ir_constant *src)
+{
+ enum hlsl_base_type type = dst_type->base_type;
+ unsigned int k;
+
+ assert(type == src->node.data_type->base_type);
+
+ for (k = 0; k < dst_type->dimx; ++k)
+ {
+ switch (type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->u[k].f = min(max(0.0f, src->value.u[k].f), 1.0f);
+ break;
+
+ default:
+ FIXME("Fold 'sat' for type %s.\n", debug_hlsl_type(ctx, dst_type));
+ return false;
+ }
+ }
+
+ return true;
+}
+
static bool fold_sqrt(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc)
{
@@ -869,6 +998,40 @@ static bool fold_nequal(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c
return true;
}
+static bool fold_ternary(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
+ const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2, const struct hlsl_ir_constant *src3)
+{
+ unsigned int k;
+
+ assert(dst_type->base_type == src2->node.data_type->base_type);
+ assert(dst_type->base_type == src3->node.data_type->base_type);
+
+ for (k = 0; k < dst_type->dimx; ++k)
+ {
+ switch (src1->node.data_type->base_type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->u[k] = src1->value.u[k].f != 0.0f ? src2->value.u[k] : src3->value.u[k];
+ break;
+
+ case HLSL_TYPE_DOUBLE:
+ dst->u[k] = src1->value.u[k].d != 0.0 ? src2->value.u[k] : src3->value.u[k];
+ break;
+
+ case HLSL_TYPE_INT:
+ case HLSL_TYPE_UINT:
+ case HLSL_TYPE_BOOL:
+ dst->u[k] = src1->value.u[k].u ? src2->value.u[k] : src3->value.u[k];
+ break;
+
+ default:
+ vkd3d_unreachable();
+ }
+ }
+ return true;
+}
+
bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_ir_constant *arg1, *arg2 = NULL, *arg3 = NULL;
@@ -912,6 +1075,14 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
success = fold_cast(ctx, &res, instr->data_type, arg1);
break;
+ case HLSL_OP1_EXP2:
+ success = fold_exp2(ctx, &res, instr->data_type, arg1);
+ break;
+
+ case HLSL_OP1_FRACT:
+ success = fold_fract(ctx, &res, instr->data_type, arg1);
+ break;
+
case HLSL_OP1_LOG2:
success = fold_log2(ctx, &res, instr->data_type, arg1, &instr->loc);
break;
@@ -924,6 +1095,10 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
success = fold_rcp(ctx, &res, instr->data_type, arg1, &instr->loc);
break;
+ case HLSL_OP1_SAT:
+ success = fold_sat(ctx, &res, instr->data_type, arg1);
+ break;
+
case HLSL_OP1_SQRT:
success = fold_sqrt(ctx, &res, instr->data_type, arg1, &instr->loc);
break;
@@ -990,6 +1165,10 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
success = fold_dp2add(ctx, &res, instr->data_type, arg1, arg2, arg3);
break;
+ case HLSL_OP3_TERNARY:
+ success = fold_ternary(ctx, &res, instr->data_type, arg1, arg2, arg3);
+ break;
+
default:
FIXME("Fold \"%s\" expression.\n", debug_hlsl_expr_op(expr->op));
success = false;
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
index d2bfb933edc..9ee38ffee37 100644
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
@@ -31,11 +31,9 @@ static bool shader_instruction_is_dcl(const struct vkd3d_shader_instruction *ins
static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *ins)
{
- ins->handler_idx = VKD3DSIH_NOP;
- ins->dst_count = 0;
- ins->src_count = 0;
- ins->dst = NULL;
- ins->src = NULL;
+ struct vkd3d_shader_location location = ins->location;
+
+ vsir_instruction_init(ins, &location, VKD3DSIH_NOP);
}
static void shader_register_eliminate_phase_addressing(struct vkd3d_shader_register *reg,
@@ -161,6 +159,7 @@ struct hull_flattener
unsigned int instance_count;
unsigned int phase_body_idx;
enum vkd3d_shader_opcode phase;
+ struct vkd3d_shader_location last_ret_location;
};
static bool flattener_is_in_fork_or_join_phase(const struct hull_flattener *flattener)
@@ -233,6 +232,7 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal
if (ins->handler_idx == VKD3DSIH_RET)
{
+ normaliser->last_ret_location = ins->location;
vkd3d_shader_instruction_make_nop(ins);
if (locations->count >= ARRAY_SIZE(locations->locations))
{
@@ -313,9 +313,11 @@ void shader_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_r
reg->immconst_type = VKD3D_IMMCONST_SCALAR;
}
-void shader_instruction_init(struct vkd3d_shader_instruction *ins, enum vkd3d_shader_opcode handler_idx)
+void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location,
+ enum vkd3d_shader_opcode handler_idx)
{
memset(ins, 0, sizeof(*ins));
+ ins->location = *location;
ins->handler_idx = handler_idx;
}
@@ -343,7 +345,7 @@ static enum vkd3d_result instruction_array_flatten_hull_shader_phases(struct vkd
if (!shader_instruction_array_reserve(&flattener.instructions, flattener.instructions.count + 1))
return VKD3D_ERROR_OUT_OF_MEMORY;
- shader_instruction_init(&instructions->elements[instructions->count++], VKD3DSIH_RET);
+ vsir_instruction_init(&instructions->elements[instructions->count++], &flattener.last_ret_location, VKD3DSIH_RET);
}
*src_instructions = flattener.instructions;
@@ -404,7 +406,8 @@ static void shader_dst_param_io_init(struct vkd3d_shader_dst_param *param, const
}
static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_point_normaliser *normaliser,
- const struct shader_signature *s, unsigned int input_control_point_count, unsigned int dst)
+ const struct shader_signature *s, unsigned int input_control_point_count, unsigned int dst,
+ const struct vkd3d_shader_location *location)
{
struct vkd3d_shader_instruction *ins;
struct vkd3d_shader_dst_param *param;
@@ -422,7 +425,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p
normaliser->instructions.count += count;
ins = &normaliser->instructions.elements[dst];
- shader_instruction_init(ins, VKD3DSIH_HS_CONTROL_POINT_PHASE);
+ vsir_instruction_init(ins, location, VKD3DSIH_HS_CONTROL_POINT_PHASE);
ins->flags = 1;
++ins;
@@ -434,13 +437,13 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p
if (e->sysval_semantic != VKD3D_SHADER_SV_NONE)
{
- shader_instruction_init(ins, VKD3DSIH_DCL_INPUT_SIV);
+ vsir_instruction_init(ins, location, VKD3DSIH_DCL_INPUT_SIV);
param = &ins->declaration.register_semantic.reg;
ins->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic);
}
else
{
- shader_instruction_init(ins, VKD3DSIH_DCL_INPUT);
+ vsir_instruction_init(ins, location, VKD3DSIH_DCL_INPUT);
param = &ins->declaration.dst;
}
@@ -511,7 +514,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i
case VKD3DSIH_HS_FORK_PHASE:
case VKD3DSIH_HS_JOIN_PHASE:
ret = control_point_normaliser_emit_hs_input(&normaliser, input_signature,
- input_control_point_count, i);
+ input_control_point_count, i, &ins->location);
*src_instructions = normaliser.instructions;
return ret;
default:
@@ -1014,7 +1017,6 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi
struct io_normaliser *normaliser)
{
struct vkd3d_shader_register *reg;
- bool keep = true;
unsigned int i;
switch (ins->handler_idx)
@@ -1033,15 +1035,16 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi
/* fall through */
case VKD3DSIH_DCL_INPUT_PS:
case VKD3DSIH_DCL_OUTPUT:
- keep = shader_dst_param_io_normalise(&ins->declaration.dst, true, normaliser);
+ if (!shader_dst_param_io_normalise(&ins->declaration.dst, true, normaliser))
+ vkd3d_shader_instruction_make_nop(ins);
break;
case VKD3DSIH_DCL_INPUT_SGV:
case VKD3DSIH_DCL_INPUT_SIV:
case VKD3DSIH_DCL_INPUT_PS_SGV:
case VKD3DSIH_DCL_INPUT_PS_SIV:
case VKD3DSIH_DCL_OUTPUT_SIV:
- keep = shader_dst_param_io_normalise(&ins->declaration.register_semantic.reg, true,
- normaliser);
+ if (!shader_dst_param_io_normalise(&ins->declaration.register_semantic.reg, true, normaliser))
+ vkd3d_shader_instruction_make_nop(ins);
break;
case VKD3DSIH_HS_CONTROL_POINT_PHASE:
case VKD3DSIH_HS_FORK_PHASE:
@@ -1060,9 +1063,6 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi
shader_src_param_io_normalise((struct vkd3d_shader_src_param *)&ins->src[i], normaliser);
break;
}
-
- if (!keep)
- shader_instruction_init(ins, VKD3DSIH_NOP);
}
static enum vkd3d_result instruction_array_normalise_io_registers(struct vkd3d_shader_instruction_array *instructions,
@@ -1290,5 +1290,117 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
if (result >= 0 && TRACE_ON())
vkd3d_shader_trace(instructions, &parser->shader_version);
+ if (result >= 0 && !parser->failed)
+ vsir_validate(parser);
+
+ if (result >= 0 && parser->failed)
+ result = VKD3D_ERROR_INVALID_SHADER;
+
return result;
}
+
+struct validation_context
+{
+ struct vkd3d_shader_parser *parser;
+ size_t instruction_idx;
+};
+
+static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx,
+ enum vkd3d_shader_error error, const char *format, ...)
+{
+ struct vkd3d_string_buffer buf;
+ va_list args;
+
+ vkd3d_string_buffer_init(&buf);
+
+ va_start(args, format);
+ vkd3d_string_buffer_vprintf(&buf, format, args);
+ va_end(args);
+
+ vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer);
+
+ vkd3d_string_buffer_cleanup(&buf);
+}
+
+static void vsir_validate_register(struct validation_context *ctx,
+ const struct vkd3d_shader_register *reg)
+{
+ if (reg->type >= VKD3DSPR_COUNT)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.",
+ reg->type);
+}
+
+static void vsir_validate_dst_param(struct validation_context *ctx,
+ const struct vkd3d_shader_dst_param *dst)
+{
+ vsir_validate_register(ctx, &dst->reg);
+
+ if (dst->write_mask & ~VKD3DSP_WRITEMASK_ALL)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination has invalid write mask %#x.",
+ dst->write_mask);
+
+ if (dst->modifiers & ~VKD3DSPDM_MASK)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.",
+ dst->modifiers);
+
+ switch (dst->shift)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 13:
+ case 14:
+ case 15:
+ break;
+
+ default:
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT, "Destination has invalid shift %#x.",
+ dst->shift);
+ }
+}
+
+static void vsir_validate_src_param(struct validation_context *ctx,
+ const struct vkd3d_shader_src_param *src)
+{
+ vsir_validate_register(ctx, &src->reg);
+
+ if (src->swizzle & ~0x03030303u)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source has invalid swizzle %#x.",
+ src->swizzle);
+
+ if (src->modifiers >= VKD3DSPSM_COUNT)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.",
+ src->modifiers);
+}
+
+static void vsir_validate_instruction(struct validation_context *ctx)
+{
+ const struct vkd3d_shader_instruction *instruction = &ctx->parser->instructions.elements[ctx->instruction_idx];
+ size_t i;
+
+ ctx->parser->location = instruction->location;
+
+ for (i = 0; i < instruction->dst_count; ++i)
+ vsir_validate_dst_param(ctx, &instruction->dst[i]);
+
+ for (i = 0; i < instruction->src_count; ++i)
+ vsir_validate_src_param(ctx, &instruction->src[i]);
+
+ if (instruction->handler_idx >= VKD3DSIH_INVALID)
+ {
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.",
+ instruction->handler_idx);
+ }
+}
+
+void vsir_validate(struct vkd3d_shader_parser *parser)
+{
+ struct validation_context ctx = { .parser = parser };
+
+ if (!(parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION))
+ return;
+
+ for (ctx.instruction_idx = 0; ctx.instruction_idx < parser->instructions.count; ++ctx.instruction_idx)
+ vsir_validate_instruction(&ctx);
+}
diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.h b/libs/vkd3d/libs/vkd3d-shader/preproc.h
index 4860cf5f90e..e1cb75e177c 100644
--- a/libs/vkd3d/libs/vkd3d-shader/preproc.h
+++ b/libs/vkd3d/libs/vkd3d-shader/preproc.h
@@ -22,7 +22,7 @@
#define __VKD3D_SHADER_PREPROC_H
#include "vkd3d_shader_private.h"
-#include "wine/rbtree.h"
+#include "rbtree.h"
struct preproc_if_state
{
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
index 638764b81bc..8285b56a17c 100644
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
@@ -18,7 +18,7 @@
*/
#include "vkd3d_shader_private.h"
-#include "wine/rbtree.h"
+#include "rbtree.h"
#include <stdarg.h>
#include <stdio.h>
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
index 045fb6c5f64..58b7f030dac 100644
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
@@ -2327,7 +2327,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str
return;
}
- ins->handler_idx = opcode_info->handler_idx;
+ vsir_instruction_init(ins, &sm4->p.location, opcode_info->handler_idx);
if (ins->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE || ins->handler_idx == VKD3DSIH_HS_FORK_PHASE
|| ins->handler_idx == VKD3DSIH_HS_JOIN_PHASE)
sm4->phase = ins->handler_idx;
@@ -2642,9 +2642,19 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
if (sm4->p.shader_version.type == VKD3D_SHADER_TYPE_HULL && !sm4->has_control_point_phase && !sm4->p.failed)
shader_sm4_validate_default_phase_index_ranges(sm4);
+ if (!sm4->p.failed)
+ vsir_validate(&sm4->p);
+
+ if (sm4->p.failed)
+ {
+ WARN("Failed to parse shader.\n");
+ shader_sm4_destroy(&sm4->p);
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
*parser = &sm4->p;
- return sm4->p.failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK;
+ return VKD3D_OK;
}
static void write_sm4_block(const struct tpf_writer *tpf, const struct hlsl_block *block);
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
index f25dbb04d69..077d0144bc5 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -22,6 +22,8 @@
#include <stdio.h>
#include <math.h>
+/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */
+
static inline int char_to_int(char c)
{
if ('0' <= c && c <= '9')
@@ -452,6 +454,25 @@ static void init_scan_signature_info(const struct vkd3d_shader_compile_info *inf
}
}
+static const struct vkd3d_debug_option vkd3d_shader_config_options[] =
+{
+ {"force_validation", VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION}, /* force validation of internal shader representations */
+};
+
+static uint64_t vkd3d_shader_init_config_flags(void)
+{
+ uint64_t config_flags;
+ const char *config;
+
+ config = getenv("VKD3D_SHADER_CONFIG");
+ config_flags = vkd3d_parse_debug_options(config, vkd3d_shader_config_options, ARRAY_SIZE(vkd3d_shader_config_options));
+
+ if (config_flags)
+ TRACE("VKD3D_SHADER_CONFIG='%s'.\n", config);
+
+ return config_flags;
+}
+
bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_message_context *message_context, const char *source_name,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops,
@@ -463,6 +484,7 @@ bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
parser->location.column = 0;
parser->shader_version = *version;
parser->ops = ops;
+ parser->config_flags = vkd3d_shader_init_config_flags();
return shader_instruction_array_init(&parser->instructions, instruction_reserve);
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
index 9443df6c232..5fd930918be 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -49,7 +49,7 @@
#include "vkd3d_common.h"
#include "vkd3d_memory.h"
#include "vkd3d_shader.h"
-#include "wine/list.h"
+#include "list.h"
#include <assert.h>
#include <inttypes.h>
@@ -183,6 +183,12 @@ enum vkd3d_shader_error
VKD3D_SHADER_WARNING_DXIL_UNHANDLED_INTRINSIC = 8305,
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE = 9002,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK = 9003,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS = 9004,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT = 9005,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE = 9006,
};
enum vkd3d_shader_opcode
@@ -585,6 +591,7 @@ enum vkd3d_shader_src_modifier
VKD3DSPSM_ABS = 11,
VKD3DSPSM_ABSNEG = 12,
VKD3DSPSM_NOT = 13,
+ VKD3DSPSM_COUNT,
};
#define VKD3DSP_WRITEMASK_0 0x1u /* .x r */
@@ -599,6 +606,7 @@ enum vkd3d_shader_dst_modifier
VKD3DSPDM_SATURATE = 1,
VKD3DSPDM_PARTIALPRECISION = 2,
VKD3DSPDM_MSAMPCENTROID = 4,
+ VKD3DSPDM_MASK = 7,
};
enum vkd3d_shader_interpolation_mode
@@ -968,8 +976,15 @@ struct vkd3d_shader_primitive_type
unsigned int patch_vertex_count;
};
+struct vkd3d_shader_location
+{
+ const char *source_name;
+ unsigned int line, column;
+};
+
struct vkd3d_shader_instruction
{
+ struct vkd3d_shader_location location;
enum vkd3d_shader_opcode handler_idx;
DWORD flags;
unsigned int dst_count;
@@ -1008,7 +1023,8 @@ struct vkd3d_shader_instruction
} declaration;
};
-void shader_instruction_init(struct vkd3d_shader_instruction *ins, enum vkd3d_shader_opcode handler_idx);
+void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location,
+ enum vkd3d_shader_opcode handler_idx);
static inline bool vkd3d_shader_instruction_has_texel_offset(const struct vkd3d_shader_instruction *ins)
{
@@ -1035,12 +1051,6 @@ static inline bool register_is_constant(const struct vkd3d_shader_register *reg)
return (reg->type == VKD3DSPR_IMMCONST || reg->type == VKD3DSPR_IMMCONST64);
}
-struct vkd3d_shader_location
-{
- const char *source_name;
- unsigned int line, column;
-};
-
struct vkd3d_shader_param_node
{
struct vkd3d_shader_param_node *next;
@@ -1093,6 +1103,11 @@ bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_
unsigned int dst, unsigned int src);
void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions);
+enum vkd3d_shader_config_flags
+{
+ VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION = 0x00000001,
+};
+
struct vkd3d_shader_parser
{
struct vkd3d_shader_message_context *message_context;
@@ -1103,6 +1118,8 @@ struct vkd3d_shader_parser
struct vkd3d_shader_version shader_version;
const struct vkd3d_shader_parser_ops *ops;
struct vkd3d_shader_instruction_array instructions;
+
+ uint64_t config_flags;
};
struct vkd3d_shader_parser_ops
@@ -1291,6 +1308,8 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info,
int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context);
+void vsir_validate(struct vkd3d_shader_parser *parser);
+
static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type(
enum vkd3d_data_type data_type)
{
diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c
index 42a98763438..3be45120d8c 100644
--- a/libs/vkd3d/libs/vkd3d/command.c
+++ b/libs/vkd3d/libs/vkd3d/command.c
@@ -5461,6 +5461,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID
view_desc.miplevel_count = 1;
view_desc.layer_idx = view->info.texture.layer_idx;
view_desc.layer_count = view->info.texture.layer_count;
+ view_desc.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
if (!vkd3d_create_texture_view(device, VKD3D_DESCRIPTOR_MAGIC_UAV, resource_impl->u.vk_image, &view_desc,
&uint_view))
diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c
index c33061073a3..69727e09cc7 100644
--- a/libs/vkd3d/libs/vkd3d/device.c
+++ b/libs/vkd3d/libs/vkd3d/device.c
@@ -2456,17 +2456,18 @@ static void vkd3d_desc_object_cache_cleanup(struct vkd3d_desc_object_cache *cach
}
/* ID3D12Device */
-static inline struct d3d12_device *impl_from_ID3D12Device1(ID3D12Device1 *iface)
+static inline struct d3d12_device *impl_from_ID3D12Device2(ID3D12Device2 *iface)
{
- return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12Device1_iface);
+ return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12Device2_iface);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device2 *iface,
REFIID riid, void **object)
{
TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
- if (IsEqualGUID(riid, &IID_ID3D12Device1)
+ if (IsEqualGUID(riid, &IID_ID3D12Device2)
+ || IsEqualGUID(riid, &IID_ID3D12Device1)
|| IsEqualGUID(riid, &IID_ID3D12Device)
|| IsEqualGUID(riid, &IID_ID3D12Object)
|| IsEqualGUID(riid, &IID_IUnknown))
@@ -2482,9 +2483,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device1 *ifac
return E_NOINTERFACE;
}
-static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device1 *iface)
+static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device2 *iface)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
ULONG refcount = InterlockedIncrement(&device->refcount);
TRACE("%p increasing refcount to %u.\n", device, refcount);
@@ -2492,9 +2493,9 @@ static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device1 *iface)
return refcount;
}
-static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device1 *iface)
+static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device2 *iface)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
ULONG refcount = InterlockedDecrement(&device->refcount);
TRACE("%p decreasing refcount to %u.\n", device, refcount);
@@ -2528,10 +2529,10 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device1 *iface)
return refcount;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_GetPrivateData(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_GetPrivateData(ID3D12Device2 *iface,
REFGUID guid, UINT *data_size, void *data)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
TRACE("iface %p, guid %s, data_size %p, data %p.\n",
iface, debugstr_guid(guid), data_size, data);
@@ -2539,10 +2540,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_GetPrivateData(ID3D12Device1 *ifac
return vkd3d_get_private_data(&device->private_store, guid, data_size, data);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateData(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateData(ID3D12Device2 *iface,
REFGUID guid, UINT data_size, const void *data)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
TRACE("iface %p, guid %s, data_size %u, data %p.\n",
iface, debugstr_guid(guid), data_size, data);
@@ -2550,19 +2551,19 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateData(ID3D12Device1 *ifac
return vkd3d_set_private_data(&device->private_store, guid, data_size, data);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateDataInterface(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateDataInterface(ID3D12Device2 *iface,
REFGUID guid, const IUnknown *data)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(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(ID3D12Device1 *iface, const WCHAR *name)
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetName(ID3D12Device2 *iface, const WCHAR *name)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
TRACE("iface %p, name %s.\n", iface, debugstr_w(name, device->wchar_size));
@@ -2570,17 +2571,17 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetName(ID3D12Device1 *iface, cons
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, name);
}
-static UINT STDMETHODCALLTYPE d3d12_device_GetNodeCount(ID3D12Device1 *iface)
+static UINT STDMETHODCALLTYPE d3d12_device_GetNodeCount(ID3D12Device2 *iface)
{
TRACE("iface %p.\n", iface);
return 1;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandQueue(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandQueue(ID3D12Device2 *iface,
const D3D12_COMMAND_QUEUE_DESC *desc, REFIID riid, void **command_queue)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_command_queue *object;
HRESULT hr;
@@ -2594,10 +2595,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandQueue(ID3D12Device1 *
riid, command_queue);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Device2 *iface,
D3D12_COMMAND_LIST_TYPE type, REFIID riid, void **command_allocator)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_command_allocator *object;
HRESULT hr;
@@ -2611,10 +2612,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Devic
riid, command_allocator);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12Device2 *iface,
const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, REFIID riid, void **pipeline_state)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_pipeline_state *object;
HRESULT hr;
@@ -2628,10 +2629,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12
&IID_ID3D12PipelineState, riid, pipeline_state);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateComputePipelineState(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateComputePipelineState(ID3D12Device2 *iface,
const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, REFIID riid, void **pipeline_state)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_pipeline_state *object;
HRESULT hr;
@@ -2645,11 +2646,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateComputePipelineState(ID3D12D
&IID_ID3D12PipelineState, riid, pipeline_state);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device2 *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_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_command_list *object;
HRESULT hr;
@@ -2772,10 +2773,10 @@ bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent)
return true;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device2 *iface,
D3D12_FEATURE feature, void *feature_data, UINT feature_data_size)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
TRACE("iface %p, feature %#x, feature_data %p, feature_data_size %u.\n",
iface, feature, feature_data, feature_data_size);
@@ -3274,10 +3275,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device1
}
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateDescriptorHeap(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateDescriptorHeap(ID3D12Device2 *iface,
const D3D12_DESCRIPTOR_HEAP_DESC *desc, REFIID riid, void **descriptor_heap)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_descriptor_heap *object;
HRESULT hr;
@@ -3291,7 +3292,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateDescriptorHeap(ID3D12Device1
&IID_ID3D12DescriptorHeap, riid, descriptor_heap);
}
-static UINT STDMETHODCALLTYPE d3d12_device_GetDescriptorHandleIncrementSize(ID3D12Device1 *iface,
+static UINT STDMETHODCALLTYPE d3d12_device_GetDescriptorHandleIncrementSize(ID3D12Device2 *iface,
D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type)
{
TRACE("iface %p, descriptor_heap_type %#x.\n", iface, descriptor_heap_type);
@@ -3314,11 +3315,11 @@ static UINT STDMETHODCALLTYPE d3d12_device_GetDescriptorHandleIncrementSize(ID3D
}
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateRootSignature(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateRootSignature(ID3D12Device2 *iface,
UINT node_mask, const void *bytecode, SIZE_T bytecode_length,
REFIID riid, void **root_signature)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_root_signature *object;
HRESULT hr;
@@ -3334,10 +3335,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateRootSignature(ID3D12Device1
&IID_ID3D12RootSignature, riid, root_signature);
}
-static void STDMETHODCALLTYPE d3d12_device_CreateConstantBufferView(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_CreateConstantBufferView(ID3D12Device2 *iface,
const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_desc tmp = {0};
TRACE("iface %p, desc %p, descriptor %#lx.\n", iface, desc, descriptor.ptr);
@@ -3346,11 +3347,11 @@ static void STDMETHODCALLTYPE d3d12_device_CreateConstantBufferView(ID3D12Device
d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device);
}
-static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(ID3D12Device2 *iface,
ID3D12Resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc,
D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_desc tmp = {0};
TRACE("iface %p, resource %p, desc %p, descriptor %#lx.\n",
@@ -3360,11 +3361,11 @@ static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(ID3D12Device
d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device);
}
-static void STDMETHODCALLTYPE d3d12_device_CreateUnorderedAccessView(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_CreateUnorderedAccessView(ID3D12Device2 *iface,
ID3D12Resource *resource, ID3D12Resource *counter_resource,
const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_desc tmp = {0};
TRACE("iface %p, resource %p, counter_resource %p, desc %p, descriptor %#lx.\n",
@@ -3375,7 +3376,7 @@ static void STDMETHODCALLTYPE d3d12_device_CreateUnorderedAccessView(ID3D12Devic
d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device);
}
-static void STDMETHODCALLTYPE d3d12_device_CreateRenderTargetView(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_CreateRenderTargetView(ID3D12Device2 *iface,
ID3D12Resource *resource, const D3D12_RENDER_TARGET_VIEW_DESC *desc,
D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
{
@@ -3383,10 +3384,10 @@ static void STDMETHODCALLTYPE d3d12_device_CreateRenderTargetView(ID3D12Device1
iface, resource, desc, descriptor.ptr);
d3d12_rtv_desc_create_rtv(d3d12_rtv_desc_from_cpu_handle(descriptor),
- impl_from_ID3D12Device1(iface), unsafe_impl_from_ID3D12Resource(resource), desc);
+ impl_from_ID3D12Device2(iface), unsafe_impl_from_ID3D12Resource(resource), desc);
}
-static void STDMETHODCALLTYPE d3d12_device_CreateDepthStencilView(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_CreateDepthStencilView(ID3D12Device2 *iface,
ID3D12Resource *resource, const D3D12_DEPTH_STENCIL_VIEW_DESC *desc,
D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
{
@@ -3394,13 +3395,13 @@ static void STDMETHODCALLTYPE d3d12_device_CreateDepthStencilView(ID3D12Device1
iface, resource, desc, descriptor.ptr);
d3d12_dsv_desc_create_dsv(d3d12_dsv_desc_from_cpu_handle(descriptor),
- impl_from_ID3D12Device1(iface), unsafe_impl_from_ID3D12Resource(resource), desc);
+ impl_from_ID3D12Device2(iface), unsafe_impl_from_ID3D12Resource(resource), desc);
}
-static void STDMETHODCALLTYPE d3d12_device_CreateSampler(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_CreateSampler(ID3D12Device2 *iface,
const D3D12_SAMPLER_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_desc tmp = {0};
TRACE("iface %p, desc %p, descriptor %#lx.\n", iface, desc, descriptor.ptr);
@@ -3409,14 +3410,14 @@ static void STDMETHODCALLTYPE d3d12_device_CreateSampler(ID3D12Device1 *iface,
d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device);
}
-static void STDMETHODCALLTYPE d3d12_device_CopyDescriptors(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_CopyDescriptors(ID3D12Device2 *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_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
unsigned int dst_range_idx, dst_idx, src_range_idx, src_idx;
unsigned int dst_range_size, src_range_size;
struct d3d12_descriptor_heap *dst_heap;
@@ -3472,7 +3473,7 @@ static void STDMETHODCALLTYPE d3d12_device_CopyDescriptors(ID3D12Device1 *iface,
}
}
-static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device2 *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)
@@ -3487,10 +3488,10 @@ static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device1 *
}
static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo(
- ID3D12Device1 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask,
+ ID3D12Device2 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask,
UINT count, const D3D12_RESOURCE_DESC *resource_descs)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
const D3D12_RESOURCE_DESC *desc;
uint64_t requested_alignment;
@@ -3563,10 +3564,10 @@ invalid:
return info;
}
-static D3D12_HEAP_PROPERTIES * STDMETHODCALLTYPE d3d12_device_GetCustomHeapProperties(ID3D12Device1 *iface,
+static D3D12_HEAP_PROPERTIES * STDMETHODCALLTYPE d3d12_device_GetCustomHeapProperties(ID3D12Device2 *iface,
D3D12_HEAP_PROPERTIES *heap_properties, UINT node_mask, D3D12_HEAP_TYPE heap_type)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
bool coherent;
TRACE("iface %p, heap_properties %p, node_mask 0x%08x, heap_type %#x.\n",
@@ -3606,12 +3607,12 @@ static D3D12_HEAP_PROPERTIES * STDMETHODCALLTYPE d3d12_device_GetCustomHeapPrope
return heap_properties;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Device2 *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_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_resource *object;
HRESULT hr;
@@ -3630,10 +3631,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Devi
return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device2 *iface,
const D3D12_HEAP_DESC *desc, REFIID iid, void **heap)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_heap *object;
HRESULT hr;
@@ -3649,12 +3650,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device1 *iface,
return return_interface(&object->ID3D12Heap_iface, &IID_ID3D12Heap, iid, heap);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device2 *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_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_heap *heap_object;
struct d3d12_resource *object;
HRESULT hr;
@@ -3673,11 +3674,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device1
return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Device2 *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_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_resource *object;
HRESULT hr;
@@ -3691,11 +3692,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Devic
return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device2 *iface,
ID3D12DeviceChild *object, const SECURITY_ATTRIBUTES *attributes, DWORD access,
const WCHAR *name, HANDLE *handle)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(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);
@@ -3703,7 +3704,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device1 *
return E_NOTIMPL;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandle(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandle(ID3D12Device2 *iface,
HANDLE handle, REFIID riid, void **object)
{
FIXME("iface %p, handle %p, riid %s, object %p stub!\n",
@@ -3712,10 +3713,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandle(ID3D12Device1 *if
return E_NOTIMPL;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandleByName(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandleByName(ID3D12Device2 *iface,
const WCHAR *name, DWORD access, HANDLE *handle)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
FIXME("iface %p, name %s, access %#x, handle %p stub!\n",
iface, debugstr_w(name, device->wchar_size), access, handle);
@@ -3723,7 +3724,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandleByName(ID3D12Devic
return E_NOTIMPL;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_MakeResident(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_MakeResident(ID3D12Device2 *iface,
UINT object_count, ID3D12Pageable * const *objects)
{
FIXME_ONCE("iface %p, object_count %u, objects %p stub!\n",
@@ -3732,7 +3733,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_MakeResident(ID3D12Device1 *iface,
return S_OK;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_Evict(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_Evict(ID3D12Device2 *iface,
UINT object_count, ID3D12Pageable * const *objects)
{
FIXME_ONCE("iface %p, object_count %u, objects %p stub!\n",
@@ -3741,10 +3742,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_Evict(ID3D12Device1 *iface,
return S_OK;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device2 *iface,
UINT64 initial_value, D3D12_FENCE_FLAGS flags, REFIID riid, void **fence)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_fence *object;
HRESULT hr;
@@ -3757,21 +3758,21 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device1 *iface,
return return_interface(&object->ID3D12Fence1_iface, &IID_ID3D12Fence1, riid, fence);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_GetDeviceRemovedReason(ID3D12Device1 *iface)
+static HRESULT STDMETHODCALLTYPE d3d12_device_GetDeviceRemovedReason(ID3D12Device2 *iface)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
TRACE("iface %p.\n", iface);
return device->removed_reason;
}
-static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device2 *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_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
unsigned int i, sub_resource_idx, miplevel_idx, row_count, row_size, row_pitch;
unsigned int width, height, depth, plane_count, sub_resources_per_plane;
@@ -3851,10 +3852,10 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device1 *
*total_bytes = total;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateQueryHeap(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateQueryHeap(ID3D12Device2 *iface,
const D3D12_QUERY_HEAP_DESC *desc, REFIID iid, void **heap)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_query_heap *object;
HRESULT hr;
@@ -3867,18 +3868,18 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateQueryHeap(ID3D12Device1 *ifa
return return_interface(&object->ID3D12QueryHeap_iface, &IID_ID3D12QueryHeap, iid, heap);
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_SetStablePowerState(ID3D12Device1 *iface, BOOL enable)
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetStablePowerState(ID3D12Device2 *iface, BOOL enable)
{
FIXME("iface %p, enable %#x stub!\n", iface, enable);
return E_NOTIMPL;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(ID3D12Device2 *iface,
const D3D12_COMMAND_SIGNATURE_DESC *desc, ID3D12RootSignature *root_signature,
REFIID iid, void **command_signature)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
struct d3d12_command_signature *object;
HRESULT hr;
@@ -3892,14 +3893,14 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(ID3D12Devic
&IID_ID3D12CommandSignature, iid, command_signature);
}
-static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device1 *iface,
+static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device2 *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)
{
const struct d3d12_resource *resource_impl = impl_from_ID3D12Resource(resource);
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
TRACE("iface %p, resource %p, total_tile_count %p, packed_mip_info %p, "
"standard_title_shape %p, sub_resource_tiling_count %p, "
@@ -3912,9 +3913,9 @@ static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device1 *ifac
sub_resource_tiling_count, first_sub_resource_tiling, sub_resource_tilings);
}
-static LUID * STDMETHODCALLTYPE d3d12_device_GetAdapterLuid(ID3D12Device1 *iface, LUID *luid)
+static LUID * STDMETHODCALLTYPE d3d12_device_GetAdapterLuid(ID3D12Device2 *iface, LUID *luid)
{
- struct d3d12_device *device = impl_from_ID3D12Device1(iface);
+ struct d3d12_device *device = impl_from_ID3D12Device2(iface);
TRACE("iface %p, luid %p.\n", iface, luid);
@@ -3923,7 +3924,7 @@ static LUID * STDMETHODCALLTYPE d3d12_device_GetAdapterLuid(ID3D12Device1 *iface
return luid;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineLibrary(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineLibrary(ID3D12Device2 *iface,
const void *blob, SIZE_T blob_size, REFIID iid, void **lib)
{
FIXME("iface %p, blob %p, blob_size %lu, iid %s, lib %p stub!\n", iface, blob, blob_size, debugstr_guid(iid), lib);
@@ -3931,7 +3932,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineLibrary(ID3D12Device
return DXGI_ERROR_UNSUPPORTED;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(ID3D12Device2 *iface,
ID3D12Fence *const *fences, const UINT64 *values, UINT fence_count,
D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags, HANDLE event)
{
@@ -3941,7 +3942,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(
return E_NOTIMPL;
}
-static HRESULT STDMETHODCALLTYPE d3d12_device_SetResidencyPriority(ID3D12Device1 *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_device_SetResidencyPriority(ID3D12Device2 *iface,
UINT object_count, ID3D12Pageable *const *objects, const D3D12_RESIDENCY_PRIORITY *priorities)
{
FIXME_ONCE("iface %p, object_count %u, objects %p, priorities %p stub!\n", iface, object_count, objects, priorities);
@@ -3949,7 +3950,15 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetResidencyPriority(ID3D12Device1
return S_OK;
}
-static const struct ID3D12Device1Vtbl d3d12_device_vtbl =
+static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineState(ID3D12Device2 *iface,
+ const D3D12_PIPELINE_STATE_STREAM_DESC *desc, REFIID iid, void **pipeline_state)
+{
+ FIXME("iface %p, desc %p, iid %s, pipeline_state %p stub!\n", iface, desc, debugstr_guid(iid), pipeline_state);
+
+ return E_NOTIMPL;
+}
+
+static const struct ID3D12Device2Vtbl d3d12_device_vtbl =
{
/* IUnknown methods */
d3d12_device_QueryInterface,
@@ -4002,14 +4011,16 @@ static const struct ID3D12Device1Vtbl d3d12_device_vtbl =
d3d12_device_CreatePipelineLibrary,
d3d12_device_SetEventOnMultipleFenceCompletion,
d3d12_device_SetResidencyPriority,
+ /* ID3D12Device2 methods */
+ d3d12_device_CreatePipelineState,
};
-struct d3d12_device *unsafe_impl_from_ID3D12Device1(ID3D12Device1 *iface)
+struct d3d12_device *unsafe_impl_from_ID3D12Device2(ID3D12Device2 *iface)
{
if (!iface)
return NULL;
assert(iface->lpVtbl == &d3d12_device_vtbl);
- return impl_from_ID3D12Device1(iface);
+ return impl_from_ID3D12Device2(iface);
}
static HRESULT d3d12_device_init(struct d3d12_device *device,
@@ -4018,7 +4029,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
const struct vkd3d_vk_device_procs *vk_procs;
HRESULT hr;
- device->ID3D12Device1_iface.lpVtbl = &d3d12_device_vtbl;
+ device->ID3D12Device2_iface.lpVtbl = &d3d12_device_vtbl;
device->refcount = 1;
vkd3d_instance_incref(device->vkd3d_instance = instance);
@@ -4215,28 +4226,28 @@ HRESULT vkd3d_join_thread(struct vkd3d_instance *instance, union vkd3d_thread_ha
IUnknown *vkd3d_get_device_parent(ID3D12Device *device)
{
- struct d3d12_device *d3d12_device = impl_from_ID3D12Device1((ID3D12Device1 *)device);
+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device2((ID3D12Device2 *)device);
return d3d12_device->parent;
}
VkDevice vkd3d_get_vk_device(ID3D12Device *device)
{
- struct d3d12_device *d3d12_device = impl_from_ID3D12Device1((ID3D12Device1 *)device);
+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device2((ID3D12Device2 *)device);
return d3d12_device->vk_device;
}
VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device)
{
- struct d3d12_device *d3d12_device = impl_from_ID3D12Device1((ID3D12Device1 *)device);
+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device2((ID3D12Device2 *)device);
return d3d12_device->vk_physical_device;
}
struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device)
{
- struct d3d12_device *d3d12_device = impl_from_ID3D12Device1((ID3D12Device1 *)device);
+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device2((ID3D12Device2 *)device);
return d3d12_device->vkd3d_instance;
}
diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c
index f3842958d96..0dfb4d379ca 100644
--- a/libs/vkd3d/libs/vkd3d/resource.c
+++ b/libs/vkd3d/libs/vkd3d/resource.c
@@ -2220,7 +2220,7 @@ HRESULT d3d12_reserved_resource_create(struct d3d12_device *device,
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_ID3D12Device1((ID3D12Device1 *)device);
+ struct d3d12_device *d3d12_device = unsafe_impl_from_ID3D12Device2((ID3D12Device2 *)device);
struct d3d12_resource *object;
HRESULT hr;
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/libs/vkd3d/vkd3d_main.c
index 159560afd8e..7651acc3820 100644
--- a/libs/vkd3d/libs/vkd3d/vkd3d_main.c
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_main.c
@@ -71,11 +71,11 @@ HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
if (!device)
{
- ID3D12Device_Release(&object->ID3D12Device1_iface);
+ ID3D12Device_Release(&object->ID3D12Device2_iface);
return S_FALSE;
}
- return return_interface(&object->ID3D12Device1_iface, &IID_ID3D12Device, iid, device);
+ return return_interface(&object->ID3D12Device2_iface, &IID_ID3D12Device, iid, device);
}
/* ID3D12RootSignatureDeserializer */
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
index 363a7132c3a..fceb06fc05a 100644
--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
@@ -31,8 +31,8 @@
#include "vkd3d_blob.h"
#include "vkd3d_memory.h"
#include "vkd3d_utf8.h"
-#include "wine/list.h"
-#include "wine/rbtree.h"
+#include "list.h"
+#include "rbtree.h"
#include "vkd3d.h"
#include "vkd3d_shader.h"
@@ -1709,7 +1709,7 @@ struct vkd3d_desc_object_cache
/* ID3D12Device */
struct d3d12_device
{
- ID3D12Device1 ID3D12Device1_iface;
+ ID3D12Device2 ID3D12Device2_iface;
LONG refcount;
VkDevice vk_device;
@@ -1775,27 +1775,27 @@ struct vkd3d_queue *d3d12_device_get_vkd3d_queue(struct d3d12_device *device, D3
bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent);
void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason,
const char *message, ...) VKD3D_PRINTF_FUNC(3, 4);
-struct d3d12_device *unsafe_impl_from_ID3D12Device1(ID3D12Device1 *iface);
+struct d3d12_device *unsafe_impl_from_ID3D12Device2(ID3D12Device2 *iface);
static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object)
{
- return ID3D12Device1_QueryInterface(&device->ID3D12Device1_iface, iid, object);
+ return ID3D12Device2_QueryInterface(&device->ID3D12Device2_iface, iid, object);
}
static inline ULONG d3d12_device_add_ref(struct d3d12_device *device)
{
- return ID3D12Device1_AddRef(&device->ID3D12Device1_iface);
+ return ID3D12Device2_AddRef(&device->ID3D12Device2_iface);
}
static inline ULONG d3d12_device_release(struct d3d12_device *device)
{
- return ID3D12Device1_Release(&device->ID3D12Device1_iface);
+ return ID3D12Device2_Release(&device->ID3D12Device2_iface);
}
static inline unsigned int d3d12_device_get_descriptor_handle_increment_size(struct d3d12_device *device,
D3D12_DESCRIPTOR_HEAP_TYPE descriptor_type)
{
- return ID3D12Device1_GetDescriptorHandleIncrementSize(&device->ID3D12Device1_iface, descriptor_type);
+ return ID3D12Device2_GetDescriptorHandleIncrementSize(&device->ID3D12Device2_iface, descriptor_type);
}
/* utils */
--
2023-09-29 01:11:42 -07:00
2.42.0