diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-5c917552c927835c6f446dbecf1aa6ff2cc.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-5c917552c927835c6f446dbecf1aa6ff2cc.patch deleted file mode 100644 index e412fabd..00000000 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-5c917552c927835c6f446dbecf1aa6ff2cc.patch +++ /dev/null @@ -1,19887 +0,0 @@ -From 481cf752dacf2a815b265a9a79175e7dde8207ca Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Fri, 8 Dec 2023 13:21:19 +1100 -Subject: [PATCH] Updated vkd3d to 5c917552c927835c6f446dbecf1aa6ff2cc30cbe. - ---- - libs/vkd3d/Makefile.in | 1 + - libs/vkd3d/include/private/list.h | 270 ++ - libs/vkd3d/include/private/rbtree.h | 378 +++ - libs/vkd3d/include/private/vkd3d_common.h | 51 +- - libs/vkd3d/include/private/vkd3d_debug.h | 27 + - libs/vkd3d/include/private/vkd3d_test.h | 430 +++ - libs/vkd3d/include/vkd3d_d3d9types.h | 237 ++ - libs/vkd3d/include/vkd3d_d3dcompiler.h | 97 + - libs/vkd3d/include/vkd3d_d3dcompiler_types.h | 45 + - libs/vkd3d/include/vkd3d_shader.h | 38 +- - libs/vkd3d/include/vkd3d_utils.h | 128 + - libs/vkd3d/include/vkd3d_windows.h | 289 ++ - libs/vkd3d/libs/vkd3d-common/blob.c | 8 +- - libs/vkd3d/libs/vkd3d-common/debug.c | 6 +- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 237 +- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 128 +- - libs/vkd3d/libs/vkd3d-shader/dxbc.c | 38 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 2521 +++++++++++++++-- - libs/vkd3d/libs/vkd3d-shader/fx.c | 515 ++++ - libs/vkd3d/libs/vkd3d-shader/glsl.c | 6 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 103 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 38 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 + - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 352 ++- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 216 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 2492 ++++++++++++++-- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 1840 ++++++------ - libs/vkd3d/libs/vkd3d-shader/tpf.c | 183 +- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 171 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 264 +- - libs/vkd3d/libs/vkd3d/command.c | 100 +- - libs/vkd3d/libs/vkd3d/device.c | 727 +++-- - libs/vkd3d/libs/vkd3d/resource.c | 163 +- - libs/vkd3d/libs/vkd3d/state.c | 72 +- - libs/vkd3d/libs/vkd3d/utils.c | 24 +- - libs/vkd3d/libs/vkd3d/vkd3d_main.c | 34 +- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 120 +- - 37 files changed, 10153 insertions(+), 2197 deletions(-) - 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_d3dcompiler_types.h - create mode 100644 libs/vkd3d/include/vkd3d_utils.h - create mode 100644 libs/vkd3d/include/vkd3d_windows.h - create mode 100644 libs/vkd3d/libs/vkd3d-shader/fx.c - -diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in -index dbc10594f62..448e9a0e61d 100644 ---- a/libs/vkd3d/Makefile.in -+++ b/libs/vkd3d/Makefile.in -@@ -17,6 +17,7 @@ SOURCES = \ - libs/vkd3d-shader/d3dbc.c \ - libs/vkd3d-shader/dxbc.c \ - libs/vkd3d-shader/dxil.c \ -+ libs/vkd3d-shader/fx.c \ - libs/vkd3d-shader/glsl.c \ - libs/vkd3d-shader/hlsl.c \ - libs/vkd3d-shader/hlsl.l \ -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 -+ -+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 34fde1a2aa0..b5a8240d28e 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -52,6 +52,7 @@ - #define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') - #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') - #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') -+#define TAG_FX10 VKD3D_MAKE_TAG('F', 'X', '1', '0') - #define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1') - #define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N') - #define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1') -@@ -70,7 +71,7 @@ - #define TAG_XNAP VKD3D_MAKE_TAG('X', 'N', 'A', 'P') - #define TAG_XNAS VKD3D_MAKE_TAG('X', 'N', 'A', 'S') - --static inline size_t align(size_t addr, size_t alignment) -+static inline uint64_t align(uint64_t addr, size_t alignment) - { - return (addr + (alignment - 1)) & ~(alignment - 1); - } -@@ -80,7 +81,7 @@ static inline size_t align(size_t addr, size_t alignment) - # ifdef __MINGW_PRINTF_FORMAT - # define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args))) - # else --# define VKD3D_PRINTF_FUNC(fmt, args) /* __attribute__((format(printf, fmt, args))) */ -+# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args))) - # endif - # define VKD3D_UNUSED __attribute__((unused)) - # define VKD3D_UNREACHABLE __builtin_unreachable() -@@ -107,7 +108,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; -@@ -266,34 +267,42 @@ static inline int ascii_strcasecmp(const char *a, const char *b) - return c_a - c_b; - } - --#ifndef _WIN32 --# if HAVE_SYNC_ADD_AND_FETCH --static inline LONG InterlockedIncrement(LONG volatile *x) -+static inline uint64_t vkd3d_atomic_add_fetch_u64(uint64_t volatile *x, uint64_t val) - { -- return __sync_add_and_fetch(x, 1); -+#if HAVE_SYNC_ADD_AND_FETCH -+ return __sync_add_and_fetch(x, val); -+#elif defined(_WIN32) -+ return InterlockedAdd64((LONG64 *)x, val); -+#else -+# error "vkd3d_atomic_add_fetch_u64() not implemented for this platform" -+#endif - } --static inline LONG64 InterlockedIncrement64(LONG64 volatile *x) -+ -+static inline uint32_t vkd3d_atomic_add_fetch_u32(uint32_t volatile *x, uint32_t val) - { -- return __sync_add_and_fetch(x, 1); -+#if HAVE_SYNC_ADD_AND_FETCH -+ return __sync_add_and_fetch(x, val); -+#elif defined(_WIN32) -+ return InterlockedAdd((LONG *)x, val); -+#else -+# error "vkd3d_atomic_add_fetch_u32() not implemented for this platform" -+#endif - } --static inline LONG InterlockedAdd(LONG volatile *x, LONG val) -+ -+static inline uint64_t vkd3d_atomic_increment_u64(uint64_t volatile *x) - { -- return __sync_add_and_fetch(x, val); -+ return vkd3d_atomic_add_fetch_u64(x, 1); - } --# else --# error "InterlockedIncrement() not implemented for this platform" --# endif /* HAVE_SYNC_ADD_AND_FETCH */ - --# if HAVE_SYNC_SUB_AND_FETCH --static inline LONG InterlockedDecrement(LONG volatile *x) -+static inline uint32_t vkd3d_atomic_decrement_u32(uint32_t volatile *x) - { -- return __sync_sub_and_fetch(x, 1); -+ return vkd3d_atomic_add_fetch_u32(x, ~0u); - } --# else --# error "InterlockedDecrement() not implemented for this platform" --# endif - --#endif /* _WIN32 */ -+static inline uint32_t vkd3d_atomic_increment_u32(uint32_t volatile *x) -+{ -+ return vkd3d_atomic_add_fetch_u32(x, 1); -+} - - static inline void vkd3d_parse_version(const char *version, int *major, int *minor) - { -diff --git a/libs/vkd3d/include/private/vkd3d_debug.h b/libs/vkd3d/include/private/vkd3d_debug.h -index 6708cad344f..c5b6ccedf81 100644 ---- a/libs/vkd3d/include/private/vkd3d_debug.h -+++ b/libs/vkd3d/include/private/vkd3d_debug.h -@@ -89,6 +89,10 @@ const char *debugstr_w(const WCHAR *wstr, size_t wchar_size); - #define TRACE_ON() (vkd3d_dbg_get_level() == VKD3D_DBG_LEVEL_TRACE) - #endif - -+#ifndef WARN_ON -+#define WARN_ON() (vkd3d_dbg_get_level() >= VKD3D_DBG_LEVEL_WARN) -+#endif -+ - #define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN) - - #define VKD3D_DEBUG_ENV_NAME(name) const char *const vkd3d_dbg_env_name = name -@@ -104,6 +108,29 @@ static inline const char *debugstr_guid(const GUID *guid) - guid->Data4[5], guid->Data4[6], guid->Data4[7]); - } - -+static inline const char *debugstr_hresult(HRESULT hr) -+{ -+ switch (hr) -+ { -+#define TO_STR(u) case u: return #u; -+ TO_STR(S_OK) -+ TO_STR(S_FALSE) -+ TO_STR(E_NOTIMPL) -+ TO_STR(E_NOINTERFACE) -+ TO_STR(E_POINTER) -+ TO_STR(E_ABORT) -+ TO_STR(E_FAIL) -+ TO_STR(E_OUTOFMEMORY) -+ TO_STR(E_INVALIDARG) -+ TO_STR(DXGI_ERROR_NOT_FOUND) -+ TO_STR(DXGI_ERROR_MORE_DATA) -+ TO_STR(DXGI_ERROR_UNSUPPORTED) -+#undef TO_STR -+ default: -+ return vkd3d_dbg_sprintf("%#x", (int)hr); -+ } -+} -+ - unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value); - - struct vkd3d_debug_option -diff --git a/libs/vkd3d/include/private/vkd3d_test.h b/libs/vkd3d/include/private/vkd3d_test.h -new file mode 100644 -index 00000000000..a337ac07269 ---- /dev/null -+++ b/libs/vkd3d/include/private/vkd3d_test.h -@@ -0,0 +1,430 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 -+{ -+ unsigned int success_count; -+ unsigned int failure_count; -+ unsigned int skip_count; -+ unsigned int todo_count; -+ unsigned int todo_success_count; -+ unsigned int 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) -+ { -+ vkd3d_atomic_increment_u32(&vkd3d_test_state.success_count); -+ if (vkd3d_test_state.debug_level > 1) -+ vkd3d_test_printf(line, "Test succeeded.\n"); -+ } -+ else -+ { -+ vkd3d_atomic_increment_u32(&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) -+ { -+ vkd3d_atomic_increment_u32(&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) -+ { -+ vkd3d_atomic_increment_u32(&vkd3d_test_state.todo_success_count); -+ vkd3d_test_printf(line, "Todo succeeded: "); -+ } -+ else -+ { -+ vkd3d_atomic_increment_u32(&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); -+ vkd3d_atomic_increment_u32(&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: %u tests executed (%u failures, %u skipped, %u todo, %u bugs).\n", -+ vkd3d_test_name, -+ vkd3d_test_state.success_count + vkd3d_test_state.failure_count -+ + vkd3d_test_state.todo_count + vkd3d_test_state.todo_success_count, -+ vkd3d_test_state.failure_count + vkd3d_test_state.todo_success_count, -+ vkd3d_test_state.skip_count, -+ vkd3d_test_state.todo_count, -+ 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..872a90bbc4b ---- /dev/null -+++ b/libs/vkd3d/include/vkd3d_d3dcompiler.h -@@ -0,0 +1,97 @@ -+/* -+ * 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__ -+ -+#include -+ -+#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 -+ -+typedef enum D3DCOMPILER_STRIP_FLAGS -+{ -+ D3DCOMPILER_STRIP_REFLECTION_DATA = 0x00000001, -+ D3DCOMPILER_STRIP_DEBUG_INFO = 0x00000002, -+ D3DCOMPILER_STRIP_TEST_BLOBS = 0x00000004, -+ D3DCOMPILER_STRIP_PRIVATE_DATA = 0x00000008, -+ D3DCOMPILER_STRIP_ROOT_SIGNATURE = 0x00000010, -+ D3DCOMPILER_STRIP_FORCE_DWORD = 0x7fffffff, -+} D3DCOMPILER_STRIP_FLAGS; -+ -+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 D3DDisassemble(const void *data, SIZE_T data_size, UINT flags, const char *comments, ID3DBlob **blob); -+HRESULT WINAPI D3DGetBlobPart(const void *data, SIZE_T data_size, D3D_BLOB_PART part, UINT flags, ID3DBlob **blob); -+HRESULT WINAPI D3DGetDebugInfo(const void *data, SIZE_T data_size, ID3DBlob **blob); -+HRESULT WINAPI D3DGetInputAndOutputSignatureBlob(const void *data, SIZE_T data_size, ID3DBlob **blob); -+HRESULT WINAPI D3DGetInputSignatureBlob(const void *data, SIZE_T data_size, ID3DBlob **blob); -+HRESULT WINAPI D3DGetOutputSignatureBlob(const void *data, SIZE_T data_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); -+HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection); -+HRESULT WINAPI D3DStripShader(const void *data, SIZE_T data_size, UINT flags, ID3DBlob **blob); -+ -+typedef HRESULT (WINAPI *pD3DDisassemble)(const void *data, SIZE_T data_size, -+ UINT flags, const char *comments, ID3DBlob **blob); -+ -+#endif /* __D3DCOMPILER_H__ */ -+#endif /* __VKD3D_D3DCOMPILER_H */ -diff --git a/libs/vkd3d/include/vkd3d_d3dcompiler_types.h b/libs/vkd3d/include/vkd3d_d3dcompiler_types.h -new file mode 100644 -index 00000000000..b3a47cdd912 ---- /dev/null -+++ b/libs/vkd3d/include/vkd3d_d3dcompiler_types.h -@@ -0,0 +1,45 @@ -+/* -+ * 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_TYPES_H -+#define __VKD3D_D3DCOMPILER_TYPES_H -+#ifndef __D3DCOMPILER_H__ -+ -+typedef enum D3D_BLOB_PART -+{ -+ D3D_BLOB_INPUT_SIGNATURE_BLOB, -+ D3D_BLOB_OUTPUT_SIGNATURE_BLOB, -+ D3D_BLOB_INPUT_AND_OUTPUT_SIGNATURE_BLOB, -+ D3D_BLOB_PATCH_CONSTANT_SIGNATURE_BLOB, -+ D3D_BLOB_ALL_SIGNATURE_BLOB, -+ D3D_BLOB_DEBUG_INFO, -+ D3D_BLOB_LEGACY_SHADER, -+ D3D_BLOB_XNA_PREPASS_SHADER, -+ D3D_BLOB_XNA_SHADER, -+ D3D_BLOB_PDB, -+ D3D_BLOB_PRIVATE_DATA, -+ D3D_BLOB_ROOT_SIGNATURE, -+ D3D_BLOB_DEBUG_NAME, -+ D3D_BLOB_TEST_ALTERNATE_SHADER = 0x8000, -+ D3D_BLOB_TEST_COMPILE_DETAILS, -+ D3D_BLOB_TEST_COMPILE_PERF, -+ D3D_BLOB_TEST_COMPILE_REPORT -+} D3D_BLOB_PART; -+ -+#endif /* __D3DCOMPILER_H__ */ -+#endif /* __VKD3D_D3DCOMPILER_TYPES_H */ -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index 290f9085d2d..2f4478a7983 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -196,6 +196,15 @@ enum vkd3d_shader_compile_option_fragment_coordinate_origin - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN), - }; - -+/** Advertises feature availability. \since 1.11 */ -+enum vkd3d_shader_compile_option_feature_flags -+{ -+ VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64 = 0x00000001, -+ VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLOAT64 = 0x00000002, -+ -+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS), -+}; -+ - enum vkd3d_shader_compile_option_name - { - /** -@@ -253,6 +262,16 @@ enum vkd3d_shader_compile_option_name - * \since 1.10 - */ - VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN = 0x00000009, -+ /** -+ * This option specifies the shader features available in the target -+ * environment. These are not extensions, i.e. they are always supported -+ * by the driver, but may not be supported by the available hardware. -+ * -+ * \a value is a member of enum vkd3d_shader_compile_option_feature_flags. -+ * -+ * \since 1.11 -+ */ -+ VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), - }; -@@ -767,6 +786,11 @@ enum vkd3d_shader_target_type - * An 'OpenGL Shading Language' shader. \since 1.3 - */ - VKD3D_SHADER_TARGET_GLSL, -+ /** -+ * Binary format used by Direct3D 9/10.x/11 effects profiles. -+ * Output is a raw FX section without container. \since 1.11 -+ */ -+ VKD3D_SHADER_TARGET_FX, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET_TYPE), - }; -@@ -853,6 +877,8 @@ enum vkd3d_shader_spirv_extension - VKD3D_SHADER_SPIRV_EXTENSION_EXT_DESCRIPTOR_INDEXING, - /** \since 1.3 */ - VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT, -+ /** \since 1.11 */ -+ VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SPIRV_EXTENSION), - }; -@@ -1252,6 +1278,8 @@ enum vkd3d_shader_descriptor_range_flags - VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2, - VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4, - VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8, -+ /** \since 1.11 */ -+ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x10000, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_RANGE_FLAGS), - }; -@@ -1551,6 +1579,8 @@ enum vkd3d_shader_component_type - VKD3D_SHADER_COMPONENT_BOOL = 0x4, - /** 64-bit IEEE floating-point. */ - VKD3D_SHADER_COMPONENT_DOUBLE = 0x5, -+ /** 64-bit unsigned integer. \since 1.11 */ -+ VKD3D_SHADER_COMPONENT_UINT64 = 0x6, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPONENT_TYPE), - }; -@@ -1747,10 +1777,10 @@ struct vkd3d_shader_dxbc_desc - * \endcode - */ - #define VKD3D_SHADER_SWIZZLE(x, y, z, w) \ -- vkd3d_shader_create_swizzle(VKD3D_SHADER_SWIZZLE_ ## x, \ -- VKD3D_SHADER_SWIZZLE_ ## y, \ -- VKD3D_SHADER_SWIZZLE_ ## z, \ -- VKD3D_SHADER_SWIZZLE_ ## w) -+ (VKD3D_SHADER_SWIZZLE_ ## x << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ -+ | VKD3D_SHADER_SWIZZLE_ ## y << VKD3D_SHADER_SWIZZLE_SHIFT(1) \ -+ | VKD3D_SHADER_SWIZZLE_ ## z << VKD3D_SHADER_SWIZZLE_SHIFT(2) \ -+ | VKD3D_SHADER_SWIZZLE_ ## w << VKD3D_SHADER_SWIZZLE_SHIFT(3)) - - /** The identity swizzle ".xyzw". */ - #define VKD3D_SHADER_NO_SWIZZLE VKD3D_SHADER_SWIZZLE(X, Y, Z, W) -diff --git a/libs/vkd3d/include/vkd3d_utils.h b/libs/vkd3d/include/vkd3d_utils.h -new file mode 100644 -index 00000000000..7616a3f3c46 ---- /dev/null -+++ b/libs/vkd3d/include/vkd3d_utils.h -@@ -0,0 +1,128 @@ -+/* -+ * 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 -+#include -+ -+#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); -+ -+/** \since 1.10 */ -+VKD3D_UTILS_API HRESULT WINAPI D3DGetBlobPart(const void *data, -+ SIZE_T data_size, D3D_BLOB_PART part, UINT flags, ID3DBlob **blob); -+/** \since 1.10 */ -+VKD3D_UTILS_API HRESULT WINAPI D3DGetDebugInfo(const void *data, SIZE_T data_size, ID3DBlob **blob); -+/** \since 1.10 */ -+VKD3D_UTILS_API HRESULT WINAPI D3DGetInputAndOutputSignatureBlob(const void *data, SIZE_T data_size, ID3DBlob **blob); -+/** \since 1.10 */ -+VKD3D_UTILS_API HRESULT WINAPI D3DGetInputSignatureBlob(const void *data, SIZE_T data_size, ID3DBlob **blob); -+/** \since 1.10 */ -+VKD3D_UTILS_API HRESULT WINAPI D3DGetOutputSignatureBlob(const void *data, SIZE_T data_size, ID3DBlob **blob); -+/** \since 1.10 */ -+VKD3D_UTILS_API HRESULT WINAPI D3DStripShader(const void *data, SIZE_T data_size, UINT flags, ID3DBlob **blob); -+ -+/** \since 1.11 */ -+VKD3D_UTILS_API HRESULT WINAPI D3DDisassemble(const void *data, -+ SIZE_T data_size, UINT flags, const char *comments, ID3DBlob **blob); -+VKD3D_UTILS_API HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection); -+ -+#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 -+# endif -+# include -+# 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 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() \ -+ { \ -+ 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() \ -+ { \ -+ return __vkd3d_uuidof(); \ -+ } \ -+ } -+ -+# define __uuidof(type) __vkd3d_uuidof() -+#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 -+# include -+# include -+ -+# 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 -+ -+#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 71ab9a2c51e..dbb26de7d73 100644 ---- a/libs/vkd3d/libs/vkd3d-common/blob.c -+++ b/libs/vkd3d/libs/vkd3d-common/blob.c -@@ -17,16 +17,18 @@ - */ - - #define COBJMACROS -+ - #define CONST_VTABLE - #include "vkd3d.h" - #include "vkd3d_blob.h" - #include "vkd3d_debug.h" - #include "vkd3d_memory.h" -+#include "d3d12shader.h" - - struct vkd3d_blob - { - ID3D10Blob ID3DBlob_iface; -- LONG refcount; -+ unsigned int refcount; - - void *buffer; - SIZE_T size; -@@ -58,7 +60,7 @@ static HRESULT STDMETHODCALLTYPE vkd3d_blob_QueryInterface(ID3DBlob *iface, REFI - static ULONG STDMETHODCALLTYPE vkd3d_blob_AddRef(ID3DBlob *iface) - { - struct vkd3d_blob *blob = impl_from_ID3DBlob(iface); -- ULONG refcount = InterlockedIncrement(&blob->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&blob->refcount); - - TRACE("%p increasing refcount to %u.\n", blob, refcount); - -@@ -68,7 +70,7 @@ static ULONG STDMETHODCALLTYPE vkd3d_blob_AddRef(ID3DBlob *iface) - static ULONG STDMETHODCALLTYPE vkd3d_blob_Release(ID3DBlob *iface) - { - struct vkd3d_blob *blob = impl_from_ID3DBlob(iface); -- ULONG refcount = InterlockedDecrement(&blob->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&blob->refcount); - - TRACE("%p decreasing refcount to %u.\n", blob, refcount); - -diff --git a/libs/vkd3d/libs/vkd3d-common/debug.c b/libs/vkd3d/libs/vkd3d-common/debug.c -index aa7df5bd764..e12cd39450a 100644 ---- a/libs/vkd3d/libs/vkd3d-common/debug.c -+++ b/libs/vkd3d/libs/vkd3d-common/debug.c -@@ -126,10 +126,10 @@ void vkd3d_dbg_set_log_callback(PFN_vkd3d_log callback) - static char *get_buffer(void) - { - static char buffers[VKD3D_DEBUG_BUFFER_COUNT][VKD3D_DEBUG_BUFFER_SIZE]; -- static LONG buffer_index; -- LONG current_index; -+ static unsigned int buffer_index; -+ unsigned int current_index; - -- current_index = InterlockedIncrement(&buffer_index) % ARRAY_SIZE(buffers); -+ current_index = vkd3d_atomic_increment_u32(&buffer_index) % ARRAY_SIZE(buffers); - return buffers[current_index]; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index 82d1d71d9d3..3f86bd45960 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -30,8 +30,11 @@ - static const char * const shader_opcode_names[] = - { - [VKD3DSIH_ABS ] = "abs", -+ [VKD3DSIH_ACOS ] = "acos", - [VKD3DSIH_ADD ] = "add", - [VKD3DSIH_AND ] = "and", -+ [VKD3DSIH_ASIN ] = "asin", -+ [VKD3DSIH_ATAN ] = "atan", - [VKD3DSIH_ATOMIC_AND ] = "atomic_and", - [VKD3DSIH_ATOMIC_CMP_STORE ] = "atomic_cmp_store", - [VKD3DSIH_ATOMIC_IADD ] = "atomic_iadd", -@@ -44,6 +47,7 @@ static const char * const shader_opcode_names[] = - [VKD3DSIH_BEM ] = "bem", - [VKD3DSIH_BFI ] = "bfi", - [VKD3DSIH_BFREV ] = "bfrev", -+ [VKD3DSIH_BRANCH ] = "branch", - [VKD3DSIH_BREAK ] = "break", - [VKD3DSIH_BREAKC ] = "breakc", - [VKD3DSIH_BREAKP ] = "breakp", -@@ -167,10 +171,13 @@ static const char * const shader_opcode_names[] = - [VKD3DSIH_GATHER4_S ] = "gather4_s", - [VKD3DSIH_GEO ] = "ge", - [VKD3DSIH_GEU ] = "ge_unord", -+ [VKD3DSIH_HCOS ] = "hcos", - [VKD3DSIH_HS_CONTROL_POINT_PHASE ] = "hs_control_point_phase", - [VKD3DSIH_HS_DECLS ] = "hs_decls", - [VKD3DSIH_HS_FORK_PHASE ] = "hs_fork_phase", - [VKD3DSIH_HS_JOIN_PHASE ] = "hs_join_phase", -+ [VKD3DSIH_HSIN ] = "hsin", -+ [VKD3DSIH_HTAN ] = "htan", - [VKD3DSIH_IADD ] = "iadd", - [VKD3DSIH_IBFE ] = "ibfe", - [VKD3DSIH_IDIV ] = "idiv", -@@ -197,8 +204,11 @@ static const char * const shader_opcode_names[] = - [VKD3DSIH_IMUL ] = "imul", - [VKD3DSIH_INE ] = "ine", - [VKD3DSIH_INEG ] = "ineg", -+ [VKD3DSIH_ISFINITE ] = "isfinite", - [VKD3DSIH_ISHL ] = "ishl", - [VKD3DSIH_ISHR ] = "ishr", -+ [VKD3DSIH_ISINF ] = "isinf", -+ [VKD3DSIH_ISNAN ] = "isnan", - [VKD3DSIH_ITOD ] = "itod", - [VKD3DSIH_ITOF ] = "itof", - [VKD3DSIH_ITOI ] = "itoi", -@@ -241,6 +251,7 @@ static const char * const shader_opcode_names[] = - [VKD3DSIH_NRM ] = "nrm", - [VKD3DSIH_OR ] = "or", - [VKD3DSIH_PHASE ] = "phase", -+ [VKD3DSIH_PHI ] = "phi", - [VKD3DSIH_POW ] = "pow", - [VKD3DSIH_RCP ] = "rcp", - [VKD3DSIH_REP ] = "rep", -@@ -278,7 +289,9 @@ static const char * const shader_opcode_names[] = - [VKD3DSIH_SUB ] = "sub", - [VKD3DSIH_SWAPC ] = "swapc", - [VKD3DSIH_SWITCH ] = "switch", -+ [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", - [VKD3DSIH_SYNC ] = "sync", -+ [VKD3DSIH_TAN ] = "tan", - [VKD3DSIH_TEX ] = "texld", - [VKD3DSIH_TEXBEM ] = "texbem", - [VKD3DSIH_TEXBEML ] = "texbeml", -@@ -364,6 +377,8 @@ struct vkd3d_d3d_asm_compiler - struct vkd3d_string_buffer buffer; - struct vkd3d_shader_version shader_version; - struct vkd3d_d3d_asm_colours colours; -+ enum vsir_asm_dialect dialect; -+ const struct vkd3d_shader_instruction *current; - }; - - static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...) -@@ -437,6 +452,11 @@ static void shader_dump_sync_flags(struct vkd3d_d3d_asm_compiler *compiler, uint - vkd3d_string_buffer_printf(&compiler->buffer, "_uglobal"); - sync_flags &= ~VKD3DSSF_GLOBAL_UAV; - } -+ if (sync_flags & VKD3DSSF_THREAD_GROUP_UAV) -+ { -+ vkd3d_string_buffer_printf(&compiler->buffer, "_ugroup"); -+ sync_flags &= ~VKD3DSSF_THREAD_GROUP_UAV; -+ } - if (sync_flags & VKD3DSSF_GROUP_SHARED_MEMORY) - { - vkd3d_string_buffer_printf(&compiler->buffer, "_g"); -@@ -606,7 +626,7 @@ static void shader_dump_resource_type(struct vkd3d_d3d_asm_compiler *compiler, e - vkd3d_string_buffer_printf(&compiler->buffer, "unknown"); - } - --static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) -+static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_data_type type) - { - static const char *const data_type_names[] = - { -@@ -623,19 +643,31 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const - [VKD3D_DATA_DOUBLE ] = "double", - [VKD3D_DATA_CONTINUED] = "", - [VKD3D_DATA_UNUSED ] = "", -+ [VKD3D_DATA_UINT8 ] = "uint8", -+ [VKD3D_DATA_UINT64 ] = "uint64", -+ [VKD3D_DATA_BOOL ] = "bool", - }; -+ - const char *name; -+ -+ if (type < ARRAY_SIZE(data_type_names)) -+ name = data_type_names[type]; -+ else -+ name = ""; -+ -+ vkd3d_string_buffer_printf(&compiler->buffer, "%s", name); -+} -+ -+static void shader_dump_resource_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) -+{ - int i; - - vkd3d_string_buffer_printf(&compiler->buffer, "("); - - for (i = 0; i < 4; i++) - { -- if (type[i] < ARRAY_SIZE(data_type_names)) -- name = data_type_names[type[i]]; -- else -- name = "unknown"; -- vkd3d_string_buffer_printf(&compiler->buffer, "%s%s", i == 0 ? "" : ",", name); -+ vkd3d_string_buffer_printf(&compiler->buffer, "%s", i == 0 ? "" : ","); -+ shader_dump_data_type(compiler, type[i]); - } - - vkd3d_string_buffer_printf(&compiler->buffer, ")"); -@@ -682,7 +714,7 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler, - if (semantic->resource.reg.reg.type == VKD3DSPR_UAV) - shader_dump_uav_flags(compiler, flags); - shader_addline(buffer, " "); -- shader_dump_data_type(compiler, semantic->resource_data_type); -+ shader_dump_resource_data_type(compiler, semantic->resource_data_type); - } - else - { -@@ -814,6 +846,13 @@ static void shader_print_uint_literal(struct vkd3d_d3d_asm_compiler *compiler, - prefix, compiler->colours.literal, i, compiler->colours.reset, suffix); - } - -+static void shader_print_uint64_literal(struct vkd3d_d3d_asm_compiler *compiler, -+ const char *prefix, uint64_t i, const char *suffix) -+{ -+ vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%"PRIu64"%s%s", -+ prefix, compiler->colours.literal, i, compiler->colours.reset, suffix); -+} -+ - static void shader_print_hex_literal(struct vkd3d_d3d_asm_compiler *compiler, - const char *prefix, unsigned int i, const char *suffix) - { -@@ -828,6 +867,27 @@ static void shader_print_bool_literal(struct vkd3d_d3d_asm_compiler *compiler, - compiler->colours.literal, b ? "true" : "false", compiler->colours.reset, suffix); - } - -+static void shader_print_untyped_literal(struct vkd3d_d3d_asm_compiler *compiler, -+ const char *prefix, uint32_t u, const char *suffix) -+{ -+ union -+ { -+ uint32_t u; -+ float f; -+ } value; -+ unsigned int exponent = (u >> 23) & 0xff; -+ -+ value.u = u; -+ -+ if (exponent != 0 && exponent != 0xff) -+ return shader_print_float_literal(compiler, prefix, value.f, suffix); -+ -+ if (u <= 10000) -+ return shader_print_uint_literal(compiler, prefix, value.u, suffix); -+ -+ return shader_print_hex_literal(compiler, prefix, value.u, suffix); -+} -+ - static void shader_print_subscript(struct vkd3d_d3d_asm_compiler *compiler, - unsigned int offset, const struct vkd3d_shader_src_param *rel_addr) - { -@@ -1089,6 +1149,19 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - - if (reg->type == VKD3DSPR_IMMCONST) - { -+ bool untyped = false; -+ -+ switch (compiler->current->handler_idx) -+ { -+ case VKD3DSIH_MOV: -+ case VKD3DSIH_MOVC: -+ untyped = true; -+ break; -+ -+ default: -+ break; -+ } -+ - shader_addline(buffer, "%s(", compiler->colours.reset); - switch (reg->dimension) - { -@@ -1096,15 +1169,18 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - switch (reg->data_type) - { - case VKD3D_DATA_FLOAT: -- shader_print_float_literal(compiler, "", reg->u.immconst_float[0], ""); -+ if (untyped) -+ shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], ""); -+ else -+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); - break; - case VKD3D_DATA_INT: -- shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], ""); -+ shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); - break; - case VKD3D_DATA_RESOURCE: - case VKD3D_DATA_SAMPLER: - case VKD3D_DATA_UINT: -- shader_print_uint_literal(compiler, "", reg->u.immconst_uint[0], ""); -+ shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); - break; - default: - shader_addline(buffer, "", reg->data_type); -@@ -1116,24 +1192,34 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - switch (reg->data_type) - { - case VKD3D_DATA_FLOAT: -- shader_print_float_literal(compiler, "", reg->u.immconst_float[0], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[1], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[2], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[3], ""); -+ if (untyped) -+ { -+ shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], ""); -+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[1], ""); -+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[2], ""); -+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[3], ""); -+ } -+ else -+ { -+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], ""); -+ } - break; - case VKD3D_DATA_INT: -- shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], ""); -- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[1], ""); -- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[2], ""); -- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[3], ""); -+ shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); -+ shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[1], ""); -+ shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[2], ""); -+ shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[3], ""); - break; - case VKD3D_DATA_RESOURCE: - case VKD3D_DATA_SAMPLER: - case VKD3D_DATA_UINT: -- shader_print_uint_literal(compiler, "", reg->u.immconst_uint[0], ""); -- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[1], ""); -- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[2], ""); -- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[3], ""); -+ shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); -+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[1], ""); -+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[2], ""); -+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[3], ""); - break; - default: - shader_addline(buffer, "", reg->data_type); -@@ -1155,9 +1241,15 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - { - if (reg->data_type == VKD3D_DATA_DOUBLE) - { -- shader_print_double_literal(compiler, "", reg->u.immconst_double[0], ""); -+ shader_print_double_literal(compiler, "", reg->u.immconst_f64[0], ""); -+ if (reg->dimension == VSIR_DIMENSION_VEC4) -+ shader_print_double_literal(compiler, ", ", reg->u.immconst_f64[1], ""); -+ } -+ else if (reg->data_type == VKD3D_DATA_UINT64) -+ { -+ shader_print_uint64_literal(compiler, "", reg->u.immconst_u64[0], ""); - if (reg->dimension == VSIR_DIMENSION_VEC4) -- shader_print_double_literal(compiler, ", ", reg->u.immconst_double[1], ""); -+ shader_print_uint64_literal(compiler, "", reg->u.immconst_u64[1], ""); - } - else - { -@@ -1265,6 +1357,32 @@ static void shader_print_non_uniform(struct vkd3d_d3d_asm_compiler *compiler, co - compiler->colours.modifier, compiler->colours.reset); - } - -+static void shader_dump_reg_type(struct vkd3d_d3d_asm_compiler *compiler, -+ const struct vkd3d_shader_register *reg) -+{ -+ static const char *dimensions[] = -+ { -+ [VSIR_DIMENSION_NONE] = "", -+ [VSIR_DIMENSION_SCALAR] = "s:", -+ [VSIR_DIMENSION_VEC4] = "v4:", -+ }; -+ -+ struct vkd3d_string_buffer *buffer = &compiler->buffer; -+ const char *dimension; -+ -+ if (compiler->dialect != VSIR_ASM_VSIR) -+ return; -+ -+ if (reg->dimension < ARRAY_SIZE(dimensions)) -+ dimension = dimensions[reg->dimension]; -+ else -+ dimension = "??"; -+ -+ shader_addline(buffer, " <%s", dimension); -+ shader_dump_data_type(compiler, reg->data_type); -+ shader_addline(buffer, ">"); -+} -+ - static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, - const struct vkd3d_shader_dst_param *param, bool is_declaration) - { -@@ -1277,8 +1395,8 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, - { - static const char write_mask_chars[] = "xyzw"; - -- if (param->reg.data_type == VKD3D_DATA_DOUBLE) -- write_mask = vkd3d_write_mask_32_from_64(write_mask); -+ if (data_type_is_64_bit(param->reg.data_type)) -+ write_mask = vsir_write_mask_32_from_64(write_mask); - - shader_addline(buffer, ".%s", compiler->colours.write_mask); - if (write_mask & VKD3DSP_WRITEMASK_0) -@@ -1294,6 +1412,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, - - shader_print_precision(compiler, ¶m->reg); - shader_print_non_uniform(compiler, ¶m->reg); -+ shader_dump_reg_type(compiler, ¶m->reg); - } - - static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, -@@ -1341,13 +1460,18 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, - if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 - && param->reg.dimension == VSIR_DIMENSION_VEC4) - { -- unsigned int swizzle_x = vkd3d_swizzle_get_component(swizzle, 0); -- unsigned int swizzle_y = vkd3d_swizzle_get_component(swizzle, 1); -- unsigned int swizzle_z = vkd3d_swizzle_get_component(swizzle, 2); -- unsigned int swizzle_w = vkd3d_swizzle_get_component(swizzle, 3); -- - static const char swizzle_chars[] = "xyzw"; - -+ unsigned int swizzle_x, swizzle_y, swizzle_z, swizzle_w; -+ -+ if (data_type_is_64_bit(param->reg.data_type)) -+ swizzle = vsir_swizzle_32_from_64(swizzle); -+ -+ swizzle_x = vsir_swizzle_get_component(swizzle, 0); -+ swizzle_y = vsir_swizzle_get_component(swizzle, 1); -+ swizzle_z = vsir_swizzle_get_component(swizzle, 2); -+ swizzle_w = vsir_swizzle_get_component(swizzle, 3); -+ - if (swizzle_x == swizzle_y - && swizzle_x == swizzle_z - && swizzle_x == swizzle_w) -@@ -1367,6 +1491,7 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, - - shader_print_precision(compiler, ¶m->reg); - shader_print_non_uniform(compiler, ¶m->reg); -+ shader_dump_reg_type(compiler, ¶m->reg); - } - - static void shader_dump_ins_modifiers(struct vkd3d_d3d_asm_compiler *compiler, -@@ -1577,6 +1702,12 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile - shader_addline(buffer, "p"); - break; - -+ case VKD3DSIH_ISHL: -+ case VKD3DSIH_ISHR: -+ case VKD3DSIH_USHR: -+ if (ins->flags & VKD3DSI_SHIFT_UNMASKED) -+ shader_addline(buffer, "_unmasked"); -+ /* fall through */ - default: - shader_dump_precise_flags(compiler, ins->flags); - break; -@@ -1631,6 +1762,8 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - struct vkd3d_string_buffer *buffer = &compiler->buffer; - unsigned int i; - -+ compiler->current = ins; -+ - if (ins->predicate) - { - vkd3d_string_buffer_printf(buffer, "("); -@@ -1835,25 +1968,25 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - vkd3d_string_buffer_printf(buffer, " %sc%u%s", compiler->colours.reg, - shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset), - compiler->colours.reset); -- shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_float[0], ""); -- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[1], ""); -- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[2], ""); -- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[3], ""); -+ shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_f32[0], ""); -+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[1], ""); -+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[2], ""); -+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[3], ""); - break; - - case VKD3DSIH_DEFI: - vkd3d_string_buffer_printf(buffer, " %si%u%s", compiler->colours.reg, - ins->dst[0].reg.idx[0].offset, compiler->colours.reset); -- shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], ""); -- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[1], ""); -- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[2], ""); -- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[3], ""); -+ shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], ""); -+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[1], ""); -+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[2], ""); -+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[3], ""); - break; - - case VKD3DSIH_DEFB: - vkd3d_string_buffer_printf(buffer, " %sb%u%s", compiler->colours.reg, - ins->dst[0].reg.idx[0].offset, compiler->colours.reset); -- shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], ""); -+ shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], ""); - break; - - default: -@@ -1883,7 +2016,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - || ins->resource_data_type[1] != VKD3D_DATA_FLOAT - || ins->resource_data_type[2] != VKD3D_DATA_FLOAT - || ins->resource_data_type[3] != VKD3D_DATA_FLOAT) -- shader_dump_data_type(compiler, ins->resource_data_type); -+ shader_dump_resource_data_type(compiler, ins->resource_data_type); - - for (i = 0; i < ins->dst_count; ++i) - { -@@ -1904,12 +2037,16 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - shader_addline(buffer, "\n"); - } - --enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, -- const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info, -- struct vkd3d_shader_code *out) -+enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, -+ const struct vkd3d_shader_compile_info *compile_info, -+ struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect) - { -+ const struct vkd3d_shader_version *shader_version = &program->shader_version; - enum vkd3d_shader_compile_option_formatting_flags formatting; -- struct vkd3d_d3d_asm_compiler compiler; -+ struct vkd3d_d3d_asm_compiler compiler = -+ { -+ .dialect = dialect, -+ }; - enum vkd3d_result result = VKD3D_OK; - struct vkd3d_string_buffer *buffer; - unsigned int indent, i, j; -@@ -1973,9 +2110,9 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio - shader_version->minor, compiler.colours.reset); - - indent = 0; -- for (i = 0; i < instructions->count; ++i) -+ for (i = 0; i < program->instructions.count; ++i) - { -- struct vkd3d_shader_instruction *ins = &instructions->elements[i]; -+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - - switch (ins->handler_idx) - { -@@ -2002,6 +2139,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio - { - case VKD3DSIH_ELSE: - case VKD3DSIH_IF: -+ case VKD3DSIH_IFC: - case VKD3DSIH_LOOP: - case VKD3DSIH_SWITCH: - ++indent; -@@ -2028,13 +2166,12 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio - return result; - } - --void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instructions, -- const struct vkd3d_shader_version *shader_version) -+void vkd3d_shader_trace(const struct vsir_program *program) - { - const char *p, *q, *end; - struct vkd3d_shader_code code; - -- if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code) != VKD3D_OK) -+ if (vkd3d_dxbc_binary_to_text(program, NULL, &code, VSIR_ASM_VSIR) != VKD3D_OK) - return; - - end = (const char *)code.code + code.size; -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 3d139416b61..9ad9f735dd1 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -414,6 +414,7 @@ static bool has_relative_address(uint32_t param) - static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info( - const struct vkd3d_shader_sm1_parser *sm1, enum vkd3d_sm1_opcode opcode) - { -+ const struct vkd3d_shader_version *version = &sm1->p.program.shader_version; - const struct vkd3d_sm1_opcode_info *info; - unsigned int i = 0; - -@@ -424,8 +425,8 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info( - return NULL; - - if (opcode == info->sm1_opcode -- && vkd3d_shader_ver_ge(&sm1->p.shader_version, info->min_version.major, info->min_version.minor) -- && (vkd3d_shader_ver_le(&sm1->p.shader_version, info->max_version.major, info->max_version.minor) -+ && vkd3d_shader_ver_ge(version, info->min_version.major, info->min_version.minor) -+ && (vkd3d_shader_ver_le(version, info->max_version.major, info->max_version.minor) - || !info->max_version.major)) - return info; - } -@@ -444,7 +445,7 @@ static uint32_t swizzle_from_sm1(uint32_t swizzle) - shader_sm1_get_swizzle_component(swizzle, 3)); - } - --static void shader_sm1_parse_src_param(uint32_t param, const struct vkd3d_shader_src_param *rel_addr, -+static void shader_sm1_parse_src_param(uint32_t param, struct vkd3d_shader_src_param *rel_addr, - struct vkd3d_shader_src_param *src) - { - enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) -@@ -465,7 +466,7 @@ static void shader_sm1_parse_src_param(uint32_t param, const struct vkd3d_shader - src->modifiers = (param & VKD3D_SM1_SRC_MODIFIER_MASK) >> VKD3D_SM1_SRC_MODIFIER_SHIFT; - } - --static void shader_sm1_parse_dst_param(uint32_t param, const struct vkd3d_shader_src_param *rel_addr, -+static void shader_sm1_parse_dst_param(uint32_t param, struct vkd3d_shader_src_param *rel_addr, - struct vkd3d_shader_dst_param *dst) - { - enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) -@@ -482,9 +483,23 @@ static void shader_sm1_parse_dst_param(uint32_t param, const struct vkd3d_shader - dst->reg.dimension = VSIR_DIMENSION_SCALAR; - else - dst->reg.dimension = VSIR_DIMENSION_VEC4; -- dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT; - dst->modifiers = (param & VKD3D_SM1_DST_MODIFIER_MASK) >> VKD3D_SM1_DST_MODIFIER_SHIFT; - dst->shift = (param & VKD3D_SM1_DSTSHIFT_MASK) >> VKD3D_SM1_DSTSHIFT_SHIFT; -+ -+ switch (dst->reg.dimension) -+ { -+ case VSIR_DIMENSION_SCALAR: -+ dst->write_mask = VKD3DSP_WRITEMASK_0; -+ break; -+ -+ case VSIR_DIMENSION_VEC4: -+ dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT; -+ break; -+ -+ default: -+ dst->write_mask = 0; -+ break; -+ } - } - - static struct signature_element *find_signature_element(const struct shader_signature *signature, -@@ -518,8 +533,6 @@ static struct signature_element *find_signature_element_by_register_index( - return NULL; - } - --#define SM1_COLOR_REGISTER_OFFSET 8 -- - static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output, - const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval, - unsigned int register_index, bool is_dcl, unsigned int mask) -@@ -555,7 +568,7 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp - element->register_count = 1; - element->mask = mask; - element->used_mask = is_dcl ? 0 : mask; -- if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output) -+ if (sm1->p.program.shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output) - element->interpolation_mode = VKD3DSIM_LINEAR; - - return true; -@@ -574,7 +587,7 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output, - - if (!(element = find_signature_element_by_register_index(signature, register_index))) - { -- vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNDECLARED_SEMANTIC, -+ vkd3d_shader_parser_warning(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNDECLARED_SEMANTIC, - "%s register %u was used without being declared.", output ? "Output" : "Input", register_index); - return; - } -@@ -585,20 +598,20 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output, - static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *sm1, - const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask) - { -+ const struct vkd3d_shader_version *version = &sm1->p.program.shader_version; - unsigned int register_index = reg->idx[0].offset; - - switch (reg->type) - { - case VKD3DSPR_TEMP: -- if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL -- && sm1->p.shader_version.major == 1 && !register_index) -+ if (version->type == VKD3D_SHADER_TYPE_PIXEL && version->major == 1 && !register_index) - return add_signature_element(sm1, true, "COLOR", 0, VKD3D_SHADER_SV_TARGET, 0, is_dcl, mask); - return true; - - case VKD3DSPR_INPUT: - /* For vertex shaders or sm3 pixel shaders, we should have already - * had a DCL instruction. Otherwise, this is a colour input. */ -- if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX || sm1->p.shader_version.major == 3) -+ if (version->type == VKD3D_SHADER_TYPE_VERTEX || version->major == 3) - { - add_signature_mask(sm1, false, register_index, mask); - return true; -@@ -608,19 +621,19 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * - - case VKD3DSPR_TEXTURE: - /* For vertex shaders, this is ADDR. */ -- if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX) -+ if (version->type == VKD3D_SHADER_TYPE_VERTEX) - return true; - return add_signature_element(sm1, false, "TEXCOORD", register_index, - VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); - - case VKD3DSPR_OUTPUT: -- if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX) -+ if (version->type == VKD3D_SHADER_TYPE_VERTEX) - { - /* For sm < 2 vertex shaders, this is TEXCRDOUT. - * - * For sm3 vertex shaders, this is OUTPUT, but we already - * should have had a DCL instruction. */ -- if (sm1->p.shader_version.major == 3) -+ if (version->major == 3) - { - add_signature_mask(sm1, true, register_index, mask); - return true; -@@ -647,15 +660,15 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * - { - case 0: - return add_signature_element(sm1, true, "POSITION", 0, -- VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask); -+ VKD3D_SHADER_SV_POSITION, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, mask); - - case 1: - return add_signature_element(sm1, true, "FOG", 0, -- VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); -+ VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1); - - case 2: - return add_signature_element(sm1, true, "PSIZE", 0, -- VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); -+ VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1); - - default: - vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, -@@ -688,6 +701,7 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * - static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *sm1, - const struct vkd3d_shader_semantic *semantic) - { -+ const struct vkd3d_shader_version *version = &sm1->p.program.shader_version; - const struct vkd3d_shader_register *reg = &semantic->resource.reg.reg; - enum vkd3d_shader_sysval_semantic sysval = VKD3D_SHADER_SV_NONE; - unsigned int mask = semantic->resource.reg.write_mask; -@@ -719,13 +733,13 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser * - return add_signature_element_from_register(sm1, reg, true, mask); - - /* sm2 pixel shaders use DCL but don't provide a semantic. */ -- if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL && sm1->p.shader_version.major == 2) -+ if (version->type == VKD3D_SHADER_TYPE_PIXEL && version->major == 2) - return add_signature_element_from_register(sm1, reg, true, mask); - - /* With the exception of vertex POSITION output, none of these are system - * values. Pixel POSITION input is not equivalent to SV_Position; the closer - * equivalent is VPOS, which is not declared as a semantic. */ -- if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX -+ if (version->type == VKD3D_SHADER_TYPE_VERTEX - && output && semantic->usage == VKD3D_DECL_USAGE_POSITION) - sysval = VKD3D_SHADER_SV_POSITION; - -@@ -751,13 +765,13 @@ static void record_constant_register(struct vkd3d_shader_sm1_parser *sm1, - static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1, - const struct vkd3d_shader_register *reg, unsigned int mask, bool from_def) - { -- struct vkd3d_shader_desc *desc = &sm1->p.shader_desc; -+ struct vsir_program *program = &sm1->p.program; - uint32_t register_index = reg->idx[0].offset; - - switch (reg->type) - { - case VKD3DSPR_TEMP: -- desc->temp_count = max(desc->temp_count, register_index + 1); -+ program->temp_count = max(program->temp_count, register_index + 1); - break; - - case VKD3DSPR_CONST: -@@ -812,7 +826,7 @@ static void shader_sm1_read_param(struct vkd3d_shader_sm1_parser *sm1, - * VS >= 2.0 have relative addressing (with token) - * VS >= 1.0 < 2.0 have relative addressing (without token) - * The version check below should work in general. */ -- if (sm1->p.shader_version.major < 2) -+ if (sm1->p.program.shader_version.major < 2) - { - *addr_token = (1u << 31) - | ((VKD3DSPR_ADDR << VKD3D_SM1_REGISTER_TYPE_SHIFT2) & VKD3D_SM1_REGISTER_TYPE_MASK2) -@@ -841,7 +855,7 @@ static void shader_sm1_skip_opcode(const struct vkd3d_shader_sm1_parser *sm1, co - /* Version 2.0+ shaders may contain address tokens, but fortunately they - * have a useful length mask - use it here. Version 1.x shaders contain no - * such tokens. */ -- if (sm1->p.shader_version.major >= 2) -+ if (sm1->p.program.shader_version.major >= 2) - { - length = (opcode_token & VKD3D_SM1_INSTRUCTION_LENGTH_MASK) >> VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT; - *ptr += length; -@@ -871,7 +885,7 @@ static void shader_sm1_destroy(struct vkd3d_shader_parser *parser) - { - struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser); - -- shader_instruction_array_destroy(&parser->instructions); -+ vsir_program_cleanup(&parser->program); - free_shader_desc(&sm1->p.shader_desc); - vkd3d_free(sm1); - } -@@ -885,7 +899,7 @@ static void shader_sm1_read_src_param(struct vkd3d_shader_sm1_parser *sm1, const - shader_sm1_read_param(sm1, ptr, &token, &addr_token); - if (has_relative_address(token)) - { -- if (!(src_rel_addr = shader_parser_get_src_params(&sm1->p, 1))) -+ if (!(src_rel_addr = vsir_program_get_src_params(&sm1->p.program, 1))) - { - vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, - "Out of memory."); -@@ -906,7 +920,7 @@ static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const - shader_sm1_read_param(sm1, ptr, &token, &addr_token); - if (has_relative_address(token)) - { -- if (!(dst_rel_addr = shader_parser_get_src_params(&sm1->p, 1))) -+ if (!(dst_rel_addr = vsir_program_get_src_params(&sm1->p.program, 1))) - { - vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, - "Out of memory."); -@@ -987,7 +1001,7 @@ static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const - src_param->reg.idx[2].rel_addr = NULL; - src_param->reg.idx_count = 0; - src_param->reg.dimension = dimension; -- memcpy(src_param->reg.u.immconst_uint, *ptr, count * sizeof(uint32_t)); -+ memcpy(src_param->reg.u.immconst_u32, *ptr, count * sizeof(uint32_t)); - src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE; - src_param->modifiers = 0; - -@@ -1063,18 +1077,19 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, - } - } - --static unsigned int mask_from_swizzle(unsigned int swizzle) -+static unsigned int mask_from_swizzle(uint32_t swizzle) - { -- return (1u << vkd3d_swizzle_get_component(swizzle, 0)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 1)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 2)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 3)); -+ return (1u << vsir_swizzle_get_component(swizzle, 0)) -+ | (1u << vsir_swizzle_get_component(swizzle, 1)) -+ | (1u << vsir_swizzle_get_component(swizzle, 2)) -+ | (1u << vsir_swizzle_get_component(swizzle, 3)); - } - - static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins) - { - struct vkd3d_shader_src_param *src_params, *predicate; - const struct vkd3d_sm1_opcode_info *opcode_info; -+ struct vsir_program *program = &sm1->p.program; - struct vkd3d_shader_dst_param *dst_param; - const uint32_t **ptr = &sm1->ptr; - uint32_t opcode_token; -@@ -1097,7 +1112,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str - vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, - "Invalid opcode %#x (token 0x%08x, shader version %u.%u).", - opcode_token & VKD3D_SM1_OPCODE_MASK, opcode_token, -- sm1->p.shader_version.major, sm1->p.shader_version.minor); -+ program->shader_version.major, program->shader_version.minor); - goto fail; - } - -@@ -1107,11 +1122,11 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str - ins->raw = false; - ins->structured = false; - predicated = !!(opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED); -- ins->predicate = predicate = predicated ? shader_parser_get_src_params(&sm1->p, 1) : NULL; -+ ins->predicate = predicate = predicated ? vsir_program_get_src_params(program, 1) : NULL; - ins->dst_count = opcode_info->dst_count; -- ins->dst = dst_param = shader_parser_get_dst_params(&sm1->p, ins->dst_count); -+ ins->dst = dst_param = vsir_program_get_dst_params(program, ins->dst_count); - ins->src_count = opcode_info->src_count; -- ins->src = src_params = shader_parser_get_src_params(&sm1->p, ins->src_count); -+ ins->src = src_params = vsir_program_get_src_params(program, ins->src_count); - if ((!predicate && predicated) || (!src_params && ins->src_count) || (!dst_param && ins->dst_count)) - { - vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory."); -@@ -1322,7 +1337,7 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi - return ret; - } - -- instructions = &sm1->p.instructions; -+ instructions = &sm1->p.program.instructions; - while (!shader_sm1_is_end(sm1)) - { - if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) -@@ -1348,18 +1363,21 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi - sm1->p.shader_desc.flat_constant_count[i].external = get_external_constant_count(sm1, i); - - if (!sm1->p.failed) -- vsir_validate(&sm1->p); -+ ret = vsir_validate(&sm1->p); -+ -+ if (sm1->p.failed && ret >= 0) -+ ret = VKD3D_ERROR_INVALID_SHADER; - -- if (sm1->p.failed) -+ if (ret < 0) - { - WARN("Failed to parse shader.\n"); - shader_sm1_destroy(&sm1->p); -- return VKD3D_ERROR_INVALID_SHADER; -+ return ret; - } - - *parser = &sm1->p; - -- return VKD3D_OK; -+ return ret; - } - - bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, -@@ -1374,7 +1392,7 @@ bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem - enum vkd3d_shader_type shader_type; - unsigned int major_version; - D3DSHADER_PARAM_REGISTER_TYPE type; -- DWORD offset; -+ unsigned int offset; - } - register_table[] = - { -@@ -2253,7 +2271,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b - { - struct hlsl_reg *reg = &jump->condition.node->reg; - -- struct sm1_instruction instr = -+ struct sm1_instruction sm1_instr = - { - .opcode = D3DSIO_TEXKILL, - -@@ -2263,7 +2281,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b - .has_dst = 1, - }; - -- write_sm1_instruction(ctx, buffer, &instr); -+ write_sm1_instruction(ctx, buffer, &sm1_instr); - break; - } - -@@ -2328,8 +2346,6 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_ - - sm1_instr = (struct sm1_instruction) - { -- .opcode = D3DSIO_TEX, -- - .dst.type = D3DSPR_TEMP, - .dst.reg = instr->reg.id, - .dst.writemask = instr->reg.writemask, -@@ -2345,8 +2361,22 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_ - - .src_count = 2, - }; -- if (load->load_type == HLSL_RESOURCE_SAMPLE_PROJ) -- sm1_instr.opcode |= VKD3DSI_TEXLD_PROJECT << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT; -+ -+ switch (load->load_type) -+ { -+ case HLSL_RESOURCE_SAMPLE: -+ sm1_instr.opcode = D3DSIO_TEX; -+ break; -+ -+ case HLSL_RESOURCE_SAMPLE_PROJ: -+ sm1_instr.opcode = D3DSIO_TEX; -+ sm1_instr.opcode |= VKD3DSI_TEXLD_PROJECT << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT; -+ break; -+ -+ default: -+ hlsl_fixme(ctx, &instr->loc, "Resource load type %u\n", load->load_type); -+ return; -+ } - - assert(instr->reg.allocated); - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -index 7834c1e1615..37ebc73c099 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -@@ -130,13 +130,13 @@ static void skip_dword_unknown(const char **ptr, unsigned int count) - } - } - --static const char *shader_get_string(const char *data, size_t data_size, DWORD offset) -+static const char *shader_get_string(const char *data, size_t data_size, size_t offset) - { - size_t len, max_len; - - if (offset >= data_size) - { -- WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size); -+ WARN("Invalid offset %#zx (data size %#zx).\n", offset, data_size); - return NULL; - } - -@@ -230,7 +230,7 @@ static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_ - chunk_offset = read_u32(&ptr); - TRACE("chunk %u at offset %#x\n", i, chunk_offset); - -- if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(DWORD), data_size)) -+ if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(uint32_t), data_size)) - { - WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size); - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET, -@@ -399,7 +399,8 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - - for (i = 0; i < count; ++i) - { -- uint32_t name_offset, mask; -+ size_t name_offset; -+ uint32_t mask; - - e[i].sort_index = i; - -@@ -411,7 +412,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - name_offset = read_u32(&ptr); - if (!(e[i].semantic_name = shader_get_string(data, section->data.size, name_offset))) - { -- WARN("Invalid name offset %#x (data size %#zx).\n", name_offset, section->data.size); -+ WARN("Invalid name offset %#zx (data size %#zx).\n", name_offset, section->data.size); - vkd3d_free(e); - return VKD3D_ERROR_INVALID_ARGUMENT; - } -@@ -431,10 +432,6 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - case TAG_OSG5: - if (e[i].sysval_semantic == VKD3D_SHADER_SV_NONE) - e[i].sysval_semantic = map_fragment_output_sysval(e[i].semantic_name); -- /* Fall through. */ -- case TAG_PCSG: -- case TAG_PSG1: -- e[i].used_mask = e[i].mask & ~e[i].used_mask; - break; - } - -@@ -596,7 +593,7 @@ static int shader_parse_descriptor_ranges(struct root_signature_parser_context * - const char *ptr; - unsigned int i; - -- if (!require_space(offset, 5 * count, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 5 * count, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -627,7 +624,8 @@ static void shader_validate_descriptor_range1(const struct vkd3d_shader_descript - | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE - | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE - | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE -- | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC); -+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC -+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS); - - if (unknown_flags) - FIXME("Unknown descriptor range flags %#x.\n", unknown_flags); -@@ -674,7 +672,7 @@ static int shader_parse_descriptor_table(struct root_signature_parser_context *c - unsigned int count; - const char *ptr; - -- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -701,7 +699,7 @@ static int shader_parse_descriptor_table1(struct root_signature_parser_context * - unsigned int count; - const char *ptr; - -- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -726,7 +724,7 @@ static int shader_parse_root_constants(struct root_signature_parser_context *con - { - const char *ptr; - -- if (!require_space(offset, 3, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 3, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -748,7 +746,7 @@ static int shader_parse_root_descriptor(struct root_signature_parser_context *co - { - const char *ptr; - -- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -780,7 +778,7 @@ static int shader_parse_root_descriptor1(struct root_signature_parser_context *c - { - const char *ptr; - -- if (!require_space(offset, 3, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 3, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -806,7 +804,7 @@ static int shader_parse_root_parameters(struct root_signature_parser_context *co - unsigned int i; - int ret; - -- if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 3 * count, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -848,13 +846,13 @@ static int shader_parse_root_parameters(struct root_signature_parser_context *co - } - - static int shader_parse_root_parameters1(struct root_signature_parser_context *context, -- uint32_t offset, DWORD count, struct vkd3d_shader_root_parameter1 *parameters) -+ uint32_t offset, unsigned int count, struct vkd3d_shader_root_parameter1 *parameters) - { - const char *ptr; - unsigned int i; - int ret; - -- if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 3 * count, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -901,7 +899,7 @@ static int shader_parse_static_samplers(struct root_signature_parser_context *co - const char *ptr; - unsigned int i; - -- if (!require_space(offset, 13 * count, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 13 * count, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); - return VKD3D_ERROR_INVALID_ARGUMENT; -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index beb9ae574dc..a001f6f0642 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -29,10 +29,18 @@ static const uint64_t MAX_ALIGNMENT_EXPONENT = 29; - static const uint64_t GLOBALVAR_FLAG_IS_CONSTANT = 1; - static const uint64_t GLOBALVAR_FLAG_EXPLICIT_TYPE = 2; - static const unsigned int GLOBALVAR_ADDRESS_SPACE_SHIFT = 2; -+static const uint64_t ALLOCA_FLAG_IN_ALLOCA = 0x20; -+static const uint64_t ALLOCA_FLAG_EXPLICIT_TYPE = 0x40; -+static const uint64_t ALLOCA_ALIGNMENT_MASK = ALLOCA_FLAG_IN_ALLOCA - 1; - static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4; -+static const size_t MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION = 5; - - static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; - -+#define VKD3D_SHADER_SWIZZLE_64_MASK \ -+ (VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ -+ | VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(1)) -+ - enum bitcode_block_id - { - BLOCKINFO_BLOCK = 0, -@@ -168,6 +176,35 @@ enum bitcode_linkage - LINKAGE_INTERNAL = 3, - }; - -+enum dxil_resource_kind -+{ -+ RESOURCE_KIND_INVALID = 0, -+ RESOURCE_KIND_TEXTURE1D = 1, -+ RESOURCE_KIND_TEXTURE2D = 2, -+ RESOURCE_KIND_TEXTURE2DMS = 3, -+ RESOURCE_KIND_TEXTURE3D = 4, -+ RESOURCE_KIND_TEXTURECUBE = 5, -+ RESOURCE_KIND_TEXTURE1DARRAY = 6, -+ RESOURCE_KIND_TEXTURE2DARRAY = 7, -+ RESOURCE_KIND_TEXTURE2DMSARRAY = 8, -+ RESOURCE_KIND_TEXTURECUBEARRAY = 9, -+ RESOURCE_KIND_TYPEDBUFFER = 10, -+ RESOURCE_KIND_RAWBUFFER = 11, -+ RESOURCE_KIND_STRUCTUREDBUFFER = 12, -+ RESOURCE_KIND_CBUFFER = 13, -+ RESOURCE_KIND_SAMPLER = 14, -+ RESOURCE_KIND_TBUFFER = 15, -+ RESOURCE_KIND_RTACCELERATIONSTRUCTURE = 16, -+ RESOURCE_KIND_FEEDBACKTEXTURE2D = 17, -+ RESOURCE_KIND_FEEDBACKTEXTURE2DARRAY = 18, -+}; -+ -+enum dxil_resource_type -+{ -+ RESOURCE_TYPE_NON_RAW_STRUCTURED = 0, -+ RESOURCE_TYPE_RAW_STRUCTURED = 1, -+}; -+ - enum dxil_component_type - { - COMPONENT_TYPE_INVALID = 0, -@@ -296,8 +333,53 @@ enum dx_intrinsic_opcode - { - DX_LOAD_INPUT = 4, - DX_STORE_OUTPUT = 5, -+ DX_ISNAN = 8, -+ DX_ISINF = 9, -+ DX_ISFINITE = 10, -+ DX_COS = 12, -+ DX_SIN = 13, -+ DX_TAN = 14, -+ DX_ACOS = 15, -+ DX_ASIN = 16, -+ DX_ATAN = 17, -+ DX_HCOS = 18, -+ DX_HSIN = 19, -+ DX_HTAN = 20, -+ DX_EXP = 21, -+ DX_FRC = 22, -+ DX_LOG = 23, -+ DX_SQRT = 24, -+ DX_RSQRT = 25, -+ DX_ROUND_NE = 26, -+ DX_ROUND_NI = 27, -+ DX_ROUND_PI = 28, -+ DX_ROUND_Z = 29, -+ DX_BFREV = 30, -+ DX_COUNT_BITS = 31, -+ DX_FIRST_BIT_LO = 32, -+ DX_FIRST_BIT_HI = 33, -+ DX_FIRST_BIT_SHI = 34, -+ DX_FMAX = 35, -+ DX_FMIN = 36, -+ DX_IMAX = 37, -+ DX_IMIN = 38, -+ DX_UMAX = 39, -+ DX_UMIN = 40, -+ DX_IBFE = 51, -+ DX_UBFE = 52, - DX_CREATE_HANDLE = 57, - DX_CBUFFER_LOAD_LEGACY = 59, -+ DX_TEXTURE_LOAD = 66, -+ DX_TEXTURE_STORE = 67, -+ DX_BUFFER_LOAD = 68, -+ DX_DERIV_COARSEX = 83, -+ DX_DERIV_COARSEY = 84, -+ DX_DERIV_FINEX = 85, -+ DX_DERIV_FINEY = 86, -+ DX_SPLIT_DOUBLE = 102, -+ DX_LEGACY_F32TOF16 = 130, -+ DX_LEGACY_F16TOF32 = 131, -+ DX_RAW_BUFFER_LOAD = 139, - }; - - enum dxil_cast_code -@@ -439,6 +521,7 @@ struct dxil_record - { - unsigned int code; - unsigned int operand_count; -+ const struct dxil_record *attachment; - uint64_t operands[]; - }; - -@@ -448,18 +531,67 @@ struct sm6_symbol - const char *name; - }; - -+struct incoming_value -+{ -+ const struct sm6_block *block; -+ struct vkd3d_shader_register reg; -+}; -+ -+struct sm6_phi -+{ -+ struct vkd3d_shader_register reg; -+ struct incoming_value *incoming; -+ size_t incoming_capacity; -+ size_t incoming_count; -+}; -+ -+enum sm6_block_terminator_type -+{ -+ TERMINATOR_UNCOND_BR, -+ TERMINATOR_COND_BR, -+ TERMINATOR_SWITCH, -+ TERMINATOR_RET, -+}; -+ -+struct terminator_case -+{ -+ const struct sm6_block *block; -+ uint64_t value; -+ bool is_default; -+}; -+ -+struct sm6_block_terminator -+{ -+ struct vkd3d_shader_register conditional_reg; -+ enum sm6_block_terminator_type type; -+ const struct sm6_block *true_block; -+ const struct sm6_block *false_block; -+ struct terminator_case *cases; -+ unsigned int case_count; -+}; -+ - struct sm6_block - { - struct vkd3d_shader_instruction *instructions; - size_t instruction_capacity; - size_t instruction_count; -+ -+ /* A nonzero id. */ -+ unsigned int id; -+ -+ struct sm6_phi *phi; -+ size_t phi_capacity; -+ size_t phi_count; -+ -+ struct sm6_block_terminator terminator; - }; - - struct sm6_function - { - const struct sm6_value *declaration; - -- struct sm6_block *blocks[1]; -+ struct sm6_block **blocks; -+ size_t block_capacity; - size_t block_count; - - size_t value_count; -@@ -541,6 +673,11 @@ struct sm6_descriptor_info - enum vkd3d_shader_descriptor_type type; - unsigned int id; - struct vkd3d_shader_register_range range; -+ enum vkd3d_shader_resource_type resource_type; -+ enum dxil_resource_kind kind; -+ enum vkd3d_data_type resource_data_type; -+ enum vkd3d_shader_register_type reg_type; -+ enum vkd3d_data_type reg_data_type; - }; - - struct sm6_parser -@@ -581,6 +718,7 @@ struct sm6_parser - size_t descriptor_count; - - unsigned int indexable_temp_count; -+ unsigned int icb_count; - - struct sm6_value *values; - size_t value_count; -@@ -796,6 +934,7 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6) - - record->code = code; - record->operand_count = count; -+ record->attachment = NULL; - - for (i = 0; i < count; ++i) - record->operands[i] = sm6_parser_read_vbr(sm6, 6); -@@ -1012,6 +1151,7 @@ static enum vkd3d_result sm6_parser_read_abbrev_record(struct sm6_parser *sm6, u - if (!abbrev->operands[i + 1].read_operand(sm6, abbrev->operands[i + 1].context, &record->operands[i])) - goto fail; - record->operand_count = count; -+ record->attachment = NULL; - - /* An array can occur only as the last operand. */ - if (abbrev->is_array) -@@ -1210,7 +1350,7 @@ static size_t dxil_block_compute_module_decl_count(const struct dxil_block *bloc - size_t i, count; - - for (i = 0, count = 0; i < block->record_count; ++i) -- count += block->records[i]->code == MODULE_CODE_FUNCTION; -+ count += block->records[i]->code == MODULE_CODE_FUNCTION || block->records[i]->code == MODULE_CODE_GLOBALVAR; - return count; - } - -@@ -1517,7 +1657,7 @@ static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6) - break; - } - -- if (!ascii_strcasecmp(struct_name, "dx.types.Handle")) -+ if (!strcmp(struct_name, "dx.types.Handle")) - sm6->handle_type = type; - - type->u.struc->name = struct_name; -@@ -1572,6 +1712,11 @@ static bool sm6_type_is_bool_i16_i32_i64(const struct sm6_type *type) - return type->class == TYPE_CLASS_INTEGER && (type->u.width == 1 || type->u.width >= 16); - } - -+static bool sm6_type_is_i16_i32_i64(const struct sm6_type *type) -+{ -+ return type->class == TYPE_CLASS_INTEGER && type->u.width >= 16; -+} -+ - static bool sm6_type_is_bool(const struct sm6_type *type) - { - return type->class == TYPE_CLASS_INTEGER && type->u.width == 1; -@@ -1587,6 +1732,21 @@ static inline bool sm6_type_is_i32(const struct sm6_type *type) - return type->class == TYPE_CLASS_INTEGER && type->u.width == 32; - } - -+static bool sm6_type_is_float(const struct sm6_type *type) -+{ -+ return type->class == TYPE_CLASS_FLOAT && type->u.width == 32; -+} -+ -+static bool sm6_type_is_f16_f32(const struct sm6_type *type) -+{ -+ return type->class == TYPE_CLASS_FLOAT && (type->u.width == 16 || type->u.width == 32); -+} -+ -+static bool sm6_type_is_double(const struct sm6_type *type) -+{ -+ return type->class == TYPE_CLASS_FLOAT && type->u.width == 64; -+} -+ - static inline bool sm6_type_is_floating_point(const struct sm6_type *type) - { - return type->class == TYPE_CLASS_FLOAT; -@@ -1844,12 +2004,12 @@ static unsigned int register_get_uint_value(const struct vkd3d_shader_register * - - if (reg->type == VKD3DSPR_IMMCONST64) - { -- if (reg->u.immconst_uint64[0] > UINT_MAX) -+ if (reg->u.immconst_u64[0] > UINT_MAX) - FIXME("Truncating 64-bit value.\n"); -- return reg->u.immconst_uint64[0]; -+ return reg->u.immconst_u64[0]; - } - -- return reg->u.immconst_uint[0]; -+ return reg->u.immconst_u32[0]; - } - - static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg) -@@ -1860,7 +2020,7 @@ static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *re - if (reg->dimension == VSIR_DIMENSION_VEC4) - WARN("Returning vec4.x.\n"); - -- return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_uint64[0] : reg->u.immconst_uint[0]; -+ return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_u64[0] : reg->u.immconst_u32[0]; - } - - static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) -@@ -1895,6 +2055,12 @@ static inline bool sm6_value_is_constant(const struct sm6_value *value) - return sm6_value_is_register(value) && register_is_constant(&value->u.reg); - } - -+static bool sm6_value_is_constant_zero(const struct sm6_value *value) -+{ -+ /* Constant vectors do not occur. */ -+ return sm6_value_is_register(value) && register_is_scalar_constant_zero(&value->u.reg); -+} -+ - static inline bool sm6_value_is_undef(const struct sm6_value *value) - { - return sm6_value_is_register(value) && value->u.reg.type == VKD3DSPR_UNDEF; -@@ -1905,6 +2071,11 @@ static bool sm6_value_is_icb(const struct sm6_value *value) - return value->value_type == VALUE_TYPE_ICB; - } - -+static bool sm6_value_is_ssa(const struct sm6_value *value) -+{ -+ return sm6_value_is_register(value) && register_is_ssa(&value->u.reg); -+} -+ - static inline unsigned int sm6_value_get_constant_uint(const struct sm6_value *value) - { - if (!sm6_value_is_constant(value)) -@@ -1912,16 +2083,33 @@ static inline unsigned int sm6_value_get_constant_uint(const struct sm6_value *v - return register_get_uint_value(&value->u.reg); - } - -+static uint64_t sm6_value_get_constant_uint64(const struct sm6_value *value) -+{ -+ if (!sm6_value_is_constant(value)) -+ return UINT64_MAX; -+ return register_get_uint64_value(&value->u.reg); -+} -+ - static unsigned int sm6_parser_alloc_ssa_id(struct sm6_parser *sm6) - { - return sm6->ssa_next_id++; - } - -+static void instruction_init_with_resource(struct vkd3d_shader_instruction *ins, -+ enum vkd3d_shader_opcode handler_idx, const struct sm6_value *resource, struct sm6_parser *sm6) -+{ -+ vsir_instruction_init(ins, &sm6->p.location, handler_idx); -+ ins->resource_type = resource->u.handle.d->resource_type; -+ ins->raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; -+ ins->structured = resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER; -+} -+ - static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_shader_instruction *ins, - unsigned int count, struct sm6_parser *sm6) - { -- struct vkd3d_shader_src_param *params = shader_parser_get_src_params(&sm6->p, count); -- if (!params) -+ struct vkd3d_shader_src_param *params; -+ -+ if (!(params = vsir_program_get_src_params(&sm6->p.program, count))) - { - ERR("Failed to allocate src params.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -@@ -1936,8 +2124,9 @@ static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_ - static struct vkd3d_shader_dst_param *instruction_dst_params_alloc(struct vkd3d_shader_instruction *ins, - unsigned int count, struct sm6_parser *sm6) - { -- struct vkd3d_shader_dst_param *params = shader_parser_get_dst_params(&sm6->p, count); -- if (!params) -+ struct vkd3d_shader_dst_param *params; -+ -+ if (!(params = vsir_program_get_dst_params(&sm6->p.program, count))) - { - ERR("Failed to allocate dst params.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -@@ -1994,21 +2183,29 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type - } - - static void register_init_ssa_vector(struct vkd3d_shader_register *reg, const struct sm6_type *type, -- unsigned int component_count, struct sm6_parser *sm6) -+ unsigned int component_count, struct sm6_value *value, struct sm6_parser *sm6) - { - enum vkd3d_data_type data_type; - unsigned int id; - -- id = sm6_parser_alloc_ssa_id(sm6); -+ if (value && register_is_ssa(&value->u.reg) && value->u.reg.idx[0].offset) -+ { -+ id = value->u.reg.idx[0].offset; -+ TRACE("Using forward-allocated id %u.\n", id); -+ } -+ else -+ { -+ id = sm6_parser_alloc_ssa_id(sm6); -+ } - data_type = vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(type, 0)); - register_init_with_id(reg, VKD3DSPR_SSA, data_type, id); - reg->dimension = component_count > 1 ? VSIR_DIMENSION_VEC4 : VSIR_DIMENSION_SCALAR; - } - - static void register_init_ssa_scalar(struct vkd3d_shader_register *reg, const struct sm6_type *type, -- struct sm6_parser *sm6) -+ struct sm6_value *value, struct sm6_parser *sm6) - { -- register_init_ssa_vector(reg, type, 1, sm6); -+ register_init_ssa_vector(reg, sm6_type_get_scalar_type(type, 0), 1, value, sm6); - } - - static void dst_param_init(struct vkd3d_shader_dst_param *param) -@@ -2018,6 +2215,13 @@ static void dst_param_init(struct vkd3d_shader_dst_param *param) - param->shift = 0; - } - -+static void dst_param_init_with_mask(struct vkd3d_shader_dst_param *param, unsigned int mask) -+{ -+ param->write_mask = mask; -+ param->modifiers = 0; -+ param->shift = 0; -+} -+ - static inline void dst_param_init_scalar(struct vkd3d_shader_dst_param *param, unsigned int component_idx) - { - param->write_mask = 1u << component_idx; -@@ -2033,10 +2237,10 @@ static void dst_param_init_vector(struct vkd3d_shader_dst_param *param, unsigned - } - - static void dst_param_init_ssa_scalar(struct vkd3d_shader_dst_param *param, const struct sm6_type *type, -- struct sm6_parser *sm6) -+ struct sm6_value *value, struct sm6_parser *sm6) - { - dst_param_init(param); -- register_init_ssa_scalar(¶m->reg, type, sm6); -+ register_init_ssa_scalar(¶m->reg, type, value, sm6); - } - - static inline void src_param_init(struct vkd3d_shader_src_param *param) -@@ -2048,6 +2252,8 @@ static inline void src_param_init(struct vkd3d_shader_src_param *param) - static void src_param_init_scalar(struct vkd3d_shader_src_param *param, unsigned int component_idx) - { - param->swizzle = vkd3d_shader_create_swizzle(component_idx, component_idx, component_idx, component_idx); -+ if (data_type_is_64_bit(param->reg.data_type)) -+ param->swizzle &= VKD3D_SHADER_SWIZZLE_64_MASK; - param->modifiers = VKD3DSPSM_NONE; - } - -@@ -2078,7 +2284,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, - } - else - { -- struct vkd3d_shader_src_param *rel_addr = shader_parser_get_src_params(&sm6->p, 1); -+ struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(&sm6->p.program, 1); - if (rel_addr) - src_param_init_from_value(rel_addr, address); - idx->offset = 0; -@@ -2091,7 +2297,7 @@ static void instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio - struct vkd3d_shader_dst_param *param = instruction_dst_params_alloc(ins, 1, sm6); - struct sm6_value *dst = sm6_parser_get_current_value(sm6); - -- dst_param_init_ssa_scalar(param, dst->type, sm6); -+ dst_param_init_ssa_scalar(param, dst->type, dst, sm6); - param->write_mask = VKD3DSP_WRITEMASK_0; - dst->u.reg = param->reg; - } -@@ -2103,7 +2309,7 @@ static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instructio - struct sm6_value *dst = sm6_parser_get_current_value(sm6); - - dst_param_init_vector(param, component_count); -- register_init_ssa_vector(¶m->reg, sm6_type_get_scalar_type(dst->type, 0), component_count, sm6); -+ register_init_ssa_vector(¶m->reg, sm6_type_get_scalar_type(dst->type, 0), component_count, dst, sm6); - dst->u.reg = param->reg; - } - -@@ -2195,6 +2401,26 @@ static bool sm6_value_validate_is_handle(const struct sm6_value *value, struct s - return true; - } - -+static bool sm6_value_validate_is_texture_handle(const struct sm6_value *value, enum dx_intrinsic_opcode op, -+ struct sm6_parser *sm6) -+{ -+ enum dxil_resource_kind kind; -+ -+ if (!sm6_value_validate_is_handle(value, sm6)) -+ return false; -+ -+ kind = value->u.handle.d->kind; -+ if (kind < RESOURCE_KIND_TEXTURE1D || kind > RESOURCE_KIND_TEXTURECUBEARRAY) -+ { -+ WARN("Resource kind %u for op %u is not a texture.\n", kind, op); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE, -+ "Resource kind %u for texture operation %u is not a texture.", kind, op); -+ return false; -+ } -+ -+ return true; -+} -+ - static bool sm6_value_validate_is_pointer(const struct sm6_value *value, struct sm6_parser *sm6) - { - if (!sm6_type_is_pointer(value->type)) -@@ -2246,6 +2472,7 @@ static const struct sm6_value *sm6_parser_get_value_safe(struct sm6_parser *sm6, - static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const struct dxil_record *record, - const struct sm6_type *fwd_type, unsigned int *rec_idx) - { -+ struct sm6_value *value; - unsigned int idx; - uint64_t val_ref; - size_t operand; -@@ -2259,23 +2486,39 @@ static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const stru - if (operand == SIZE_MAX) - return SIZE_MAX; - -- if (operand >= sm6->value_count) -+ if (operand >= sm6->value_count && !fwd_type) -+ { -+ /* Forward references are followed by a type id unless an earlier operand set the type, -+ * or it is contained in a function declaration. */ -+ if (!dxil_record_validate_operand_min_count(record, idx + 1, sm6)) -+ return SIZE_MAX; -+ if (!(fwd_type = sm6_parser_get_type(sm6, record->operands[idx++]))) -+ return SIZE_MAX; -+ } -+ *rec_idx = idx; -+ -+ if (fwd_type) - { -- if (!fwd_type) -+ value = &sm6->values[operand]; -+ if (value->type) - { -- /* Forward references are followed by a type id unless an earlier operand set the type, -- * or it is contained in a function declaration. */ -- if (!dxil_record_validate_operand_min_count(record, idx + 1, sm6)) -- return SIZE_MAX; -- if (!(fwd_type = sm6_parser_get_type(sm6, record->operands[idx++]))) -- return SIZE_MAX; -+ if (value->type != fwd_type) -+ { -+ WARN("Value already has a mismatching type.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "The type of a source value does not match the predefined type."); -+ } -+ } -+ else -+ { -+ value->type = fwd_type; -+ value->value_type = VALUE_TYPE_REG; -+ register_init_with_id(&value->u.reg, VKD3DSPR_SSA, vkd3d_data_type_from_sm6_type( -+ sm6_type_get_scalar_type(fwd_type, 0)), sm6_parser_alloc_ssa_id(sm6)); -+ value->u.reg.dimension = sm6_type_is_scalar(fwd_type) ? VSIR_DIMENSION_SCALAR -+ : VSIR_DIMENSION_VEC4; - } -- FIXME("Forward value references are not supported yet.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Unsupported value forward reference."); -- return SIZE_MAX; - } -- *rec_idx = idx; - - return operand; - } -@@ -2289,8 +2532,8 @@ static const struct sm6_value *sm6_parser_get_value_by_ref(struct sm6_parser *sm - - static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxil_record *record) - { -+ const struct sm6_type *type, *ret_type; - const unsigned int max_count = 15; -- const struct sm6_type *ret_type; - struct sm6_value *fn; - unsigned int i, j; - -@@ -2305,18 +2548,18 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi - fn->u.function.name = ""; - } - -- if (!(fn->type = sm6_parser_get_type(sm6, record->operands[0]))) -+ if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) - return false; -- if (!sm6_type_is_function(fn->type)) -+ if (!sm6_type_is_function(type)) - { - WARN("Type is not a function.\n"); - return false; - } -- ret_type = fn->type->u.function->ret_type; -+ ret_type = type->u.function->ret_type; - -- if (!(fn->type = sm6_type_get_pointer_to_type(fn->type, ADDRESS_SPACE_DEFAULT, sm6))) -+ if (!(fn->type = sm6_type_get_pointer_to_type(type, ADDRESS_SPACE_DEFAULT, sm6))) - { -- WARN("Failed to get pointer type for type %u.\n", fn->type->class); -+ WARN("Failed to get pointer type for type %u.\n", type->class); - return false; - } - -@@ -2412,7 +2655,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - return VKD3D_ERROR_INVALID_SHADER; - } - size = max(size, sizeof(icb->data[0])); -- count = type->u.array.count * size / sizeof(icb->data[0]); -+ count = operands ? type->u.array.count * size / sizeof(icb->data[0]) : 0; - - if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count])))) - { -@@ -2421,7 +2664,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - "Out of memory allocating an immediate constant buffer of count %u.", count); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -- if (!shader_instruction_array_add_icb(&sm6->p.instructions, icb)) -+ if (!shader_instruction_array_add_icb(&sm6->p.program.instructions, icb)) - { - ERR("Failed to store icb object.\n"); - vkd3d_free(icb); -@@ -2433,9 +2676,14 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - dst->value_type = VALUE_TYPE_ICB; - dst->u.icb = icb; - -+ icb->register_idx = sm6->icb_count++; - icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); - icb->element_count = type->u.array.count; - icb->component_count = 1; -+ icb->is_null = !operands; -+ -+ if (!operands) -+ return VKD3D_OK; - - count = type->u.array.count; - if (size > sizeof(icb->data[0])) -@@ -2510,12 +2758,10 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - switch (record->code) - { - case CST_CODE_NULL: -- if (sm6_type_is_array(type)) -+ if (sm6_type_is_array(type) -+ && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) - { -- FIXME("Constant null arrays are not supported.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Constant null arrays are not supported."); -- return VKD3D_ERROR_INVALID_SHADER; -+ return ret; - } - /* For non-aggregates, register constant data is already zero-filled. */ - break; -@@ -2532,9 +2778,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - - value = decode_rotated_signed_value(record->operands[0]); - if (type->u.width <= 32) -- dst->u.reg.u.immconst_uint[0] = value & ((1ull << type->u.width) - 1); -+ dst->u.reg.u.immconst_u32[0] = value & ((1ull << type->u.width) - 1); - else -- dst->u.reg.u.immconst_uint64[0] = value; -+ dst->u.reg.u.immconst_u64[0] = value; - - break; - -@@ -2551,9 +2797,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - if (type->u.width == 16) - FIXME("Half float type is not supported yet.\n"); - else if (type->u.width == 32) -- dst->u.reg.u.immconst_float[0] = bitcast_uint64_to_float(record->operands[0]); -+ dst->u.reg.u.immconst_f32[0] = bitcast_uint64_to_float(record->operands[0]); - else if (type->u.width == 64) -- dst->u.reg.u.immconst_double[0] = bitcast_uint64_to_double(record->operands[0]); -+ dst->u.reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]); - else - vkd3d_unreachable(); - -@@ -2588,6 +2834,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - break; - } - -+ if (record->attachment) -+ { -+ WARN("Ignoring metadata attachment.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata attachment for a constant."); -+ } -+ - ++sm6->value_count; - } - -@@ -2607,12 +2860,12 @@ static bool bitcode_parse_alignment(uint64_t encoded_alignment, unsigned int *al - - static struct vkd3d_shader_instruction *sm6_parser_require_space(struct sm6_parser *sm6, size_t extra) - { -- if (!shader_instruction_array_reserve(&sm6->p.instructions, sm6->p.instructions.count + extra)) -+ if (!shader_instruction_array_reserve(&sm6->p.program.instructions, sm6->p.program.instructions.count + extra)) - { - ERR("Failed to allocate instruction.\n"); - return NULL; - } -- return &sm6->p.instructions.elements[sm6->p.instructions.count]; -+ return &sm6->p.program.instructions.elements[sm6->p.program.instructions.count]; - } - - /* Space should be reserved before calling this. It is intended to require no checking of the returned pointer. */ -@@ -2622,22 +2875,38 @@ 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); - vsir_instruction_init(ins, &sm6->p.location, handler_idx); -- ++sm6->p.instructions.count; -+ ++sm6->p.program.instructions.count; - return ins; - } - --static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, -- unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst) -+static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count, -+ unsigned int alignment, unsigned int init, struct sm6_value *dst) - { - enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); - struct vkd3d_shader_instruction *ins; - -- ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER); -+ /* The icb value index will be resolved later so forward references can be handled. */ -+ ins->declaration.icb = (void *)(intptr_t)init; -+ register_init_with_id(&dst->u.reg, VKD3DSPR_IMMCONSTBUFFER, data_type, init); -+} -+ -+static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, -+ unsigned int count, unsigned int alignment, bool has_function_scope, unsigned int init, -+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+{ -+ enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); -+ -+ if (ins) -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_DCL_INDEXABLE_TEMP); -+ else -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); - ins->declaration.indexable_temp.register_idx = sm6->indexable_temp_count++; - ins->declaration.indexable_temp.register_size = count; - ins->declaration.indexable_temp.alignment = alignment; - ins->declaration.indexable_temp.data_type = data_type; - ins->declaration.indexable_temp.component_count = 1; -+ ins->declaration.indexable_temp.has_function_scope = has_function_scope; - /* The initialiser value index will be resolved later so forward references can be handled. */ - ins->declaration.indexable_temp.initialiser = (void *)(uintptr_t)init; - -@@ -2762,7 +3031,10 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ - - if (address_space == ADDRESS_SPACE_DEFAULT) - { -- sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); -+ if (is_constant) -+ sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst); -+ else -+ sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, false, init, NULL, dst); - } - else if (address_space == ADDRESS_SPACE_GROUPSHARED) - { -@@ -2790,31 +3062,37 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init - - assert(index); - --index; -- if (!(value = sm6_parser_get_value_safe(sm6, index)) || !sm6_value_is_icb(value)) -+ if (!(value = sm6_parser_get_value_safe(sm6, index)) || (!sm6_value_is_icb(value) && !sm6_value_is_undef(value))) - { - WARN("Invalid initialiser index %zu.\n", index); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Global variable initialiser value index %zu is invalid.", index); - return NULL; - } -- else -+ else if (sm6_value_is_icb(value)) - { - return value->u.icb; - } -+ /* In VSIR, initialisation with undefined values of objects is implied, not explicit. */ -+ return NULL; - } - - static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) - { -+ size_t i, count, base_value_idx = sm6->value_count; - const struct dxil_block *block = &sm6->root_block; - struct vkd3d_shader_instruction *ins; - const struct dxil_record *record; - enum vkd3d_result ret; - uint64_t version; -- size_t i; - - sm6->p.location.line = block->id; - sm6->p.location.column = 0; - -+ for (i = 0, count = 0; i < block->record_count; ++i) -+ count += block->records[i]->code == MODULE_CODE_GLOBALVAR; -+ sm6_parser_require_space(sm6, count); -+ - for (i = 0; i < block->record_count; ++i) - { - sm6->p.location.column = i; -@@ -2860,14 +3138,29 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) - } - - /* Resolve initialiser forward references. */ -- for (i = 0; i < sm6->p.instructions.count; ++i) -+ for (i = 0; i < sm6->p.program.instructions.count; ++i) - { -- ins = &sm6->p.instructions.elements[i]; -+ ins = &sm6->p.program.instructions.elements[i]; - if (ins->handler_idx == VKD3DSIH_DCL_INDEXABLE_TEMP && ins->declaration.indexable_temp.initialiser) - { - ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser( - (uintptr_t)ins->declaration.indexable_temp.initialiser, sm6); - } -+ else if (ins->handler_idx == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER) -+ { -+ ins->declaration.icb = resolve_forward_initialiser((uintptr_t)ins->declaration.icb, sm6); -+ } -+ } -+ for (i = base_value_idx; i < sm6->value_count; ++i) -+ { -+ const struct vkd3d_shader_immediate_constant_buffer *icb; -+ struct sm6_value *value = &sm6->values[i]; -+ -+ if (!sm6_value_is_register(value) || value->u.reg.type != VKD3DSPR_IMMCONSTBUFFER) -+ continue; -+ -+ if ((icb = resolve_forward_initialiser(value->u.reg.idx[0].offset, sm6))) -+ value->u.reg.idx[0].offset = icb->register_idx; - } - - return VKD3D_OK; -@@ -2887,6 +3180,15 @@ static void dst_param_io_init(struct vkd3d_shader_dst_param *param, - param->reg.dimension = VSIR_DIMENSION_VEC4; - } - -+static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_params, -+ const struct sm6_value **operands, unsigned int count) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < count; ++i) -+ src_param_init_from_value(&src_params[i], operands[i]); -+} -+ - static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shader_signature *s, - enum vkd3d_shader_register_type reg_type, struct vkd3d_shader_dst_param *params) - { -@@ -2908,45 +3210,6 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade - } - } - --static void sm6_parser_emit_signature(struct sm6_parser *sm6, const struct shader_signature *s, -- enum vkd3d_shader_opcode handler_idx, enum vkd3d_shader_opcode siv_handler_idx, -- struct vkd3d_shader_dst_param *params) --{ -- struct vkd3d_shader_instruction *ins; -- struct vkd3d_shader_dst_param *param; -- const struct signature_element *e; -- unsigned int i; -- -- for (i = 0; i < s->element_count; ++i) -- { -- e = &s->elements[i]; -- -- /* Do not check e->used_mask because in some cases it is zero for used elements. -- * TODO: scan ahead for used I/O elements. */ -- -- if (e->sysval_semantic != VKD3D_SHADER_SV_NONE && e->sysval_semantic != VKD3D_SHADER_SV_TARGET) -- { -- ins = sm6_parser_add_instruction(sm6, siv_handler_idx); -- param = &ins->declaration.register_semantic.reg; -- ins->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic); -- } -- else -- { -- ins = sm6_parser_add_instruction(sm6, handler_idx); -- param = &ins->declaration.dst; -- } -- -- ins->flags = e->interpolation_mode; -- *param = params[i]; -- -- if (e->register_count > 1) -- { -- param->reg.idx[0].rel_addr = NULL; -- param->reg.idx[0].offset = e->register_count; -- } -- } --} -- - static void sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) - { - sm6_parser_init_signature(sm6, output_signature, VKD3DSPR_OUTPUT, sm6->output_params); -@@ -2957,19 +3220,6 @@ static void sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct - sm6_parser_init_signature(sm6, input_signature, VKD3DSPR_INPUT, sm6->input_params); - } - --static void sm6_parser_emit_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) --{ -- sm6_parser_emit_signature(sm6, output_signature, VKD3DSIH_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT_SIV, sm6->output_params); --} -- --static void sm6_parser_emit_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature) --{ -- sm6_parser_emit_signature(sm6, input_signature, -- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS : VKD3DSIH_DCL_INPUT, -- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS_SIV : VKD3DSIH_DCL_INPUT_SIV, -- sm6->input_params); --} -- - static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_parser *sm6) - { - size_t i, count = sm6->function_count; -@@ -2992,6 +3242,108 @@ static struct sm6_block *sm6_block_create() - return block; - } - -+static struct sm6_phi *sm6_block_phi_require_space(struct sm6_block *block, struct sm6_parser *sm6) -+{ -+ struct sm6_phi *phi; -+ -+ if (!vkd3d_array_reserve((void **)&block->phi, &block->phi_capacity, block->phi_count + 1, sizeof(*block->phi))) -+ { -+ ERR("Failed to allocate phi array.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory allocating a phi instruction."); -+ return NULL; -+ } -+ phi = &block->phi[block->phi_count++]; -+ -+ phi->incoming = NULL; -+ phi->incoming_capacity = 0; -+ phi->incoming_count = 0; -+ -+ return phi; -+} -+ -+struct function_emission_state -+{ -+ struct sm6_block *code_block; -+ struct vkd3d_shader_instruction *ins; -+ unsigned int temp_idx; -+}; -+ -+static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+{ -+ const struct sm6_type *type[2], *elem_type; -+ const struct sm6_value *size; -+ unsigned int i, alignment; -+ uint64_t packed_operands; -+ -+ if (!dxil_record_validate_operand_count(record, 4, 4, sm6)) -+ return; -+ -+ for (i = 0; i < 2; ++i) -+ { -+ if (!(type[i] = sm6_parser_get_type(sm6, record->operands[i]))) -+ return; -+ } -+ -+ packed_operands = record->operands[3]; -+ if (packed_operands & ALLOCA_FLAG_IN_ALLOCA) -+ WARN("Ignoring in_alloca flag.\n"); -+ if (!(packed_operands & ALLOCA_FLAG_EXPLICIT_TYPE)) -+ { -+ FIXME("Unhandled implicit type.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Implicit result type for ALLOCA instructions is not supported."); -+ return; -+ } -+ packed_operands &= ~(ALLOCA_FLAG_IN_ALLOCA | ALLOCA_FLAG_EXPLICIT_TYPE); -+ -+ if (!sm6_type_is_array(type[0]) || !sm6_type_is_numeric(elem_type = type[0]->u.array.elem_type)) -+ { -+ WARN("Type is not a numeric array.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Result type of an ALLOCA instruction is not a numeric array."); -+ return; -+ } -+ /* The second type operand is the type of the allocation size operand, in case it is a -+ * forward reference. We only support a constant size, so no forward ref support is needed. */ -+ if (!sm6_type_is_integer(type[1])) -+ { -+ WARN("Size operand type is not scalar integer.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "The type of the allocation size operand of an ALLOCA instruction is not scalar integer."); -+ return; -+ } -+ -+ if (!(dst->type = sm6_type_get_pointer_to_type(type[0], ADDRESS_SPACE_DEFAULT, sm6))) -+ { -+ WARN("Failed to get pointer type for type class %u.\n", type[0]->class); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, -+ "Module does not define a pointer type for an ALLOCA instruction."); -+ return; -+ } -+ -+ if (!(size = sm6_parser_get_value_safe(sm6, record->operands[2]))) -+ return; -+ /* A size of 1 means one instance of type[0], i.e. one array. */ -+ if (sm6_value_get_constant_uint(size) != 1) -+ { -+ FIXME("Allocation size is not 1.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "ALLOCA instruction allocation sizes other than 1 are not supported."); -+ return; -+ } -+ -+ if (!bitcode_parse_alignment(packed_operands & ALLOCA_ALIGNMENT_MASK, &alignment)) -+ WARN("Invalid alignment %"PRIu64".\n", packed_operands); -+ packed_operands &= ~ALLOCA_ALIGNMENT_MASK; -+ -+ if (packed_operands) -+ WARN("Ignoring flags %#"PRIx64".\n", packed_operands); -+ -+ sm6_parser_declare_indexable_temp(sm6, elem_type, type[0]->u.array.count, alignment, true, 0, ins, dst); -+} -+ - static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_type *type_a, - const struct sm6_type *type_b, struct sm6_parser *sm6) - { -@@ -3092,8 +3444,10 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - unsigned int i = 0; - - a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); -+ if (!a) -+ return; - b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); -- if (!a || !b) -+ if (!b) - return; - - if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) -@@ -3161,52 +3515,322 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - - dst_param_init(&dst_params[0]); - dst_param_init(&dst_params[1]); -- register_init_ssa_scalar(&dst_params[index].reg, a->type, sm6); -+ register_init_ssa_scalar(&dst_params[index].reg, a->type, dst, sm6); - vsir_register_init(&dst_params[index ^ 1].reg, VKD3DSPR_NULL, VKD3D_DATA_UNUSED, 0); - dst->u.reg = dst_params[index].reg; - } - else - { -+ if (handler_idx == VKD3DSIH_ISHL || handler_idx == VKD3DSIH_ISHR || handler_idx == VKD3DSIH_USHR) -+ { -+ /* DXC emits AND instructions where necessary to mask shift counts. Shift binops -+ * do not imply masking the shift as the TPF equivalents do. */ -+ ins->flags |= VKD3DSI_SHIFT_UNMASKED; -+ } - instruction_dst_param_init_ssa_scalar(ins, sm6); - } - } - --static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, struct sm6_block *code_block, -- enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) -+static const struct sm6_block *sm6_function_get_block(const struct sm6_function *function, uint64_t index, -+ struct sm6_parser *sm6) - { -- struct sm6_value *dst = sm6_parser_get_current_value(sm6); -- struct vkd3d_shader_src_param *src_param; -- const struct sm6_value *buffer; -- const struct sm6_type *type; -- -- buffer = operands[0]; -- if (!sm6_value_validate_is_handle(buffer, sm6)) -- return; -- -- vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); -- -- src_param = instruction_src_params_alloc(ins, 1, sm6); -- src_param_init_vector_from_reg(src_param, &buffer->u.handle.reg); -- register_index_address_init(&src_param->reg.idx[2], operands[1], sm6); -- assert(src_param->reg.idx_count == 3); -- -- type = sm6_type_get_scalar_type(dst->type, 0); -- assert(type); -- src_param->reg.data_type = vkd3d_data_type_from_sm6_type(type); -- -- instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6); -+ if (index >= function->block_count) -+ { -+ WARN("Invalid code block index %#"PRIx64".\n", index); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Invalid code block index %#"PRIx64" for a control flow instruction.", index); -+ return NULL; -+ } -+ return function->blocks[index]; - } - --static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_parser *sm6, -- enum vkd3d_shader_descriptor_type type, unsigned int id, const struct sm6_value *address) -+static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) - { -- const struct sm6_descriptor_info *d; -- unsigned int register_index; -- size_t i; -+ const struct sm6_value *value; -+ unsigned int i = 2; - -- for (i = 0; i < sm6->descriptor_count; ++i) -+ if (record->operand_count != 1 && record->operand_count < 3) - { -- d = &sm6->descriptors[i]; -+ WARN("Invalid operand count %u.\n", record->operand_count); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Invalid operand count %u for a branch instruction.", record->operand_count); -+ return; -+ } -+ -+ if (record->operand_count == 1) -+ { -+ code_block->terminator.type = TERMINATOR_UNCOND_BR; -+ code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); -+ } -+ else -+ { -+ if (!sm6->bool_type) -+ { -+ WARN("Bool type not found.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, -+ "Module does not define a boolean type for conditions."); -+ return; -+ } -+ if (!(value = sm6_parser_get_value_by_ref(sm6, record, sm6->bool_type, &i)) -+ || !sm6_value_validate_is_bool(value, sm6)) -+ return; -+ dxil_record_validate_operand_max_count(record, i, sm6); -+ -+ code_block->terminator.type = TERMINATOR_COND_BR; -+ code_block->terminator.conditional_reg = value->u.reg; -+ code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); -+ code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); -+ } -+ -+ ins->handler_idx = VKD3DSIH_NOP; -+} -+ -+static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, const struct vkd3d_shader_register **operand_regs, -+ unsigned int component_count, struct function_emission_state *state, struct vkd3d_shader_register *reg) -+{ -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_params; -+ struct vkd3d_shader_dst_param *dst_param; -+ bool all_constant = true; -+ unsigned int i; -+ -+ if (component_count == 1) -+ { -+ *reg = *operand_regs[0]; -+ return true; -+ } -+ -+ for (i = 0; i < component_count; ++i) -+ all_constant &= register_is_constant(operand_regs[i]); -+ -+ if (all_constant) -+ { -+ vsir_register_init(reg, VKD3DSPR_IMMCONST, operand_regs[0]->data_type, 0); -+ reg->dimension = VSIR_DIMENSION_VEC4; -+ for (i = 0; i < component_count; ++i) -+ reg->u.immconst_u32[i] = operand_regs[i]->u.immconst_u32[0]; -+ for (; i < VKD3D_VEC4_SIZE; ++i) -+ reg->u.immconst_u32[i] = 0; -+ return true; -+ } -+ -+ register_init_with_id(reg, VKD3DSPR_TEMP, operand_regs[0]->data_type, state->temp_idx++); -+ reg->dimension = VSIR_DIMENSION_VEC4; -+ -+ for (i = 0; i < component_count; ++i, ++ins) -+ { -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); -+ -+ if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) -+ return false; -+ -+ src_param_init(&src_params[0]); -+ src_params[0].reg = *operand_regs[i]; -+ -+ if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) -+ return false; -+ -+ dst_param_init_scalar(dst_param, i); -+ dst_param->reg = *reg; -+ } -+ -+ state->ins = ins; -+ state->code_block->instruction_count += component_count; -+ -+ return true; -+} -+ -+static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const struct sm6_value **operands, -+ unsigned int component_count, struct function_emission_state *state, struct vkd3d_shader_register *reg) -+{ -+ const struct vkd3d_shader_register *operand_regs[VKD3D_VEC4_SIZE]; -+ unsigned int i; -+ -+ for (i = 0; i < component_count; ++i) -+ operand_regs[i] = &operands[i]->u.reg; -+ -+ return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); -+} -+ -+static bool sm6_parser_emit_coordinate_construct(struct sm6_parser *sm6, const struct sm6_value **operands, -+ const struct sm6_value *z_operand, struct function_emission_state *state, -+ struct vkd3d_shader_register *reg) -+{ -+ const struct vkd3d_shader_register *operand_regs[VKD3D_VEC4_SIZE]; -+ const unsigned int max_operands = 3; -+ unsigned int component_count; -+ -+ for (component_count = 0; component_count < max_operands; ++component_count) -+ { -+ if (!z_operand && operands[component_count]->is_undefined) -+ break; -+ operand_regs[component_count] = &operands[component_count]->u.reg; -+ } -+ if (z_operand) -+ { -+ operand_regs[component_count++] = &z_operand->u.reg; -+ } -+ -+ return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); -+} -+ -+static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) -+{ -+ switch (op) -+ { -+ case DX_ISNAN: -+ return VKD3DSIH_ISNAN; -+ case DX_ISINF: -+ return VKD3DSIH_ISINF; -+ case DX_ISFINITE: -+ return VKD3DSIH_ISFINITE; -+ case DX_TAN: -+ return VKD3DSIH_TAN; -+ case DX_ACOS: -+ return VKD3DSIH_ACOS; -+ case DX_ASIN: -+ return VKD3DSIH_ASIN; -+ case DX_ATAN: -+ return VKD3DSIH_ATAN; -+ case DX_HCOS: -+ return VKD3DSIH_HCOS; -+ case DX_HSIN: -+ return VKD3DSIH_HSIN; -+ case DX_HTAN: -+ return VKD3DSIH_HTAN; -+ case DX_EXP: -+ return VKD3DSIH_EXP; -+ case DX_FRC: -+ return VKD3DSIH_FRC; -+ case DX_LOG: -+ return VKD3DSIH_LOG; -+ case DX_SQRT: -+ return VKD3DSIH_SQRT; -+ case DX_RSQRT: -+ return VKD3DSIH_RSQ; -+ case DX_ROUND_NE: -+ return VKD3DSIH_ROUND_NE; -+ case DX_ROUND_NI: -+ return VKD3DSIH_ROUND_NI; -+ case DX_ROUND_PI: -+ return VKD3DSIH_ROUND_PI; -+ case DX_ROUND_Z: -+ return VKD3DSIH_ROUND_Z; -+ case DX_BFREV: -+ return VKD3DSIH_BFREV; -+ case DX_COUNT_BITS: -+ return VKD3DSIH_COUNTBITS; -+ case DX_FIRST_BIT_LO: -+ return VKD3DSIH_FIRSTBIT_LO; -+ case DX_FIRST_BIT_HI: -+ return VKD3DSIH_FIRSTBIT_HI; -+ case DX_FIRST_BIT_SHI: -+ return VKD3DSIH_FIRSTBIT_SHI; -+ case DX_DERIV_COARSEX: -+ return VKD3DSIH_DSX_COARSE; -+ case DX_DERIV_COARSEY: -+ return VKD3DSIH_DSY_COARSE; -+ case DX_DERIV_FINEX: -+ return VKD3DSIH_DSX_FINE; -+ case DX_DERIV_FINEY: -+ return VKD3DSIH_DSY_FINE; -+ case DX_LEGACY_F32TOF16: -+ return VKD3DSIH_F32TOF16; -+ case DX_LEGACY_F16TOF32: -+ return VKD3DSIH_F16TOF32; -+ default: -+ vkd3d_unreachable(); -+ } -+} -+ -+static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_param; -+ -+ vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); -+ src_param = instruction_src_params_alloc(ins, 1, sm6); -+ src_param_init_from_value(src_param, operands[0]); -+ -+ instruction_dst_param_init_ssa_scalar(ins, sm6); -+} -+ -+static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, const struct sm6_type *type) -+{ -+ switch (op) -+ { -+ case DX_FMAX: -+ return type->u.width == 64 ? VKD3DSIH_DMAX : VKD3DSIH_MAX; -+ case DX_FMIN: -+ return type->u.width == 64 ? VKD3DSIH_DMIN : VKD3DSIH_MIN; -+ case DX_IMAX: -+ return VKD3DSIH_IMAX; -+ case DX_IMIN: -+ return VKD3DSIH_IMIN; -+ case DX_UMAX: -+ return VKD3DSIH_UMAX; -+ case DX_UMIN: -+ return VKD3DSIH_UMIN; -+ default: -+ vkd3d_unreachable(); -+ } -+} -+ -+static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_params; -+ -+ vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type)); -+ src_params = instruction_src_params_alloc(ins, 2, sm6); -+ src_param_init_from_value(&src_params[0], operands[0]); -+ src_param_init_from_value(&src_params[1], operands[1]); -+ -+ instruction_dst_param_init_ssa_scalar(ins, sm6); -+} -+ -+static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct sm6_value *dst = sm6_parser_get_current_value(sm6); -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_param; -+ const struct sm6_value *buffer; -+ const struct sm6_type *type; -+ -+ buffer = operands[0]; -+ if (!sm6_value_validate_is_handle(buffer, sm6)) -+ return; -+ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); -+ -+ src_param = instruction_src_params_alloc(ins, 1, sm6); -+ src_param_init_vector_from_reg(src_param, &buffer->u.handle.reg); -+ register_index_address_init(&src_param->reg.idx[2], operands[1], sm6); -+ assert(src_param->reg.idx_count == 3); -+ -+ type = sm6_type_get_scalar_type(dst->type, 0); -+ assert(type); -+ src_param->reg.data_type = vkd3d_data_type_from_sm6_type(type); -+ if (data_type_is_64_bit(src_param->reg.data_type)) -+ src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); -+ -+ instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6); -+} -+ -+static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_parser *sm6, -+ enum vkd3d_shader_descriptor_type type, unsigned int id, const struct sm6_value *address) -+{ -+ const struct sm6_descriptor_info *d; -+ unsigned int register_index; -+ size_t i; -+ -+ for (i = 0; i < sm6->descriptor_count; ++i) -+ { -+ d = &sm6->descriptors[i]; - - if (d->type != type || d->id != id) - continue; -@@ -3222,9 +3846,10 @@ static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_pa - return NULL; - } - --static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, struct sm6_block *code_block, -- enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) -+static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) - { -+ struct vkd3d_shader_instruction *ins = state->ins; - enum vkd3d_shader_descriptor_type type; - const struct sm6_descriptor_info *d; - struct vkd3d_shader_register *reg; -@@ -3246,9 +3871,9 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, struct sm6_ - dst->u.handle.d = d; - - reg = &dst->u.handle.reg; -- /* Set idx_count to 3 for use with load instructions. -- * TODO: set register type from resource type when other types are supported. */ -- vsir_register_init(reg, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 3); -+ /* Set idx_count to 3 for use with load/store instructions. */ -+ vsir_register_init(reg, d->reg_type, d->reg_data_type, 3); -+ reg->dimension = VSIR_DIMENSION_VEC4; - reg->idx[0].offset = id; - register_index_address_init(®->idx[1], operands[2], sm6); - reg->non_uniform = !!sm6_value_get_constant_uint(operands[3]); -@@ -3257,9 +3882,38 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, struct sm6_ - ins->handler_idx = VKD3DSIH_NOP; - } - --static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, struct sm6_block *code_block, -- enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) -+static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode op) -+{ -+ switch (op) -+ { -+ case DX_IBFE: -+ return VKD3DSIH_IBFE; -+ case DX_UBFE: -+ return VKD3DSIH_UBFE; -+ default: -+ vkd3d_unreachable(); -+ } -+} -+ -+static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_params; -+ unsigned int i; -+ -+ vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_tertiary_op(op)); -+ src_params = instruction_src_params_alloc(ins, 3, sm6); -+ for (i = 0; i < 3; ++i) -+ src_param_init_from_value(&src_params[i], operands[i]); -+ -+ instruction_dst_param_init_ssa_scalar(ins, sm6); -+} -+ -+static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) - { -+ struct vkd3d_shader_instruction *ins = state->ins; - struct vkd3d_shader_src_param *src_param; - const struct shader_signature *signature; - unsigned int row_index, column_index; -@@ -3289,9 +3943,142 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, struct sm6_blo - instruction_dst_param_init_ssa_scalar(ins, sm6); - } - --static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_block *code_block, -- enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) -+static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ unsigned int operand_count, write_mask, component_count = VKD3D_VEC4_SIZE; -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_params; -+ const struct sm6_value *resource; -+ bool raw; -+ -+ resource = operands[0]; -+ if (!sm6_value_validate_is_handle(resource, sm6)) -+ return; -+ raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; -+ -+ if (op == DX_RAW_BUFFER_LOAD) -+ { -+ write_mask = sm6_value_get_constant_uint(operands[3]); -+ if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) -+ { -+ WARN("Invalid write mask %#x.\n", write_mask); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Write mask %#x for a raw/structured buffer load operation is invalid.", write_mask); -+ return; -+ } -+ else if (write_mask & (write_mask + 1)) -+ { -+ FIXME("Unhandled write mask %#x.\n", write_mask); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Write mask %#x for a raw/structured buffer load operation is unhandled.", write_mask); -+ } -+ component_count = vsir_write_mask_component_count(write_mask); -+ } -+ -+ instruction_init_with_resource(ins, raw ? VKD3DSIH_LD_RAW : VKD3DSIH_LD_STRUCTURED, resource, sm6); -+ operand_count = 2 + !raw; -+ if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) -+ return; -+ src_params_init_from_operands(src_params, &operands[1], operand_count - 1); -+ src_param_init_vector_from_reg(&src_params[operand_count - 1], &resource->u.handle.reg); -+ -+ instruction_dst_param_init_ssa_vector(ins, component_count, sm6); -+} -+ -+static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_params; -+ const struct sm6_value *resource; -+ -+ resource = operands[0]; -+ if (!sm6_value_validate_is_handle(resource, sm6)) -+ return; -+ -+ if (resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER -+ || resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER) -+ { -+ return sm6_parser_emit_dx_raw_buffer_load(sm6, op, operands, state); -+ } -+ -+ if (resource->u.handle.d->kind != RESOURCE_KIND_TYPEDBUFFER) -+ { -+ WARN("Resource is not a typed buffer.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION, -+ "Resource for a typed buffer load is not a typed buffer."); -+ } -+ -+ instruction_init_with_resource(ins, (resource->u.handle.d->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) -+ ? VKD3DSIH_LD_UAV_TYPED : VKD3DSIH_LD, resource, sm6); -+ -+ src_params = instruction_src_params_alloc(ins, 2, sm6); -+ src_param_init_from_value(&src_params[0], operands[1]); -+ if (!sm6_value_is_undef(operands[2])) -+ { -+ /* Constant zero would be ok, but is not worth checking for unless it shows up. */ -+ WARN("Ignoring structure offset.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring structure offset for a typed buffer load."); -+ } -+ src_param_init_vector_from_reg(&src_params[1], &resource->u.handle.reg); -+ -+ instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); -+} -+ -+static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value) -+{ -+ return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value); -+} -+ -+static void instruction_set_texel_offset(struct vkd3d_shader_instruction *ins, -+ const struct sm6_value **operands, struct sm6_parser *sm6) -+{ -+ ins->texel_offset.u = sm6_value_get_texel_offset(operands[0]); -+ ins->texel_offset.v = sm6_value_get_texel_offset(operands[1]); -+ ins->texel_offset.w = sm6_value_get_texel_offset(operands[2]); -+} -+ -+static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct sm6_value *dst = sm6_parser_get_current_value(sm6); -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_dst_param *dst_params; -+ struct vkd3d_shader_src_param *src_param; -+ unsigned int index; -+ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SINCOS); -+ src_param = instruction_src_params_alloc(ins, 1, sm6); -+ src_param_init_from_value(src_param, operands[0]); -+ -+ index = op == DX_COS; -+ dst_params = instruction_dst_params_alloc(ins, 2, sm6); -+ dst_param_init(&dst_params[0]); -+ dst_param_init(&dst_params[1]); -+ register_init_ssa_scalar(&dst_params[index].reg, dst->type, dst, sm6); -+ vsir_register_init(&dst_params[index ^ 1].reg, VKD3DSPR_NULL, VKD3D_DATA_UNUSED, 0); -+ dst->u.reg = dst_params[index].reg; -+} -+ -+static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_param; -+ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); -+ src_param = instruction_src_params_alloc(ins, 1, sm6); -+ src_param_init_from_value(src_param, operands[0]); -+ -+ instruction_dst_param_init_ssa_vector(ins, 2, sm6); -+} -+ -+static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) - { -+ struct vkd3d_shader_instruction *ins = state->ins; - struct vkd3d_shader_src_param *src_param; - struct vkd3d_shader_dst_param *dst_param; - const struct shader_signature *signature; -@@ -3342,33 +4129,181 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b - src_param_init_from_value(src_param, value); - } - -+static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ const struct sm6_value *resource, *mip_level_or_sample_count; -+ enum vkd3d_shader_resource_type resource_type; -+ struct vkd3d_shader_src_param *src_params; -+ struct vkd3d_shader_instruction *ins; -+ struct vkd3d_shader_register coord; -+ bool is_multisample, is_uav; -+ unsigned int i; -+ -+ resource = operands[0]; -+ if (!sm6_value_validate_is_texture_handle(resource, op, sm6)) -+ return; -+ -+ resource_type = resource->u.handle.d->resource_type; -+ is_multisample = resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY; -+ is_uav = resource->u.handle.d->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; -+ -+ mip_level_or_sample_count = (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) ? operands[1] : NULL; -+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], -+ is_multisample ? NULL : mip_level_or_sample_count, state, &coord)) -+ { -+ return; -+ } -+ -+ ins = state->ins; -+ instruction_init_with_resource(ins, is_uav ? VKD3DSIH_LD_UAV_TYPED -+ : is_multisample ? VKD3DSIH_LD2DMS : VKD3DSIH_LD, resource, sm6); -+ instruction_set_texel_offset(ins, &operands[5], sm6); -+ -+ for (i = 0; i < VKD3D_VEC4_SIZE; ++i) -+ ins->resource_data_type[i] = resource->u.handle.d->resource_data_type; -+ -+ src_params = instruction_src_params_alloc(ins, 2 + is_multisample, sm6); -+ src_param_init_vector_from_reg(&src_params[0], &coord); -+ src_param_init_vector_from_reg(&src_params[1], &resource->u.handle.reg); -+ if (is_multisample) -+ src_param_init_from_value(&src_params[2], mip_level_or_sample_count); -+ -+ instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); -+} -+ -+static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_register coord, texel; -+ struct vkd3d_shader_src_param *src_params; -+ struct vkd3d_shader_dst_param *dst_param; -+ unsigned int write_mask, component_count; -+ struct vkd3d_shader_instruction *ins; -+ const struct sm6_value *resource; -+ -+ resource = operands[0]; -+ if (!sm6_value_validate_is_texture_handle(resource, op, sm6)) -+ return; -+ -+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[1], NULL, state, &coord)) -+ return; -+ -+ write_mask = sm6_value_get_constant_uint(operands[8]); -+ if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) -+ { -+ WARN("Invalid write mask %#x.\n", write_mask); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Write mask %#x for a texture store operation is invalid.", write_mask); -+ return; -+ } -+ else if (write_mask & (write_mask + 1)) -+ { -+ /* In this case, it is unclear which source operands will be defined unless we encounter it in a shader. */ -+ FIXME("Unhandled write mask %#x.\n", write_mask); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Write mask %#x for a texture store operation is unhandled.", write_mask); -+ } -+ component_count = vsir_write_mask_component_count(write_mask); -+ -+ if (!sm6_parser_emit_composite_construct(sm6, &operands[4], component_count, state, &texel)) -+ return; -+ -+ ins = state->ins; -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_STORE_UAV_TYPED); -+ -+ if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) -+ return; -+ src_param_init_vector_from_reg(&src_params[0], &coord); -+ src_param_init_vector_from_reg(&src_params[1], &texel); -+ -+ dst_param = instruction_dst_params_alloc(ins, 1, sm6); -+ dst_param->reg = resource->u.handle.reg; -+ dst_param_init_with_mask(dst_param, write_mask); -+} -+ - struct sm6_dx_opcode_info - { -- const char ret_type; -+ const char *ret_type; - const char *operand_info; -- void (*handler)(struct sm6_parser *, struct sm6_block *, enum dx_intrinsic_opcode, -- const struct sm6_value **, struct vkd3d_shader_instruction *); -+ void (*handler)(struct sm6_parser *, enum dx_intrinsic_opcode, const struct sm6_value **, -+ struct function_emission_state *); - }; - - /* -+ 1 -> int1 - 8 -> int8 - b -> constant int1 - c -> constant int8/16/32 -+ C -> constant or undefined int8/16/32 - i -> int32 -+ m -> int16/32/64 -+ f -> float -+ d -> double -+ e -> half/float -+ g -> half/float/double - H -> handle -+ S -> splitdouble - v -> void - o -> overloaded -+ R -> matches the return type - */ - static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - { -- [DX_CBUFFER_LOAD_LEGACY ] = {'o', "Hi", sm6_parser_emit_dx_cbuffer_load}, -- [DX_CREATE_HANDLE ] = {'H', "ccib", sm6_parser_emit_dx_create_handle}, -- [DX_LOAD_INPUT ] = {'o', "ii8i", sm6_parser_emit_dx_load_input}, -- [DX_STORE_OUTPUT ] = {'v', "ii8o", sm6_parser_emit_dx_store_output}, -+ [DX_ACOS ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_ASIN ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_ATAN ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_BFREV ] = {"m", "R", sm6_parser_emit_dx_unary}, -+ [DX_BUFFER_LOAD ] = {"o", "Hii", sm6_parser_emit_dx_buffer_load}, -+ [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, -+ [DX_COS ] = {"g", "R", sm6_parser_emit_dx_sincos}, -+ [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, -+ [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, -+ [DX_DERIV_COARSEX ] = {"e", "R", sm6_parser_emit_dx_unary}, -+ [DX_DERIV_COARSEY ] = {"e", "R", sm6_parser_emit_dx_unary}, -+ [DX_DERIV_FINEX ] = {"e", "R", sm6_parser_emit_dx_unary}, -+ [DX_DERIV_FINEY ] = {"e", "R", sm6_parser_emit_dx_unary}, -+ [DX_EXP ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary}, -+ [DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary}, -+ [DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary}, -+ [DX_FMAX ] = {"g", "RR", sm6_parser_emit_dx_binary}, -+ [DX_FMIN ] = {"g", "RR", sm6_parser_emit_dx_binary}, -+ [DX_FRC ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_IBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, -+ [DX_HCOS ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_HSIN ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_HTAN ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_IMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, -+ [DX_IMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, -+ [DX_ISFINITE ] = {"1", "g", sm6_parser_emit_dx_unary}, -+ [DX_ISINF ] = {"1", "g", sm6_parser_emit_dx_unary}, -+ [DX_ISNAN ] = {"1", "g", sm6_parser_emit_dx_unary}, -+ [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary}, -+ [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary}, -+ [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, -+ [DX_LOG ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_RAW_BUFFER_LOAD ] = {"o", "Hii8i", sm6_parser_emit_dx_raw_buffer_load}, -+ [DX_ROUND_NE ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_ROUND_NI ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_ROUND_PI ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_ROUND_Z ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_RSQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_SIN ] = {"g", "R", sm6_parser_emit_dx_sincos}, -+ [DX_SPLIT_DOUBLE ] = {"S", "d", sm6_parser_emit_dx_split_double}, -+ [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, -+ [DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_TEXTURE_LOAD ] = {"o", "HiiiiCCC", sm6_parser_emit_dx_texture_load}, -+ [DX_TEXTURE_STORE ] = {"v", "Hiiiooooc", sm6_parser_emit_dx_texture_store}, -+ [DX_UBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, -+ [DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, -+ [DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, - }; - - static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, -- bool is_return) -+ const struct sm6_type *ret_type, bool is_return) - { - const struct sm6_type *type = value->type; - -@@ -3380,6 +4315,8 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc - case 0: - FIXME("Invalid operand count.\n"); - return false; -+ case '1': -+ return sm6_type_is_bool(type); - case '8': - return sm6_type_is_i8(type); - case 'b': -@@ -3387,15 +4324,32 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc - case 'c': - return sm6_value_is_constant(value) && sm6_type_is_integer(type) && type->u.width >= 8 - && type->u.width <= 32; -+ case 'C': -+ return (sm6_value_is_constant(value) || sm6_value_is_undef(value)) -+ && sm6_type_is_integer(type) && type->u.width >= 8 && type->u.width <= 32; - case 'i': - return sm6_type_is_i32(type); -+ case 'm': -+ return sm6_type_is_i16_i32_i64(type); -+ case 'f': -+ return sm6_type_is_float(type); -+ case 'd': -+ return sm6_type_is_double(type); -+ case 'e': -+ return sm6_type_is_f16_f32(type); -+ case 'g': -+ return sm6_type_is_floating_point(type); - case 'H': - return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; -+ case 'S': -+ return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.splitdouble"); - case 'v': - return !type; - case 'o': - /* TODO: some type checking may be possible */ - return true; -+ case 'R': -+ return type == ret_type; - default: - FIXME("Unhandled operand code '%c'.\n", info_type); - return false; -@@ -3410,7 +4364,8 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ - - info = &sm6_dx_op_table[op]; - -- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type, true)) -+ assert(info->ret_type[0]); -+ if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], NULL, true)) - { - WARN("Failed to validate return type for dx intrinsic id %u, '%s'.\n", op, name); - /* Return type validation failure is not so critical. We only need to set -@@ -3420,7 +4375,7 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ - for (i = 0; i < operand_count; ++i) - { - const struct sm6_value *value = operands[i]; -- if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], false)) -+ if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], dst->type, false)) - { - WARN("Failed to validate operand %u for dx intrinsic id %u, '%s'.\n", i + 1, op, name); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -3454,27 +4409,27 @@ static void sm6_parser_emit_unhandled(struct sm6_parser *sm6, struct vkd3d_shade - /* dst->is_undefined is not set here because it flags only explicitly undefined values. */ - } - --static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, struct sm6_block *code_block, enum dx_intrinsic_opcode op, -+static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, - const char *name, const struct sm6_value **operands, unsigned int operand_count, -- struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+ struct function_emission_state *state, struct sm6_value *dst) - { - if (op >= ARRAY_SIZE(sm6_dx_op_table) || !sm6_dx_op_table[op].operand_info) - { - FIXME("Unhandled dx intrinsic function id %u, '%s'.\n", op, name); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, - "Call to intrinsic function %s is unhandled.", name); -- sm6_parser_emit_unhandled(sm6, ins, dst); -+ sm6_parser_emit_unhandled(sm6, state->ins, dst); - return; - } - - if (sm6_parser_validate_dx_op(sm6, op, name, operands, operand_count, dst)) -- sm6_dx_op_table[op].handler(sm6, code_block, op, operands, ins); -+ sm6_dx_op_table[op].handler(sm6, op, operands, state); - else -- sm6_parser_emit_unhandled(sm6, ins, dst); -+ sm6_parser_emit_unhandled(sm6, state->ins, dst); - } - - static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_record *record, -- struct sm6_block *code_block, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+ struct function_emission_state *state, struct sm6_value *dst) - { - const struct sm6_value *operands[DXIL_OP_MAX_OPERANDS]; - const struct sm6_value *fn_value, *op_value; -@@ -3556,8 +4511,8 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor - "Expected a constant integer dx intrinsic function id."); - return; - } -- sm6_parser_decode_dx_op(sm6, code_block, register_get_uint_value(&op_value->u.reg), -- fn_value->u.function.name, &operands[1], operand_count - 1, ins, dst); -+ sm6_parser_decode_dx_op(sm6, register_get_uint_value(&op_value->u.reg), -+ fn_value->u.function.name, &operands[1], operand_count - 1, state, dst); - } - - static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_type *from, -@@ -3700,6 +4655,9 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - if (handler_idx == VKD3DSIH_NOP) - { - dst->u.reg = value->u.reg; -+ /* Set the result type for casts from 16-bit min precision. */ -+ if (type->u.width != 16) -+ dst->u.reg.data_type = vkd3d_data_type_from_sm6_type(type); - return; - } - -@@ -3775,8 +4733,10 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor - } - - a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); -+ if (!a) -+ return; - b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); -- if (!a || !b) -+ if (!b) - return; - - if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) -@@ -3896,8 +4856,8 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - - src_param = instruction_src_params_alloc(ins, 1, sm6); -- src_param_init_from_value(src_param, src); -- src_param->swizzle = vkd3d_shader_create_swizzle(elem_idx, elem_idx, elem_idx, elem_idx); -+ src_param->reg = src->u.reg; -+ src_param_init_scalar(src_param, elem_idx); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -4053,25 +5013,257 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor - instruction_dst_param_init_ssa_scalar(ins, sm6); - } - --static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record *record, -- struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) -+static int phi_incoming_compare(const void *a, const void *b) - { -- if (!dxil_record_validate_operand_count(record, 0, 1, sm6)) -- return; -- -- if (record->operand_count) -- FIXME("Non-void return is not implemented.\n"); -+ const struct incoming_value *incoming_a = a, *incoming_b = b; - -- ins->handler_idx = VKD3DSIH_NOP; -+ return (incoming_a->block > incoming_b->block) - (incoming_a->block < incoming_b->block); - } - --static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, -- struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins, -+ struct sm6_value *dst) - { -- struct vkd3d_shader_src_param *src_params; -- const struct sm6_value *src[3]; -- unsigned int i = 0; -- -+ struct incoming_value *incoming; -+ const struct sm6_type *type; -+ struct sm6_phi *phi; -+ unsigned int i, j; -+ uint64_t src_idx; -+ -+ if (!(record->operand_count & 1)) -+ { -+ WARN("Invalid operand count %u.\n", record->operand_count); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Invalid operand count %u for phi instruction.", record->operand_count); -+ return; -+ } -+ -+ if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) -+ return; -+ if (!sm6_type_is_numeric(type)) -+ { -+ /* dxc doesn't seem to use buffer/resource read return types here. */ -+ FIXME("Only scalar numeric types are supported.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Result type class %u of a phi instruction is not scalar numeric.", type->class); -+ return; -+ } -+ -+ dst->type = type; -+ register_init_ssa_scalar(&dst->u.reg, type, dst, sm6); -+ -+ if (!(phi = sm6_block_phi_require_space(code_block, sm6))) -+ return; -+ phi->reg = dst->u.reg; -+ phi->incoming_count = record->operand_count / 2u; -+ -+ if (!vkd3d_array_reserve((void **)&phi->incoming, &phi->incoming_capacity, phi->incoming_count, -+ sizeof(*phi->incoming))) -+ { -+ ERR("Failed to allocate phi incoming array.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory allocating a phi incoming array."); -+ return; -+ } -+ incoming = phi->incoming; -+ -+ for (i = 1; i < record->operand_count; i += 2) -+ { -+ src_idx = sm6->value_count - decode_rotated_signed_value(record->operands[i]); -+ /* May be a forward reference. */ -+ if (src_idx >= sm6->cur_max_value) -+ { -+ WARN("Invalid value index %"PRIu64".\n", src_idx); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Invalid value index %"PRIu64" for a phi incoming value.", src_idx); -+ return; -+ } -+ -+ j = i / 2u; -+ /* Store the value index in the register for later resolution. */ -+ incoming[j].reg.idx[0].offset = src_idx; -+ incoming[j].block = sm6_function_get_block(function, record->operands[i + 1], sm6); -+ } -+ -+ ins->handler_idx = VKD3DSIH_NOP; -+ -+ qsort(incoming, phi->incoming_count, sizeof(*incoming), phi_incoming_compare); -+ -+ for (i = 1, j = 1; i < phi->incoming_count; ++i) -+ { -+ if (incoming[i].block != incoming[i - 1].block) -+ { -+ incoming[j++] = incoming[i]; -+ continue; -+ } -+ -+ if (incoming[i].reg.idx[0].offset != incoming[i - 1].reg.idx[0].offset) -+ { -+ WARN("PHI conflict.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Two phi incomings have the same block but different values."); -+ } -+ } -+ /* if (j == 1) we should be able to set dst->u.reg to incoming[0].reg, but structurisation -+ * may potentially add new incomings. */ -+ phi->incoming_count = j; -+} -+ -+static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) -+{ -+ if (!dxil_record_validate_operand_count(record, 0, 1, sm6)) -+ return; -+ -+ if (record->operand_count) -+ FIXME("Non-void return is not implemented.\n"); -+ -+ code_block->terminator.type = TERMINATOR_RET; -+ -+ ins->handler_idx = VKD3DSIH_NOP; -+} -+ -+static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+{ -+ struct vkd3d_shader_src_param *src_param; -+ struct vkd3d_shader_dst_param *dst_param; -+ const struct sm6_type *pointee_type; -+ const struct sm6_value *ptr, *src; -+ unsigned int i = 0, alignment; -+ uint64_t alignment_code; -+ -+ if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i)) -+ || !sm6_value_validate_is_register(ptr, sm6) -+ || !sm6_value_validate_is_pointer(ptr, sm6)) -+ { -+ return; -+ } -+ -+ pointee_type = ptr->type->u.pointer.type; -+ if (!(src = sm6_parser_get_value_by_ref(sm6, record, pointee_type, &i))) -+ return; -+ if (!sm6_value_validate_is_numeric(src, sm6)) -+ return; -+ -+ if (pointee_type != src->type) -+ { -+ WARN("Type mismatch.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "Type mismatch in pointer store arguments."); -+ } -+ -+ if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6)) -+ return; -+ -+ alignment_code = record->operands[i++]; -+ if (!bitcode_parse_alignment(alignment_code, &alignment)) -+ WARN("Invalid alignment %"PRIu64".\n", alignment_code); -+ -+ if (record->operands[i]) -+ WARN("Ignoring volatile modifier.\n"); -+ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); -+ -+ src_param = instruction_src_params_alloc(ins, 1, sm6); -+ src_param_init_from_value(&src_param[0], src); -+ -+ dst_param = instruction_dst_params_alloc(ins, 1, sm6); -+ dst_param_init(dst_param); -+ dst_param->reg = ptr->u.reg; -+ dst_param->reg.alignment = alignment; -+} -+ -+static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) -+{ -+ struct sm6_block_terminator *terminator = &code_block->terminator; -+ const struct sm6_type *type; -+ const struct sm6_value *src; -+ unsigned int i = 1, j; -+ -+ if (record->operand_count < 3 || !(record->operand_count & 1)) -+ { -+ WARN("Invalid operand count %u.\n", record->operand_count); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Invalid operand count %u for a switch instruction.", record->operand_count); -+ return; -+ } -+ -+ if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) -+ return; -+ -+ if (!(src = sm6_parser_get_value_by_ref(sm6, record, type, &i)) -+ || !sm6_value_validate_is_register(src, sm6)) -+ return; -+ assert(i == 2); -+ -+ if (src->type != type) -+ { -+ WARN("Type mismatch.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "The type of a switch selector value does not match the selector type."); -+ } -+ if (!sm6_type_is_integer(type)) -+ { -+ WARN("Selector is not scalar integer.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Selector type class %u of a switch instruction is not scalar integer.", type->class); -+ return; -+ } -+ -+ terminator->conditional_reg = src->u.reg; -+ terminator->type = TERMINATOR_SWITCH; -+ -+ terminator->case_count = record->operand_count / 2u; -+ if (!(terminator->cases = vkd3d_calloc(terminator->case_count, sizeof(*terminator->cases)))) -+ { -+ ERR("Failed to allocate case array.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory allocating a switch case array."); -+ return; -+ } -+ -+ /* Executes 'operand_count / 2' times because operand_count is uneven. */ -+ for (; i < record->operand_count; i += 2) -+ { -+ j = i / 2u - 1; -+ terminator->cases[j].block = sm6_function_get_block(function, record->operands[i], sm6); -+ /* For structurisation it is convenient to store the default in the case array. */ -+ terminator->cases[j].is_default = !j; -+ } -+ -+ for (i = 3; i < record->operand_count; i += 2) -+ { -+ if (!(src = sm6_parser_get_value_safe(sm6, record->operands[i]))) -+ return; -+ -+ if (src->type != type) -+ { -+ WARN("Type mismatch.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "The type of a switch case value does not match the selector type."); -+ } -+ if (!sm6_value_is_constant(src)) -+ { -+ WARN("Case value is not a constant.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "A switch case value is not a constant."); -+ } -+ -+ terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src); -+ } -+ -+ ins->handler_idx = VKD3DSIH_NOP; -+} -+ -+static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+{ -+ struct vkd3d_shader_src_param *src_params; -+ const struct sm6_value *src[3]; -+ unsigned int i = 0; -+ - if (!(src[1] = sm6_parser_get_value_by_ref(sm6, record, NULL, &i)) - || !(src[2] = sm6_parser_get_value_by_ref(sm6, record, src[1]->type, &i)) - || !(src[0] = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))) -@@ -4115,6 +5307,12 @@ static bool sm6_metadata_value_is_string(const struct sm6_metadata_value *m) - return m && m->type == VKD3D_METADATA_STRING; - } - -+static bool sm6_metadata_value_is_zero_or_undef(const struct sm6_metadata_value *m) -+{ -+ return sm6_metadata_value_is_value(m) -+ && (sm6_value_is_undef(m->u.value) || sm6_value_is_constant_zero(m->u.value)); -+} -+ - static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, - const struct sm6_metadata_value *m, unsigned int *u) - { -@@ -4153,12 +5351,279 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, - return true; - } - -+static void sm6_parser_metadata_attachment_block_init(struct sm6_parser *sm6, const struct dxil_block *target_block, -+ const struct dxil_block *block) -+{ -+ struct dxil_record *target_record; -+ const struct dxil_record *record; -+ unsigned int i; -+ uint64_t index; -+ -+ for (i = 0; i < block->record_count; ++i) -+ { -+ record = block->records[i]; -+ if (record->code != METADATA_ATTACHMENT) -+ { -+ WARN("Ignoring record with code %u.\n", record->code); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata attachment record with code %u.", record->code); -+ continue; -+ } -+ if (!(record->operand_count & 1)) -+ { -+ WARN("Ignoring function attachment.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata function attachment."); -+ continue; -+ } -+ -+ index = record->operands[0]; -+ if (!target_block->record_count || index >= target_block->record_count - 1) -+ { -+ WARN("Invalid record index %"PRIu64".\n", index); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Invalid record index %"PRIu64" for a metadata attachment.", index); -+ continue; -+ } -+ /* 'index' is an instruction index, but records[0] is DECLAREBLOCKS, not an instruction. */ -+ target_record = target_block->records[index + 1]; -+ if (target_record->attachment) -+ { -+ WARN("Overwriting record attachment.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "The target record for a metadata attachment already has an attachment."); -+ } -+ target_record->attachment = record; -+ } -+} -+ -+static void sm6_parser_metadata_attachments_init(struct sm6_parser *sm6, const struct dxil_block *block) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < block->child_block_count; ++i) -+ { -+ if (block->child_blocks[i]->id == METADATA_ATTACHMENT_BLOCK) -+ sm6_parser_metadata_attachment_block_init(sm6, block, block->child_blocks[i]); -+ } -+} -+ -+static const struct sm6_metadata_value *sm6_parser_find_metadata_kind(const struct sm6_parser *sm6, uint64_t id) -+{ -+ unsigned int i, j; -+ -+ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) -+ { -+ for (j = 0; j < sm6->metadata_tables[i].count; ++j) -+ { -+ if (sm6->metadata_tables[i].values[j].type == VKD3D_METADATA_KIND -+ && sm6->metadata_tables[i].values[j].u.kind.id == id) -+ return &sm6->metadata_tables[i].values[j]; -+ } -+ } -+ -+ return NULL; -+} -+ -+static const struct sm6_metadata_value *sm6_parser_metadata_get_value(const struct sm6_parser *sm6, uint64_t index) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) -+ { -+ if (sm6->metadata_tables[i].count > index) -+ break; -+ index -= sm6->metadata_tables[i].count; -+ } -+ -+ return (index < sm6->metadata_tables[i].count) ? &sm6->metadata_tables[i].values[index] : NULL; -+} -+ -+static bool metadata_node_get_unary_uint(const struct sm6_metadata_node *node, unsigned int *operand, -+ struct sm6_parser *sm6) -+{ -+ if (node->operand_count != 1) -+ { -+ FIXME("Ignoring node with %u operands.\n", node->operand_count); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring metadata attachment node with %u operands; expected unary.", node->operand_count); -+ return false; -+ } -+ if (!sm6_metadata_value_is_value(node->operands[0]) -+ || !sm6_metadata_get_uint_value(sm6, node->operands[0], operand)) -+ { -+ WARN("Failed to get operand value.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Failed to get a metadata attachment operand value; ignoring the attachment."); -+ return false; -+ } -+ -+ return true; -+} -+ -+static void metadata_attachment_record_apply(const struct dxil_record *record, enum bitcode_function_code func_code, -+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst, struct sm6_parser *sm6) -+{ -+ static const char *ignored_names[] = -+ { -+ "alias.scope", -+ "dx.controlflow.hints", -+ "llvm.loop", -+ "noalias", -+ "tbaa", -+ "range", -+ }; -+ const struct sm6_metadata_node *node; -+ const struct sm6_metadata_value *m; -+ unsigned int i, j, operand; -+ bool ignored = false; -+ const char *name; -+ -+ if (record->attachment) -+ { -+ WARN("Ignoring nested metadata attachment.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a nested metadata attachment."); -+ } -+ -+ assert(record->operand_count & 1); -+ for (i = 1; i < record->operand_count; i += 2) -+ { -+ if (!(m = sm6_parser_find_metadata_kind(sm6, record->operands[i]))) -+ { -+ WARN("Failed to find metadata kind %"PRIx64".\n", record->operands[i]); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Failed to find metadata kind %"PRIx64" for an attachment.", record->operands[i]); -+ continue; -+ } -+ name = m->u.kind.name; -+ -+ m = sm6_parser_metadata_get_value(sm6, record->operands[i + 1]); -+ if (!m || !sm6_metadata_value_is_node(m)) -+ { -+ WARN("Failed to retrieve metadata attachment node.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Failed to retrieve a metadata attachment node."); -+ continue; -+ } -+ node = m->u.node; -+ -+ if (!strcmp(name, "dx.precise")) -+ { -+ if (!sm6_value_is_register(dst)) -+ { -+ WARN("Precise value is not a register.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "A value marked as precise is not a register."); -+ } -+ else if (metadata_node_get_unary_uint(node, &operand, sm6) && operand) -+ { -+ ins->flags |= sm6_type_is_scalar(dst->type) ? VKD3DSI_PRECISE_X : VKD3DSI_PRECISE_XYZW; -+ } -+ } -+ else if (!strcmp(name, "dx.nonuniform")) -+ { -+ if (!sm6_value_is_register(dst)) -+ { -+ WARN("Non-uniform value is not a register.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "A value marked as non-uniform is not a register."); -+ } -+ else if (metadata_node_get_unary_uint(node, &operand, sm6)) -+ { -+ dst->u.reg.non_uniform = !!operand; -+ } -+ } -+ else -+ { -+ for (j = 0; j < ARRAY_SIZE(ignored_names); ++j) -+ if (!strcmp(name, ignored_names[j])) -+ break; -+ if (j == ARRAY_SIZE(ignored_names)) -+ { -+ WARN("Ignoring metadata attachment '%s'.\n", name); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata attachment named '%s'.", name); -+ } -+ ignored = true; -+ } -+ -+ if (func_code != FUNC_CODE_INST_CALL && !ignored) -+ WARN("Metadata attachment target is not a function call.\n"); -+ } -+} -+ -+static bool sm6_function_blocks_reserve(struct sm6_function *function, unsigned int reserve) -+{ -+ if (!vkd3d_array_reserve((void **)&function->blocks, &function->block_capacity, -+ reserve, sizeof(*function->blocks))) -+ { -+ ERR("Failed to allocate code block array.\n"); -+ return false; -+ } -+ return true; -+} -+ -+static struct sm6_block *sm6_function_create_block(struct sm6_function *function) -+{ -+ struct sm6_block *block; -+ -+ if (!(block = sm6_block_create())) -+ return NULL; -+ -+ function->blocks[function->block_count++] = block; -+ /* Set the id to the array index + 1. */ -+ block->id = function->block_count; -+ -+ return block; -+} -+ -+static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_function *function, -+ struct sm6_parser *sm6) -+{ -+ const struct sm6_block *block; -+ size_t i, j, block_idx; -+ -+ for (block_idx = 0; block_idx < function->block_count; ++block_idx) -+ { -+ block = function->blocks[block_idx]; -+ -+ for (i = 0; i < block->phi_count; ++i) -+ { -+ struct sm6_phi *phi = &block->phi[i]; -+ const struct sm6_value *src; -+ -+ for (j = 0; j < phi->incoming_count; ++j) -+ { -+ src = &sm6->values[phi->incoming[j].reg.idx[0].offset]; -+ if (!sm6_value_is_constant(src) && !sm6_value_is_undef(src) && !sm6_value_is_ssa(src)) -+ { -+ FIXME("PHI incoming value is not a constant or SSA register.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "A PHI incoming value is not a constant or SSA register."); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ if (src->u.reg.data_type != phi->reg.data_type) -+ { -+ WARN("Type mismatch.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "The type of a phi incoming value does not match the result type."); -+ } -+ phi->incoming[j].reg = src->u.reg; -+ } -+ } -+ } -+ -+ return VKD3D_OK; -+} -+ - static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, - struct sm6_function *function) - { - struct vkd3d_shader_instruction *ins; - size_t i, block_idx, block_count; - const struct dxil_record *record; -+ const struct sm6_type *fwd_type; - bool ret_found, is_terminator; - struct sm6_block *code_block; - struct sm6_value *dst; -@@ -4192,16 +5657,18 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - WARN("Function contains no blocks.\n"); - return VKD3D_ERROR_INVALID_SHADER; - } -- if (block_count > 1) -- { -- FIXME("Branched shaders are not supported yet.\n"); -- return VKD3D_ERROR_INVALID_SHADER; -- } - -- if (!(function->blocks[0] = sm6_block_create())) -- { -- ERR("Failed to allocate code block.\n"); -+ if (!sm6_function_blocks_reserve(function, block_count)) - return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ /* Pre-allocate all blocks to simplify instruction parsing. */ -+ for (i = 0; i < block_count; ++i) -+ { -+ if (!sm6_function_create_block(function)) -+ { -+ ERR("Failed to allocate code block.\n"); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } - } - function->block_count = block_count; - code_block = function->blocks[0]; -@@ -4220,10 +5687,10 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - return VKD3D_ERROR_INVALID_SHADER; - } - -- /* block->record_count - 1 is the instruction count, but some instructions -- * can emit >1 IR instruction, so extra may be used. */ -+ /* Some instructions can emit >1 IR instruction, so extra may be used. */ - if (!vkd3d_array_reserve((void **)&code_block->instructions, &code_block->instruction_capacity, -- max(code_block->instruction_count + 1, block->record_count), sizeof(*code_block->instructions))) -+ code_block->instruction_count + MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION, -+ sizeof(*code_block->instructions))) - { - ERR("Failed to allocate instructions.\n"); - return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -4233,6 +5700,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - ins->handler_idx = VKD3DSIH_INVALID; - - dst = sm6_parser_get_current_value(sm6); -+ fwd_type = dst->type; - dst->type = NULL; - dst->value_type = VALUE_TYPE_REG; - is_terminator = false; -@@ -4240,12 +5708,23 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - record = block->records[i]; - switch (record->code) - { -+ case FUNC_CODE_INST_ALLOCA: -+ sm6_parser_emit_alloca(sm6, record, ins, dst); -+ break; - case FUNC_CODE_INST_BINOP: - sm6_parser_emit_binop(sm6, record, ins, dst); - break; -+ case FUNC_CODE_INST_BR: -+ sm6_parser_emit_br(sm6, record, function, code_block, ins); -+ is_terminator = true; -+ break; - case FUNC_CODE_INST_CALL: -- sm6_parser_emit_call(sm6, record, code_block, ins, dst); -+ { -+ struct function_emission_state state = {code_block, ins}; -+ sm6_parser_emit_call(sm6, record, &state, dst); -+ sm6->p.program.temp_count = max(sm6->p.program.temp_count, state.temp_idx); - break; -+ } - case FUNC_CODE_INST_CAST: - sm6_parser_emit_cast(sm6, record, ins, dst); - break; -@@ -4261,11 +5740,21 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - case FUNC_CODE_INST_LOAD: - sm6_parser_emit_load(sm6, record, ins, dst); - break; -+ case FUNC_CODE_INST_PHI: -+ sm6_parser_emit_phi(sm6, record, function, code_block, ins, dst); -+ break; - case FUNC_CODE_INST_RET: - sm6_parser_emit_ret(sm6, record, code_block, ins); - is_terminator = true; - ret_found = true; - break; -+ case FUNC_CODE_INST_STORE: -+ sm6_parser_emit_store(sm6, record, ins, dst); -+ break; -+ case FUNC_CODE_INST_SWITCH: -+ sm6_parser_emit_switch(sm6, record, function, code_block, ins); -+ is_terminator = true; -+ break; - case FUNC_CODE_INST_VSELECT: - sm6_parser_emit_vselect(sm6, record, ins, dst); - break; -@@ -4278,41 +5767,159 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - return VKD3D_ERROR; - assert(ins->handler_idx != VKD3DSIH_INVALID); - -- if (is_terminator) -- { -- ++block_idx; -- code_block = (block_idx < function->block_count) ? function->blocks[block_idx] : NULL; -- } -- if (code_block) -- code_block->instruction_count += ins->handler_idx != VKD3DSIH_NOP; -- else -- assert(ins->handler_idx == VKD3DSIH_NOP); -+ if (record->attachment) -+ metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); -+ -+ if (is_terminator) -+ { -+ ++block_idx; -+ code_block = (block_idx < function->block_count) ? function->blocks[block_idx] : NULL; -+ } -+ if (code_block) -+ code_block->instruction_count += ins->handler_idx != VKD3DSIH_NOP; -+ else -+ assert(ins->handler_idx == VKD3DSIH_NOP); -+ -+ if (dst->type && fwd_type && dst->type != fwd_type) -+ { -+ WARN("Type mismatch.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "The type of a result value does not match the type defined by a forward reference."); -+ } -+ -+ sm6->value_count += !!dst->type; -+ } -+ -+ if (!ret_found) -+ { -+ WARN("Function contains no RET instruction.\n"); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ return sm6_function_resolve_phi_incomings(function, sm6); -+} -+ -+static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_parser *sm6) -+{ -+ struct vkd3d_shader_src_param *src_params; -+ struct vkd3d_shader_instruction *ins; -+ unsigned int i, count; -+ -+ switch (block->terminator.type) -+ { -+ case TERMINATOR_UNCOND_BR: -+ if (!block->terminator.true_block) -+ return; -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_BRANCH); -+ if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) -+ return; -+ vsir_src_param_init_label(&src_params[0], block->terminator.true_block->id); -+ break; -+ -+ case TERMINATOR_COND_BR: -+ if (!block->terminator.true_block || !block->terminator.false_block) -+ return; -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_BRANCH); -+ if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) -+ return; -+ src_param_init(&src_params[0]); -+ src_params[0].reg = block->terminator.conditional_reg; -+ vsir_src_param_init_label(&src_params[1], block->terminator.true_block->id); -+ vsir_src_param_init_label(&src_params[2], block->terminator.false_block->id); -+ break; -+ -+ case TERMINATOR_SWITCH: -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_SWITCH_MONOLITHIC); -+ if (!(src_params = instruction_src_params_alloc(ins, block->terminator.case_count * 2u + 1, sm6))) -+ return; -+ src_param_init(&src_params[0]); -+ src_params[0].reg = block->terminator.conditional_reg; -+ /* TODO: emit the merge block id. */ -+ vsir_src_param_init_label(&src_params[2], 0); -+ -+ for (i = 0, count = 3; i < block->terminator.case_count; ++i) -+ { -+ const struct terminator_case *switch_case; -+ const struct sm6_block *case_block; -+ -+ switch_case = &block->terminator.cases[i]; -+ if (!(case_block = switch_case->block)) -+ { -+ assert(sm6->p.failed); -+ continue; -+ } -+ if (switch_case->is_default) -+ { -+ vsir_src_param_init_label(&src_params[1], case_block->id); -+ continue; -+ } -+ -+ if (src_params[0].reg.data_type == VKD3D_DATA_UINT64) -+ { -+ vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST64, VKD3D_DATA_UINT64, 0); -+ src_params[count++].reg.u.immconst_u64[0] = switch_case->value; -+ } -+ else -+ { -+ if (switch_case->value > UINT_MAX) -+ { -+ WARN("Truncating 64-bit constant %"PRIx64".\n", switch_case->value); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "Truncating 64-bit switch case value %"PRIx64" to 32 bits.", switch_case->value); -+ } -+ vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST, VKD3D_DATA_UINT, 0); -+ src_params[count++].reg.u.immconst_u32[0] = switch_case->value; -+ } -+ vsir_src_param_init_label(&src_params[count++], case_block->id); -+ } -+ -+ break; - -- sm6->value_count += !!dst->type; -- } -+ case TERMINATOR_RET: -+ sm6_parser_add_instruction(sm6, VKD3DSIH_RET); -+ break; - -- if (!ret_found) -- { -- WARN("Function contains no RET instruction.\n"); -- return VKD3D_ERROR_INVALID_SHADER; -+ default: -+ vkd3d_unreachable(); - } -- -- return VKD3D_OK; - } - --static bool sm6_block_emit_instructions(struct sm6_block *block, struct sm6_parser *sm6) -+static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser *sm6) - { -- struct vkd3d_shader_instruction *ins = sm6_parser_require_space(sm6, block->instruction_count + 1); -+ struct vkd3d_shader_instruction *ins; -+ unsigned int i, j, incoming_count; -+ const struct sm6_phi *src_phi; - -- if (!ins) -- return false; -+ for (i = 0; i < block->phi_count; ++i) -+ { -+ struct vkd3d_shader_src_param *src_params; -+ struct vkd3d_shader_dst_param *dst_param; - -- memcpy(ins, block->instructions, block->instruction_count * sizeof(*block->instructions)); -- sm6->p.instructions.count += block->instruction_count; -+ src_phi = &block->phi[i]; -+ incoming_count = src_phi->incoming_count; - -- sm6_parser_add_instruction(sm6, VKD3DSIH_RET); -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_PHI); -+ if (!(src_params = instruction_src_params_alloc(ins, incoming_count * 2u, sm6))) -+ return; -+ if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) -+ return; - -- return true; -+ for (j = 0; j < incoming_count; ++j) -+ { -+ const struct sm6_block *incoming_block = src_phi->incoming[j].block; -+ unsigned int index = j * 2; -+ -+ src_param_init(&src_params[index]); -+ src_params[index].reg = src_phi->incoming[j].reg; -+ if (incoming_block) -+ vsir_src_param_init_label(&src_params[index + 1], incoming_block->id); -+ else -+ assert(sm6->p.failed); -+ } -+ -+ dst_param_init(dst_param); -+ dst_param->reg = src_phi->reg; -+ } - } - - static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const struct dxil_block *block, -@@ -4331,6 +5938,8 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st - sm6->p.location.line = block->id; - sm6->p.location.column = 0; - -+ sm6_parser_metadata_attachments_init(sm6, block); -+ - switch (block->id) - { - case CONSTANTS_BLOCK: -@@ -4370,6 +5979,48 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st - return VKD3D_OK; - } - -+static void sm6_parser_emit_label(struct sm6_parser *sm6, unsigned int label_id) -+{ -+ struct vkd3d_shader_src_param *src_param; -+ struct vkd3d_shader_instruction *ins; -+ -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_LABEL); -+ -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; -+ vsir_src_param_init_label(src_param, label_id); -+} -+ -+static enum vkd3d_result sm6_function_emit_blocks(const struct sm6_function *function, struct sm6_parser *sm6) -+{ -+ unsigned int i; -+ -+ sm6->p.program.block_count = function->block_count; -+ -+ for (i = 0; i < function->block_count; ++i) -+ { -+ const struct sm6_block *block = function->blocks[i]; -+ -+ /* Space for the label and terminator. */ -+ if (!sm6_parser_require_space(sm6, block->instruction_count + block->phi_count + 2)) -+ { -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory emitting shader instructions."); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ sm6_parser_emit_label(sm6, block->id); -+ sm6_block_emit_phi(block, sm6); -+ -+ memcpy(&sm6->p.program.instructions.elements[sm6->p.program.instructions.count], block->instructions, -+ block->instruction_count * sizeof(*block->instructions)); -+ sm6->p.program.instructions.count += block->instruction_count; -+ -+ sm6_block_emit_terminator(block, sm6); -+ } -+ -+ return VKD3D_OK; -+} -+ - static bool sm6_parser_allocate_named_metadata(struct sm6_parser *sm6) - { - struct dxil_block *block; -@@ -4644,8 +6295,10 @@ static enum vkd3d_shader_minimum_precision minimum_precision_from_dxil_component - static const enum vkd3d_shader_sysval_semantic sysval_semantic_table[] = - { - [SEMANTIC_KIND_ARBITRARY] = VKD3D_SHADER_SV_NONE, -+ [SEMANTIC_KIND_VERTEXID] = VKD3D_SHADER_SV_VERTEX_ID, - [SEMANTIC_KIND_POSITION] = VKD3D_SHADER_SV_POSITION, -- [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_NONE, -+ [SEMANTIC_KIND_ISFRONTFACE] = VKD3D_SHADER_SV_IS_FRONT_FACE, -+ [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_TARGET, - }; - - static enum vkd3d_shader_sysval_semantic sysval_semantic_from_dxil_semantic_kind(enum dxil_semantic_kind kind) -@@ -4727,6 +6380,332 @@ static bool sm6_parser_resources_load_register_range(struct sm6_parser *sm6, - return true; - } - -+static bool resource_kind_is_texture(enum dxil_resource_kind kind) -+{ -+ return kind >= RESOURCE_KIND_TEXTURE1D && kind <= RESOURCE_KIND_TEXTURECUBEARRAY; -+} -+ -+static bool resource_kind_is_multisampled(enum dxil_resource_kind kind) -+{ -+ return kind == RESOURCE_KIND_TEXTURE2DMS || kind == RESOURCE_KIND_TEXTURE2DMSARRAY; -+} -+ -+static enum vkd3d_shader_resource_type shader_resource_type_from_dxil_resource_kind(enum dxil_resource_kind kind) -+{ -+ if (resource_kind_is_texture(kind)) -+ return kind + 1; -+ -+ switch (kind) -+ { -+ case RESOURCE_KIND_TYPEDBUFFER: -+ case RESOURCE_KIND_RAWBUFFER: -+ case RESOURCE_KIND_STRUCTUREDBUFFER: -+ return VKD3D_SHADER_RESOURCE_BUFFER; -+ default: -+ return VKD3D_SHADER_RESOURCE_NONE; -+ } -+} -+ -+static const enum vkd3d_data_type data_type_table[] = -+{ -+ [COMPONENT_TYPE_INVALID] = VKD3D_DATA_UNUSED, -+ [COMPONENT_TYPE_I1] = VKD3D_DATA_UNUSED, -+ [COMPONENT_TYPE_I16] = VKD3D_DATA_INT, -+ [COMPONENT_TYPE_U16] = VKD3D_DATA_UINT, -+ [COMPONENT_TYPE_I32] = VKD3D_DATA_INT, -+ [COMPONENT_TYPE_U32] = VKD3D_DATA_UINT, -+ [COMPONENT_TYPE_I64] = VKD3D_DATA_UNUSED, -+ [COMPONENT_TYPE_U64] = VKD3D_DATA_UNUSED, -+ [COMPONENT_TYPE_F16] = VKD3D_DATA_FLOAT, -+ [COMPONENT_TYPE_F32] = VKD3D_DATA_FLOAT, -+ [COMPONENT_TYPE_F64] = VKD3D_DATA_DOUBLE, -+ [COMPONENT_TYPE_SNORMF16] = VKD3D_DATA_SNORM, -+ [COMPONENT_TYPE_UNORMF16] = VKD3D_DATA_UNORM, -+ [COMPONENT_TYPE_SNORMF32] = VKD3D_DATA_SNORM, -+ [COMPONENT_TYPE_UNORMF32] = VKD3D_DATA_UNORM, -+ [COMPONENT_TYPE_SNORMF64] = VKD3D_DATA_DOUBLE, -+ [COMPONENT_TYPE_UNORMF64] = VKD3D_DATA_DOUBLE, -+ [COMPONENT_TYPE_PACKEDS8X32] = VKD3D_DATA_UNUSED, -+ [COMPONENT_TYPE_PACKEDU8X32] = VKD3D_DATA_UNUSED, -+}; -+ -+static enum vkd3d_data_type vkd3d_data_type_from_dxil_component_type(enum dxil_component_type type, -+ struct sm6_parser *sm6) -+{ -+ enum vkd3d_data_type data_type; -+ -+ if (type >= ARRAY_SIZE(data_type_table) || (data_type = data_type_table[type]) == VKD3D_DATA_UNUSED) -+ { -+ FIXME("Unhandled component type %u.\n", type); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Resource descriptor component type %u is unhandled.", type); -+ return VKD3D_DATA_FLOAT; -+ } -+ -+ return data_type; -+} -+ -+static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struct sm6_parser *sm6, -+ const struct sm6_metadata_value *type_value, bool is_uav, enum dxil_resource_kind kind, -+ const struct sm6_metadata_value *m, struct vkd3d_shader_instruction *ins) -+{ -+ enum vkd3d_shader_resource_type resource_type; -+ enum dxil_resource_type dxil_resource_type; -+ const struct sm6_metadata_node *node; -+ enum vkd3d_data_type data_type; -+ unsigned int i, values[2]; -+ -+ if (!(resource_type = shader_resource_type_from_dxil_resource_kind(kind))) -+ { -+ FIXME("Unhandled resource kind %u.\n", kind); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Resource kind %u is unhandled.", kind); -+ return NULL; -+ } -+ ins->resource_type = resource_type; -+ -+ if (!m) -+ { -+ ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; -+ ins->declaration.raw_resource.resource.reg.write_mask = 0; -+ return &ins->declaration.raw_resource.resource; -+ } -+ -+ if (!sm6_metadata_value_is_node(m)) -+ { -+ WARN("Resource metadata list is not a node.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Resource descriptor metadata list is not a node."); -+ return NULL; -+ } -+ -+ node = m->u.node; -+ -+ if (node->operand_count < 2) -+ { -+ WARN("Invalid operand count %u.\n", node->operand_count); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Invalid operand count %u for a resource descriptor.", node->operand_count); -+ return NULL; -+ } -+ if (node->operand_count > 2) -+ { -+ WARN("Ignoring %u extra operands.\n", node->operand_count - 2); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring %u extra operands for a resource descriptor.", node->operand_count - 2); -+ } -+ -+ for (i = 0; i < 2; ++i) -+ { -+ if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &values[i])) -+ { -+ WARN("Failed to load uint value at index %u.\n", i); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "A resource descriptor operand metadata value is not an integer."); -+ return NULL; -+ } -+ } -+ -+ if ((dxil_resource_type = values[0]) == RESOURCE_TYPE_NON_RAW_STRUCTURED) -+ { -+ if (kind != RESOURCE_KIND_TYPEDBUFFER && !resource_kind_is_texture(kind)) -+ { -+ WARN("Unhandled resource kind %u.\n", kind); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Resource kind %u for a typed resource is unhandled.", kind); -+ return NULL; -+ } -+ -+ data_type = vkd3d_data_type_from_dxil_component_type(values[1], sm6); -+ ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_TYPED : VKD3DSIH_DCL; -+ for (i = 0; i < VKD3D_VEC4_SIZE; ++i) -+ ins->declaration.semantic.resource_data_type[i] = data_type; -+ ins->declaration.semantic.resource_type = resource_type; -+ ins->declaration.semantic.resource.reg.write_mask = VKD3DSP_WRITEMASK_ALL; -+ -+ return &ins->declaration.semantic.resource; -+ } -+ else if (dxil_resource_type == RESOURCE_TYPE_RAW_STRUCTURED) -+ { -+ if (kind == RESOURCE_KIND_RAWBUFFER) -+ { -+ ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; -+ ins->declaration.raw_resource.resource.reg.write_mask = 0; -+ -+ return &ins->declaration.raw_resource.resource; -+ } -+ -+ if (kind != RESOURCE_KIND_STRUCTUREDBUFFER) -+ { -+ WARN("Unhandled resource kind %u.\n", kind); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Resource kind %u for a raw or structured buffer is unhandled.", kind); -+ return NULL; -+ } -+ -+ ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_STRUCTURED : VKD3DSIH_DCL_RESOURCE_STRUCTURED; -+ ins->declaration.structured_resource.byte_stride = values[1]; -+ ins->declaration.structured_resource.resource.reg.write_mask = 0; -+ -+ /* TODO: 16-bit resources. */ -+ if (ins->declaration.structured_resource.byte_stride % 4u) -+ { -+ WARN("Byte stride %u is not a multiple of 4.\n", ins->declaration.structured_resource.byte_stride); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Structured resource byte stride %u is not a multiple of 4.", -+ ins->declaration.structured_resource.byte_stride); -+ } -+ -+ return &ins->declaration.structured_resource.resource; -+ } -+ else -+ { -+ FIXME("Unhandled resource type %u.\n", dxil_resource_type); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Resource type %u is unhandled.", dxil_resource_type); -+ } -+ -+ return NULL; -+} -+ -+static void init_resource_declaration(struct vkd3d_shader_resource *resource, -+ enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int id, -+ const struct vkd3d_shader_register_range *range) -+{ -+ struct vkd3d_shader_dst_param *param = &resource->reg; -+ -+ param->modifiers = 0; -+ param->shift = 0; -+ vsir_register_init(¶m->reg, reg_type, data_type, 3); -+ param->reg.idx[0].offset = id; -+ param->reg.idx[1].offset = range->first; -+ param->reg.idx[2].offset = range->last; -+ -+ resource->range = *range; -+} -+ -+static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, -+ const struct sm6_metadata_node *node, struct sm6_descriptor_info *d, struct vkd3d_shader_instruction *ins) -+{ -+ struct vkd3d_shader_resource *resource; -+ unsigned int kind; -+ -+ if (node->operand_count < 9) -+ { -+ WARN("Invalid operand count %u.\n", node->operand_count); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Invalid operand count %u for an SRV descriptor.", node->operand_count); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ if (node->operand_count > 9) -+ { -+ WARN("Ignoring %u extra operands.\n", node->operand_count - 9); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring %u extra operands for an SRV descriptor.", node->operand_count - 9); -+ } -+ -+ if (!sm6_metadata_get_uint_value(sm6, node->operands[6], &kind)) -+ { -+ WARN("Failed to load resource type.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "SRV resource type metadata value is not an integer."); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_INVALID); -+ -+ if (!(resource = sm6_parser_resources_load_common_info(sm6, node->operands[1], false, kind, -+ node->operands[8], ins))) -+ { -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ d->resource_type = ins->resource_type; -+ d->kind = kind; -+ d->reg_type = VKD3DSPR_RESOURCE; -+ d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_RESOURCE; -+ d->resource_data_type = (ins->handler_idx == VKD3DSIH_DCL) -+ ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; -+ -+ init_resource_declaration(resource, VKD3DSPR_RESOURCE, d->reg_data_type, d->id, &d->range); -+ -+ if (resource_kind_is_multisampled(kind)) -+ { -+ if (!sm6_metadata_get_uint_value(sm6, node->operands[7], &ins->declaration.semantic.sample_count)) -+ { -+ WARN("Failed to load sample count.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "SRV sample count metadata value is not an integer."); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ } -+ else if (!sm6_metadata_value_is_zero_or_undef(node->operands[7])) -+ { -+ WARN("Ignoring sample count value.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring an SRV descriptor sample count metadata value which is not constant zero or undefined."); -+ } -+ -+ return VKD3D_OK; -+} -+ -+static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, -+ const struct sm6_metadata_node *node, struct sm6_descriptor_info *d, struct vkd3d_shader_instruction *ins) -+{ -+ struct vkd3d_shader_resource *resource; -+ unsigned int i, values[4]; -+ -+ if (node->operand_count < 11) -+ { -+ WARN("Invalid operand count %u.\n", node->operand_count); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Invalid operand count %u for a UAV descriptor.", node->operand_count); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ if (node->operand_count > 11) -+ { -+ WARN("Ignoring %u extra operands.\n", node->operand_count - 11); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring %u extra operands for a UAV descriptor.", node->operand_count - 11); -+ } -+ -+ for (i = 6; i < 10; ++i) -+ { -+ if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &values[i - 6])) -+ { -+ WARN("Failed to load uint value at index %u.\n", i); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "A UAV descriptor operand metadata value is not an integer."); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ } -+ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_INVALID); -+ if (values[1]) -+ ins->flags = VKD3DSUF_GLOBALLY_COHERENT; -+ if (values[2]) -+ ins->flags |= VKD3DSUF_ORDER_PRESERVING_COUNTER; -+ if (values[3]) -+ ins->flags |= VKD3DSUF_RASTERISER_ORDERED_VIEW; -+ -+ if (!(resource = sm6_parser_resources_load_common_info(sm6, node->operands[1], true, values[0], -+ node->operands[10], ins))) -+ { -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ d->resource_type = ins->resource_type; -+ d->kind = values[0]; -+ d->reg_type = VKD3DSPR_UAV; -+ d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_UAV; -+ d->resource_data_type = (ins->handler_idx == VKD3DSIH_DCL_UAV_TYPED) -+ ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; -+ -+ init_resource_declaration(resource, VKD3DSPR_UAV, d->reg_data_type, d->id, &d->range); -+ -+ return VKD3D_OK; -+} -+ - static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6, - const struct sm6_metadata_node *node, struct sm6_descriptor_info *d, struct vkd3d_shader_instruction *ins) - { -@@ -4769,6 +6748,10 @@ static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6, - - ins->declaration.cb.range = d->range; - -+ d->reg_type = VKD3DSPR_CONSTBUFFER; -+ d->reg_data_type = VKD3D_DATA_FLOAT; -+ d->resource_data_type = VKD3D_DATA_FLOAT; -+ - return VKD3D_OK; - } - -@@ -4840,6 +6823,14 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, - if ((ret = sm6_parser_resources_load_cbv(sm6, node, d, ins)) < 0) - return ret; - break; -+ case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: -+ if ((ret = sm6_parser_resources_load_srv(sm6, node, d, ins)) < 0) -+ return ret; -+ break; -+ case VKD3D_SHADER_DESCRIPTOR_TYPE_UAV: -+ if ((ret = sm6_parser_resources_load_uav(sm6, node, d, ins)) < 0) -+ return ret; -+ break; - default: - FIXME("Unsupported descriptor type %u.\n", type); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -@@ -4848,7 +6839,7 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, - } - - ++sm6->descriptor_count; -- ++sm6->p.instructions.count; -+ ++sm6->p.program.instructions.count; - } - - return VKD3D_OK; -@@ -5198,9 +7189,9 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co - unsigned int group_sizes[3]; - unsigned int i; - -- if (sm6->p.shader_version.type != VKD3D_SHADER_TYPE_COMPUTE) -+ if (sm6->p.program.shader_version.type != VKD3D_SHADER_TYPE_COMPUTE) - { -- WARN("Shader of type %#x has thread group dimensions.\n", sm6->p.shader_version.type); -+ WARN("Shader of type %#x has thread group dimensions.\n", sm6->p.program.shader_version.type); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, - "Shader has thread group dimensions but is not a compute shader."); - return VKD3D_ERROR_INVALID_SHADER; -@@ -5285,7 +7276,7 @@ static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) - - sm6->entry_point = value->u.function.name; - if (!sm6_metadata_value_is_string(entry_node->operands[1]) -- || ascii_strcasecmp(sm6->entry_point, entry_node->operands[1]->u.string_value)) -+ || strcmp(sm6->entry_point, entry_node->operands[1]->u.string_value)) - { - WARN("Entry point function name %s mismatch.\n", sm6->entry_point); - vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH, -@@ -5419,9 +7410,20 @@ static void sm6_symtab_cleanup(struct sm6_symbol *symbols, size_t count) - vkd3d_free(symbols); - } - -+static void sm6_phi_destroy(struct sm6_phi *phi) -+{ -+ vkd3d_free(phi->incoming); -+} -+ - static void sm6_block_destroy(struct sm6_block *block) - { -+ unsigned int i; -+ - vkd3d_free(block->instructions); -+ for (i = 0; i < block->phi_count; ++i) -+ sm6_phi_destroy(&block->phi[i]); -+ vkd3d_free(block->phi); -+ vkd3d_free(block->terminator.cases); - vkd3d_free(block); - } - -@@ -5433,6 +7435,7 @@ static void sm6_functions_cleanup(struct sm6_function *functions, size_t count) - { - for (j = 0; j < functions[i].block_count; ++j) - sm6_block_destroy(functions[i].blocks[j]); -+ vkd3d_free(functions[i].blocks); - } - vkd3d_free(functions); - } -@@ -5443,7 +7446,7 @@ static void sm6_parser_destroy(struct vkd3d_shader_parser *parser) - - dxil_block_destroy(&sm6->root_block); - dxil_global_abbrevs_cleanup(sm6->abbrevs, sm6->abbrev_count); -- shader_instruction_array_destroy(&parser->instructions); -+ vsir_program_cleanup(&parser->program); - sm6_type_table_cleanup(sm6->types, sm6->type_count); - sm6_symtab_cleanup(sm6->global_symbols, sm6->global_symbol_count); - sm6_functions_cleanup(sm6->functions, sm6->function_count); -@@ -5463,7 +7466,7 @@ static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6 - { - size_t i; - for (i = 0; i < sm6->function_count; ++i) -- if (!ascii_strcasecmp(sm6->functions[i].declaration->u.function.name, name)) -+ if (!strcmp(sm6->functions[i].declaration->u.function.name, name)) - return &sm6->functions[i]; - return NULL; - } -@@ -5538,7 +7541,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((magic = sm6->start[0]) != BITCODE_MAGIC) - { - WARN("Unknown magic number 0x%08x.\n", magic); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER, -+ vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER, - "DXIL bitcode chunk magic number 0x%08x is not the expected 0x%08x.", magic, BITCODE_MAGIC); - } - -@@ -5547,7 +7550,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((version.type = version_token >> 16) >= VKD3D_SHADER_TYPE_COUNT) - { - FIXME("Unknown shader type %#x.\n", version.type); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE, -+ vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE, - "Unknown shader type %#x.", version.type); - } - -@@ -5573,10 +7576,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((ret = dxil_block_init(block, NULL, sm6)) < 0) - { - if (ret == VKD3D_ERROR_OUT_OF_MEMORY) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory parsing DXIL bitcode chunk."); - else if (ret == VKD3D_ERROR_INVALID_SHADER) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE, - "DXIL bitcode chunk has invalid bitcode."); - else - vkd3d_unreachable(); -@@ -5606,10 +7609,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((ret = sm6_parser_type_table_init(sm6)) < 0) - { - if (ret == VKD3D_ERROR_OUT_OF_MEMORY) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory parsing DXIL type table."); - else if (ret == VKD3D_ERROR_INVALID_SHADER) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE, - "DXIL type table is invalid."); - else - vkd3d_unreachable(); -@@ -5619,21 +7622,21 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((ret = sm6_parser_symtab_init(sm6)) < 0) - { - if (ret == VKD3D_ERROR_OUT_OF_MEMORY) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory parsing DXIL value symbol table."); - else if (ret == VKD3D_ERROR_INVALID_SHADER) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB, - "DXIL value symbol table is invalid."); - else - vkd3d_unreachable(); - return ret; - } - -- if (!(sm6->output_params = shader_parser_get_dst_params(&sm6->p, output_signature->element_count)) -- || !(sm6->input_params = shader_parser_get_dst_params(&sm6->p, input_signature->element_count))) -+ if (!(sm6->output_params = vsir_program_get_dst_params(&sm6->p.program, output_signature->element_count)) -+ || !(sm6->input_params = vsir_program_get_dst_params(&sm6->p.program, input_signature->element_count))) - { - ERR("Failed to allocate input/output parameters.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory allocating input/output parameters."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -@@ -5642,7 +7645,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if (!(sm6->functions = vkd3d_calloc(function_count, sizeof(*sm6->functions)))) - { - ERR("Failed to allocate function array.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory allocating DXIL function array."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -@@ -5650,14 +7653,14 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if (sm6_parser_compute_max_value_count(sm6, &sm6->root_block, 0) == SIZE_MAX) - { - WARN("Value array count overflowed.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, - "Overflow occurred in the DXIL module value count."); - return VKD3D_ERROR_INVALID_SHADER; - } - if (!(sm6->values = vkd3d_calloc(sm6->value_capacity, sizeof(*sm6->values)))) - { - ERR("Failed to allocate value array.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory allocating DXIL value array."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -@@ -5684,7 +7687,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if (j == ARRAY_SIZE(sm6->metadata_tables)) - { - FIXME("Too many metadata tables.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, - "A metadata table count greater than %zu is unsupported.", ARRAY_SIZE(sm6->metadata_tables)); - return VKD3D_ERROR_INVALID_SHADER; - } -@@ -5702,24 +7705,22 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((ret = sm6_parser_module_init(sm6, &sm6->root_block, 0)) < 0) - { - if (ret == VKD3D_ERROR_OUT_OF_MEMORY) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory parsing DXIL module."); - else if (ret == VKD3D_ERROR_INVALID_SHADER) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, - "DXIL module is invalid."); - return ret; - } - - if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count)) - { -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory emitting shader signature declarations."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -- sm6_parser_emit_output_signature(sm6, output_signature); -- sm6_parser_emit_input_signature(sm6, input_signature); - -- sm6->p.shader_desc.ssa_count = sm6->ssa_next_id; -+ sm6->p.program.ssa_count = sm6->ssa_next_id; - - if (!(fn = sm6_parser_get_function(sm6, sm6->entry_point))) - { -@@ -5730,12 +7731,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - } - - assert(sm6->function_count == 1); -- if (!sm6_block_emit_instructions(fn->blocks[0], sm6)) -- { -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -- "Out of memory emitting shader instructions."); -- return VKD3D_ERROR_OUT_OF_MEMORY; -- } -+ if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) -+ return ret; - - dxil_block_destroy(&sm6->root_block); - -@@ -5786,7 +7783,7 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi - vkd3d_free(byte_code); - - if (!sm6->p.failed && ret >= 0) -- vsir_validate(&sm6->p); -+ ret = vsir_validate(&sm6->p); - - if (sm6->p.failed && ret >= 0) - ret = VKD3D_ERROR_INVALID_SHADER; -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -new file mode 100644 -index 00000000000..e1459f76c14 ---- /dev/null -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -0,0 +1,515 @@ -+/* -+ * FX (Direct3D 9/10/11 effect) support -+ * -+ * Copyright 2023 Nikolay Sivov for CodeWeavers -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#include "hlsl.h" -+ -+struct string_entry -+{ -+ struct rb_entry entry; -+ /* String points to original data, should not be freed. */ -+ const char *string; -+ uint32_t offset; -+}; -+ -+static int string_storage_compare(const void *key, const struct rb_entry *entry) -+{ -+ struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); -+ const char *string = key; -+ -+ return strcmp(string, string_entry->string); -+} -+ -+static void string_storage_destroy(struct rb_entry *entry, void *context) -+{ -+ struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); -+ -+ vkd3d_free(string_entry); -+} -+ -+struct fx_write_context; -+ -+struct fx_write_context_ops -+{ -+ uint32_t (*write_string)(const char *string, struct fx_write_context *fx); -+ void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx); -+ void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx); -+}; -+ -+struct fx_write_context -+{ -+ struct hlsl_ctx *ctx; -+ -+ struct vkd3d_bytecode_buffer unstructured; -+ struct vkd3d_bytecode_buffer structured; -+ -+ struct rb_tree strings; -+ -+ unsigned int min_technique_version; -+ unsigned int max_technique_version; -+ -+ uint32_t technique_count; -+ uint32_t group_count; -+ int status; -+ -+ const struct fx_write_context_ops *ops; -+}; -+ -+static uint32_t write_string(const char *string, struct fx_write_context *fx) -+{ -+ return fx->ops->write_string(string, fx); -+} -+ -+static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ fx->ops->write_pass(var, fx); -+} -+ -+static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_context_ops *ops, -+ struct fx_write_context *fx) -+{ -+ unsigned int version = ctx->profile->major_version; -+ -+ memset(fx, 0, sizeof(*fx)); -+ -+ fx->ctx = ctx; -+ fx->ops = ops; -+ if (version == 2) -+ { -+ fx->min_technique_version = 9; -+ fx->max_technique_version = 9; -+ } -+ else if (version == 4) -+ { -+ fx->min_technique_version = 10; -+ fx->max_technique_version = 10; -+ } -+ else if (version == 5) -+ { -+ fx->min_technique_version = 10; -+ fx->max_technique_version = 11; -+ } -+ -+ rb_init(&fx->strings, string_storage_compare); -+} -+ -+static int fx_write_context_cleanup(struct fx_write_context *fx) -+{ -+ int status = fx->status; -+ rb_destroy(&fx->strings, string_storage_destroy, NULL); -+ -+ return status; -+} -+ -+static bool technique_matches_version(const struct hlsl_ir_var *var, const struct fx_write_context *fx) -+{ -+ const struct hlsl_type *type = var->data_type; -+ -+ if (type->base_type != HLSL_TYPE_TECHNIQUE) -+ return false; -+ -+ return type->e.version >= fx->min_technique_version && type->e.version <= fx->max_technique_version; -+} -+ -+static uint32_t write_fx_4_string(const char *string, struct fx_write_context *fx) -+{ -+ struct string_entry *string_entry; -+ struct rb_entry *entry; -+ -+ /* NULLs are emitted as empty strings using the same 4 bytes at the start of the section. */ -+ if (!string) -+ return 0; -+ -+ if ((entry = rb_get(&fx->strings, string))) -+ { -+ string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); -+ return string_entry->offset; -+ } -+ -+ if (!(string_entry = hlsl_alloc(fx->ctx, sizeof(*string_entry)))) -+ return 0; -+ -+ string_entry->offset = put_string(&fx->unstructured, string); -+ string_entry->string = string; -+ -+ rb_put(&fx->strings, string, &string_entry->entry); -+ -+ return string_entry->offset; -+} -+ -+static void write_fx_4_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t name_offset; -+ -+ name_offset = write_string(var->name, fx); -+ put_u32(buffer, name_offset); -+ put_u32(buffer, 0); /* Assignment count. */ -+ put_u32(buffer, 0); /* Annotation count. */ -+ -+ /* TODO: annotations */ -+ /* TODO: assignments */ -+} -+ -+static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t name_offset; -+ -+ name_offset = write_string(var->name, fx); -+ put_u32(buffer, name_offset); -+ put_u32(buffer, 0); /* Annotation count. */ -+ put_u32(buffer, 0); /* Assignment count. */ -+ -+ /* TODO: annotations */ -+ /* TODO: assignments */ -+} -+ -+static void write_fx_4_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t name_offset, count = 0; -+ struct hlsl_ir_var *pass; -+ uint32_t count_offset; -+ -+ name_offset = write_string(var->name, fx); -+ put_u32(buffer, name_offset); -+ count_offset = put_u32(buffer, 0); -+ put_u32(buffer, 0); /* Annotation count. */ -+ -+ LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ write_pass(pass, fx); -+ ++count; -+ } -+ -+ set_u32(buffer, count_offset, count); -+} -+ -+static void set_status(struct fx_write_context *fx, int status) -+{ -+ if (fx->status < 0) -+ return; -+ if (status < 0) -+ fx->status = status; -+} -+ -+static void write_techniques(struct hlsl_scope *scope, struct fx_write_context *fx) -+{ -+ struct hlsl_ir_var *var; -+ -+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ if (technique_matches_version(var, fx)) -+ { -+ fx->ops->write_technique(var, fx); -+ ++fx->technique_count; -+ } -+ } -+ -+ set_status(fx, fx->unstructured.status); -+ set_status(fx, fx->structured.status); -+} -+ -+static void write_group(struct hlsl_scope *scope, const char *name, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t name_offset = write_string(name, fx); -+ uint32_t count_offset, count; -+ -+ put_u32(buffer, name_offset); -+ count_offset = put_u32(buffer, 0); /* Technique count */ -+ put_u32(buffer, 0); /* Annotation count */ -+ -+ count = fx->technique_count; -+ write_techniques(scope, fx); -+ set_u32(buffer, count_offset, fx->technique_count - count); -+ -+ ++fx->group_count; -+} -+ -+static void write_groups(struct hlsl_scope *scope, struct fx_write_context *fx) -+{ -+ bool needs_default_group = false; -+ struct hlsl_ir_var *var; -+ -+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ if (technique_matches_version(var, fx)) -+ { -+ needs_default_group = true; -+ break; -+ } -+ } -+ -+ if (needs_default_group) -+ write_group(scope, NULL, fx); -+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ const struct hlsl_type *type = var->data_type; -+ -+ if (type->base_type == HLSL_TYPE_EFFECT_GROUP) -+ write_group(var->scope, var->name, fx); -+ } -+} -+ -+static uint32_t write_fx_2_string(const char *string, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; -+ const char *s = string ? string : ""; -+ uint32_t size, offset; -+ -+ size = strlen(s) + 1; -+ offset = put_u32(buffer, size); -+ bytecode_put_bytes(buffer, s, size); -+ return offset; -+} -+ -+static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t name_offset, count_offset, count = 0; -+ struct hlsl_ir_var *pass; -+ -+ name_offset = write_string(var->name, fx); -+ put_u32(buffer, name_offset); -+ put_u32(buffer, 0); /* Annotation count. */ -+ count_offset = put_u32(buffer, 0); /* Pass count. */ -+ -+ /* FIXME: annotations */ -+ -+ LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ write_pass(pass, fx); -+ ++count; -+ } -+ -+ set_u32(buffer, count_offset, count); -+} -+ -+static const struct fx_write_context_ops fx_2_ops = -+{ -+ .write_string = write_fx_2_string, -+ .write_technique = write_fx_2_technique, -+ .write_pass = write_fx_2_pass, -+}; -+ -+static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -+{ -+ struct vkd3d_bytecode_buffer buffer = { 0 }; -+ struct vkd3d_bytecode_buffer *structured; -+ uint32_t offset, size, technique_count; -+ struct fx_write_context fx; -+ -+ fx_write_context_init(ctx, &fx_2_ops, &fx); -+ structured = &fx.structured; -+ -+ /* First entry is always zeroed and skipped. */ -+ put_u32(&fx.unstructured, 0); -+ -+ put_u32(&buffer, 0xfeff0901); /* Version. */ -+ offset = put_u32(&buffer, 0); -+ -+ put_u32(structured, 0); /* Parameter count */ -+ technique_count = put_u32(structured, 0); -+ put_u32(structured, 0); /* Unknown */ -+ put_u32(structured, 0); /* Object count */ -+ -+ /* TODO: parameters */ -+ -+ write_techniques(ctx->globals, &fx); -+ set_u32(structured, technique_count, fx.technique_count); -+ -+ put_u32(structured, 0); /* String count */ -+ put_u32(structured, 0); /* Resource count */ -+ -+ /* TODO: strings */ -+ /* TODO: resources */ -+ -+ size = align(fx.unstructured.size, 4); -+ set_u32(&buffer, offset, size); -+ -+ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); -+ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); -+ -+ vkd3d_free(fx.unstructured.data); -+ vkd3d_free(fx.structured.data); -+ -+ if (!fx.status) -+ { -+ out->code = buffer.data; -+ out->size = buffer.size; -+ } -+ -+ if (fx.status < 0) -+ ctx->result = fx.status; -+ -+ return fx_write_context_cleanup(&fx); -+} -+ -+static const struct fx_write_context_ops fx_4_ops = -+{ -+ .write_string = write_fx_4_string, -+ .write_technique = write_fx_4_technique, -+ .write_pass = write_fx_4_pass, -+}; -+ -+static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -+{ -+ struct vkd3d_bytecode_buffer buffer = { 0 }; -+ struct fx_write_context fx; -+ uint32_t size_offset, size; -+ -+ fx_write_context_init(ctx, &fx_4_ops, &fx); -+ -+ put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ -+ -+ /* TODO: buffers */ -+ /* TODO: objects */ -+ /* TODO: shared buffers */ -+ /* TODO: shared objects */ -+ -+ write_techniques(ctx->globals, &fx); -+ -+ put_u32(&buffer, ctx->profile->minor_version == 0 ? 0xfeff1001 : 0xfeff1011); /* Version. */ -+ put_u32(&buffer, 0); /* Buffer count. */ -+ put_u32(&buffer, 0); /* Variable count. */ -+ put_u32(&buffer, 0); /* Object count. */ -+ put_u32(&buffer, 0); /* Pool buffer count. */ -+ put_u32(&buffer, 0); /* Pool variable count. */ -+ put_u32(&buffer, 0); /* Pool object count. */ -+ put_u32(&buffer, fx.technique_count); -+ size_offset = put_u32(&buffer, 0); /* Unstructured size. */ -+ put_u32(&buffer, 0); /* String count. */ -+ put_u32(&buffer, 0); /* Texture object count. */ -+ put_u32(&buffer, 0); /* Depth stencil state count. */ -+ put_u32(&buffer, 0); /* Blend state count. */ -+ put_u32(&buffer, 0); /* Rasterizer state count. */ -+ put_u32(&buffer, 0); /* Sampler state count. */ -+ put_u32(&buffer, 0); /* Rendertarget view count. */ -+ put_u32(&buffer, 0); /* Depth stencil view count. */ -+ put_u32(&buffer, 0); /* Shader count. */ -+ put_u32(&buffer, 0); /* Inline shader count. */ -+ -+ size = align(fx.unstructured.size, 4); -+ set_u32(&buffer, size_offset, size); -+ -+ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); -+ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); -+ -+ vkd3d_free(fx.unstructured.data); -+ vkd3d_free(fx.structured.data); -+ -+ set_status(&fx, buffer.status); -+ -+ if (!fx.status) -+ { -+ out->code = buffer.data; -+ out->size = buffer.size; -+ } -+ -+ if (fx.status < 0) -+ ctx->result = fx.status; -+ -+ return fx_write_context_cleanup(&fx); -+} -+ -+static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -+{ -+ struct vkd3d_bytecode_buffer buffer = { 0 }; -+ struct fx_write_context fx; -+ uint32_t size_offset, size; -+ -+ fx_write_context_init(ctx, &fx_4_ops, &fx); -+ -+ put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ -+ -+ /* TODO: buffers */ -+ /* TODO: objects */ -+ /* TODO: interface variables */ -+ -+ write_groups(ctx->globals, &fx); -+ -+ put_u32(&buffer, 0xfeff2001); /* Version. */ -+ put_u32(&buffer, 0); /* Buffer count. */ -+ put_u32(&buffer, 0); /* Variable count. */ -+ put_u32(&buffer, 0); /* Object count. */ -+ put_u32(&buffer, 0); /* Pool buffer count. */ -+ put_u32(&buffer, 0); /* Pool variable count. */ -+ put_u32(&buffer, 0); /* Pool object count. */ -+ put_u32(&buffer, fx.technique_count); -+ size_offset = put_u32(&buffer, 0); /* Unstructured size. */ -+ put_u32(&buffer, 0); /* String count. */ -+ put_u32(&buffer, 0); /* Texture object count. */ -+ put_u32(&buffer, 0); /* Depth stencil state count. */ -+ put_u32(&buffer, 0); /* Blend state count. */ -+ put_u32(&buffer, 0); /* Rasterizer state count. */ -+ put_u32(&buffer, 0); /* Sampler state count. */ -+ put_u32(&buffer, 0); /* Rendertarget view count. */ -+ put_u32(&buffer, 0); /* Depth stencil view count. */ -+ put_u32(&buffer, 0); /* Shader count. */ -+ put_u32(&buffer, 0); /* Inline shader count. */ -+ put_u32(&buffer, fx.group_count); /* Group count. */ -+ put_u32(&buffer, 0); /* UAV count. */ -+ put_u32(&buffer, 0); /* Interface variables count. */ -+ put_u32(&buffer, 0); /* Interface variable element count. */ -+ put_u32(&buffer, 0); /* Class instance elements count. */ -+ -+ size = align(fx.unstructured.size, 4); -+ set_u32(&buffer, size_offset, size); -+ -+ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); -+ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); -+ -+ vkd3d_free(fx.unstructured.data); -+ vkd3d_free(fx.structured.data); -+ -+ set_status(&fx, buffer.status); -+ -+ if (!fx.status) -+ { -+ out->code = buffer.data; -+ out->size = buffer.size; -+ } -+ -+ if (fx.status < 0) -+ ctx->result = fx.status; -+ -+ return fx_write_context_cleanup(&fx); -+} -+ -+int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -+{ -+ if (ctx->profile->major_version == 2) -+ { -+ return hlsl_fx_2_write(ctx, out); -+ } -+ else if (ctx->profile->major_version == 4) -+ { -+ return hlsl_fx_4_write(ctx, out); -+ } -+ else if (ctx->profile->major_version == 5) -+ { -+ return hlsl_fx_5_write(ctx, out); -+ } -+ else -+ { -+ vkd3d_unreachable(); -+ } -+} -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index f8d68b5a798..bdd03c1e72a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -91,7 +91,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator - } - - int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, -- struct vkd3d_shader_parser *parser, struct vkd3d_shader_code *out) -+ struct vsir_program *program, struct vkd3d_shader_code *out) - { - unsigned int i; - void *code; -@@ -100,10 +100,10 @@ int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, - vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n"); - - generator->location.column = 0; -- for (i = 0; i < parser->instructions.count; ++i) -+ for (i = 0; i < program->instructions.count; ++i) - { - generator->location.line = i + 1; -- vkd3d_glsl_handle_instruction(generator, &parser->instructions.elements[i]); -+ vkd3d_glsl_handle_instruction(generator, &program->instructions.elements[i]); - } - - if (generator->failed) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index da3bbda1bc3..04c37498d84 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -98,19 +98,22 @@ bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var - struct hlsl_scope *scope = ctx->cur_scope; - struct hlsl_ir_var *var; - -- LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) -+ if (decl->name) - { -- if (!strcmp(decl->name, var->name)) -- return false; -- } -- if (local_var && scope->upper->upper == ctx->globals) -- { -- /* Check whether the variable redefines a function parameter. */ -- LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) -+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) - { -- if (!strcmp(decl->name, var->name)) -+ if (var->name && !strcmp(decl->name, var->name)) - return false; - } -+ if (local_var && scope->upper->upper == ctx->globals) -+ { -+ /* Check whether the variable redefines a function parameter. */ -+ LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) -+ { -+ if (var->name && !strcmp(decl->name, var->name)) -+ return false; -+ } -+ } - } - - list_add_tail(&scope->vars, &decl->scope_entry); -@@ -123,7 +126,7 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name) - - LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) - { -- if (!strcmp(name, var->name)) -+ if (var->name && !strcmp(name, var->name)) - return var; - } - if (!scope->upper) -@@ -915,12 +918,17 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 - if (t1->class == HLSL_CLASS_ARRAY) - return t1->e.array.elements_count == t2->e.array.elements_count - && hlsl_types_are_equal(t1->e.array.type, t2->e.array.type); -+ if (t1->class == HLSL_CLASS_OBJECT) -+ { -+ if (t1->base_type == HLSL_TYPE_TECHNIQUE && t1->e.version != t2->e.version) -+ return false; -+ } - - return true; - } - - struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, -- unsigned int default_majority, unsigned int modifiers) -+ unsigned int default_majority, uint32_t modifiers) - { - struct hlsl_type *type; - -@@ -945,6 +953,8 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, - type->modifiers |= default_majority; - type->sampler_dim = old->sampler_dim; - type->is_minimum_precision = old->is_minimum_precision; -+ type->sample_count = old->sample_count; -+ - switch (old->class) - { - case HLSL_CLASS_ARRAY: -@@ -993,6 +1003,13 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, - break; - } - -+ case HLSL_CLASS_OBJECT: -+ if (type->base_type == HLSL_TYPE_TECHNIQUE) -+ type->e.version = old->e.version; -+ if (old->base_type == HLSL_TYPE_TEXTURE || old->base_type == HLSL_TYPE_UAV) -+ type->e.resource_format = old->e.resource_format; -+ break; -+ - default: - break; - } -@@ -1030,7 +1047,7 @@ struct hlsl_ir_node *hlsl_new_copy(struct hlsl_ctx *ctx, struct hlsl_ir_node *no - } - - struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, -- const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers, -+ const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, uint32_t modifiers, - const struct hlsl_reg_reservation *reg_reservation) - { - struct hlsl_ir_var *var; -@@ -1505,7 +1522,7 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct - return &store->node; - } - --struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components, -+struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components, - struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc) - { - struct hlsl_ir_swizzle *swizzle; -@@ -2246,7 +2263,7 @@ const char *debug_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type) - return ret; - } - --struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, unsigned int modifiers) -+struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, uint32_t modifiers) - { - struct vkd3d_string_buffer *string; - -@@ -2432,7 +2449,7 @@ const char *debug_hlsl_writemask(unsigned int writemask) - return vkd3d_dbg_sprintf(".%s", string); - } - --const char *debug_hlsl_swizzle(unsigned int swizzle, unsigned int size) -+const char *debug_hlsl_swizzle(uint32_t swizzle, unsigned int size) - { - static const char components[] = {'x', 'y', 'z', 'w'}; - char string[5]; -@@ -3147,9 +3164,10 @@ void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function - rb_put(&ctx->functions, func->name, &func->entry); - } - --unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask) -+uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask) - { -- unsigned int i, ret = 0; -+ uint32_t ret = 0; -+ unsigned int i; - - /* Leave replicate swizzles alone; some instructions need them. */ - if (swizzle == HLSL_SWIZZLE(X, X, X, X) -@@ -3169,7 +3187,7 @@ unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask) - return ret; - } - --unsigned int hlsl_swizzle_from_writemask(unsigned int writemask) -+uint32_t hlsl_swizzle_from_writemask(unsigned int writemask) - { - static const unsigned int swizzles[16] = - { -@@ -3210,9 +3228,10 @@ unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second) - return ret; - } - --unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim) -+uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim) - { -- unsigned int ret = 0, i; -+ uint32_t ret = 0; -+ unsigned int i; - for (i = 0; i < dim; ++i) - { - unsigned int s = hlsl_swizzle_get_component(second, i); -@@ -3346,15 +3365,28 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) - effect_types[] = - { - {"dword", HLSL_CLASS_SCALAR, HLSL_TYPE_UINT, 1, 1}, -- {"float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1}, - {"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1}, - {"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4}, -+ {"fxgroup", HLSL_CLASS_OBJECT, HLSL_TYPE_EFFECT_GROUP, 1, 1}, -+ {"pass", HLSL_CLASS_OBJECT, HLSL_TYPE_PASS, 1, 1}, - {"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1}, - {"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1}, - {"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1}, - {"VERTEXSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_VERTEXSHADER, 1, 1}, - }; - -+ static const struct -+ { -+ char *name; -+ unsigned int version; -+ } -+ technique_types[] = -+ { -+ {"technique", 9}, -+ {"technique10", 10}, -+ {"technique11", 11}, -+ }; -+ - for (bt = 0; bt <= HLSL_TYPE_LAST_SCALAR; ++bt) - { - for (y = 1; y <= 4; ++y) -@@ -3459,6 +3491,13 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) - effect_types[i].base_type, effect_types[i].dimx, effect_types[i].dimy); - hlsl_scope_add_type(ctx->globals, type); - } -+ -+ for (i = 0; i < ARRAY_SIZE(technique_types); ++i) -+ { -+ type = hlsl_new_type(ctx, technique_types[i].name, HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE, 1, 1); -+ type->e.version = technique_types[i].version; -+ hlsl_scope_add_type(ctx->globals, type); -+ } - } - - static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, -@@ -3594,7 +3633,13 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d - return VKD3D_ERROR_NOT_IMPLEMENTED; - } - -- if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) -+ if (compile_info->target_type != VKD3D_SHADER_TARGET_FX && profile->type == VKD3D_SHADER_TYPE_EFFECT) -+ { -+ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -+ "The '%s' target profile is only compatible with the 'fx' target type.", profile->name); -+ return VKD3D_ERROR_INVALID_ARGUMENT; -+ } -+ else if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) - { - vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, - "The '%s' target profile is incompatible with the 'd3dbc' target type.", profile->name); -@@ -3606,6 +3651,12 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d - "The '%s' target profile is incompatible with the 'dxbc-tpf' target type.", profile->name); - return VKD3D_ERROR_INVALID_ARGUMENT; - } -+ else if (compile_info->target_type == VKD3D_SHADER_TARGET_FX && profile->type != VKD3D_SHADER_TYPE_EFFECT) -+ { -+ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -+ "The '%s' target profile is incompatible with the 'fx' target type.", profile->name); -+ return VKD3D_ERROR_INVALID_ARGUMENT; -+ } - - if (!hlsl_ctx_init(&ctx, compile_info, profile, message_context)) - return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -3630,6 +3681,14 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d - return VKD3D_ERROR_NOT_IMPLEMENTED; - } - -+ if (ctx.profile->type == VKD3D_SHADER_TYPE_EFFECT) -+ { -+ ret = hlsl_emit_effect_binary(&ctx, out); -+ -+ hlsl_ctx_cleanup(&ctx); -+ return ret; -+ } -+ - if ((func = hlsl_get_function(&ctx, entry_point))) - { - LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index ca75a1936f1..984ac7e4883 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -65,7 +65,7 @@ - #define HLSL_SWIZZLE_MASK (0x3u) - #define HLSL_SWIZZLE_SHIFT(idx) (2u * (idx)) - --static inline unsigned int hlsl_swizzle_get_component(unsigned int swizzle, unsigned int idx) -+static inline unsigned int hlsl_swizzle_get_component(uint32_t swizzle, unsigned int idx) - { - return (swizzle >> HLSL_SWIZZLE_SHIFT(idx)) & HLSL_SWIZZLE_MASK; - } -@@ -95,6 +95,9 @@ enum hlsl_base_type - HLSL_TYPE_UAV, - HLSL_TYPE_PIXELSHADER, - HLSL_TYPE_VERTEXSHADER, -+ HLSL_TYPE_PASS, -+ HLSL_TYPE_TECHNIQUE, -+ HLSL_TYPE_EFFECT_GROUP, - HLSL_TYPE_STRING, - HLSL_TYPE_VOID, - }; -@@ -138,8 +141,10 @@ struct hlsl_type - struct rb_entry scope_entry; - - enum hlsl_type_class class; -- /* If type is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR. -- * If type is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR. -+ /* If class is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR. -+ * If class is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR. -+ * If class is HLSL_CLASS_OBJECT and base_type is HLSL_TYPE_TECHNIQUE, additional version -+ * field is used to distinguish between technique types. - * Otherwise, base_type is not used. */ - enum hlsl_base_type base_type; - -@@ -155,7 +160,7 @@ struct hlsl_type - /* Bitfield for storing type modifiers, subset of HLSL_TYPE_MODIFIERS_MASK. - * Modifiers that don't fall inside this mask are to be stored in the variable in - * hlsl_ir_var.modifiers, or in the struct field in hlsl_ir_field.modifiers. */ -- unsigned int modifiers; -+ uint32_t modifiers; - /* Size of the type values on each dimension. For non-numeric types, they are set for the - * convenience of the sm1/sm4 backends. - * If type is HLSL_CLASS_SCALAR, then both dimx = 1 and dimy = 1. -@@ -191,6 +196,8 @@ struct hlsl_type - /* Format of the data contained within the type if the base_type is HLSL_TYPE_TEXTURE or - * HLSL_TYPE_UAV. */ - struct hlsl_type *resource_format; -+ /* Additional field to distinguish object types. Currently used only for technique types. */ -+ unsigned int version; - } e; - - /* Number of numeric register components used by one value of this type, for each regset. -@@ -234,7 +241,7 @@ struct hlsl_struct_field - /* Bitfield for storing modifiers that are not in HLSL_TYPE_MODIFIERS_MASK (these are stored in - * type->modifiers instead) and that also are specific to the field and not the whole variable. - * In particular, interpolation modifiers. */ -- unsigned int storage_modifiers; -+ uint32_t storage_modifiers; - /* Offset of the field within the type it belongs to, in register components, for each regset. */ - unsigned int reg_offset[HLSL_REGSET_LAST + 1]; - -@@ -392,7 +399,7 @@ struct hlsl_ir_var - /* Buffer where the variable's value is stored, in case it is uniform. */ - struct hlsl_buffer *buffer; - /* Bitfield for storage modifiers (type modifiers are stored in data_type->modifiers). */ -- unsigned int storage_modifiers; -+ uint32_t storage_modifiers; - /* Optional reservations of registers and/or offsets for variables within constant buffers. */ - struct hlsl_reg_reservation reg_reservation; - -@@ -400,6 +407,10 @@ struct hlsl_ir_var - struct list scope_entry; - /* Item entry in hlsl_ctx.extern_vars, if the variable is extern. */ - struct list extern_entry; -+ /* Scope that variable itself defines, used to provide a container for techniques and passes. */ -+ struct hlsl_scope *scope; -+ /* Scope that contains annotations for this variable. */ -+ struct hlsl_scope *annotations; - - /* Indexes of the IR instructions where the variable is first written and last read (liveness - * range). The IR instructions are numerated starting from 2, because 0 means unused, and 1 -@@ -622,7 +633,7 @@ struct hlsl_ir_swizzle - { - struct hlsl_ir_node node; - struct hlsl_src val; -- DWORD swizzle; -+ uint32_t swizzle; - }; - - struct hlsl_ir_index -@@ -1160,6 +1171,7 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl - - int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, - enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out); -+int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out); - - bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain); - bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other); -@@ -1250,7 +1262,7 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct - struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); - struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, - struct hlsl_struct_field *fields, size_t field_count); --struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components, -+struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components, - struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc); - struct hlsl_ir_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template, - struct hlsl_type *type, const struct vkd3d_shader_location *loc); -@@ -1264,7 +1276,7 @@ struct hlsl_ir_node *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n - struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, - const struct vkd3d_shader_location *loc); - struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, -- const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers, -+ const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, uint32_t modifiers, - const struct hlsl_reg_reservation *reg_reservation); - struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned int value, bool is_default, - struct hlsl_block *body, const struct vkd3d_shader_location *loc); -@@ -1286,7 +1298,7 @@ void hlsl_pop_scope(struct hlsl_ctx *ctx); - bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type); - - struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, -- unsigned int default_majority, unsigned int modifiers); -+ unsigned int default_majority, uint32_t modifiers); - unsigned int hlsl_type_component_count(const struct hlsl_type *type); - unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type, enum hlsl_regset regset); - struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type, -@@ -1304,10 +1316,10 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 - const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type); - unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type); - --unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim); -+uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim); - unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second); --unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask); --unsigned int hlsl_swizzle_from_writemask(unsigned int writemask); -+uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask); -+uint32_t hlsl_swizzle_from_writemask(unsigned int writemask); - - struct hlsl_type *hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); - enum hlsl_regset hlsl_deref_get_regset(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -index fe838750747..6cef0e02eff 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -@@ -89,6 +89,7 @@ else {return KW_ELSE; } - extern {return KW_EXTERN; } - false {return KW_FALSE; } - for {return KW_FOR; } -+fxgroup {return KW_FXGROUP; } - GeometryShader {return KW_GEOMETRYSHADER; } - groupshared {return KW_GROUPSHARED; } - if {return KW_IF; } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 0dde4c18587..8dc353e11c0 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -40,7 +40,7 @@ struct parse_parameter - const char *name; - struct hlsl_semantic semantic; - struct hlsl_reg_reservation reg_reservation; -- unsigned int modifiers; -+ uint32_t modifiers; - }; - - struct parse_colon_attribute -@@ -75,7 +75,7 @@ struct parse_variable_def - struct parse_initializer initializer; - - struct hlsl_type *basic_type; -- unsigned int modifiers; -+ uint32_t modifiers; - struct vkd3d_shader_location modifiers_loc; - }; - -@@ -292,6 +292,21 @@ static bool implicit_compatible_data_types(struct hlsl_ctx *ctx, struct hlsl_typ - return hlsl_types_are_componentwise_equal(ctx, src, dst); - } - -+static void check_condition_type(struct hlsl_ctx *ctx, const struct hlsl_ir_node *cond) -+{ -+ const struct hlsl_type *type = cond->data_type; -+ -+ if (type->class > HLSL_CLASS_LAST_NUMERIC || type->dimx > 1 || type->dimy > 1) -+ { -+ struct vkd3d_string_buffer *string; -+ -+ if ((string = hlsl_type_to_string(ctx, type))) -+ hlsl_error(ctx, &cond->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "Condition type '%s' is not a scalar numeric type.", string->buffer); -+ hlsl_release_string_buffer(ctx, string); -+ } -+} -+ - static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct hlsl_block *block, - struct hlsl_ir_node *node, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc) - { -@@ -405,7 +420,7 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct - return add_cast(ctx, block, node, dst_type, loc); - } - --static DWORD add_modifiers(struct hlsl_ctx *ctx, DWORD modifiers, DWORD mod, -+static uint32_t add_modifiers(struct hlsl_ctx *ctx, uint32_t modifiers, uint32_t mod, - const struct vkd3d_shader_location *loc) - { - if (modifiers & mod) -@@ -431,6 +446,9 @@ static bool append_conditional_break(struct hlsl_ctx *ctx, struct hlsl_block *co - return true; - - condition = node_from_block(cond_block); -+ -+ check_condition_type(ctx, condition); -+ - if (!(not = hlsl_new_unary_expr(ctx, HLSL_OP1_LOGIC_NOT, condition, &condition->loc))) - return false; - hlsl_block_add_instr(cond_block, not); -@@ -487,27 +505,27 @@ static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block - else if (instr->type == HLSL_IR_JUMP) - { - struct hlsl_ir_jump *jump = hlsl_ir_jump(instr); -- struct hlsl_block block; -+ struct hlsl_block cond_block; - - if (jump->type != HLSL_IR_JUMP_UNRESOLVED_CONTINUE) - continue; - - if (type == LOOP_DO_WHILE) - { -- if (!hlsl_clone_block(ctx, &block, cond)) -+ if (!hlsl_clone_block(ctx, &cond_block, cond)) - return; -- if (!append_conditional_break(ctx, &block)) -+ if (!append_conditional_break(ctx, &cond_block)) - { -- hlsl_block_cleanup(&block); -+ hlsl_block_cleanup(&cond_block); - return; - } -- list_move_before(&instr->entry, &block.instrs); -+ list_move_before(&instr->entry, &cond_block.instrs); - } - else if (type == LOOP_FOR) - { -- if (!hlsl_clone_block(ctx, &block, iter)) -+ if (!hlsl_clone_block(ctx, &cond_block, iter)) - return; -- list_move_before(&instr->entry, &block.instrs); -+ list_move_before(&instr->entry, &cond_block.instrs); - } - jump->type = HLSL_IR_JUMP_CONTINUE; - } -@@ -868,7 +886,7 @@ static const struct hlsl_struct_field *get_struct_field(const struct hlsl_struct - } - - static struct hlsl_type *apply_type_modifiers(struct hlsl_ctx *ctx, struct hlsl_type *type, -- unsigned int *modifiers, bool force_majority, const struct vkd3d_shader_location *loc) -+ uint32_t *modifiers, bool force_majority, const struct vkd3d_shader_location *loc) - { - unsigned int default_majority = 0; - struct hlsl_type *new_type; -@@ -926,7 +944,7 @@ static bool shader_profile_version_lt(const struct hlsl_ctx *ctx, unsigned int m - } - - static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields, -- struct hlsl_type *type, unsigned int modifiers, struct list *defs) -+ struct hlsl_type *type, uint32_t modifiers, struct list *defs) - { - struct parse_variable_def *v, *v_next; - size_t i = 0; -@@ -1019,7 +1037,7 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type, - } - else - { -- unsigned int var_modifiers = 0; -+ uint32_t var_modifiers = 0; - - if (!(type = apply_type_modifiers(ctx, orig_type, &var_modifiers, true, &v->loc))) - { -@@ -1096,6 +1114,83 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters - return true; - } - -+static bool add_pass(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *annotations, -+ const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_var *var; -+ struct hlsl_type *type; -+ -+ type = hlsl_get_type(ctx->globals, "pass", false, false); -+ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) -+ return false; -+ var->annotations = annotations; -+ -+ if (!hlsl_add_var(ctx, var, false)) -+ { -+ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); -+ -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, -+ "Identifier \"%s\" was already declared in this scope.", var->name); -+ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); -+ hlsl_free_var(var); -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, -+ struct hlsl_scope *annotations, const char *typename, const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_var *var; -+ struct hlsl_type *type; -+ -+ type = hlsl_get_type(ctx->globals, typename, false, false); -+ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) -+ return false; -+ var->scope = scope; -+ var->annotations = annotations; -+ -+ if (!hlsl_add_var(ctx, var, false)) -+ { -+ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); -+ -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, -+ "Identifier \"%s\" was already declared in this scope.", var->name); -+ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); -+ hlsl_free_var(var); -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, -+ struct hlsl_scope *annotations, const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_var *var; -+ struct hlsl_type *type; -+ -+ type = hlsl_get_type(ctx->globals, "fxgroup", false, false); -+ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) -+ return false; -+ var->scope = scope; -+ var->annotations = annotations; -+ -+ if (!hlsl_add_var(ctx, var, false)) -+ { -+ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); -+ -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, -+ "Identifier \"%s\" was already declared in this scope.", var->name); -+ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); -+ hlsl_free_var(var); -+ return false; -+ } -+ -+ return true; -+} -+ - static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string) - { - struct hlsl_reg_reservation reservation = {0}; -@@ -1717,7 +1812,7 @@ static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op) - return ops[op]; - } - --static bool invert_swizzle(unsigned int *swizzle, unsigned int *writemask, unsigned int *ret_width) -+static bool invert_swizzle(uint32_t *swizzle, unsigned int *writemask, unsigned int *ret_width) - { - unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0; - -@@ -1791,8 +1886,9 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - else if (lhs->type == HLSL_IR_SWIZZLE) - { - struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs); -- unsigned int width, s = swizzle->swizzle; - struct hlsl_ir_node *new_swizzle; -+ uint32_t s = swizzle->swizzle; -+ unsigned int width; - - if (lhs->data_type->class == HLSL_CLASS_MATRIX) - hlsl_fixme(ctx, &lhs->loc, "Matrix assignment with a writemask."); -@@ -3553,7 +3649,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * - { - struct hlsl_resource_load_params load_params = { 0 }; - const struct hlsl_type *sampler_type; -- struct hlsl_ir_node *coords, *load; -+ struct hlsl_ir_node *coords, *sample; - - if (params->args_count != 2 && params->args_count != 4) - { -@@ -3688,9 +3784,9 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * - load_params.format = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); - load_params.sampling_dim = dim; - -- if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) -+ if (!(sample = hlsl_new_resource_load(ctx, &load_params, loc))) - return false; -- hlsl_block_add_instr(params->instrs, load); -+ hlsl_block_add_instr(params->instrs, sample); - return true; - } - -@@ -4034,6 +4130,89 @@ static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type - return params->instrs; - } - -+static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, -+ struct hlsl_ir_node *cond, struct hlsl_ir_node *first, struct hlsl_ir_node *second) -+{ -+ struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; -+ struct hlsl_type *cond_type = cond->data_type; -+ struct hlsl_type *common_type; -+ -+ if (cond_type->class > HLSL_CLASS_LAST_NUMERIC) -+ { -+ struct vkd3d_string_buffer *string; -+ -+ if ((string = hlsl_type_to_string(ctx, cond_type))) -+ hlsl_error(ctx, &cond->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "Ternary condition type '%s' is not numeric.", string->buffer); -+ hlsl_release_string_buffer(ctx, string); -+ } -+ -+ if (first->data_type->class <= HLSL_CLASS_LAST_NUMERIC -+ && second->data_type->class <= HLSL_CLASS_LAST_NUMERIC) -+ { -+ if (!(common_type = get_common_numeric_type(ctx, first, second, &first->loc))) -+ return false; -+ -+ if (cond_type->dimx == 1 && cond_type->dimy == 1) -+ { -+ cond_type = hlsl_get_numeric_type(ctx, common_type->class, -+ HLSL_TYPE_BOOL, common_type->dimx, common_type->dimy); -+ if (!(cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc))) -+ return false; -+ } -+ else if (common_type->dimx == 1 && common_type->dimy == 1) -+ { -+ common_type = hlsl_get_numeric_type(ctx, cond_type->class, -+ common_type->base_type, cond_type->dimx, cond_type->dimy); -+ } -+ else if (cond_type->dimx != common_type->dimx || cond_type->dimy != common_type->dimy) -+ { -+ /* This condition looks wrong but is correct. -+ * floatN is compatible with float1xN, but not with floatNx1. */ -+ -+ struct vkd3d_string_buffer *cond_string, *value_string; -+ -+ cond_string = hlsl_type_to_string(ctx, cond_type); -+ value_string = hlsl_type_to_string(ctx, common_type); -+ if (cond_string && value_string) -+ hlsl_error(ctx, &first->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "Ternary condition type '%s' is not compatible with value type '%s'.", -+ cond_string->buffer, value_string->buffer); -+ hlsl_release_string_buffer(ctx, cond_string); -+ hlsl_release_string_buffer(ctx, value_string); -+ } -+ -+ if (!(first = add_implicit_conversion(ctx, block, first, common_type, &first->loc))) -+ return false; -+ -+ if (!(second = add_implicit_conversion(ctx, block, second, common_type, &second->loc))) -+ return false; -+ } -+ else -+ { -+ struct vkd3d_string_buffer *first_string, *second_string; -+ -+ if (!hlsl_types_are_equal(first->data_type, second->data_type)) -+ { -+ first_string = hlsl_type_to_string(ctx, first->data_type); -+ second_string = hlsl_type_to_string(ctx, second->data_type); -+ if (first_string && second_string) -+ hlsl_error(ctx, &first->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "Ternary argument types '%s' and '%s' do not match.", -+ first_string->buffer, second_string->buffer); -+ hlsl_release_string_buffer(ctx, first_string); -+ hlsl_release_string_buffer(ctx, second_string); -+ } -+ -+ common_type = first->data_type; -+ } -+ -+ args[0] = cond; -+ args[1] = first; -+ args[2] = second; -+ return add_expr(ctx, block, HLSL_OP3_TERNARY, args, common_type, &first->loc); -+} -+ - static unsigned int hlsl_offset_dim_count(enum hlsl_sampler_dim dim) - { - switch (dim) -@@ -4844,7 +5023,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - FLOAT floatval; - bool boolval; - char *name; -- DWORD modifiers; -+ uint32_t modifiers; - struct hlsl_ir_node *instr; - struct hlsl_block *block; - struct list *list; -@@ -4865,6 +5044,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - struct hlsl_attribute *attr; - struct parse_attribute_list attr_list; - struct hlsl_ir_switch_case *switch_case; -+ struct hlsl_scope *scope; - } - - %token KW_BLENDSTATE -@@ -4887,6 +5067,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - %token KW_EXTERN - %token KW_FALSE - %token KW_FOR -+%token KW_FXGROUP - %token KW_GEOMETRYSHADER - %token KW_GROUPSHARED - %token KW_IF -@@ -4989,6 +5170,8 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - %token STRING - %token TYPE_IDENTIFIER - -+%type annotations_opt -+ - %type arrays - - %type assign_op -@@ -5051,7 +5234,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - - %type any_identifier - %type var_identifier --%type technique_name -+%type name_opt - - %type parameter - -@@ -5093,50 +5276,114 @@ hlsl_prog: - destroy_block($2); - } - | hlsl_prog preproc_directive -- | hlsl_prog technique -+ | hlsl_prog global_technique -+ | hlsl_prog effect_group - | hlsl_prog ';' - --technique_name: -+name_opt: - %empty - { - $$ = NULL; - } - | any_identifier - --pass_list: -+pass: -+ KW_PASS name_opt annotations_opt '{' '}' -+ { -+ if (!add_pass(ctx, $2, $3, &@1)) -+ YYABORT; -+ } -+ -+annotations_list: -+ variables_def_typed ';' -+ | annotations_list variables_def_typed ';' -+ -+annotations_opt: - %empty -+ { -+ $$ = NULL; -+ } -+ | '<' scope_start '>' -+ { -+ hlsl_pop_scope(ctx); -+ $$ = NULL; -+ } -+ | '<' scope_start annotations_list '>' -+ { -+ struct hlsl_scope *scope = ctx->cur_scope; -+ -+ hlsl_pop_scope(ctx); -+ $$ = scope; -+ } -+ -+pass_list: -+ pass -+ | pass_list pass -+ -+passes: -+ scope_start -+ | scope_start pass_list - - technique9: -- KW_TECHNIQUE technique_name '{' pass_list '}' -+ KW_TECHNIQUE name_opt annotations_opt '{' passes '}' - { -- hlsl_fixme(ctx, &@$, "Unsupported \'technique\' declaration."); -+ struct hlsl_scope *scope = ctx->cur_scope; -+ hlsl_pop_scope(ctx); -+ -+ if (!add_technique(ctx, $2, scope, $3, "technique", &@1)) -+ YYABORT; - } - - technique10: -- KW_TECHNIQUE10 technique_name '{' pass_list '}' -+ KW_TECHNIQUE10 name_opt annotations_opt '{' passes '}' - { -+ struct hlsl_scope *scope = ctx->cur_scope; -+ hlsl_pop_scope(ctx); -+ - if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, - "The 'technique10' keyword is invalid for this profile."); - -- hlsl_fixme(ctx, &@$, "Unsupported \'technique10\' declaration."); -+ if (!add_technique(ctx, $2, scope, $3, "technique10", &@1)) -+ YYABORT; - } - - technique11: -- KW_TECHNIQUE11 technique_name '{' pass_list '}' -+ KW_TECHNIQUE11 name_opt annotations_opt '{' passes '}' - { -+ struct hlsl_scope *scope = ctx->cur_scope; -+ hlsl_pop_scope(ctx); -+ - if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, - "The 'technique11' keyword is invalid for this profile."); - -- hlsl_fixme(ctx, &@$, "Unsupported \'technique11\' declaration."); -+ if (!add_technique(ctx, $2, scope, $3, "technique11", &@1)) -+ YYABORT; - } - --technique: -+global_technique: - technique9 - | technique10 - | technique11 - -+group_technique: -+ technique10 -+ | technique11 -+ -+group_techniques: -+ group_technique -+ | group_techniques group_technique -+ -+effect_group: -+ KW_FXGROUP any_identifier annotations_opt '{' scope_start group_techniques '}' -+ { -+ struct hlsl_scope *scope = ctx->cur_scope; -+ hlsl_pop_scope(ctx); -+ if (!(add_effect_group(ctx, $2, scope, $3, &@2))) -+ YYABORT; -+ } -+ - buffer_declaration: - buffer_type any_identifier colon_attribute - { -@@ -5282,7 +5529,7 @@ field: - var_modifiers field_type variables_def ';' - { - struct hlsl_type *type; -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - - if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) - YYABORT; -@@ -5435,7 +5682,7 @@ func_prototype_no_attrs: - /* var_modifiers is necessary to avoid shift/reduce conflicts. */ - var_modifiers type var_identifier '(' parameters ')' colon_attribute - { -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - struct hlsl_ir_var *var; - struct hlsl_type *type; - -@@ -5709,7 +5956,7 @@ param_list: - parameter: - var_modifiers type_no_void any_identifier arrays colon_attribute - { -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - struct hlsl_type *type; - unsigned int i; - -@@ -6023,7 +6270,7 @@ typedef: - KW_TYPEDEF var_modifiers typedef_type type_specs ';' - { - struct parse_variable_def *v, *v_next; -- unsigned int modifiers = $2; -+ uint32_t modifiers = $2; - struct hlsl_type *type; - - if (!(type = apply_type_modifiers(ctx, $3, &modifiers, false, &@2))) -@@ -6160,7 +6407,7 @@ variable_def: - variable_def_typed: - var_modifiers struct_spec variable_def - { -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - struct hlsl_type *type; - - if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) -@@ -6175,7 +6422,7 @@ variable_def_typed: - } - | var_modifiers type variable_def - { -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - struct hlsl_type *type; - - if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) -@@ -6516,6 +6763,15 @@ selection_statement: - } - } - -+ check_condition_type(ctx, condition); -+ -+ if (!(condition = add_cast(ctx, $4, condition, hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL), &@4))) -+ { -+ destroy_block($6.then_block); -+ destroy_block($6.else_block); -+ YYABORT; -+ } -+ - if (!(instr = hlsl_new_if(ctx, condition, $6.then_block, $6.else_block, &@2))) - { - destroy_block($6.then_block); -@@ -6524,15 +6780,7 @@ selection_statement: - } - destroy_block($6.then_block); - destroy_block($6.else_block); -- if (condition->data_type->dimx > 1 || condition->data_type->dimy > 1) -- { -- struct vkd3d_string_buffer *string; - -- if ((string = hlsl_type_to_string(ctx, condition->data_type))) -- hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -- "if condition type %s is not scalar.", string->buffer); -- hlsl_release_string_buffer(ctx, string); -- } - $$ = $4; - hlsl_block_add_instr($$, instr); - } -@@ -7112,27 +7360,13 @@ conditional_expr: - struct hlsl_ir_node *cond = node_from_block($1); - struct hlsl_ir_node *first = node_from_block($3); - struct hlsl_ir_node *second = node_from_block($5); -- struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = { 0 }; -- struct hlsl_type *common_type; - - hlsl_block_add_block($1, $3); - hlsl_block_add_block($1, $5); - destroy_block($3); - destroy_block($5); - -- if (!(common_type = get_common_numeric_type(ctx, first, second, &@3))) -- YYABORT; -- -- if (!(first = add_implicit_conversion(ctx, $1, first, common_type, &@3))) -- YYABORT; -- -- if (!(second = add_implicit_conversion(ctx, $1, second, common_type, &@5))) -- YYABORT; -- -- args[0] = cond; -- args[1] = first; -- args[2] = second; -- if (!add_expr(ctx, $1, HLSL_OP3_TERNARY, args, common_type, &@1)) -+ if (!add_ternary(ctx, $1, cond, first, second)) - YYABORT; - $$ = $1; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 4a622185741..6ad60e4c6c2 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -32,6 +32,11 @@ static struct hlsl_ir_node *new_offset_from_path_index(struct hlsl_ctx *ctx, str - switch (type->class) - { - case HLSL_CLASS_VECTOR: -+ if (idx->type != HLSL_IR_CONSTANT) -+ { -+ hlsl_fixme(ctx, &idx->loc, "Non-constant vector addressing."); -+ break; -+ } - *offset_component += hlsl_ir_constant(idx)->value.u[0].u; - break; - -@@ -263,7 +268,7 @@ static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hls - } - - static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, -- struct hlsl_type *type, unsigned int modifiers, struct hlsl_semantic *semantic, -+ struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, - uint32_t index, bool output, const struct vkd3d_shader_location *loc) - { - struct hlsl_semantic new_semantic; -@@ -331,7 +336,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir - } - - static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *lhs, -- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) -+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) - { - struct hlsl_type *type = lhs->node.data_type, *vector_type_src, *vector_type_dst; - struct vkd3d_shader_location *loc = &lhs->node.loc; -@@ -395,7 +400,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s - } - - static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *lhs, -- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) -+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) - { - struct vkd3d_shader_location *loc = &lhs->node.loc; - struct hlsl_type *type = lhs->node.data_type; -@@ -411,7 +416,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * - - for (i = 0; i < hlsl_type_element_count(type); ++i) - { -- unsigned int element_modifiers = modifiers; -+ uint32_t element_modifiers = modifiers; - - if (type->class == HLSL_CLASS_ARRAY) - { -@@ -473,7 +478,7 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_block *bloc - } - - static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *rhs, -- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) -+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) - { - struct hlsl_type *type = rhs->node.data_type, *vector_type; - struct vkd3d_shader_location *loc = &rhs->node.loc; -@@ -529,7 +534,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s - } - - static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *rhs, -- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) -+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) - { - struct vkd3d_shader_location *loc = &rhs->node.loc; - struct hlsl_type *type = rhs->node.data_type; -@@ -1090,7 +1095,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, - unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim); - struct hlsl_ir_node *coords = index->idx.node; - struct hlsl_resource_load_params params = {0}; -- struct hlsl_ir_node *load; -+ struct hlsl_ir_node *resource_load; - - assert(coords->data_type->class == HLSL_CLASS_VECTOR); - assert(coords->data_type->base_type == HLSL_TYPE_UINT); -@@ -1104,9 +1109,9 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, - params.coords = coords; - params.format = val->data_type->e.resource_format; - -- if (!(load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) -+ if (!(resource_load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) - return false; -- hlsl_block_add_instr(block, load); -+ hlsl_block_add_instr(block, resource_load); - return true; - } - -@@ -1519,7 +1524,7 @@ static void copy_propagation_set_value(struct hlsl_ctx *ctx, struct copy_propaga - - static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, - const struct copy_propagation_state *state, const struct hlsl_ir_load *load, -- unsigned int swizzle, struct hlsl_ir_node *instr) -+ uint32_t swizzle, struct hlsl_ir_node *instr) - { - const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type); - const struct hlsl_deref *deref = &load->src; -@@ -1527,7 +1532,7 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, - struct hlsl_ir_node *new_instr = NULL; - unsigned int time = load->node.index; - unsigned int start, count, i; -- unsigned int ret_swizzle = 0; -+ uint32_t ret_swizzle = 0; - - if (!hlsl_component_index_range_from_deref(ctx, deref, &start, &count)) - return false; -@@ -1573,7 +1578,7 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, - - static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx, - const struct copy_propagation_state *state, const struct hlsl_ir_load *load, -- unsigned int swizzle, struct hlsl_ir_node *instr) -+ uint32_t swizzle, struct hlsl_ir_node *instr) - { - const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type); - const struct hlsl_deref *deref = &load->src; -@@ -2239,7 +2244,7 @@ static bool fold_swizzle_chains(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr - if (next_instr->type == HLSL_IR_SWIZZLE) - { - struct hlsl_ir_node *new_swizzle; -- unsigned int combined_swizzle; -+ uint32_t combined_swizzle; - - combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->swizzle, - swizzle->swizzle, instr->data_type->dimx); -@@ -2301,7 +2306,6 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in - struct hlsl_ir_switch_case *c, *def = NULL; - bool missing_terminal_break = false; - struct hlsl_ir_node *node; -- struct hlsl_ir_jump *jump; - struct hlsl_ir_switch *s; - - if (instr->type != HLSL_IR_SWITCH) -@@ -2320,10 +2324,7 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in - { - node = LIST_ENTRY(list_tail(&c->body.instrs), struct hlsl_ir_node, entry); - if (node->type == HLSL_IR_JUMP) -- { -- jump = hlsl_ir_jump(node); -- terminal_break = jump->type == HLSL_IR_JUMP_BREAK; -- } -+ terminal_break = (hlsl_ir_jump(node)->type == HLSL_IR_JUMP_BREAK); - } - - missing_terminal_break |= !terminal_break; -@@ -2482,6 +2483,38 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir - return false; - } - -+static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) -+{ -+ struct hlsl_ir_node *idx; -+ struct hlsl_deref *deref; -+ struct hlsl_type *type; -+ unsigned int i; -+ -+ if (instr->type != HLSL_IR_STORE) -+ return false; -+ -+ deref = &hlsl_ir_store(instr)->lhs; -+ assert(deref->var); -+ -+ if (deref->path_len == 0) -+ return false; -+ -+ type = deref->var->data_type; -+ for (i = 0; i < deref->path_len - 1; ++i) -+ type = hlsl_get_element_type_from_path_index(ctx, type, deref->path[i].node); -+ -+ idx = deref->path[deref->path_len - 1].node; -+ -+ if (type->class == HLSL_CLASS_VECTOR && idx->type != HLSL_IR_CONSTANT) -+ { -+ /* We should turn this into an hlsl_error after we implement unrolling, because if we get -+ * here after that, it means that the HLSL is invalid. */ -+ hlsl_fixme(ctx, &instr->loc, "Non-constant vector addressing on store. Unrolling may be missing."); -+ } -+ -+ return false; -+} -+ - /* Lower combined samples and sampler variables to synthesized separated textures and samplers. - * That is, translate SM1-style samples in the source to SM4-style samples in the bytecode. */ - static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) -@@ -2857,6 +2890,12 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru - first = expr->operands[1].node; - second = expr->operands[2].node; - -+ if (cond->data_type->class > HLSL_CLASS_VECTOR || instr->data_type->class > HLSL_CLASS_VECTOR) -+ { -+ hlsl_fixme(ctx, &instr->loc, "Lower ternary of type other than scalar or vector.\n"); -+ return false; -+ } -+ - if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL) - { - struct hlsl_ir_node *abs, *neg; -@@ -3149,7 +3188,7 @@ static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru - - for (i = 0; i < dimx; ++i) - { -- unsigned int s = hlsl_swizzle_from_writemask(1 << i); -+ uint32_t s = hlsl_swizzle_from_writemask(1 << i); - - if (!(comps[i] = hlsl_new_swizzle(ctx, s, 1, mult, &instr->loc))) - return false; -@@ -4084,13 +4123,46 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi - - LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) - { -- if (var->is_uniform && var->last_read) -+ unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; -+ -+ if (!var->is_uniform || !var->last_read || reg_size == 0) -+ continue; -+ -+ if (var->reg_reservation.reg_type == 'c') - { -- unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; -+ unsigned int reg_idx = var->reg_reservation.reg_index; -+ unsigned int i; - -- if (reg_size == 0) -- continue; -+ assert(reg_size % 4 == 0); -+ for (i = 0; i < reg_size / 4; ++i) -+ { -+ if (get_available_writemask(&allocator, 1, UINT_MAX, reg_idx + i) != VKD3DSP_WRITEMASK_ALL) -+ { -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -+ "Overlapping register() reservations on 'c%u'.", reg_idx + i); -+ } -+ -+ record_allocation(ctx, &allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX); -+ } -+ -+ var->regs[HLSL_REGSET_NUMERIC].id = reg_idx; -+ var->regs[HLSL_REGSET_NUMERIC].allocation_size = reg_size / 4; -+ var->regs[HLSL_REGSET_NUMERIC].writemask = VKD3DSP_WRITEMASK_ALL; -+ var->regs[HLSL_REGSET_NUMERIC].allocated = true; -+ TRACE("Allocated reserved %s to %s.\n", var->name, -+ debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type)); -+ } -+ } - -+ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) -+ { -+ unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; -+ -+ if (!var->is_uniform || !var->last_read || reg_size == 0) -+ continue; -+ -+ if (!var->regs[HLSL_REGSET_NUMERIC].allocated) -+ { - var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, &allocator, - 1, UINT_MAX, var->data_type); - TRACE("Allocated %s to %s.\n", var->name, -@@ -4230,45 +4302,52 @@ static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint3 - return NULL; - } - --static void calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *var) -+static void calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, bool register_reservation) - { - unsigned int var_reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; - enum hlsl_type_class var_class = var->data_type->class; - struct hlsl_buffer *buffer = var->buffer; - -- if (var->reg_reservation.offset_type == 'c') -+ if (register_reservation) -+ { -+ var->buffer_offset = 4 * var->reg_reservation.reg_index; -+ } -+ else - { -- if (var->reg_reservation.offset_index % 4) -+ if (var->reg_reservation.offset_type == 'c') - { -- if (var_class == HLSL_CLASS_MATRIX) -- { -- hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -- "packoffset() reservations with matrix types must be aligned with the beginning of a register."); -- } -- else if (var_class == HLSL_CLASS_ARRAY) -+ if (var->reg_reservation.offset_index % 4) - { -- hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -- "packoffset() reservations with array types must be aligned with the beginning of a register."); -- } -- else if (var_class == HLSL_CLASS_STRUCT) -- { -- hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -- "packoffset() reservations with struct types must be aligned with the beginning of a register."); -- } -- else if (var_class == HLSL_CLASS_VECTOR) -- { -- unsigned int aligned_offset = hlsl_type_get_sm4_offset(var->data_type, var->reg_reservation.offset_index); -- -- if (var->reg_reservation.offset_index != aligned_offset) -+ if (var_class == HLSL_CLASS_MATRIX) -+ { - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -- "packoffset() reservations with vector types cannot span multiple registers."); -+ "packoffset() reservations with matrix types must be aligned with the beginning of a register."); -+ } -+ else if (var_class == HLSL_CLASS_ARRAY) -+ { -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -+ "packoffset() reservations with array types must be aligned with the beginning of a register."); -+ } -+ else if (var_class == HLSL_CLASS_STRUCT) -+ { -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -+ "packoffset() reservations with struct types must be aligned with the beginning of a register."); -+ } -+ else if (var_class == HLSL_CLASS_VECTOR) -+ { -+ unsigned int aligned_offset = hlsl_type_get_sm4_offset(var->data_type, var->reg_reservation.offset_index); -+ -+ if (var->reg_reservation.offset_index != aligned_offset) -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -+ "packoffset() reservations with vector types cannot span multiple registers."); -+ } - } -+ var->buffer_offset = var->reg_reservation.offset_index; -+ } -+ else -+ { -+ var->buffer_offset = hlsl_type_get_sm4_offset(var->data_type, buffer->size); - } -- var->buffer_offset = var->reg_reservation.offset_index; -- } -- else -- { -- var->buffer_offset = hlsl_type_get_sm4_offset(var->data_type, buffer->size); - } - - TRACE("Allocated buffer offset %u to %s.\n", var->buffer_offset, var->name); -@@ -4337,6 +4416,11 @@ static void validate_buffer_offsets(struct hlsl_ctx *ctx) - } - } - -+static bool var_has_buffer_offset_register_reservation(struct hlsl_ctx *ctx, const struct hlsl_ir_var *var) -+{ -+ return var->reg_reservation.reg_type == 'c' && var->buffer == ctx->globals_buffer; -+} -+ - static void allocate_buffers(struct hlsl_ctx *ctx) - { - struct hlsl_buffer *buffer; -@@ -4345,13 +4429,29 @@ static void allocate_buffers(struct hlsl_ctx *ctx) - - LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) - { -- if (var->is_uniform && !hlsl_type_is_resource(var->data_type)) -- { -- if (var->is_param) -- var->buffer = ctx->params_buffer; -+ if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) -+ continue; - -- calculate_buffer_offset(ctx, var); -- } -+ if (var->is_param) -+ var->buffer = ctx->params_buffer; -+ } -+ -+ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) -+ { -+ if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) -+ continue; -+ -+ if (var_has_buffer_offset_register_reservation(ctx, var)) -+ calculate_buffer_offset(ctx, var, true); -+ } -+ -+ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) -+ { -+ if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) -+ continue; -+ -+ if (!var_has_buffer_offset_register_reservation(ctx, var)) -+ calculate_buffer_offset(ctx, var, false); - } - - validate_buffer_offsets(ctx); -@@ -4973,6 +5073,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry - lower_ir(ctx, lower_abs, body); - } - -+ lower_ir(ctx, validate_nonconstant_vector_store_derefs, body); -+ - /* TODO: move forward, remove when no longer needed */ - transform_derefs(ctx, replace_deref_path_with_offset, body); - while (hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL)); -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 710811c6761..88634487482 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -18,15 +18,32 @@ - - #include "vkd3d_shader_private.h" - -+bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve) -+{ -+ program->shader_version = *version; -+ return shader_instruction_array_init(&program->instructions, reserve); -+} -+ -+void vsir_program_cleanup(struct vsir_program *program) -+{ -+ size_t i; -+ -+ for (i = 0; i < program->block_name_count; ++i) -+ vkd3d_free((void *)program->block_names[i]); -+ vkd3d_free(program->block_names); -+ shader_instruction_array_destroy(&program->instructions); -+} -+ - static inline bool shader_register_is_phase_instance_id(const struct vkd3d_shader_register *reg) - { - return reg->type == VKD3DSPR_FORKINSTID || reg->type == VKD3DSPR_JOININSTID; - } - --static bool shader_instruction_is_dcl(const struct vkd3d_shader_instruction *ins) -+static bool vsir_instruction_is_dcl(const struct vkd3d_shader_instruction *instruction) - { -- return (VKD3DSIH_DCL <= ins->handler_idx && ins->handler_idx <= VKD3DSIH_DCL_VERTICES_OUT) -- || ins->handler_idx == VKD3DSIH_HS_DECLS; -+ enum vkd3d_shader_opcode handler_idx = instruction->handler_idx; -+ return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT) -+ || handler_idx == VKD3DSIH_HS_DECLS; - } - - static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *ins) -@@ -36,6 +53,129 @@ static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *i - vsir_instruction_init(ins, &location, VKD3DSIH_NOP); - } - -+static void remove_dcl_temps(struct vsir_program *program) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < program->instructions.count; ++i) -+ { -+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; -+ -+ if (ins->handler_idx == VKD3DSIH_DCL_TEMPS) -+ vkd3d_shader_instruction_make_nop(ins); -+ } -+} -+ -+static bool vsir_instruction_init_with_params(struct vsir_program *program, -+ struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, -+ enum vkd3d_shader_opcode handler_idx, unsigned int dst_count, unsigned int src_count) -+{ -+ vsir_instruction_init(ins, location, handler_idx); -+ ins->dst_count = dst_count; -+ ins->src_count = src_count; -+ -+ if (!(ins->dst = vsir_program_get_dst_params(program, ins->dst_count))) -+ { -+ ERR("Failed to allocate %u destination parameters.\n", dst_count); -+ return false; -+ } -+ -+ if (!(ins->src = vsir_program_get_src_params(program, ins->src_count))) -+ { -+ ERR("Failed to allocate %u source parameters.\n", src_count); -+ return false; -+ } -+ -+ memset(ins->dst, 0, sizeof(*ins->dst) * ins->dst_count); -+ memset(ins->src, 0, sizeof(*ins->src) * ins->src_count); -+ return true; -+} -+ -+static enum vkd3d_result instruction_array_lower_texkills(struct vkd3d_shader_parser *parser) -+{ -+ struct vsir_program *program = &parser->program; -+ struct vkd3d_shader_instruction_array *instructions = &program->instructions; -+ struct vkd3d_shader_instruction *texkill_ins, *ins; -+ unsigned int components_read = 3 + (program->shader_version.major >= 2); -+ unsigned int tmp_idx = ~0u; -+ unsigned int i, k; -+ -+ for (i = 0; i < instructions->count; ++i) -+ { -+ texkill_ins = &instructions->elements[i]; -+ -+ if (texkill_ins->handler_idx != VKD3DSIH_TEXKILL) -+ continue; -+ -+ if (!shader_instruction_array_insert_at(instructions, i + 1, components_read + 1)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ if (tmp_idx == ~0u) -+ tmp_idx = program->temp_count++; -+ -+ /* tmp = ins->dst[0] < 0 */ -+ -+ ins = &instructions->elements[i + 1]; -+ if (!vsir_instruction_init_with_params(program, ins, &texkill_ins->location, VKD3DSIH_LTO, 1, 2)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -+ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->dst[0].reg.idx[0].offset = tmp_idx; -+ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; -+ -+ ins->src[0].reg = texkill_ins->dst[0].reg; -+ vsir_register_init(&ins->src[1].reg, VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); -+ ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[1].reg.u.immconst_f32[0] = 0.0f; -+ ins->src[1].reg.u.immconst_f32[1] = 0.0f; -+ ins->src[1].reg.u.immconst_f32[2] = 0.0f; -+ ins->src[1].reg.u.immconst_f32[3] = 0.0f; -+ -+ /* tmp.x = tmp.x || tmp.y */ -+ /* tmp.x = tmp.x || tmp.z */ -+ /* tmp.x = tmp.x || tmp.w, if sm >= 2.0 */ -+ -+ for (k = 1; k < components_read; ++k) -+ { -+ ins = &instructions->elements[i + 1 + k]; -+ if (!(vsir_instruction_init_with_params(program, ins, &texkill_ins->location, VKD3DSIH_OR, 1, 2))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -+ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->dst[0].reg.idx[0].offset = tmp_idx; -+ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; -+ -+ vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -+ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[0].reg.idx[0].offset = tmp_idx; -+ ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); -+ vsir_register_init(&ins->src[1].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -+ ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[1].reg.idx[0].offset = tmp_idx; -+ ins->src[1].swizzle = vkd3d_shader_create_swizzle(k, k, k, k); -+ } -+ -+ /* discard_nz tmp.x */ -+ -+ ins = &instructions->elements[i + 1 + components_read]; -+ if (!(vsir_instruction_init_with_params(program, ins, &texkill_ins->location, VKD3DSIH_DISCARD, 0, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; -+ -+ vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -+ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[0].reg.idx[0].offset = tmp_idx; -+ ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); -+ -+ /* Make the original instruction no-op */ -+ vkd3d_shader_instruction_make_nop(texkill_ins); -+ } -+ -+ return VKD3D_OK; -+} -+ - static void shader_register_eliminate_phase_addressing(struct vkd3d_shader_register *reg, - unsigned int instance_id) - { -@@ -63,7 +203,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i - if (shader_register_is_phase_instance_id(reg)) - { - vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0); -- reg->u.immconst_uint[0] = instance_id; -+ reg->u.immconst_u32[0] = instance_id; - continue; - } - shader_register_eliminate_phase_addressing(reg, instance_id); -@@ -143,9 +283,6 @@ struct hull_flattener - { - struct vkd3d_shader_instruction_array instructions; - -- unsigned int max_temp_count; -- unsigned int temp_dcl_idx; -- - unsigned int instance_count; - unsigned int phase_body_idx; - enum vkd3d_shader_opcode phase; -@@ -203,23 +340,8 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal - vkd3d_shader_instruction_make_nop(ins); - return; - } -- else if (ins->handler_idx == VKD3DSIH_DCL_TEMPS && normaliser->phase != VKD3DSIH_INVALID) -- { -- /* Leave only the first temp declaration and set it to the max count later. */ -- if (!normaliser->max_temp_count) -- { -- normaliser->max_temp_count = ins->declaration.count; -- normaliser->temp_dcl_idx = index; -- } -- else -- { -- normaliser->max_temp_count = max(normaliser->max_temp_count, ins->declaration.count); -- vkd3d_shader_instruction_make_nop(ins); -- } -- return; -- } - -- if (normaliser->phase == VKD3DSIH_INVALID || shader_instruction_is_dcl(ins)) -+ if (normaliser->phase == VKD3DSIH_INVALID || vsir_instruction_is_dcl(ins)) - return; - - if (normaliser->phase_body_idx == ~0u) -@@ -312,6 +434,61 @@ void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_reg - reg->alignment = 0; - } - -+void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader_register_type reg_type, -+ enum vkd3d_data_type data_type, unsigned int idx_count) -+{ -+ vsir_register_init(¶m->reg, reg_type, data_type, idx_count); -+ param->swizzle = 0; -+ param->modifiers = VKD3DSPSM_NONE; -+} -+ -+void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, -+ enum vkd3d_data_type data_type, unsigned int idx_count) -+{ -+ vsir_register_init(¶m->reg, reg_type, data_type, idx_count); -+ param->write_mask = VKD3DSP_WRITEMASK_0; -+ param->modifiers = VKD3DSPDM_NONE; -+ param->shift = 0; -+} -+ -+void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id) -+{ -+ vsir_src_param_init(param, VKD3DSPR_LABEL, VKD3D_DATA_UINT, 1); -+ param->reg.dimension = VSIR_DIMENSION_NONE; -+ param->reg.idx[0].offset = label_id; -+} -+ -+static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx) -+{ -+ vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); -+ src->reg.idx[0].offset = idx; -+} -+ -+static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) -+{ -+ vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); -+ dst->reg.idx[0].offset = idx; -+} -+ -+static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigned int idx) -+{ -+ vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -+ dst->reg.idx[0].offset = idx; -+ dst->write_mask = VKD3DSP_WRITEMASK_0; -+} -+ -+static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx) -+{ -+ vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -+ src->reg.idx[0].offset = idx; -+} -+ -+static void src_param_init_const_uint(struct vkd3d_shader_src_param *src, uint32_t value) -+{ -+ vsir_src_param_init(src, VKD3DSPR_IMMCONST, VKD3D_DATA_UINT, 0); -+ src->reg.u.immconst_u32[0] = value; -+} -+ - void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, - enum vkd3d_shader_opcode handler_idx) - { -@@ -320,6 +497,23 @@ void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vk - ins->handler_idx = handler_idx; - } - -+static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, -+ const struct vkd3d_shader_location *location, unsigned int label_id, struct vsir_program *program) -+{ -+ struct vkd3d_shader_src_param *src_param; -+ -+ if (!(src_param = vsir_program_get_src_params(program, 1))) -+ return false; -+ -+ vsir_src_param_init_label(src_param, label_id); -+ -+ vsir_instruction_init(ins, location, VKD3DSIH_LABEL); -+ ins->src = src_param; -+ ins->src_count = 1; -+ -+ return true; -+} -+ - static enum vkd3d_result instruction_array_flatten_hull_shader_phases(struct vkd3d_shader_instruction_array *src_instructions) - { - struct hull_flattener flattener = {*src_instructions}; -@@ -339,9 +533,6 @@ static enum vkd3d_result instruction_array_flatten_hull_shader_phases(struct vkd - - if (flattener.phase != VKD3DSIH_INVALID) - { -- if (flattener.temp_dcl_idx) -- instructions->elements[flattener.temp_dcl_idx].declaration.count = flattener.max_temp_count; -- - if (!shader_instruction_array_reserve(&flattener.instructions, flattener.instructions.count + 1)) - return VKD3D_ERROR_OUT_OF_MEMORY; - vsir_instruction_init(&instructions->elements[instructions->count++], &flattener.last_ret_location, VKD3DSIH_RET); -@@ -463,6 +654,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - struct vkd3d_shader_instruction_array *instructions; - struct control_point_normaliser normaliser; - unsigned int input_control_point_count; -+ struct vkd3d_shader_location location; - struct vkd3d_shader_instruction *ins; - enum vkd3d_result ret; - unsigned int i, j; -@@ -488,10 +680,10 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - normaliser.phase = ins->handler_idx; - break; - default: -- if (shader_instruction_is_dcl(ins)) -+ if (vsir_instruction_is_dcl(ins)) - break; - for (j = 0; j < ins->dst_count; ++j) -- shader_dst_param_normalise_outpointid((struct vkd3d_shader_dst_param *)&ins->dst[j], &normaliser); -+ shader_dst_param_normalise_outpointid(&ins->dst[j], &normaliser); - break; - } - } -@@ -513,8 +705,10 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - return VKD3D_OK; - case VKD3DSIH_HS_FORK_PHASE: - case VKD3DSIH_HS_JOIN_PHASE: -+ /* ins may be relocated if the instruction array expands. */ -+ location = ins->location; - ret = control_point_normaliser_emit_hs_input(&normaliser, input_signature, -- input_control_point_count, i, &ins->location); -+ input_control_point_count, i, &location); - *src_instructions = normaliser.instructions; - return ret; - default: -@@ -530,13 +724,11 @@ struct io_normaliser - { - struct vkd3d_shader_instruction_array instructions; - enum vkd3d_shader_type shader_type; -+ uint8_t major; - struct shader_signature *input_signature; - struct shader_signature *output_signature; - struct shader_signature *patch_constant_signature; - -- unsigned int max_temp_count; -- unsigned int temp_dcl_idx; -- - unsigned int instance_count; - unsigned int phase_body_idx; - enum vkd3d_shader_opcode phase; -@@ -567,7 +759,7 @@ static bool io_normaliser_is_in_control_point_phase(const struct io_normaliser * - static unsigned int shader_signature_find_element_for_reg(const struct shader_signature *signature, - unsigned int reg_idx, unsigned int write_mask) - { -- unsigned int i; -+ unsigned int i, base_write_mask; - - for (i = 0; i < signature->element_count; ++i) - { -@@ -579,7 +771,14 @@ static unsigned int shader_signature_find_element_for_reg(const struct shader_si - } - } - -- /* Validated in the TPF reader. */ -+ /* Validated in the TPF reader, but failure in signature_element_range_expand_mask() -+ * can land us here on an unmatched vector mask. */ -+ FIXME("Failed to find signature element for register index %u, mask %#x; using scalar mask.\n", -+ reg_idx, write_mask); -+ base_write_mask = 1u << vsir_write_mask_get_component_idx(write_mask); -+ if (base_write_mask != write_mask) -+ return shader_signature_find_element_for_reg(signature, reg_idx, base_write_mask); -+ - vkd3d_unreachable(); - } - -@@ -590,19 +789,19 @@ struct signature_element *vsir_signature_find_element_for_reg(const struct shade - } - - static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE], -- unsigned int register_idx, unsigned int write_mask) -+ unsigned int register_idx, uint32_t write_mask) - { -- return range_map[register_idx][vkd3d_write_mask_get_component_idx(write_mask)]; -+ return range_map[register_idx][vsir_write_mask_get_component_idx(write_mask)]; - } - - static void range_map_set_register_range(uint8_t range_map[][VKD3D_VEC4_SIZE], unsigned int register_idx, -- unsigned int register_count, unsigned int write_mask, bool is_dcl_indexrange) -+ unsigned int register_count, uint32_t write_mask, bool is_dcl_indexrange) - { - unsigned int i, j, r, c, component_idx, component_count; - - assert(write_mask <= VKD3DSP_WRITEMASK_ALL); -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -- component_count = vkd3d_write_mask_component_count(write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); -+ component_count = vsir_write_mask_component_count(write_mask); - - assert(register_idx < MAX_REG_OUTPUT && MAX_REG_OUTPUT - register_idx >= register_count); - -@@ -746,12 +945,58 @@ static int signature_element_index_compare(const void *a, const void *b) - return vkd3d_u32_compare(e->sort_index, f->sort_index); - } - -+static unsigned int signature_element_range_expand_mask(struct signature_element *e, unsigned int register_count, -+ uint8_t range_map[][VKD3D_VEC4_SIZE]) -+{ -+ unsigned int i, j, component_idx, component_count, merged_write_mask = e->mask; -+ -+ /* dcl_indexrange instructions can declare a subset of the full mask, and the masks of -+ * the elements within the range may differ. TPF's handling of arrayed inputs with -+ * dcl_indexrange is really just a hack. Here we create a mask which covers all element -+ * masks, and check for collisions with other ranges. */ -+ -+ for (i = 1; i < register_count; ++i) -+ merged_write_mask |= e[i].mask; -+ -+ if (merged_write_mask == e->mask) -+ return merged_write_mask; -+ -+ /* Reaching this point is very rare to begin with, and collisions are even rarer or -+ * impossible. If the latter shows up, the fallback in shader_signature_find_element_for_reg() -+ * may be sufficient. */ -+ -+ component_idx = vsir_write_mask_get_component_idx(e->mask); -+ component_count = vsir_write_mask_component_count(e->mask); -+ -+ for (i = e->register_index; i < e->register_index + register_count; ++i) -+ { -+ for (j = 0; j < component_idx; ++j) -+ if (range_map[i][j]) -+ break; -+ for (j = component_idx + component_count; j < VKD3D_VEC4_SIZE; ++j) -+ if (range_map[i][j]) -+ break; -+ } -+ -+ if (i == register_count) -+ { -+ WARN("Expanding mask %#x to %#x for %s, base reg %u, count %u.\n", e->mask, merged_write_mask, -+ e->semantic_name, e->register_index, register_count); -+ return merged_write_mask; -+ } -+ -+ WARN("Cannot expand mask %#x to %#x for %s, base reg %u, count %u.\n", e->mask, merged_write_mask, -+ e->semantic_name, e->register_index, register_count); -+ return e->mask; -+} -+ - static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map[][VKD3D_VEC4_SIZE], - bool is_patch_constant) - { - unsigned int i, j, element_count, new_count, register_count; - struct signature_element *elements; - struct signature_element *e, *f; -+ bool used; - - element_count = s->element_count; - if (!(elements = vkd3d_malloc(element_count * sizeof(*elements)))) -@@ -772,14 +1017,15 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map - if (range_map_get_register_count(range_map, e->register_index, e->mask) > 1) - continue; - -+ used = e->used_mask; -+ - for (; j < element_count; ++j) - { - f = &elements[j]; - - /* Merge different components of the same register unless sysvals are different, -- * interpolation modes are different, or it will be relative-addressed. */ -+ * or it will be relative-addressed. */ - if (f->register_index != e->register_index || f->sysval_semantic != e->sysval_semantic -- || f->interpolation_mode != e->interpolation_mode - || range_map_get_register_count(range_map, f->register_index, f->mask) > 1) - break; - -@@ -790,6 +1036,16 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map - e->mask |= f->mask; - e->used_mask |= f->used_mask; - e->semantic_index = min(e->semantic_index, f->semantic_index); -+ -+ /* The first element may have no interpolation mode if it is unused. Elements which -+ * actually have different interpolation modes are assigned different registers. */ -+ if (f->used_mask && !used) -+ { -+ if (e->interpolation_mode && e->interpolation_mode != f->interpolation_mode) -+ FIXME("Mismatching interpolation modes %u and %u.\n", e->interpolation_mode, f->interpolation_mode); -+ else -+ e->interpolation_mode = f->interpolation_mode; -+ } - } - } - element_count = new_count; -@@ -816,6 +1072,7 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map - { - TRACE("Merging %s, base reg %u, count %u.\n", e->semantic_name, e->register_index, register_count); - e->register_count = register_count; -+ e->mask = signature_element_range_expand_mask(e, register_count, range_map); - } - } - element_count = new_count; -@@ -840,6 +1097,13 @@ static unsigned int shader_register_normalise_arrayed_addressing(struct vkd3d_sh - reg->idx[id_idx + 1].rel_addr = NULL; - reg->idx[id_idx + 1].offset = reg->idx[id_idx].offset; - reg->idx[id_idx].offset -= register_index; -+ if (id_idx) -+ { -+ /* idx[id_idx] now contains the array index, which must be moved below the control point id. */ -+ struct vkd3d_shader_register_index tmp = reg->idx[id_idx]; -+ reg->idx[id_idx] = reg->idx[id_idx - 1]; -+ reg->idx[id_idx - 1] = tmp; -+ } - ++id_idx; - } - /* Otherwise we have no address for the arrayed register, so insert one. This happens e.g. where -@@ -864,39 +1128,70 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par - const struct shader_signature *signature; - const struct signature_element *e; - -- if ((reg->type == VKD3DSPR_OUTPUT && io_normaliser_is_in_fork_or_join_phase(normaliser)) -- || reg->type == VKD3DSPR_PATCHCONST) -- { -- signature = normaliser->patch_constant_signature; -- /* Convert patch constant outputs to the patch constant register type to avoid the need -- * to convert compiler symbols when accessed as inputs in a later stage. */ -- reg->type = VKD3DSPR_PATCHCONST; -- dcl_params = normaliser->pc_dcl_params; -- } -- else if (reg->type == VKD3DSPR_OUTPUT || dst_param->reg.type == VKD3DSPR_COLOROUT) -- { -- signature = normaliser->output_signature; -- reg->type = VKD3DSPR_OUTPUT; -- dcl_params = normaliser->output_dcl_params; -- } -- else if (dst_param->reg.type == VKD3DSPR_INCONTROLPOINT || dst_param->reg.type == VKD3DSPR_INPUT) -- { -- signature = normaliser->input_signature; -- reg->type = VKD3DSPR_INPUT; -- dcl_params = normaliser->input_dcl_params; -- } -- else -+ switch (reg->type) - { -- return true; -+ case VKD3DSPR_OUTPUT: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; -+ if (io_normaliser_is_in_fork_or_join_phase(normaliser)) -+ { -+ signature = normaliser->patch_constant_signature; -+ /* Convert patch constant outputs to the patch constant register type to avoid the need -+ * to convert compiler symbols when accessed as inputs in a later stage. */ -+ reg->type = VKD3DSPR_PATCHCONST; -+ dcl_params = normaliser->pc_dcl_params; -+ } -+ else -+ { -+ signature = normaliser->output_signature; -+ dcl_params = normaliser->output_dcl_params; -+ } -+ break; -+ -+ case VKD3DSPR_PATCHCONST: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; -+ signature = normaliser->patch_constant_signature; -+ dcl_params = normaliser->pc_dcl_params; -+ break; -+ -+ case VKD3DSPR_COLOROUT: -+ reg_idx = reg->idx[0].offset; -+ signature = normaliser->output_signature; -+ reg->type = VKD3DSPR_OUTPUT; -+ dcl_params = normaliser->output_dcl_params; -+ break; -+ -+ case VKD3DSPR_INCONTROLPOINT: -+ case VKD3DSPR_INPUT: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; -+ signature = normaliser->input_signature; -+ reg->type = VKD3DSPR_INPUT; -+ dcl_params = normaliser->input_dcl_params; -+ break; -+ -+ case VKD3DSPR_ATTROUT: -+ reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset; -+ signature = normaliser->output_signature; -+ reg->type = VKD3DSPR_OUTPUT; -+ dcl_params = normaliser->output_dcl_params; -+ break; -+ -+ case VKD3DSPR_RASTOUT: -+ reg_idx = SM1_RASTOUT_REGISTER_OFFSET + reg->idx[0].offset; -+ signature = normaliser->output_signature; -+ reg->type = VKD3DSPR_OUTPUT; -+ dcl_params = normaliser->output_dcl_params; -+ break; -+ -+ default: -+ return true; - } - - id_idx = reg->idx_count - 1; -- reg_idx = reg->idx[id_idx].offset; - write_mask = dst_param->write_mask; - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); - e = &signature->elements[element_idx]; - -- dst_param->write_mask >>= vkd3d_write_mask_get_component_idx(e->mask); -+ dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask); - if (is_io_dcl) - { - /* Validated in the TPF reader. */ -@@ -979,27 +1274,43 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par - switch (reg->type) - { - case VKD3DSPR_PATCHCONST: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; - signature = normaliser->patch_constant_signature; - break; -+ - case VKD3DSPR_INCONTROLPOINT: - reg->type = VKD3DSPR_INPUT; - /* fall through */ - case VKD3DSPR_INPUT: -+ if (normaliser->major < 3 && normaliser->shader_type == VKD3D_SHADER_TYPE_PIXEL) -+ reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset; -+ else -+ reg_idx = reg->idx[reg->idx_count - 1].offset; - signature = normaliser->input_signature; - break; -+ - case VKD3DSPR_OUTCONTROLPOINT: - reg->type = VKD3DSPR_OUTPUT; - /* fall through */ - case VKD3DSPR_OUTPUT: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; - signature = normaliser->output_signature; - break; -+ -+ case VKD3DSPR_TEXTURE: -+ if (normaliser->shader_type != VKD3D_SHADER_TYPE_PIXEL) -+ return; -+ reg->type = VKD3DSPR_INPUT; -+ reg_idx = reg->idx[0].offset; -+ signature = normaliser->input_signature; -+ break; -+ - default: - return; - } - - id_idx = reg->idx_count - 1; -- reg_idx = reg->idx[id_idx].offset; -- write_mask = VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(src_param->swizzle, 0); -+ write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0); - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); - - e = &signature->elements[element_idx]; -@@ -1008,10 +1319,10 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par - reg->idx[id_idx].offset = element_idx; - reg->idx_count = id_idx + 1; - -- if ((component_idx = vkd3d_write_mask_get_component_idx(e->mask))) -+ if ((component_idx = vsir_write_mask_get_component_idx(e->mask))) - { - for (i = 0; i < VKD3D_VEC4_SIZE; ++i) -- if (vkd3d_swizzle_get_component(src_param->swizzle, i)) -+ if (vsir_swizzle_get_component(src_param->swizzle, i)) - src_param->swizzle -= component_idx << VKD3D_SHADER_SWIZZLE_SHIFT(i); - } - } -@@ -1062,32 +1373,34 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi - memset(normaliser->pc_dcl_params, 0, sizeof(normaliser->pc_dcl_params)); - break; - default: -- if (shader_instruction_is_dcl(ins)) -+ if (vsir_instruction_is_dcl(ins)) - break; - for (i = 0; i < ins->dst_count; ++i) -- shader_dst_param_io_normalise((struct vkd3d_shader_dst_param *)&ins->dst[i], false, normaliser); -+ shader_dst_param_io_normalise(&ins->dst[i], false, normaliser); - for (i = 0; i < ins->src_count; ++i) -- shader_src_param_io_normalise((struct vkd3d_shader_src_param *)&ins->src[i], normaliser); -+ shader_src_param_io_normalise(&ins->src[i], normaliser); - break; - } - } - - static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parser *parser) - { -- struct io_normaliser normaliser = {parser->instructions}; -+ struct io_normaliser normaliser = {parser->program.instructions}; -+ struct vsir_program *program = &parser->program; - struct vkd3d_shader_instruction *ins; - bool has_control_point_phase; - unsigned int i, j; - - normaliser.phase = VKD3DSIH_INVALID; -- normaliser.shader_type = parser->shader_version.type; -+ normaliser.shader_type = program->shader_version.type; -+ normaliser.major = program->shader_version.major; - normaliser.input_signature = &parser->shader_desc.input_signature; - normaliser.output_signature = &parser->shader_desc.output_signature; - normaliser.patch_constant_signature = &parser->shader_desc.patch_constant_signature; - -- for (i = 0, has_control_point_phase = false; i < parser->instructions.count; ++i) -+ for (i = 0, has_control_point_phase = false; i < program->instructions.count; ++i) - { -- ins = &parser->instructions.elements[i]; -+ ins = &program->instructions.elements[i]; - - switch (ins->handler_idx) - { -@@ -1130,7 +1443,7 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse - || !shader_signature_merge(&parser->shader_desc.output_signature, normaliser.output_range_map, false) - || !shader_signature_merge(&parser->shader_desc.patch_constant_signature, normaliser.pc_range_map, true)) - { -- parser->instructions = normaliser.instructions; -+ program->instructions = normaliser.instructions; - return VKD3D_ERROR_OUT_OF_MEMORY; - } - -@@ -1138,8 +1451,8 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse - for (i = 0; i < normaliser.instructions.count; ++i) - shader_instruction_normalise_io_params(&normaliser.instructions.elements[i], &normaliser); - -- parser->instructions = normaliser.instructions; -- parser->shader_desc.use_vocp = normaliser.use_vocp; -+ program->instructions = normaliser.instructions; -+ program->use_vocp = normaliser.use_vocp; - return VKD3D_OK; - } - -@@ -1152,7 +1465,6 @@ struct flat_constant_def - - struct flat_constants_normaliser - { -- struct vkd3d_shader_parser *parser; - struct flat_constant_def *defs; - size_t def_count, defs_capacity; - }; -@@ -1215,7 +1527,7 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par - param->reg.idx_count = 0; - param->reg.dimension = VSIR_DIMENSION_VEC4; - for (j = 0; j < 4; ++j) -- param->reg.u.immconst_uint[j] = normaliser->defs[i].value[j]; -+ param->reg.u.immconst_u32[j] = normaliser->defs[i].value[j]; - return; - } - } -@@ -1227,14 +1539,14 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par - param->reg.idx_count = 3; - } - --static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d_shader_parser *parser) -+static enum vkd3d_result instruction_array_normalise_flat_constants(struct vsir_program *program) - { -- struct flat_constants_normaliser normaliser = {.parser = parser}; -+ struct flat_constants_normaliser normaliser = {0}; - unsigned int i, j; - -- for (i = 0; i < parser->instructions.count; ++i) -+ for (i = 0; i < program->instructions.count; ++i) - { -- struct vkd3d_shader_instruction *ins = &parser->instructions.elements[i]; -+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - - if (ins->handler_idx == VKD3DSIH_DEF || ins->handler_idx == VKD3DSIH_DEFI || ins->handler_idx == VKD3DSIH_DEFB) - { -@@ -1251,14 +1563,14 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d - - get_flat_constant_register_type((struct vkd3d_shader_register *)&ins->dst[0].reg, &def->set, &def->index); - for (j = 0; j < 4; ++j) -- def->value[j] = ins->src[0].reg.u.immconst_uint[j]; -+ def->value[j] = ins->src[0].reg.u.immconst_u32[j]; - - vkd3d_shader_instruction_make_nop(ins); - } - else - { - for (j = 0; j < ins->src_count; ++j) -- shader_register_normalise_flat_constants((struct vkd3d_shader_src_param *)&ins->src[j], &normaliser); -+ shader_register_normalise_flat_constants(&ins->src[j], &normaliser); - } - } - -@@ -1266,14 +1578,14 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d - return VKD3D_OK; - } - --static void remove_dead_code(struct vkd3d_shader_parser *parser) -+static void remove_dead_code(struct vsir_program *program) - { - size_t i, depth = 0; - bool dead = false; - -- for (i = 0; i < parser->instructions.count; ++i) -+ for (i = 0; i < program->instructions.count; ++i) - { -- struct vkd3d_shader_instruction *ins = &parser->instructions.elements[i]; -+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - - switch (ins->handler_idx) - { -@@ -1360,15 +1672,15 @@ static enum vkd3d_result normalise_combined_samplers(struct vkd3d_shader_parser - { - unsigned int i; - -- for (i = 0; i < parser->instructions.count; ++i) -+ for (i = 0; i < parser->program.instructions.count; ++i) - { -- struct vkd3d_shader_instruction *ins = &parser->instructions.elements[i]; -+ struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; - struct vkd3d_shader_src_param *srcs; - - switch (ins->handler_idx) - { - case VKD3DSIH_TEX: -- if (!(srcs = shader_src_param_allocator_get(&parser->instructions.src_params, 3))) -+ if (!(srcs = shader_src_param_allocator_get(&parser->program.instructions.src_params, 3))) - return VKD3D_ERROR_OUT_OF_MEMORY; - memset(srcs, 0, sizeof(*srcs) * 3); - -@@ -1424,95 +1736,1420 @@ static enum vkd3d_result normalise_combined_samplers(struct vkd3d_shader_parser - return VKD3D_OK; - } - --enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, -- const struct vkd3d_shader_compile_info *compile_info) -+struct cf_flattener_if_info - { -- struct vkd3d_shader_instruction_array *instructions = &parser->instructions; -- enum vkd3d_result result = VKD3D_OK; -- -- if (parser->shader_desc.is_dxil) -- return result; -+ struct vkd3d_shader_src_param *false_param; -+ unsigned int id; -+ uint32_t merge_block_id; -+ unsigned int else_block_id; -+}; - -- if (parser->shader_version.type != VKD3D_SHADER_TYPE_PIXEL -- && (result = remap_output_signature(parser, compile_info)) < 0) -- return result; -+struct cf_flattener_loop_info -+{ -+ unsigned int header_block_id; -+ unsigned int continue_block_id; -+ uint32_t merge_block_id; -+}; - -- if (parser->shader_version.type == VKD3D_SHADER_TYPE_HULL -- && (result = instruction_array_flatten_hull_shader_phases(instructions)) >= 0) -- { -- result = instruction_array_normalise_hull_shader_control_point_io(instructions, -- &parser->shader_desc.input_signature); -- } -- if (result >= 0) -- result = shader_normalise_io_registers(parser); -+struct cf_flattener_switch_case -+{ -+ unsigned int value; -+ unsigned int block_id; -+}; - -- if (result >= 0) -- result = instruction_array_normalise_flat_constants(parser); -+struct cf_flattener_switch_info -+{ -+ size_t ins_location; -+ const struct vkd3d_shader_src_param *condition; -+ unsigned int id; -+ unsigned int merge_block_id; -+ unsigned int default_block_id; -+ struct cf_flattener_switch_case *cases; -+ size_t cases_size; -+ unsigned int cases_count; -+}; - -- if (result >= 0) -- remove_dead_code(parser); -+struct cf_flattener_info -+{ -+ union -+ { -+ struct cf_flattener_if_info if_; -+ struct cf_flattener_loop_info loop; -+ struct cf_flattener_switch_info switch_; -+ } u; - -- if (result >= 0) -- result = normalise_combined_samplers(parser); -+ enum -+ { -+ VKD3D_BLOCK_IF, -+ VKD3D_BLOCK_LOOP, -+ VKD3D_BLOCK_SWITCH, -+ } current_block; -+ bool inside_block; -+}; - -- if (result >= 0 && TRACE_ON()) -- vkd3d_shader_trace(instructions, &parser->shader_version); -+struct cf_flattener -+{ -+ struct vkd3d_shader_parser *parser; - -- if (result >= 0 && !parser->failed) -- vsir_validate(parser); -+ struct vkd3d_shader_location location; -+ bool allocation_failed; - -- if (result >= 0 && parser->failed) -- result = VKD3D_ERROR_INVALID_SHADER; -+ struct vkd3d_shader_instruction *instructions; -+ size_t instruction_capacity; -+ size_t instruction_count; - -- return result; --} -+ unsigned int block_id; -+ const char **block_names; -+ size_t block_name_capacity; -+ size_t block_name_count; - --struct validation_context --{ -- struct vkd3d_shader_parser *parser; -- size_t instruction_idx; -- bool dcl_temps_found; -- unsigned int temp_count; -- enum vkd3d_shader_opcode phase; -+ unsigned int branch_id; -+ unsigned int loop_id; -+ unsigned int switch_id; - -- enum vkd3d_shader_opcode *blocks; -- size_t depth; -- size_t blocks_capacity; -+ unsigned int control_flow_depth; -+ struct cf_flattener_info *control_flow_info; -+ size_t control_flow_info_size; - }; - --static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx, -- enum vkd3d_shader_error error, const char *format, ...) -+static struct vkd3d_shader_instruction *cf_flattener_require_space(struct cf_flattener *flattener, size_t count) - { -- struct vkd3d_string_buffer buf; -- va_list args; -+ if (!vkd3d_array_reserve((void **)&flattener->instructions, &flattener->instruction_capacity, -+ flattener->instruction_count + count, sizeof(*flattener->instructions))) -+ { -+ ERR("Failed to allocate instructions.\n"); -+ flattener->allocation_failed = true; -+ return NULL; -+ } -+ return &flattener->instructions[flattener->instruction_count]; -+} - -- vkd3d_string_buffer_init(&buf); -+static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ struct vkd3d_shader_instruction *dst_ins; - -- va_start(args, format); -- vkd3d_string_buffer_vprintf(&buf, format, args); -- va_end(args); -+ if (instruction->handler_idx == VKD3DSIH_NOP) -+ return true; - -- vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); -- ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); -+ if (!(dst_ins = cf_flattener_require_space(flattener, 1))) -+ return false; - -- vkd3d_string_buffer_cleanup(&buf); -+ *dst_ins = *instruction; -+ ++flattener->instruction_count; -+ return true; - } - --static void vsir_validate_src_param(struct validation_context *ctx, -- const struct vkd3d_shader_src_param *src); -- --static void vsir_validate_register(struct validation_context *ctx, -- const struct vkd3d_shader_register *reg) -+static unsigned int cf_flattener_alloc_block_id(struct cf_flattener *flattener) - { -- unsigned int i, temp_count = ctx->temp_count; -+ return ++flattener->block_id; -+} - -- /* SM1-3 shaders do not include a DCL_TEMPS instruction. */ -- if (ctx->parser->shader_version.major <= 3) -- temp_count = ctx->parser->shader_desc.temp_count; -+static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_shader_instruction *ins, -+ unsigned int count, struct cf_flattener *flattener) -+{ -+ struct vkd3d_shader_src_param *params; - -- if (reg->type >= VKD3DSPR_COUNT) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.", -- reg->type); -+ if (!(params = vsir_program_get_src_params(&flattener->parser->program, count))) -+ { -+ flattener->allocation_failed = true; -+ return NULL; -+ } -+ ins->src = params; -+ ins->src_count = count; -+ return params; -+} -+ -+static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int label_id) -+{ -+ struct vkd3d_shader_instruction *ins; -+ -+ if (!(ins = cf_flattener_require_space(flattener, 1))) -+ return; -+ if (vsir_instruction_init_label(ins, &flattener->location, label_id, &flattener->parser->program)) -+ ++flattener->instruction_count; -+ else -+ flattener->allocation_failed = true; -+} -+ -+/* For conditional branches, this returns the false target branch parameter. */ -+static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flattener *flattener, -+ unsigned int merge_block_id, unsigned int continue_block_id, -+ const struct vkd3d_shader_src_param *condition, unsigned int true_id, unsigned int false_id, -+ unsigned int flags) -+{ -+ struct vkd3d_shader_src_param *src_params, *false_branch_param; -+ struct vkd3d_shader_instruction *ins; -+ -+ if (!(ins = cf_flattener_require_space(flattener, 1))) -+ return NULL; -+ vsir_instruction_init(ins, &flattener->location, VKD3DSIH_BRANCH); -+ -+ if (condition) -+ { -+ if (!(src_params = instruction_src_params_alloc(ins, 4 + !!continue_block_id, flattener))) -+ return NULL; -+ src_params[0] = *condition; -+ if (flags == VKD3D_SHADER_CONDITIONAL_OP_Z) -+ { -+ vsir_src_param_init_label(&src_params[1], false_id); -+ vsir_src_param_init_label(&src_params[2], true_id); -+ false_branch_param = &src_params[1]; -+ } -+ else -+ { -+ vsir_src_param_init_label(&src_params[1], true_id); -+ vsir_src_param_init_label(&src_params[2], false_id); -+ false_branch_param = &src_params[2]; -+ } -+ vsir_src_param_init_label(&src_params[3], merge_block_id); -+ if (continue_block_id) -+ vsir_src_param_init_label(&src_params[4], continue_block_id); -+ } -+ else -+ { -+ if (!(src_params = instruction_src_params_alloc(ins, merge_block_id ? 3 : 1, flattener))) -+ return NULL; -+ vsir_src_param_init_label(&src_params[0], true_id); -+ if (merge_block_id) -+ { -+ /* An unconditional branch may only have merge information for a loop, which -+ * must have both a merge block and continue block. */ -+ vsir_src_param_init_label(&src_params[1], merge_block_id); -+ vsir_src_param_init_label(&src_params[2], continue_block_id); -+ } -+ false_branch_param = NULL; -+ } -+ -+ ++flattener->instruction_count; -+ -+ return false_branch_param; -+} -+ -+static void cf_flattener_emit_conditional_branch_and_merge(struct cf_flattener *flattener, -+ const struct vkd3d_shader_src_param *condition, unsigned int true_id, unsigned int flags) -+{ -+ unsigned int merge_block_id; -+ -+ merge_block_id = cf_flattener_alloc_block_id(flattener); -+ cf_flattener_emit_branch(flattener, merge_block_id, 0, condition, true_id, merge_block_id, flags); -+ cf_flattener_emit_label(flattener, merge_block_id); -+} -+ -+static void cf_flattener_emit_unconditional_branch(struct cf_flattener *flattener, unsigned int target_block_id) -+{ -+ cf_flattener_emit_branch(flattener, 0, 0, NULL, target_block_id, 0, 0); -+} -+ -+static struct cf_flattener_info *cf_flattener_push_control_flow_level(struct cf_flattener *flattener) -+{ -+ if (!vkd3d_array_reserve((void **)&flattener->control_flow_info, &flattener->control_flow_info_size, -+ flattener->control_flow_depth + 1, sizeof(*flattener->control_flow_info))) -+ { -+ ERR("Failed to allocate control flow info structure.\n"); -+ flattener->allocation_failed = true; -+ return NULL; -+ } -+ -+ return &flattener->control_flow_info[flattener->control_flow_depth++]; -+} -+ -+static void cf_flattener_pop_control_flow_level(struct cf_flattener *flattener) -+{ -+ struct cf_flattener_info *cf_info; -+ -+ cf_info = &flattener->control_flow_info[--flattener->control_flow_depth]; -+ memset(cf_info, 0, sizeof(*cf_info)); -+} -+ -+static struct cf_flattener_info *cf_flattener_find_innermost_loop(struct cf_flattener *flattener) -+{ -+ int depth; -+ -+ for (depth = flattener->control_flow_depth - 1; depth >= 0; --depth) -+ { -+ if (flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP) -+ return &flattener->control_flow_info[depth]; -+ } -+ -+ return NULL; -+} -+ -+static struct cf_flattener_info *cf_flattener_find_innermost_breakable_cf_construct(struct cf_flattener *flattener) -+{ -+ int depth; -+ -+ for (depth = flattener->control_flow_depth - 1; depth >= 0; --depth) -+ { -+ if (flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP -+ || flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_SWITCH) -+ return &flattener->control_flow_info[depth]; -+ } -+ -+ return NULL; -+} -+ -+static void VKD3D_PRINTF_FUNC(3, 4) cf_flattener_create_block_name(struct cf_flattener *flattener, -+ unsigned int block_id, const char *fmt, ...) -+{ -+ struct vkd3d_string_buffer buffer; -+ size_t block_name_count; -+ va_list args; -+ -+ --block_id; -+ -+ block_name_count = max(flattener->block_name_count, block_id + 1); -+ if (!vkd3d_array_reserve((void **)&flattener->block_names, &flattener->block_name_capacity, -+ block_name_count, sizeof(*flattener->block_names))) -+ return; -+ memset(&flattener->block_names[flattener->block_name_count], 0, -+ (block_name_count - flattener->block_name_count) * sizeof(*flattener->block_names)); -+ flattener->block_name_count = block_name_count; -+ -+ vkd3d_string_buffer_init(&buffer); -+ va_start(args, fmt); -+ vkd3d_string_buffer_vprintf(&buffer, fmt, args); -+ va_end(args); -+ -+ flattener->block_names[block_id] = buffer.buffer; -+} -+ -+static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flattener *flattener) -+{ -+ bool main_block_open, is_hull_shader, after_declarations_section; -+ struct vkd3d_shader_parser *parser = flattener->parser; -+ struct vkd3d_shader_instruction_array *instructions; -+ struct vsir_program *program = &parser->program; -+ struct vkd3d_shader_instruction *dst_ins; -+ size_t i; -+ -+ instructions = &program->instructions; -+ is_hull_shader = program->shader_version.type == VKD3D_SHADER_TYPE_HULL; -+ main_block_open = !is_hull_shader; -+ after_declarations_section = is_hull_shader; -+ -+ if (!cf_flattener_require_space(flattener, instructions->count + 1)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ for (i = 0; i < instructions->count; ++i) -+ { -+ unsigned int loop_header_block_id, loop_body_block_id, continue_block_id, merge_block_id, true_block_id; -+ const struct vkd3d_shader_instruction *instruction = &instructions->elements[i]; -+ const struct vkd3d_shader_src_param *src = instruction->src; -+ struct cf_flattener_info *cf_info; -+ -+ flattener->location = instruction->location; -+ -+ /* Declarations should occur before the first code block, which in hull shaders is marked by the first -+ * phase instruction, and in all other shader types begins with the first label instruction. */ -+ if (!after_declarations_section && !vsir_instruction_is_dcl(instruction) -+ && instruction->handler_idx != VKD3DSIH_NOP) -+ { -+ after_declarations_section = true; -+ cf_flattener_emit_label(flattener, cf_flattener_alloc_block_id(flattener)); -+ } -+ -+ cf_info = flattener->control_flow_depth -+ ? &flattener->control_flow_info[flattener->control_flow_depth - 1] : NULL; -+ -+ switch (instruction->handler_idx) -+ { -+ case VKD3DSIH_HS_CONTROL_POINT_PHASE: -+ case VKD3DSIH_HS_FORK_PHASE: -+ case VKD3DSIH_HS_JOIN_PHASE: -+ if (!cf_flattener_copy_instruction(flattener, instruction)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ if (instruction->handler_idx != VKD3DSIH_HS_CONTROL_POINT_PHASE || !instruction->flags) -+ after_declarations_section = false; -+ break; -+ -+ case VKD3DSIH_LABEL: -+ vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -+ "Aborting due to not yet implemented feature: Label instruction."); -+ return VKD3D_ERROR_NOT_IMPLEMENTED; -+ -+ case VKD3DSIH_IF: -+ if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ true_block_id = cf_flattener_alloc_block_id(flattener); -+ merge_block_id = cf_flattener_alloc_block_id(flattener); -+ cf_info->u.if_.false_param = cf_flattener_emit_branch(flattener, merge_block_id, 0, -+ src, true_block_id, merge_block_id, instruction->flags); -+ if (!cf_info->u.if_.false_param) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ cf_flattener_emit_label(flattener, true_block_id); -+ -+ cf_info->u.if_.id = flattener->branch_id; -+ cf_info->u.if_.merge_block_id = merge_block_id; -+ cf_info->u.if_.else_block_id = 0; -+ cf_info->inside_block = true; -+ cf_info->current_block = VKD3D_BLOCK_IF; -+ -+ cf_flattener_create_block_name(flattener, merge_block_id, "branch%u_merge", flattener->branch_id); -+ cf_flattener_create_block_name(flattener, true_block_id, "branch%u_true", flattener->branch_id); -+ ++flattener->branch_id; -+ break; -+ -+ case VKD3DSIH_ELSE: -+ if (cf_info->inside_block) -+ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.if_.merge_block_id); -+ -+ cf_info->u.if_.else_block_id = cf_flattener_alloc_block_id(flattener); -+ cf_info->u.if_.false_param->reg.idx[0].offset = cf_info->u.if_.else_block_id; -+ -+ cf_flattener_create_block_name(flattener, -+ cf_info->u.if_.else_block_id, "branch%u_false", cf_info->u.if_.id); -+ cf_flattener_emit_label(flattener, cf_info->u.if_.else_block_id); -+ -+ cf_info->inside_block = true; -+ break; -+ -+ case VKD3DSIH_ENDIF: -+ if (cf_info->inside_block) -+ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.if_.merge_block_id); -+ -+ cf_flattener_emit_label(flattener, cf_info->u.if_.merge_block_id); -+ -+ cf_flattener_pop_control_flow_level(flattener); -+ break; -+ -+ case VKD3DSIH_LOOP: -+ if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ loop_header_block_id = cf_flattener_alloc_block_id(flattener); -+ loop_body_block_id = cf_flattener_alloc_block_id(flattener); -+ continue_block_id = cf_flattener_alloc_block_id(flattener); -+ merge_block_id = cf_flattener_alloc_block_id(flattener); -+ -+ cf_flattener_emit_unconditional_branch(flattener, loop_header_block_id); -+ cf_flattener_emit_label(flattener, loop_header_block_id); -+ cf_flattener_emit_branch(flattener, merge_block_id, continue_block_id, -+ NULL, loop_body_block_id, 0, 0); -+ -+ cf_flattener_emit_label(flattener, loop_body_block_id); -+ -+ cf_info->u.loop.header_block_id = loop_header_block_id; -+ cf_info->u.loop.continue_block_id = continue_block_id; -+ cf_info->u.loop.merge_block_id = merge_block_id; -+ cf_info->current_block = VKD3D_BLOCK_LOOP; -+ cf_info->inside_block = true; -+ -+ cf_flattener_create_block_name(flattener, loop_header_block_id, "loop%u_header", flattener->loop_id); -+ cf_flattener_create_block_name(flattener, loop_body_block_id, "loop%u_body", flattener->loop_id); -+ cf_flattener_create_block_name(flattener, continue_block_id, "loop%u_continue", flattener->loop_id); -+ cf_flattener_create_block_name(flattener, merge_block_id, "loop%u_merge", flattener->loop_id); -+ ++flattener->loop_id; -+ break; -+ -+ case VKD3DSIH_ENDLOOP: -+ if (cf_info->inside_block) -+ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.loop.continue_block_id); -+ -+ cf_flattener_emit_label(flattener, cf_info->u.loop.continue_block_id); -+ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.loop.header_block_id); -+ cf_flattener_emit_label(flattener, cf_info->u.loop.merge_block_id); -+ -+ cf_flattener_pop_control_flow_level(flattener); -+ break; -+ -+ case VKD3DSIH_SWITCH: -+ if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ merge_block_id = cf_flattener_alloc_block_id(flattener); -+ -+ cf_info->u.switch_.ins_location = flattener->instruction_count; -+ cf_info->u.switch_.condition = src; -+ -+ if (!(dst_ins = cf_flattener_require_space(flattener, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ vsir_instruction_init(dst_ins, &instruction->location, VKD3DSIH_SWITCH_MONOLITHIC); -+ ++flattener->instruction_count; -+ -+ cf_info->u.switch_.id = flattener->switch_id; -+ cf_info->u.switch_.merge_block_id = merge_block_id; -+ cf_info->u.switch_.cases = NULL; -+ cf_info->u.switch_.cases_size = 0; -+ cf_info->u.switch_.cases_count = 0; -+ cf_info->u.switch_.default_block_id = 0; -+ cf_info->inside_block = false; -+ cf_info->current_block = VKD3D_BLOCK_SWITCH; -+ -+ cf_flattener_create_block_name(flattener, merge_block_id, "switch%u_merge", flattener->switch_id); -+ ++flattener->switch_id; -+ -+ if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.cases, &cf_info->u.switch_.cases_size, -+ 10, sizeof(*cf_info->u.switch_.cases))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ break; -+ -+ case VKD3DSIH_ENDSWITCH: -+ { -+ struct vkd3d_shader_src_param *src_params; -+ unsigned int j; -+ -+ if (!cf_info->u.switch_.default_block_id) -+ cf_info->u.switch_.default_block_id = cf_info->u.switch_.merge_block_id; -+ -+ cf_flattener_emit_label(flattener, cf_info->u.switch_.merge_block_id); -+ -+ /* The SWITCH instruction is completed when the endswitch -+ * instruction is processed because we do not know the number -+ * of case statements or the default block id in advance.*/ -+ dst_ins = &flattener->instructions[cf_info->u.switch_.ins_location]; -+ if (!(src_params = instruction_src_params_alloc(dst_ins, cf_info->u.switch_.cases_count * 2 + 3, flattener))) -+ { -+ vkd3d_free(cf_info->u.switch_.cases); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ src_params[0] = *cf_info->u.switch_.condition; -+ vsir_src_param_init_label(&src_params[1], cf_info->u.switch_.default_block_id); -+ vsir_src_param_init_label(&src_params[2], cf_info->u.switch_.merge_block_id); -+ for (j = 0; j < cf_info->u.switch_.cases_count; ++j) -+ { -+ unsigned int index = j * 2 + 3; -+ vsir_src_param_init(&src_params[index], VKD3DSPR_IMMCONST, VKD3D_DATA_UINT, 0); -+ src_params[index].reg.u.immconst_u32[0] = cf_info->u.switch_.cases[j].value; -+ vsir_src_param_init_label(&src_params[index + 1], cf_info->u.switch_.cases[j].block_id); -+ } -+ vkd3d_free(cf_info->u.switch_.cases); -+ -+ cf_flattener_pop_control_flow_level(flattener); -+ break; -+ } -+ -+ case VKD3DSIH_CASE: -+ { -+ unsigned int label_id, value; -+ -+ if (src->swizzle != VKD3D_SHADER_SWIZZLE(X, X, X, X)) -+ { -+ WARN("Unexpected src swizzle %#x.\n", src->swizzle); -+ vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, -+ "The swizzle for a switch case value is not scalar X."); -+ } -+ value = *src->reg.u.immconst_u32; -+ -+ if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.cases, &cf_info->u.switch_.cases_size, -+ cf_info->u.switch_.cases_count + 1, sizeof(*cf_info->u.switch_.cases))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ label_id = cf_flattener_alloc_block_id(flattener); -+ if (cf_info->inside_block) /* fall-through */ -+ cf_flattener_emit_unconditional_branch(flattener, label_id); -+ -+ cf_info->u.switch_.cases[cf_info->u.switch_.cases_count].value = value; -+ cf_info->u.switch_.cases[cf_info->u.switch_.cases_count].block_id = label_id; -+ ++cf_info->u.switch_.cases_count; -+ -+ cf_flattener_emit_label(flattener, label_id); -+ cf_flattener_create_block_name(flattener, label_id, "switch%u_case%u", cf_info->u.switch_.id, value); -+ cf_info->inside_block = true; -+ break; -+ } -+ -+ case VKD3DSIH_DEFAULT: -+ cf_info->u.switch_.default_block_id = cf_flattener_alloc_block_id(flattener); -+ if (cf_info->inside_block) /* fall-through */ -+ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.switch_.default_block_id); -+ -+ cf_flattener_emit_label(flattener, cf_info->u.switch_.default_block_id); -+ -+ cf_flattener_create_block_name(flattener, cf_info->u.switch_.default_block_id, -+ "switch%u_default", cf_info->u.switch_.id); -+ cf_info->inside_block = true; -+ break; -+ -+ case VKD3DSIH_BREAK: -+ { -+ struct cf_flattener_info *breakable_cf_info; -+ -+ if (!(breakable_cf_info = cf_flattener_find_innermost_breakable_cf_construct(flattener))) -+ { -+ FIXME("Unhandled break instruction.\n"); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ if (breakable_cf_info->current_block == VKD3D_BLOCK_LOOP) -+ { -+ cf_flattener_emit_unconditional_branch(flattener, breakable_cf_info->u.loop.merge_block_id); -+ } -+ else if (breakable_cf_info->current_block == VKD3D_BLOCK_SWITCH) -+ { -+ cf_flattener_emit_unconditional_branch(flattener, breakable_cf_info->u.switch_.merge_block_id); -+ } -+ -+ cf_info->inside_block = false; -+ break; -+ } -+ -+ case VKD3DSIH_BREAKP: -+ { -+ struct cf_flattener_info *loop_cf_info; -+ -+ if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener))) -+ { -+ ERR("Invalid 'breakc' instruction outside loop.\n"); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ cf_flattener_emit_conditional_branch_and_merge(flattener, -+ src, loop_cf_info->u.loop.merge_block_id, instruction->flags); -+ break; -+ } -+ -+ case VKD3DSIH_CONTINUE: -+ { -+ struct cf_flattener_info *loop_cf_info; -+ -+ if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener))) -+ { -+ ERR("Invalid 'continue' instruction outside loop.\n"); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ cf_flattener_emit_unconditional_branch(flattener, loop_cf_info->u.loop.continue_block_id); -+ -+ cf_info->inside_block = false; -+ break; -+ } -+ -+ case VKD3DSIH_CONTINUEP: -+ { -+ struct cf_flattener_info *loop_cf_info; -+ -+ if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener))) -+ { -+ ERR("Invalid 'continuec' instruction outside loop.\n"); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ cf_flattener_emit_conditional_branch_and_merge(flattener, -+ src, loop_cf_info->u.loop.continue_block_id, instruction->flags); -+ break; -+ } -+ -+ case VKD3DSIH_RET: -+ if (!cf_flattener_copy_instruction(flattener, instruction)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ if (cf_info) -+ cf_info->inside_block = false; -+ else -+ main_block_open = false; -+ break; -+ -+ default: -+ if (!cf_flattener_copy_instruction(flattener, instruction)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ break; -+ } -+ } -+ -+ if (main_block_open) -+ { -+ if (!(dst_ins = cf_flattener_require_space(flattener, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ vsir_instruction_init(dst_ins, &flattener->location, VKD3DSIH_RET); -+ ++flattener->instruction_count; -+ } -+ -+ return flattener->allocation_failed ? VKD3D_ERROR_OUT_OF_MEMORY : VKD3D_OK; -+} -+ -+static enum vkd3d_result flatten_control_flow_constructs(struct vkd3d_shader_parser *parser) -+{ -+ struct vsir_program *program = &parser->program; -+ struct cf_flattener flattener = {0}; -+ enum vkd3d_result result; -+ -+ flattener.parser = parser; -+ result = cf_flattener_iterate_instruction_array(&flattener); -+ -+ if (result >= 0) -+ { -+ vkd3d_free(parser->program.instructions.elements); -+ program->instructions.elements = flattener.instructions; -+ program->instructions.capacity = flattener.instruction_capacity; -+ program->instructions.count = flattener.instruction_count; -+ program->block_count = flattener.block_id; -+ } -+ else -+ { -+ vkd3d_free(flattener.instructions); -+ } -+ -+ vkd3d_free(flattener.control_flow_info); -+ /* Simpler to always free these in vsir_program_cleanup(). */ -+ program->block_names = flattener.block_names; -+ program->block_name_count = flattener.block_name_count; -+ -+ return result; -+} -+ -+static unsigned int label_from_src_param(const struct vkd3d_shader_src_param *param) -+{ -+ assert(param->reg.type == VKD3DSPR_LABEL); -+ return param->reg.idx[0].offset; -+} -+ -+static bool reserve_instructions(struct vkd3d_shader_instruction **instructions, size_t *capacity, size_t count) -+{ -+ if (!vkd3d_array_reserve((void **)instructions, capacity, count, sizeof(**instructions))) -+ { -+ ERR("Failed to allocate instructions.\n"); -+ return false; -+ } -+ -+ return true; -+} -+ -+/* A record represents replacing a jump from block `switch_label' to -+ * block `target_label' with a jump from block `if_label' to block -+ * `target_label'. */ -+struct lower_switch_to_if_ladder_block_mapping -+{ -+ unsigned int switch_label; -+ unsigned int if_label; -+ unsigned int target_label; -+}; -+ -+static bool lower_switch_to_if_ladder_add_block_mapping(struct lower_switch_to_if_ladder_block_mapping **block_map, -+ size_t *map_capacity, size_t *map_count, unsigned int switch_label, unsigned int if_label, unsigned int target_label) -+{ -+ if (!vkd3d_array_reserve((void **)block_map, map_capacity, *map_count + 1, sizeof(**block_map))) -+ { -+ ERR("Failed to allocate block mapping.\n"); -+ return false; -+ } -+ -+ (*block_map)[*map_count].switch_label = switch_label; -+ (*block_map)[*map_count].if_label = if_label; -+ (*block_map)[*map_count].target_label = target_label; -+ -+ *map_count += 1; -+ -+ return true; -+} -+ -+static enum vkd3d_result lower_switch_to_if_ladder(struct vsir_program *program) -+{ -+ unsigned int block_count = program->block_count, ssa_count = program->ssa_count, current_label = 0, if_label; -+ size_t ins_capacity = 0, ins_count = 0, i, map_capacity = 0, map_count = 0; -+ struct vkd3d_shader_instruction *instructions = NULL; -+ struct lower_switch_to_if_ladder_block_mapping *block_map = NULL; -+ -+ if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count)) -+ goto fail; -+ -+ /* First subpass: convert SWITCH_MONOLITHIC instructions to -+ * selection ladders, keeping a map between blocks before and -+ * after the subpass. */ -+ for (i = 0; i < program->instructions.count; ++i) -+ { -+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; -+ unsigned int case_count, j, default_label; -+ -+ switch (ins->handler_idx) -+ { -+ case VKD3DSIH_LABEL: -+ current_label = label_from_src_param(&ins->src[0]); -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) -+ goto fail; -+ instructions[ins_count++] = *ins; -+ continue; -+ -+ case VKD3DSIH_SWITCH_MONOLITHIC: -+ break; -+ -+ default: -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) -+ goto fail; -+ instructions[ins_count++] = *ins; -+ continue; -+ } -+ -+ case_count = (ins->src_count - 3) / 2; -+ default_label = label_from_src_param(&ins->src[1]); -+ -+ /* In principle we can have a switch with no cases, and we -+ * just have to jump to the default label. */ -+ if (case_count == 0) -+ { -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) -+ goto fail; -+ -+ if (!vsir_instruction_init_with_params(program, &instructions[ins_count], -+ &ins->location, VKD3DSIH_BRANCH, 0, 1)) -+ goto fail; -+ vsir_src_param_init_label(&instructions[ins_count].src[0], default_label); -+ ++ins_count; -+ } -+ -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3 * case_count - 1)) -+ goto fail; -+ -+ if_label = current_label; -+ -+ for (j = 0; j < case_count; ++j) -+ { -+ unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]); -+ -+ if (!vsir_instruction_init_with_params(program, -+ &instructions[ins_count], &ins->location, VKD3DSIH_IEQ, 1, 2)) -+ goto fail; -+ dst_param_init_ssa_bool(&instructions[ins_count].dst[0], ssa_count); -+ instructions[ins_count].src[0] = ins->src[0]; -+ instructions[ins_count].src[1] = ins->src[3 + 2 * j]; -+ ++ins_count; -+ -+ /* For all cases except the last one we fall through to -+ * the following case; the last one has to jump to the -+ * default label. */ -+ if (j == case_count - 1) -+ fallthrough_label = default_label; -+ else -+ fallthrough_label = block_count + 1; -+ -+ if (!vsir_instruction_init_with_params(program, &instructions[ins_count], -+ &ins->location, VKD3DSIH_BRANCH, 0, 3)) -+ goto fail; -+ src_param_init_ssa_bool(&instructions[ins_count].src[0], ssa_count); -+ vsir_src_param_init_label(&instructions[ins_count].src[1], case_label); -+ vsir_src_param_init_label(&instructions[ins_count].src[2], fallthrough_label); -+ ++ins_count; -+ -+ ++ssa_count; -+ -+ if (!lower_switch_to_if_ladder_add_block_mapping(&block_map, &map_capacity, &map_count, -+ current_label, if_label, case_label)) -+ goto fail; -+ -+ if (j == case_count - 1) -+ { -+ if (!lower_switch_to_if_ladder_add_block_mapping(&block_map, &map_capacity, &map_count, -+ current_label, if_label, default_label)) -+ goto fail; -+ } -+ else -+ { -+ if (!vsir_instruction_init_with_params(program, -+ &instructions[ins_count], &ins->location, VKD3DSIH_LABEL, 0, 1)) -+ goto fail; -+ vsir_src_param_init_label(&instructions[ins_count].src[0], ++block_count); -+ ++ins_count; -+ -+ if_label = block_count; -+ } -+ } -+ } -+ -+ /* Second subpass: creating new blocks might have broken -+ * references in PHI instructions, so we use the block map to fix -+ * them. */ -+ current_label = 0; -+ for (i = 0; i < ins_count; ++i) -+ { -+ struct vkd3d_shader_instruction *ins = &instructions[i]; -+ struct vkd3d_shader_src_param *new_src; -+ unsigned int j, l, new_src_count = 0; -+ -+ switch (ins->handler_idx) -+ { -+ case VKD3DSIH_LABEL: -+ current_label = label_from_src_param(&ins->src[0]); -+ continue; -+ -+ case VKD3DSIH_PHI: -+ break; -+ -+ default: -+ continue; -+ } -+ -+ /* First count how many source parameters we need. */ -+ for (j = 0; j < ins->src_count; j += 2) -+ { -+ unsigned int source_label = label_from_src_param(&ins->src[j + 1]); -+ size_t k, match_count = 0; -+ -+ for (k = 0; k < map_count; ++k) -+ { -+ struct lower_switch_to_if_ladder_block_mapping *mapping = &block_map[k]; -+ -+ if (mapping->switch_label == source_label && mapping->target_label == current_label) -+ match_count += 1; -+ } -+ -+ new_src_count += (match_count != 0) ? 2 * match_count : 2; -+ } -+ -+ assert(new_src_count >= ins->src_count); -+ -+ /* Allocate more source parameters if needed. */ -+ if (new_src_count == ins->src_count) -+ { -+ new_src = ins->src; -+ } -+ else -+ { -+ if (!(new_src = vsir_program_get_src_params(program, new_src_count))) -+ { -+ ERR("Failed to allocate %u source parameters.\n", new_src_count); -+ goto fail; -+ } -+ } -+ -+ /* Then do the copy. */ -+ for (j = 0, l = 0; j < ins->src_count; j += 2) -+ { -+ unsigned int source_label = label_from_src_param(&ins->src[j + 1]); -+ size_t k, match_count = 0; -+ -+ for (k = 0; k < map_count; ++k) -+ { -+ struct lower_switch_to_if_ladder_block_mapping *mapping = &block_map[k]; -+ -+ if (mapping->switch_label == source_label && mapping->target_label == current_label) -+ { -+ match_count += 1; -+ -+ new_src[l] = ins->src[j]; -+ new_src[l + 1] = ins->src[j + 1]; -+ new_src[l + 1].reg.idx[0].offset = mapping->if_label; -+ l += 2; -+ } -+ } -+ -+ if (match_count == 0) -+ { -+ new_src[l] = ins->src[j]; -+ new_src[l + 1] = ins->src[j + 1]; -+ l += 2; -+ } -+ } -+ -+ assert(l == new_src_count); -+ -+ ins->src_count = new_src_count; -+ ins->src = new_src; -+ } -+ -+ vkd3d_free(program->instructions.elements); -+ vkd3d_free(block_map); -+ program->instructions.elements = instructions; -+ program->instructions.capacity = ins_capacity; -+ program->instructions.count = ins_count; -+ program->block_count = block_count; -+ program->ssa_count = ssa_count; -+ -+ return VKD3D_OK; -+ -+fail: -+ vkd3d_free(instructions); -+ vkd3d_free(block_map); -+ -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+} -+ -+static void materialize_ssas_to_temps_process_src_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_src_param *src); -+ -+/* This is idempotent: it can be safely applied more than once on the -+ * same register. */ -+static void materialize_ssas_to_temps_process_reg(struct vkd3d_shader_parser *parser, struct vkd3d_shader_register *reg) -+{ -+ unsigned int i; -+ -+ if (reg->type == VKD3DSPR_SSA) -+ { -+ reg->type = VKD3DSPR_TEMP; -+ reg->idx[0].offset += parser->program.temp_count; -+ } -+ -+ for (i = 0; i < reg->idx_count; ++i) -+ if (reg->idx[i].rel_addr) -+ materialize_ssas_to_temps_process_src_param(parser, reg->idx[i].rel_addr); -+} -+ -+static void materialize_ssas_to_temps_process_dst_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_dst_param *dst) -+{ -+ materialize_ssas_to_temps_process_reg(parser, &dst->reg); -+} -+ -+static void materialize_ssas_to_temps_process_src_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_src_param *src) -+{ -+ materialize_ssas_to_temps_process_reg(parser, &src->reg); -+} -+ -+static const struct vkd3d_shader_src_param *materialize_ssas_to_temps_compute_source(struct vkd3d_shader_instruction *ins, -+ unsigned int label) -+{ -+ unsigned int i; -+ -+ assert(ins->handler_idx == VKD3DSIH_PHI); -+ -+ for (i = 0; i < ins->src_count; i += 2) -+ { -+ if (label_from_src_param(&ins->src[i + 1]) == label) -+ return &ins->src[i]; -+ } -+ -+ vkd3d_unreachable(); -+} -+ -+static bool materialize_ssas_to_temps_synthesize_mov(struct vkd3d_shader_parser *parser, -+ struct vkd3d_shader_instruction *instruction, const struct vkd3d_shader_location *loc, -+ const struct vkd3d_shader_dst_param *dest, const struct vkd3d_shader_src_param *cond, -+ const struct vkd3d_shader_src_param *source, bool invert) -+{ -+ struct vkd3d_shader_src_param *src; -+ struct vkd3d_shader_dst_param *dst; -+ -+ if (!vsir_instruction_init_with_params(&parser->program, instruction, loc, -+ cond ? VKD3DSIH_MOVC : VKD3DSIH_MOV, 1, cond ? 3 : 1)) -+ return false; -+ -+ dst = instruction->dst; -+ src = instruction->src; -+ -+ dst[0] = *dest; -+ materialize_ssas_to_temps_process_dst_param(parser, &dst[0]); -+ -+ assert(dst[0].write_mask == VKD3DSP_WRITEMASK_0); -+ assert(dst[0].modifiers == 0); -+ assert(dst[0].shift == 0); -+ -+ if (cond) -+ { -+ src[0] = *cond; -+ src[1 + invert] = *source; -+ memset(&src[2 - invert], 0, sizeof(src[2 - invert])); -+ src[2 - invert].reg = dst[0].reg; -+ materialize_ssas_to_temps_process_src_param(parser, &src[1]); -+ materialize_ssas_to_temps_process_src_param(parser, &src[2]); -+ } -+ else -+ { -+ src[0] = *source; -+ materialize_ssas_to_temps_process_src_param(parser, &src[0]); -+ } -+ -+ return true; -+} -+ -+static enum vkd3d_result materialize_ssas_to_temps(struct vkd3d_shader_parser *parser) -+{ -+ struct vkd3d_shader_instruction *instructions = NULL; -+ struct materialize_ssas_to_temps_block_data -+ { -+ size_t phi_begin; -+ size_t phi_count; -+ } *block_index = NULL; -+ size_t ins_capacity = 0, ins_count = 0, i; -+ unsigned int current_label = 0; -+ -+ if (!reserve_instructions(&instructions, &ins_capacity, parser->program.instructions.count)) -+ goto fail; -+ -+ if (!(block_index = vkd3d_calloc(parser->program.block_count, sizeof(*block_index)))) -+ { -+ ERR("Failed to allocate block index.\n"); -+ goto fail; -+ } -+ -+ for (i = 0; i < parser->program.instructions.count; ++i) -+ { -+ struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; -+ -+ switch (ins->handler_idx) -+ { -+ case VKD3DSIH_LABEL: -+ current_label = label_from_src_param(&ins->src[0]); -+ break; -+ -+ case VKD3DSIH_PHI: -+ assert(current_label != 0); -+ assert(i != 0); -+ if (block_index[current_label - 1].phi_begin == 0) -+ block_index[current_label - 1].phi_begin = i; -+ block_index[current_label - 1].phi_count += 1; -+ break; -+ -+ default: -+ current_label = 0; -+ break; -+ } -+ } -+ -+ for (i = 0; i < parser->program.instructions.count; ++i) -+ { -+ struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; -+ size_t j; -+ -+ for (j = 0; j < ins->dst_count; ++j) -+ materialize_ssas_to_temps_process_dst_param(parser, &ins->dst[j]); -+ -+ for (j = 0; j < ins->src_count; ++j) -+ materialize_ssas_to_temps_process_src_param(parser, &ins->src[j]); -+ -+ switch (ins->handler_idx) -+ { -+ case VKD3DSIH_LABEL: -+ current_label = label_from_src_param(&ins->src[0]); -+ break; -+ -+ case VKD3DSIH_BRANCH: -+ { -+ if (vsir_register_is_label(&ins->src[0].reg)) -+ { -+ const struct materialize_ssas_to_temps_block_data *data = &block_index[label_from_src_param(&ins->src[0]) - 1]; -+ -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + data->phi_count)) -+ goto fail; -+ -+ for (j = data->phi_begin; j < data->phi_begin + data->phi_count; ++j) -+ { -+ const struct vkd3d_shader_src_param *source; -+ -+ source = materialize_ssas_to_temps_compute_source(&parser->program.instructions.elements[j], current_label); -+ if (!materialize_ssas_to_temps_synthesize_mov(parser, &instructions[ins_count], &ins->location, -+ &parser->program.instructions.elements[j].dst[0], NULL, source, false)) -+ goto fail; -+ -+ ++ins_count; -+ } -+ } -+ else -+ { -+ struct materialize_ssas_to_temps_block_data *data_true = &block_index[label_from_src_param(&ins->src[1]) - 1], -+ *data_false = &block_index[label_from_src_param(&ins->src[2]) - 1]; -+ const struct vkd3d_shader_src_param *cond = &ins->src[0]; -+ -+ if (!reserve_instructions(&instructions, &ins_capacity, -+ ins_count + data_true->phi_count + data_false->phi_count)) -+ goto fail; -+ -+ for (j = data_true->phi_begin; j < data_true->phi_begin + data_true->phi_count; ++j) -+ { -+ const struct vkd3d_shader_src_param *source; -+ -+ source = materialize_ssas_to_temps_compute_source(&parser->program.instructions.elements[j], current_label); -+ if (!materialize_ssas_to_temps_synthesize_mov(parser, &instructions[ins_count], &ins->location, -+ &parser->program.instructions.elements[j].dst[0], cond, source, false)) -+ goto fail; -+ -+ ++ins_count; -+ } -+ -+ for (j = data_false->phi_begin; j < data_false->phi_begin + data_false->phi_count; ++j) -+ { -+ const struct vkd3d_shader_src_param *source; -+ -+ source = materialize_ssas_to_temps_compute_source(&parser->program.instructions.elements[j], current_label); -+ if (!materialize_ssas_to_temps_synthesize_mov(parser, &instructions[ins_count], &ins->location, -+ &parser->program.instructions.elements[j].dst[0], cond, source, true)) -+ goto fail; -+ -+ ++ins_count; -+ } -+ } -+ break; -+ } -+ -+ case VKD3DSIH_PHI: -+ continue; -+ -+ default: -+ break; -+ } -+ -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) -+ goto fail; -+ -+ instructions[ins_count++] = *ins; -+ } -+ -+ vkd3d_free(parser->program.instructions.elements); -+ vkd3d_free(block_index); -+ parser->program.instructions.elements = instructions; -+ parser->program.instructions.capacity = ins_capacity; -+ parser->program.instructions.count = ins_count; -+ parser->program.temp_count += parser->program.ssa_count; -+ parser->program.ssa_count = 0; -+ -+ return VKD3D_OK; -+ -+fail: -+ vkd3d_free(instructions); -+ vkd3d_free(block_index); -+ -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+} -+ -+static enum vkd3d_result simple_structurizer_run(struct vkd3d_shader_parser *parser) -+{ -+ const unsigned int block_temp_idx = parser->program.temp_count; -+ struct vkd3d_shader_instruction *instructions = NULL; -+ const struct vkd3d_shader_location no_loc = {0}; -+ size_t ins_capacity = 0, ins_count = 0, i; -+ bool first_label_found = false; -+ -+ if (!reserve_instructions(&instructions, &ins_capacity, parser->program.instructions.count)) -+ goto fail; -+ -+ for (i = 0; i < parser->program.instructions.count; ++i) -+ { -+ struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; -+ -+ switch (ins->handler_idx) -+ { -+ case VKD3DSIH_PHI: -+ case VKD3DSIH_SWITCH_MONOLITHIC: -+ vkd3d_unreachable(); -+ -+ case VKD3DSIH_LABEL: -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 4)) -+ goto fail; -+ -+ if (!first_label_found) -+ { -+ first_label_found = true; -+ -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_MOV, 1, 1)) -+ goto fail; -+ dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); -+ src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); -+ ins_count++; -+ -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_LOOP, 0, 0)) -+ goto fail; -+ ins_count++; -+ -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_SWITCH, 0, 1)) -+ goto fail; -+ src_param_init_temp_uint(&instructions[ins_count].src[0], block_temp_idx); -+ ins_count++; -+ } -+ -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_CASE, 0, 1)) -+ goto fail; -+ src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); -+ ins_count++; -+ break; -+ -+ case VKD3DSIH_BRANCH: -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 2)) -+ goto fail; -+ -+ if (vsir_register_is_label(&ins->src[0].reg)) -+ { -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_MOV, 1, 1)) -+ goto fail; -+ dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); -+ src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); -+ ins_count++; -+ } -+ else -+ { -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_MOVC, 1, 3)) -+ goto fail; -+ dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); -+ instructions[ins_count].src[0] = ins->src[0]; -+ src_param_init_const_uint(&instructions[ins_count].src[1], label_from_src_param(&ins->src[1])); -+ src_param_init_const_uint(&instructions[ins_count].src[2], label_from_src_param(&ins->src[2])); -+ ins_count++; -+ } -+ -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_BREAK, 0, 0)) -+ goto fail; -+ ins_count++; -+ break; -+ -+ case VKD3DSIH_RET: -+ default: -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) -+ goto fail; -+ -+ instructions[ins_count++] = *ins; -+ break; -+ } -+ } -+ -+ assert(first_label_found); -+ -+ if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3)) -+ goto fail; -+ -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_ENDSWITCH, 0, 0)) -+ goto fail; -+ ins_count++; -+ -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_ENDLOOP, 0, 0)) -+ goto fail; -+ ins_count++; -+ -+ if (!vsir_instruction_init_with_params(&parser->program, &instructions[ins_count], &no_loc, VKD3DSIH_RET, 0, 0)) -+ goto fail; -+ ins_count++; -+ -+ vkd3d_free(parser->program.instructions.elements); -+ parser->program.instructions.elements = instructions; -+ parser->program.instructions.capacity = ins_capacity; -+ parser->program.instructions.count = ins_count; -+ parser->program.temp_count += 1; -+ -+ return VKD3D_OK; -+ -+fail: -+ vkd3d_free(instructions); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+} -+ -+enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, -+ const struct vkd3d_shader_compile_info *compile_info) -+{ -+ struct vkd3d_shader_instruction_array *instructions = &parser->program.instructions; -+ enum vkd3d_result result = VKD3D_OK; -+ -+ remove_dcl_temps(&parser->program); -+ -+ if ((result = instruction_array_lower_texkills(parser)) < 0) -+ return result; -+ -+ if (parser->shader_desc.is_dxil) -+ { -+ if ((result = lower_switch_to_if_ladder(&parser->program)) < 0) -+ return result; -+ -+ if ((result = materialize_ssas_to_temps(parser)) < 0) -+ return result; -+ -+ if ((result = simple_structurizer_run(parser)) < 0) -+ return result; -+ } -+ else -+ { -+ if (parser->program.shader_version.type != VKD3D_SHADER_TYPE_PIXEL) -+ { -+ if ((result = remap_output_signature(parser, compile_info)) < 0) -+ return result; -+ } -+ -+ if (parser->program.shader_version.type == VKD3D_SHADER_TYPE_HULL) -+ { -+ if ((result = instruction_array_flatten_hull_shader_phases(instructions)) < 0) -+ return result; -+ -+ if ((result = instruction_array_normalise_hull_shader_control_point_io(instructions, -+ &parser->shader_desc.input_signature)) < 0) -+ return result; -+ } -+ -+ if ((result = shader_normalise_io_registers(parser)) < 0) -+ return result; -+ -+ if ((result = instruction_array_normalise_flat_constants(&parser->program)) < 0) -+ return result; -+ -+ remove_dead_code(&parser->program); -+ -+ if ((result = normalise_combined_samplers(parser)) < 0) -+ return result; -+ } -+ -+ if ((result = flatten_control_flow_constructs(parser)) < 0) -+ return result; -+ -+ if (TRACE_ON()) -+ vkd3d_shader_trace(&parser->program); -+ -+ if (!parser->failed && (result = vsir_validate(parser)) < 0) -+ return result; -+ -+ if (parser->failed) -+ result = VKD3D_ERROR_INVALID_SHADER; -+ -+ return result; -+} -+ -+struct validation_context -+{ -+ struct vkd3d_shader_parser *parser; -+ const struct vsir_program *program; -+ size_t instruction_idx; -+ bool invalid_instruction_idx; -+ bool dcl_temps_found; -+ enum vkd3d_shader_opcode phase; -+ enum cf_type -+ { -+ CF_TYPE_UNKNOWN = 0, -+ CF_TYPE_STRUCTURED, -+ CF_TYPE_BLOCKS, -+ } cf_type; -+ bool inside_block; -+ -+ struct validation_context_temp_data -+ { -+ enum vsir_dimension dimension; -+ size_t first_seen; -+ } *temps; -+ -+ struct validation_context_ssa_data -+ { -+ enum vsir_dimension dimension; -+ enum vkd3d_data_type data_type; -+ size_t first_seen; -+ uint32_t write_mask; -+ uint32_t read_mask; -+ size_t first_assigned; -+ } *ssas; -+ -+ enum vkd3d_shader_opcode *blocks; -+ size_t depth; -+ size_t blocks_capacity; -+}; -+ -+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); -+ -+ if (ctx->invalid_instruction_idx) -+ { -+ vkd3d_shader_parser_error(ctx->parser, error, "%s", buf.buffer); -+ ERR("VSIR validation error: %s\n", buf.buffer); -+ } -+ else -+ { -+ vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); -+ ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); -+ } -+ -+ vkd3d_string_buffer_cleanup(&buf); -+} -+ -+static void vsir_validate_src_param(struct validation_context *ctx, -+ const struct vkd3d_shader_src_param *src); -+ -+static void vsir_validate_register(struct validation_context *ctx, -+ const struct vkd3d_shader_register *reg) -+{ -+ unsigned int i; -+ -+ if (reg->type >= VKD3DSPR_COUNT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.", -+ reg->type); - - if (reg->precision >= VKD3D_SHADER_REGISTER_PRECISION_COUNT) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid register precision %#x.", -@@ -1540,16 +3177,135 @@ static void vsir_validate_register(struct validation_context *ctx, - switch (reg->type) - { - case VKD3DSPR_TEMP: -+ { -+ struct validation_context_temp_data *data; -+ - if (reg->idx_count != 1) -+ { - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a TEMP register.", - reg->idx_count); -+ break; -+ } - -- if (reg->idx_count >= 1 && reg->idx[0].rel_addr) -+ if (reg->idx[0].rel_addr) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a TEMP register."); - -- if (reg->idx_count >= 1 && reg->idx[0].offset >= temp_count) -+ if (reg->idx[0].offset >= ctx->parser->program.temp_count) -+ { - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the maximum count %u.", -- reg->idx[0].offset, temp_count); -+ reg->idx[0].offset, ctx->parser->program.temp_count); -+ break; -+ } -+ -+ data = &ctx->temps[reg->idx[0].offset]; -+ -+ if (reg->dimension == VSIR_DIMENSION_NONE) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension NONE for a TEMP register."); -+ break; -+ } -+ -+ /* TEMP registers can be scalar or vec4, provided that -+ * each individual register always appears with the same -+ * dimension. */ -+ if (data->dimension == VSIR_DIMENSION_NONE) -+ { -+ data->dimension = reg->dimension; -+ data->first_seen = ctx->instruction_idx; -+ } -+ else if (data->dimension != reg->dimension) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a TEMP register: " -+ "it has already been seen with dimension %#x at instruction %zu.", -+ reg->dimension, data->dimension, data->first_seen); -+ } -+ break; -+ } -+ -+ case VKD3DSPR_SSA: -+ { -+ struct validation_context_ssa_data *data; -+ -+ if (reg->idx_count != 1) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a SSA register.", -+ reg->idx_count); -+ break; -+ } -+ -+ if (reg->idx[0].rel_addr) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a SSA register."); -+ -+ if (reg->idx[0].offset >= ctx->program->ssa_count) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "SSA register index %u exceeds the maximum count %u.", -+ reg->idx[0].offset, ctx->program->ssa_count); -+ break; -+ } -+ -+ data = &ctx->ssas[reg->idx[0].offset]; -+ -+ if (reg->dimension == VSIR_DIMENSION_NONE) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension NONE for a SSA register."); -+ break; -+ } -+ -+ /* SSA registers can be scalar or vec4, provided that each -+ * individual register always appears with the same -+ * dimension. */ -+ if (data->dimension == VSIR_DIMENSION_NONE) -+ { -+ data->dimension = reg->dimension; -+ data->data_type = reg->data_type; -+ data->first_seen = ctx->instruction_idx; -+ } -+ else -+ { -+ if (data->dimension != reg->dimension) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a SSA register: " -+ "it has already been seen with dimension %#x at instruction %zu.", -+ reg->dimension, data->dimension, data->first_seen); -+ -+ if (data_type_is_64_bit(data->data_type) != data_type_is_64_bit(reg->data_type)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid data type %#x for a SSA register: " -+ "it has already been seen with data type %#x at instruction %zu.", -+ reg->data_type, data->data_type, data->first_seen); -+ } -+ break; -+ } -+ -+ case VKD3DSPR_LABEL: -+ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid precision %#x for a LABEL register.", -+ reg->precision); -+ -+ if (reg->data_type != VKD3D_DATA_UINT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid data type %#x for a LABEL register.", -+ reg->data_type); -+ -+ if (reg->dimension != VSIR_DIMENSION_NONE) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a LABEL register.", -+ reg->dimension); -+ -+ if (reg->idx_count != 1) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a LABEL register.", -+ reg->idx_count); -+ break; -+ } -+ -+ if (reg->idx[0].rel_addr) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a LABEL register."); -+ -+ /* Index == 0 is invalid, but it is temporarily allowed -+ * for intermediate stages. Once we support validation -+ * dialects we can selectively check for that. */ -+ if (reg->idx[0].offset > ctx->program->block_count) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "LABEL register index %u exceeds the maximum count %u.", -+ reg->idx[0].offset, ctx->program->block_count); - break; - - case VKD3DSPR_NULL: -@@ -1584,6 +3340,26 @@ static void vsir_validate_dst_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination has invalid write mask %#x.", - dst->write_mask); - -+ switch (dst->reg.dimension) -+ { -+ case VSIR_DIMENSION_SCALAR: -+ if (dst->write_mask != VKD3DSP_WRITEMASK_0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Scalar destination has invalid write mask %#x.", -+ dst->write_mask); -+ break; -+ -+ case VSIR_DIMENSION_VEC4: -+ if (dst->write_mask == 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Vec4 destination has empty write mask."); -+ break; -+ -+ default: -+ if (dst->write_mask != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination of dimension %u has invalid write mask %#x.", -+ dst->reg.dimension, dst->write_mask); -+ break; -+ } -+ - if (dst->modifiers & ~VKD3DSPDM_MASK) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.", - dst->modifiers); -@@ -1603,6 +3379,41 @@ static void vsir_validate_dst_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT, "Destination has invalid shift %#x.", - dst->shift); - } -+ -+ switch (dst->reg.type) -+ { -+ case VKD3DSPR_SSA: -+ if (dst->reg.idx[0].offset < ctx->parser->program.ssa_count) -+ { -+ struct validation_context_ssa_data *data = &ctx->ssas[dst->reg.idx[0].offset]; -+ -+ if (data->write_mask == 0) -+ { -+ data->write_mask = dst->write_mask; -+ data->first_assigned = ctx->instruction_idx; -+ } -+ else -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE, -+ "SSA register is already assigned at instruction %zu.", -+ data->first_assigned); -+ } -+ } -+ break; -+ -+ case VKD3DSPR_IMMCONST: -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid IMMCONST register used as destination parameter."); -+ break; -+ -+ case VKD3DSPR_IMMCONST64: -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid IMMCONST64 register used as destination parameter."); -+ break; -+ -+ default: -+ break; -+ } - } - - static void vsir_validate_src_param(struct validation_context *ctx, -@@ -1614,9 +3425,30 @@ static void vsir_validate_src_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source has invalid swizzle %#x.", - src->swizzle); - -+ if (src->reg.dimension != VSIR_DIMENSION_VEC4 && src->swizzle != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source of dimension %u has invalid swizzle %#x.", -+ src->reg.dimension, src->swizzle); -+ - if (src->modifiers >= VKD3DSPSM_COUNT) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", - src->modifiers); -+ -+ switch (src->reg.type) -+ { -+ case VKD3DSPR_SSA: -+ if (src->reg.idx[0].offset < ctx->parser->program.ssa_count) -+ { -+ struct validation_context_ssa_data *data = &ctx->ssas[src->reg.idx[0].offset]; -+ unsigned int i; -+ -+ for (i = 0; i < VKD3D_VEC4_SIZE; ++i) -+ data->read_mask |= (1u << vsir_swizzle_get_component(src->swizzle, i)); -+ } -+ break; -+ -+ default: -+ break; -+ } - } - - static void vsir_validate_dst_count(struct validation_context *ctx, -@@ -1637,11 +3469,64 @@ static void vsir_validate_src_count(struct validation_context *ctx, - instruction->src_count, instruction->handler_idx, count); - } - -+static bool vsir_validate_src_min_count(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction, unsigned int count) -+{ -+ if (instruction->src_count < count) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, -+ "Invalid source count %u for an instruction of type %#x, expected at least %u.", -+ instruction->src_count, instruction->handler_idx, count); -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool vsir_validate_src_max_count(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction, unsigned int count) -+{ -+ if (instruction->src_count > count) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, -+ "Invalid source count %u for an instruction of type %#x, expected at most %u.", -+ instruction->src_count, instruction->handler_idx, count); -+ return false; -+ } -+ -+ return true; -+} -+ -+static const char *name_from_cf_type(enum cf_type type) -+{ -+ switch (type) -+ { -+ case CF_TYPE_STRUCTURED: -+ return "structured"; -+ case CF_TYPE_BLOCKS: -+ return "block-based"; -+ default: -+ vkd3d_unreachable(); -+ } -+} -+ -+static void vsir_validate_cf_type(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction, enum cf_type expected_type) -+{ -+ assert(ctx->cf_type != CF_TYPE_UNKNOWN); -+ assert(expected_type != CF_TYPE_UNKNOWN); -+ if (ctx->cf_type != expected_type) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x in %s shader.", -+ instruction->handler_idx, name_from_cf_type(ctx->cf_type)); -+} -+ - static void vsir_validate_instruction(struct validation_context *ctx) - { -- const struct vkd3d_shader_instruction *instruction = &ctx->parser->instructions.elements[ctx->instruction_idx]; -+ const struct vkd3d_shader_version *version = &ctx->program->shader_version; -+ const struct vkd3d_shader_instruction *instruction; - size_t i; - -+ instruction = &ctx->program->instructions.elements[ctx->instruction_idx]; - ctx->parser->location = instruction->location; - - for (i = 0; i < instruction->dst_count; ++i) -@@ -1664,26 +3549,68 @@ static void vsir_validate_instruction(struct validation_context *ctx) - case VKD3DSIH_HS_JOIN_PHASE: - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 0); -- if (ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL) -+ if (version->type != VKD3D_SHADER_TYPE_HULL) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Phase instruction %#x is only valid in a hull shader.", - instruction->handler_idx); - if (ctx->depth != 0) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "Phase instruction %#x must appear to top level.", -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Phase instruction %#x must appear to top level.", - instruction->handler_idx); - ctx->phase = instruction->handler_idx; - ctx->dcl_temps_found = false; -- ctx->temp_count = 0; - return; - - default: - break; - } - -- if (ctx->parser->shader_version.type == VKD3D_SHADER_TYPE_HULL && -- ctx->phase == VKD3DSIH_INVALID) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Instruction %#x appear before any phase instruction in a hull shader.", -+ if (version->type == VKD3D_SHADER_TYPE_HULL && ctx->phase == VKD3DSIH_INVALID) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, -+ "Instruction %#x appear before any phase instruction in a hull shader.", - instruction->handler_idx); - -+ /* We support two different control flow types in shaders: -+ * block-based, like DXIL and SPIR-V, and structured, like D3DBC -+ * and TPF. The shader is detected as block-based when its first -+ * instruction, except for DCL_* and phases, is a LABEL. Currently -+ * we mandate that each shader is either purely block-based or -+ * purely structured. In principle we could allow structured -+ * constructs in a block, provided they are confined in a single -+ * block, but need for that hasn't arisen yet, so we don't. */ -+ if (ctx->cf_type == CF_TYPE_UNKNOWN && !vsir_instruction_is_dcl(instruction)) -+ { -+ if (instruction->handler_idx == VKD3DSIH_LABEL) -+ ctx->cf_type = CF_TYPE_BLOCKS; -+ else -+ ctx->cf_type = CF_TYPE_STRUCTURED; -+ } -+ -+ if (ctx->cf_type == CF_TYPE_BLOCKS && !vsir_instruction_is_dcl(instruction)) -+ { -+ switch (instruction->handler_idx) -+ { -+ case VKD3DSIH_LABEL: -+ if (ctx->inside_block) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid LABEL instruction inside a block."); -+ ctx->inside_block = true; -+ break; -+ -+ case VKD3DSIH_RET: -+ case VKD3DSIH_BRANCH: -+ case VKD3DSIH_SWITCH_MONOLITHIC: -+ if (!ctx->inside_block) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x outside any block.", -+ instruction->handler_idx); -+ ctx->inside_block = false; -+ break; -+ -+ default: -+ if (!ctx->inside_block) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x outside any block.", -+ instruction->handler_idx); -+ break; -+ } -+ } -+ - switch (instruction->handler_idx) - { - case VKD3DSIH_DCL_TEMPS: -@@ -1691,14 +3618,15 @@ static void vsir_validate_instruction(struct validation_context *ctx) - vsir_validate_src_count(ctx, instruction, 0); - if (ctx->dcl_temps_found) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, "Duplicate DCL_TEMPS instruction."); -- if (instruction->declaration.count > ctx->parser->shader_desc.temp_count) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, "Invalid DCL_TEMPS count %u, expected at most %u.", -- instruction->declaration.count, ctx->parser->shader_desc.temp_count); -+ if (instruction->declaration.count > ctx->program->temp_count) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, -+ "Invalid DCL_TEMPS count %u, expected at most %u.", -+ instruction->declaration.count, ctx->program->temp_count); - ctx->dcl_temps_found = true; -- ctx->temp_count = instruction->declaration.count; - break; - - case VKD3DSIH_IF: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 1); - if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) -@@ -1707,6 +3635,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) - break; - - case VKD3DSIH_IFC: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 2); - if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) -@@ -1715,41 +3644,46 @@ static void vsir_validate_instruction(struct validation_context *ctx) - break; - - case VKD3DSIH_ELSE: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 0); - if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ELSE instruction doesn't terminate IF block."); -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ELSE instruction doesn't terminate IF block."); - else - ctx->blocks[ctx->depth - 1] = instruction->handler_idx; - break; - - case VKD3DSIH_ENDIF: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 0); - if (ctx->depth == 0 || (ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF && ctx->blocks[ctx->depth - 1] != VKD3DSIH_ELSE)) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ENDIF instruction doesn't terminate IF/ELSE block."); -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDIF instruction doesn't terminate IF/ELSE block."); - else - --ctx->depth; - break; - - case VKD3DSIH_LOOP: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); -- vsir_validate_src_count(ctx, instruction, ctx->parser->shader_version.major <= 3 ? 2 : 0); -+ vsir_validate_src_count(ctx, instruction, version->major <= 3 ? 2 : 0); - if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) - return; - ctx->blocks[ctx->depth++] = instruction->handler_idx; - break; - - case VKD3DSIH_ENDLOOP: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 0); - if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_LOOP) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ENDLOOP instruction doesn't terminate LOOP block."); -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDLOOP instruction doesn't terminate LOOP block."); - else - --ctx->depth; - break; - - case VKD3DSIH_REP: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 1); - if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) -@@ -1758,15 +3692,17 @@ static void vsir_validate_instruction(struct validation_context *ctx) - break; - - case VKD3DSIH_ENDREP: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 0); - if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_REP) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ENDREP instruction doesn't terminate REP block."); -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDREP instruction doesn't terminate REP block."); - else - --ctx->depth; - break; - - case VKD3DSIH_SWITCH: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 1); - if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) -@@ -1775,35 +3711,223 @@ static void vsir_validate_instruction(struct validation_context *ctx) - break; - - case VKD3DSIH_ENDSWITCH: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED); - vsir_validate_dst_count(ctx, instruction, 0); - vsir_validate_src_count(ctx, instruction, 0); - if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_SWITCH) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ENDSWITCH instruction doesn't terminate SWITCH block."); -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDSWITCH instruction doesn't terminate SWITCH block."); - else - --ctx->depth; - break; - -+ case VKD3DSIH_RET: -+ vsir_validate_dst_count(ctx, instruction, 0); -+ vsir_validate_src_count(ctx, instruction, 0); -+ break; -+ -+ case VKD3DSIH_LABEL: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS); -+ vsir_validate_dst_count(ctx, instruction, 0); -+ vsir_validate_src_count(ctx, instruction, 1); -+ if (instruction->src_count >= 1 && !vsir_register_is_label(&instruction->src[0].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid register of type %#x in a LABEL instruction, expected LABEL.", -+ instruction->src[0].reg.type); -+ break; -+ -+ case VKD3DSIH_BRANCH: -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS); -+ vsir_validate_dst_count(ctx, instruction, 0); -+ if (!vsir_validate_src_min_count(ctx, instruction, 1)) -+ break; -+ if (vsir_register_is_label(&instruction->src[0].reg)) -+ { -+ /* Unconditional branch: parameters are jump label, -+ * optional merge label, optional continue label. */ -+ vsir_validate_src_max_count(ctx, instruction, 3); -+ -+ for (i = 0; i < instruction->src_count; ++i) -+ { -+ if (!vsir_register_is_label(&instruction->src[i].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid register of type %#x in unconditional BRANCH instruction, expected LABEL.", -+ instruction->src[i].reg.type); -+ } -+ } -+ else -+ { -+ /* Conditional branch: parameters are condition, true -+ * jump label, false jump label, optional merge label, -+ * optional continue label. */ -+ vsir_validate_src_min_count(ctx, instruction, 3); -+ vsir_validate_src_max_count(ctx, instruction, 5); -+ -+ for (i = 1; i < instruction->src_count; ++i) -+ { -+ if (!vsir_register_is_label(&instruction->src[i].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid register of type %#x in conditional BRANCH instruction, expected LABEL.", -+ instruction->src[i].reg.type); -+ } -+ } -+ break; -+ -+ case VKD3DSIH_SWITCH_MONOLITHIC: -+ { -+ unsigned int case_count; -+ -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS); -+ vsir_validate_dst_count(ctx, instruction, 0); -+ /* Parameters are source, default label, merge label and -+ * then pairs of constant value and case label. */ -+ if (!vsir_validate_src_min_count(ctx, instruction, 3)) -+ break; -+ if (instruction->src_count % 2 != 1) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, -+ "Invalid source count %u for a monolithic SWITCH instruction, it must be an odd number.", -+ instruction->src_count); -+ -+ if (!vsir_register_is_label(&instruction->src[1].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid default label register of type %#x in monolithic SWITCH instruction, expected LABEL.", -+ instruction->src[1].reg.type); -+ -+ if (!vsir_register_is_label(&instruction->src[2].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid merge label register of type %#x in monolithic SWITCH instruction, expected LABEL.", -+ instruction->src[2].reg.type); -+ -+ case_count = (instruction->src_count - 3) / 2; -+ -+ for (i = 0; i < case_count; ++i) -+ { -+ unsigned int value_idx = 3 + 2 * i; -+ unsigned int label_idx = 3 + 2 * i + 1; -+ -+ if (!register_is_constant(&instruction->src[value_idx].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid value register for case %zu of type %#x in monolithic SWITCH instruction, " -+ "expected IMMCONST or IMMCONST64.", i, instruction->src[value_idx].reg.type); -+ -+ if (!vsir_register_is_label(&instruction->src[label_idx].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid label register for case %zu of type %#x in monolithic SWITCH instruction, " -+ "expected LABEL.", i, instruction->src[value_idx].reg.type); -+ } -+ break; -+ } -+ -+ case VKD3DSIH_PHI: -+ { -+ unsigned int incoming_count; -+ -+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS); -+ vsir_validate_dst_count(ctx, instruction, 1); -+ vsir_validate_src_min_count(ctx, instruction, 2); -+ if (instruction->src_count % 2 != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, -+ "Invalid source count %u for a PHI instruction, it must be an even number.", -+ instruction->src_count); -+ incoming_count = instruction->src_count / 2; -+ -+ if (!register_is_ssa(&instruction->dst[0].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid destination of type %#x in PHI instruction, expected SSA.", -+ instruction->dst[0].reg.type); -+ -+ if (instruction->dst[0].reg.dimension != VSIR_DIMENSION_SCALAR) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, -+ "Invalid destination dimension %#x in PHI instruction, expected scalar.", -+ instruction->dst[0].reg.dimension); -+ -+ if (instruction->dst[0].modifiers != VKD3DSPDM_NONE) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, -+ "Invalid modifiers %#x for the destination of a PHI instruction, expected none.", -+ instruction->dst[0].modifiers); -+ -+ if (instruction->dst[0].shift != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT, -+ "Invalid shift %#x for the destination of a PHI instruction, expected none.", -+ instruction->dst[0].shift); -+ -+ for (i = 0; i < incoming_count; ++i) -+ { -+ unsigned int value_idx = 2 * i; -+ unsigned int label_idx = 2 * i + 1; -+ -+ if (!register_is_constant(&instruction->src[value_idx].reg) && !register_is_ssa(&instruction->src[value_idx].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid value register for incoming %zu of type %#x in PHI instruction, " -+ "expected SSA, IMMCONST or IMMCONST64.", i, instruction->src[value_idx].reg.type); -+ -+ if (instruction->src[value_idx].reg.dimension != VSIR_DIMENSION_SCALAR) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, -+ "Invalid value dimension %#x for incoming %zu in PHI instruction, expected scalar.", -+ instruction->src[value_idx].reg.dimension, i); -+ -+ if (!vsir_register_is_label(&instruction->src[label_idx].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid label register for case %zu of type %#x in PHI instruction, " -+ "expected LABEL.", i, instruction->src[value_idx].reg.type); -+ } -+ break; -+ } -+ - default: - break; - } - } - --void vsir_validate(struct vkd3d_shader_parser *parser) -+enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser) - { - struct validation_context ctx = - { - .parser = parser, -+ .program = &parser->program, - .phase = VKD3DSIH_INVALID, - }; -+ unsigned int i; - - if (!(parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)) -- return; -+ return VKD3D_OK; - -- for (ctx.instruction_idx = 0; ctx.instruction_idx < parser->instructions.count; ++ctx.instruction_idx) -+ if (!(ctx.temps = vkd3d_calloc(ctx.program->temp_count, sizeof(*ctx.temps)))) -+ goto fail; -+ -+ if (!(ctx.ssas = vkd3d_calloc(ctx.program->ssa_count, sizeof(*ctx.ssas)))) -+ goto fail; -+ -+ for (ctx.instruction_idx = 0; ctx.instruction_idx < parser->program.instructions.count; ++ctx.instruction_idx) - vsir_validate_instruction(&ctx); - -+ ctx.invalid_instruction_idx = true; -+ - if (ctx.depth != 0) -- validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "%zu nested blocks were not closed.", ctx.depth); -+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "%zu nested blocks were not closed.", ctx.depth); -+ -+ if (ctx.inside_block) -+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Last block was not closed."); -+ -+ for (i = 0; i < ctx.program->ssa_count; ++i) -+ { -+ struct validation_context_ssa_data *data = &ctx.ssas[i]; -+ -+ if ((data->write_mask | data->read_mask) != data->write_mask) -+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE, -+ "SSA register %u has invalid read mask %#x, which is not a subset of the write mask %#x " -+ "at the point of definition.", i, data->read_mask, data->write_mask); -+ } -+ -+ vkd3d_free(ctx.blocks); -+ vkd3d_free(ctx.temps); -+ vkd3d_free(ctx.ssas); -+ -+ return VKD3D_OK; -+ -+fail: -+ vkd3d_free(ctx.blocks); -+ vkd3d_free(ctx.temps); -+ vkd3d_free(ctx.ssas); - -- free(ctx.blocks); -+ return VKD3D_ERROR_OUT_OF_MEMORY; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index c8a43adbe03..6c92b03b216 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -133,7 +133,7 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, - } - } - --static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, -+static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv, - enum vkd3d_shader_spirv_environment environment) - { - spv_diagnostic diagnostic = NULL; -@@ -145,12 +145,13 @@ static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, - if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t), - &diagnostic))) - { -- FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret); -- FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error)); -+ vkd3d_string_buffer_printf(buffer, "%s", diagnostic->error); - } - - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(context); -+ -+ return !ret; - } - - #else -@@ -163,8 +164,11 @@ static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_co - } - static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, - enum vkd3d_shader_spirv_environment environment) {} --static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, -- enum vkd3d_shader_spirv_environment environment) {} -+static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv, -+ enum vkd3d_shader_spirv_environment environment) -+{ -+ return true; -+} - - #endif /* HAVE_SPIRV_TOOLS */ - -@@ -219,16 +223,6 @@ enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d - } - } - --static inline bool register_is_undef(const struct vkd3d_shader_register *reg) --{ -- return reg->type == VKD3DSPR_UNDEF; --} -- --static inline bool register_is_constant_or_undef(const struct vkd3d_shader_register *reg) --{ -- return register_is_constant(reg) || register_is_undef(reg); --} -- - #define VKD3D_SPIRV_VERSION 0x00010000 - #define VKD3D_SPIRV_GENERATOR_ID 18 - #define VKD3D_SPIRV_GENERATOR_VERSION 10 -@@ -851,20 +845,6 @@ static void vkd3d_spirv_end_function_stream_insertion(struct vkd3d_spirv_builder - builder->insertion_location = ~(size_t)0; - } - --struct vkd3d_spirv_op_branch_conditional --{ -- uint32_t opcode; -- uint32_t condition_id; -- uint32_t true_label; -- uint32_t false_label; --}; -- --static struct vkd3d_spirv_op_branch_conditional *vkd3d_spirv_as_op_branch_conditional( -- struct vkd3d_spirv_stream *stream, size_t location) --{ -- return (struct vkd3d_spirv_op_branch_conditional *)&stream->words[location]; --} -- - static void vkd3d_spirv_build_op_capability(struct vkd3d_spirv_stream *stream, - SpvCapability cap) - { -@@ -1194,6 +1174,16 @@ static uint32_t vkd3d_spirv_get_op_constant64(struct vkd3d_spirv_builder *builde - (const uint32_t *)&value, 2, vkd3d_spirv_build_op_constant64); - } - -+static uint32_t vkd3d_spirv_build_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) -+{ -+ return vkd3d_spirv_build_op_tr(builder, &builder->global_stream, SpvOpConstantNull, result_type); -+} -+ -+static uint32_t vkd3d_spirv_get_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) -+{ -+ return vkd3d_spirv_build_once1(builder, SpvOpConstantNull, result_type, vkd3d_spirv_build_op_constant_null); -+} -+ - static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder, - uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) - { -@@ -1515,6 +1505,25 @@ static uint32_t vkd3d_spirv_build_op_uless_than_equal(struct vkd3d_spirv_builder - SpvOpULessThanEqual, result_type, operand0, operand1); - } - -+static uint32_t vkd3d_spirv_build_op_is_inf(struct vkd3d_spirv_builder *builder, -+ uint32_t result_type, uint32_t operand) -+{ -+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpIsInf, result_type, operand); -+} -+ -+static uint32_t vkd3d_spirv_build_op_is_nan(struct vkd3d_spirv_builder *builder, -+ uint32_t result_type, uint32_t operand) -+{ -+ return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpIsNan, result_type, operand); -+} -+ -+static uint32_t vkd3d_spirv_build_op_logical_equal(struct vkd3d_spirv_builder *builder, -+ uint32_t result_type, uint32_t operand0, uint32_t operand1) -+{ -+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, -+ SpvOpLogicalEqual, result_type, operand0, operand1); -+} -+ - static uint32_t vkd3d_spirv_build_op_convert_utof(struct vkd3d_spirv_builder *builder, - uint32_t result_type, uint32_t unsigned_value) - { -@@ -1750,6 +1759,15 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_max(struct vkd3d_spirv_builder - GLSLstd450NMax, operands, ARRAY_SIZE(operands)); - } - -+static uint32_t vkd3d_spirv_build_op_glsl_std450_umin(struct vkd3d_spirv_builder *builder, -+ uint32_t result_type, uint32_t x, uint32_t y) -+{ -+ uint32_t glsl_std450_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); -+ uint32_t operands[] = {x, y}; -+ return vkd3d_spirv_build_op_ext_inst(builder, result_type, glsl_std450_id, -+ GLSLstd450UMin, operands, ARRAY_SIZE(operands)); -+} -+ - static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_builder *builder, - uint32_t result_type, uint32_t x, uint32_t min, uint32_t max) - { -@@ -1783,6 +1801,8 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, - break; - case VKD3D_SHADER_COMPONENT_DOUBLE: - return vkd3d_spirv_get_op_type_float(builder, 64); -+ case VKD3D_SHADER_COMPONENT_UINT64: -+ return vkd3d_spirv_get_op_type_int(builder, 64, 0); - default: - FIXME("Unhandled component type %#x.\n", component_type); - return 0; -@@ -1816,6 +1836,8 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder - break; - case VKD3D_DATA_DOUBLE: - return vkd3d_spirv_get_op_type_float(builder, 64); -+ case VKD3D_DATA_UINT64: -+ return vkd3d_spirv_get_op_type_int(builder, 64, 0); - case VKD3D_DATA_BOOL: - return vkd3d_spirv_get_op_type_bool(builder); - default: -@@ -1858,8 +1880,6 @@ static void vkd3d_spirv_builder_begin_main_function(struct vkd3d_spirv_builder * - - vkd3d_spirv_build_op_function(builder, void_id, - builder->main_function_id, SpvFunctionControlMaskNone, function_type_id); -- vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); -- builder->main_function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); - } - - static void vkd3d_spirv_builder_free(struct vkd3d_spirv_builder *builder) -@@ -1922,6 +1942,8 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, - vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_descriptor_indexing"); - if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStencilExportEXT)) - vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_shader_stencil_export"); -+ if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityShaderViewportIndexLayerEXT)) -+ vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_shader_viewport_index_layer"); - - if (builder->ext_instr_set_glsl_450) - vkd3d_spirv_build_op_ext_inst_import(&stream, builder->ext_instr_set_glsl_450, "GLSL.std.450"); -@@ -2152,6 +2174,7 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, - break; - - case VKD3DSPR_IMMCONSTBUFFER: -+ symbol->key.reg.idx = reg->idx_count > 1 ? reg->idx[0].offset : 0; - break; - - default: -@@ -2159,9 +2182,18 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, - } - } - -+static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol, -+ enum vkd3d_shader_register_type type, unsigned int index) -+{ -+ symbol->type = VKD3D_SYMBOL_REGISTER; -+ memset(&symbol->key, 0, sizeof(symbol->key)); -+ symbol->key.reg.type = type; -+ symbol->key.reg.idx = index; -+} -+ - static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol, - uint32_t val_id, SpvStorageClass storage_class, -- enum vkd3d_shader_component_type component_type, DWORD write_mask) -+ enum vkd3d_shader_component_type component_type, uint32_t write_mask) - { - symbol->id = val_id; - symbol->descriptor_array = NULL; -@@ -2230,51 +2262,6 @@ static const char *debug_vkd3d_symbol(const struct vkd3d_symbol *symbol) - } - } - --struct vkd3d_if_cf_info --{ -- size_t stream_location; -- unsigned int id; -- uint32_t merge_block_id; -- uint32_t else_block_id; --}; -- --struct vkd3d_loop_cf_info --{ -- uint32_t header_block_id; -- uint32_t continue_block_id; -- uint32_t merge_block_id; --}; -- --struct vkd3d_switch_cf_info --{ -- size_t stream_location; -- unsigned int id; -- uint32_t selector_id; -- uint32_t merge_block_id; -- uint32_t default_block_id; -- uint32_t *case_blocks; -- size_t case_blocks_size; -- unsigned int case_block_count; --}; -- --struct vkd3d_control_flow_info --{ -- union -- { -- struct vkd3d_if_cf_info if_; -- struct vkd3d_loop_cf_info loop; -- struct vkd3d_switch_cf_info switch_; -- } u; -- -- enum -- { -- VKD3D_BLOCK_IF, -- VKD3D_BLOCK_LOOP, -- VKD3D_BLOCK_SWITCH, -- } current_block; -- bool inside_block; --}; -- - struct vkd3d_push_constant_buffer_binding - { - struct vkd3d_shader_register reg; -@@ -2328,13 +2315,6 @@ struct spirv_compiler - - enum vkd3d_shader_type shader_type; - -- unsigned int branch_id; -- unsigned int loop_id; -- unsigned int switch_id; -- unsigned int control_flow_depth; -- struct vkd3d_control_flow_info *control_flow_info; -- size_t control_flow_info_size; -- - struct vkd3d_shader_interface_info shader_interface; - struct vkd3d_shader_descriptor_offset_info offset_info; - uint32_t descriptor_offsets_member_id; -@@ -2343,8 +2323,7 @@ struct spirv_compiler - struct vkd3d_push_constant_buffer_binding *push_constants; - const struct vkd3d_shader_spirv_target_info *spirv_target_info; - -- bool main_block_open; -- bool after_declarations_section; -+ bool prolog_emitted; - struct shader_signature input_signature; - struct shader_signature output_signature; - struct shader_signature patch_constant_signature; -@@ -2358,13 +2337,16 @@ struct spirv_compiler - uint32_t private_output_variable[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */ - uint32_t private_output_variable_write_mask[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */ - uint32_t epilogue_function_id; -+ uint32_t discard_function_id; - - uint32_t binding_idx; - - const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info; - unsigned int input_control_point_count; - unsigned int output_control_point_count; -+ - bool use_vocp; -+ bool emit_point_size; - - enum vkd3d_shader_opcode phase; - bool emit_default_control_point_phase; -@@ -2376,12 +2358,21 @@ struct spirv_compiler - struct vkd3d_shader_spec_constant *spec_constants; - size_t spec_constants_size; - enum vkd3d_shader_compile_option_formatting_flags formatting; -+ enum vkd3d_shader_compile_option_feature_flags features; -+ enum vkd3d_shader_api_version api_version; - bool write_tess_geom_point_size; - - struct vkd3d_string_buffer_cache string_buffers; - - struct ssa_register_info *ssa_register_info; - unsigned int ssa_register_count; -+ -+ uint64_t config_flags; -+ -+ uint32_t *block_label_ids; -+ unsigned int block_count; -+ const char **block_names; -+ size_t block_name_count; - }; - - static bool is_in_default_phase(const struct spirv_compiler *compiler) -@@ -2400,6 +2391,9 @@ static bool is_in_fork_or_join_phase(const struct spirv_compiler *compiler) - } - - static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *compiler); -+static size_t spirv_compiler_get_current_function_location(struct spirv_compiler *compiler); -+static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler); -+static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler); - - static const char *spirv_compiler_get_entry_point_name(const struct spirv_compiler *compiler) - { -@@ -2410,8 +2404,6 @@ static const char *spirv_compiler_get_entry_point_name(const struct spirv_compil - - static void spirv_compiler_destroy(struct spirv_compiler *compiler) - { -- vkd3d_free(compiler->control_flow_info); -- - vkd3d_free(compiler->output_info); - - vkd3d_free(compiler->push_constants); -@@ -2430,6 +2422,7 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) - shader_signature_cleanup(&compiler->patch_constant_signature); - - vkd3d_free(compiler->ssa_register_info); -+ vkd3d_free(compiler->block_label_ids); - - vkd3d_free(compiler); - } -@@ -2437,7 +2430,8 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) - static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *shader_version, - struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, - const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info, -- struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location) -+ struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location, -+ uint64_t config_flags) - { - const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature; - const struct shader_signature *output_signature = &shader_desc->output_signature; -@@ -2454,6 +2448,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve - memset(compiler, 0, sizeof(*compiler)); - compiler->message_context = message_context; - compiler->location = *location; -+ compiler->config_flags = config_flags; - - if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO))) - { -@@ -2509,6 +2504,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve - break; - - case VKD3D_SHADER_COMPILE_OPTION_API_VERSION: -+ compiler->api_version = option->value; - break; - - case VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV: -@@ -2533,12 +2529,20 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve - WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name); - break; - -+ case VKD3D_SHADER_COMPILE_OPTION_FEATURE: -+ compiler->features = option->value; -+ break; -+ - default: - WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value); - break; - } - } - -+ /* Explicit enabling of float64 was not required for API versions <= 1.10. */ -+ if (compiler->api_version <= VKD3D_SHADER_API_VERSION_1_10) -+ compiler->features |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLOAT64; -+ - rb_init(&compiler->symbol_table, vkd3d_symbol_compare); - - compiler->shader_type = shader_version->type; -@@ -2546,6 +2550,8 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve - if ((shader_interface = vkd3d_find_struct(compile_info->next, INTERFACE_INFO))) - { - compiler->xfb_info = vkd3d_find_struct(compile_info->next, TRANSFORM_FEEDBACK_INFO); -+ compiler->emit_point_size = compiler->xfb_info && compiler->xfb_info->element_count -+ && compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY; - - compiler->shader_interface = *shader_interface; - if (shader_interface->push_constant_buffer_count) -@@ -2759,6 +2765,14 @@ static struct vkd3d_string_buffer *vkd3d_shader_register_range_string(struct spi - return buffer; - } - -+static uint32_t spirv_compiler_get_label_id(struct spirv_compiler *compiler, unsigned int block_id) -+{ -+ --block_id; -+ if (!compiler->block_label_ids[block_id]) -+ compiler->block_label_ids[block_id] = vkd3d_spirv_alloc_id(&compiler->spirv_builder); -+ return compiler->block_label_ids[block_id]; -+} -+ - static struct vkd3d_shader_descriptor_binding spirv_compiler_get_descriptor_binding( - struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg, - const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type, -@@ -2955,7 +2969,7 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, - assert(0 < component_count && component_count <= VKD3D_DVEC2_SIZE); - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); - -- if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE) -+ if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE && component_type != VKD3D_SHADER_COMPONENT_UINT64) - { - FIXME("Unhandled component_type %#x.\n", component_type); - return vkd3d_spirv_get_op_undef(builder, type_id); -@@ -3015,14 +3029,21 @@ static uint32_t spirv_compiler_get_constant_double_vector(struct spirv_compiler - component_count, (const uint64_t *)values); - } - -+static uint32_t spirv_compiler_get_constant_uint64_vector(struct spirv_compiler *compiler, -+ uint64_t value, unsigned int component_count) -+{ -+ const uint64_t values[] = {value, value}; -+ return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_UINT64, component_count, values); -+} -+ - static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - - return vkd3d_spirv_get_type_id(builder, - vkd3d_component_type_from_data_type(reg->data_type), -- vkd3d_write_mask_component_count(write_mask)); -+ vsir_write_mask_component_count(write_mask)); - } - - static uint32_t spirv_compiler_get_type_id_for_dst(struct spirv_compiler *compiler, -@@ -3317,7 +3338,7 @@ static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *comp - } - - static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, -- const struct vkd3d_shader_src_param *src, DWORD write_mask); -+ const struct vkd3d_shader_src_param *src, uint32_t write_mask); - - static uint32_t spirv_compiler_emit_register_addressing(struct spirv_compiler *compiler, - const struct vkd3d_shader_register_index *reg_index) -@@ -3467,11 +3488,13 @@ static uint32_t spirv_compiler_get_descriptor_index(struct spirv_compiler *compi - index_ids[0] = compiler->descriptor_offsets_member_id; - index_ids[1] = spirv_compiler_get_constant_uint(compiler, push_constant_index); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPushConstant, type_id); -+ vkd3d_spirv_begin_function_stream_insertion(builder, -+ spirv_compiler_get_current_function_location(compiler)); - ptr_id = vkd3d_spirv_build_op_in_bounds_access_chain(builder, ptr_type_id, - compiler->push_constants_var_id, index_ids, 2); - offset_id = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone); -- if (!compiler->control_flow_depth) -- compiler->descriptor_offset_ids[push_constant_index] = offset_id; -+ vkd3d_spirv_end_function_stream_insertion(builder); -+ compiler->descriptor_offset_ids[push_constant_index] = offset_id; - } - index_id = vkd3d_spirv_build_op_iadd(builder, type_id, index_id, offset_id); - } -@@ -3498,7 +3521,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp - } - else if (reg->type == VKD3DSPR_IMMCONSTBUFFER) - { -- indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[0]); -+ indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[reg->idx_count - 1]); - } - else if (reg->type == VKD3DSPR_IDXTEMP) - { -@@ -3530,7 +3553,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp - - if (index_count) - { -- component_count = vkd3d_write_mask_component_count(register_info->write_mask); -+ component_count = vsir_write_mask_component_count(register_info->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, register_info->component_type, component_count); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id); - register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, -@@ -3556,30 +3579,35 @@ static uint32_t spirv_compiler_get_register_id(struct spirv_compiler *compiler, - SpvStorageClassPrivate, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); - } - --static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask, -- unsigned int swizzle, unsigned int write_mask) -+static bool vkd3d_swizzle_is_equal(uint32_t dst_write_mask, uint32_t swizzle, uint32_t write_mask) - { - return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask); - } - --static bool vkd3d_swizzle_is_scalar(unsigned int swizzle) -+static bool vkd3d_swizzle_is_scalar(uint32_t swizzle, const struct vkd3d_shader_register *reg) - { -- unsigned int component_idx = vkd3d_swizzle_get_component(swizzle, 0); -- return vkd3d_swizzle_get_component(swizzle, 1) == component_idx -- && vkd3d_swizzle_get_component(swizzle, 2) == component_idx -- && vkd3d_swizzle_get_component(swizzle, 3) == component_idx; -+ unsigned int component_idx = vsir_swizzle_get_component(swizzle, 0); -+ -+ if (vsir_swizzle_get_component(swizzle, 1) != component_idx) -+ return false; -+ -+ if (data_type_is_64_bit(reg->data_type)) -+ return true; -+ -+ return vsir_swizzle_get_component(swizzle, 2) == component_idx -+ && vsir_swizzle_get_component(swizzle, 3) == component_idx; - } - - static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, -- uint32_t val_id, unsigned int val_write_mask, enum vkd3d_shader_component_type component_type, -- unsigned int swizzle, unsigned int write_mask) -+ uint32_t val_id, uint32_t val_write_mask, enum vkd3d_shader_component_type component_type, -+ uint32_t swizzle, uint32_t write_mask) - { - unsigned int i, component_idx, component_count, val_component_count; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, components[VKD3D_VEC4_SIZE]; - -- component_count = vkd3d_write_mask_component_count(write_mask); -- val_component_count = vkd3d_write_mask_component_count(val_write_mask); -+ component_count = vsir_write_mask_component_count(write_mask); -+ val_component_count = vsir_write_mask_component_count(val_write_mask); - - if (component_count == val_component_count - && (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask))) -@@ -3589,9 +3617,9 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - - if (component_count == 1) - { -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -- component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); -- component_idx -= vkd3d_write_mask_get_component_idx(val_write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); -+ component_idx = vsir_swizzle_get_component(swizzle, component_idx); -+ component_idx -= vsir_write_mask_get_component_idx(val_write_mask); - return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); - } - -@@ -3601,7 +3629,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - { -- assert(VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(swizzle, i) == val_write_mask); -+ assert(VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(swizzle, i) == val_write_mask); - components[component_idx++] = val_id; - } - } -@@ -3611,14 +3639,14 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - for (i = 0, component_idx = 0; i < VKD3D_VEC4_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- components[component_idx++] = vkd3d_swizzle_get_component(swizzle, i); -+ components[component_idx++] = vsir_swizzle_get_component(swizzle, i); - } - return vkd3d_spirv_build_op_vector_shuffle(builder, - type_id, val_id, val_id, components, component_count); - } - - static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compiler, -- uint32_t vector1_id, uint32_t vector2_id, unsigned int swizzle, unsigned int write_mask, -+ uint32_t vector1_id, uint32_t vector2_id, uint32_t swizzle, uint32_t write_mask, - enum vkd3d_shader_component_type component_type, unsigned int component_count) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -@@ -3631,9 +3659,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil - for (i = 0; i < component_count; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- components[i] = vkd3d_swizzle_get_component(swizzle, i); -+ components[i] = vsir_swizzle_get_component(swizzle, i); - else -- components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(swizzle, i); -+ components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle, i); - } - - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -@@ -3641,10 +3669,77 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil - type_id, vector1_id, vector2_id, components, component_count); - } - -+static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, -+ enum vkd3d_shader_conditional_op condition, enum vkd3d_data_type data_type, -+ unsigned int component_count, uint32_t val_id) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t type_id; -+ SpvOp op; -+ -+ assert(!(condition & ~(VKD3D_SHADER_CONDITIONAL_OP_NZ | VKD3D_SHADER_CONDITIONAL_OP_Z))); -+ -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual; -+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id, -+ data_type == VKD3D_DATA_UINT64 -+ ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count) -+ : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); -+} -+ -+static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, -+ unsigned int component_count, uint32_t val_id, bool signedness) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t type_id, true_id, false_id; -+ -+ true_id = spirv_compiler_get_constant_uint_vector(compiler, signedness ? 0xffffffff : 1, component_count); -+ false_id = spirv_compiler_get_constant_uint_vector(compiler, 0, component_count); -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); -+ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -+} -+ -+static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compiler, -+ unsigned int component_count, uint32_t val_id, bool signedness) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t type_id, true_id, false_id; -+ -+ true_id = spirv_compiler_get_constant_uint64_vector(compiler, signedness ? UINT64_MAX : 1, -+ component_count); -+ false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count); -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT64, component_count); -+ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -+} -+ -+static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler, -+ unsigned int component_count, uint32_t val_id, bool signedness) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t type_id, true_id, false_id; -+ -+ true_id = spirv_compiler_get_constant_float_vector(compiler, signedness ? -1.0f : 1.0f, component_count); -+ false_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); -+ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -+} -+ -+static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compiler, -+ unsigned int component_count, uint32_t val_id, bool signedness) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t type_id, true_id, false_id; -+ -+ true_id = spirv_compiler_get_constant_double_vector(compiler, signedness ? -1.0 : 1.0, component_count); -+ false_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_DOUBLE, component_count); -+ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -+} -+ - static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) - { -- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(write_mask); - uint32_t values[VKD3D_VEC4_SIZE] = {0}; - unsigned int i, j; - -@@ -3653,14 +3748,14 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile - if (reg->dimension == VSIR_DIMENSION_SCALAR) - { - for (i = 0; i < component_count; ++i) -- values[i] = *reg->u.immconst_uint; -+ values[i] = *reg->u.immconst_u32; - } - else - { - for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- values[j++] = reg->u.immconst_uint[vkd3d_swizzle_get_component(swizzle, i)]; -+ values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; - } - } - -@@ -3669,9 +3764,9 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile - } - - static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) - { -- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(write_mask); - uint64_t values[VKD3D_DVEC2_SIZE] = {0}; - unsigned int i, j; - -@@ -3680,14 +3775,14 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi - if (reg->dimension == VSIR_DIMENSION_SCALAR) - { - for (i = 0; i < component_count; ++i) -- values[i] = *reg->u.immconst_uint64; -+ values[i] = *reg->u.immconst_u64; - } - else - { - for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- values[j++] = reg->u.immconst_uint64[vkd3d_swizzle_get_component64(swizzle, i)]; -+ values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component(swizzle, i)]; - } - } - -@@ -3696,9 +3791,9 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi - } - - static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask) - { -- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(write_mask); - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id; - -@@ -3709,28 +3804,28 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask, -+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask, - const struct vkd3d_shader_register_info *reg_info) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, ptr_type_id, index, reg_id, val_id; - unsigned int component_idx, reg_component_count; - enum vkd3d_shader_component_type component_type; -- unsigned int skipped_component_mask; -+ uint32_t skipped_component_mask; - - assert(!register_is_constant_or_undef(reg)); -- assert(vkd3d_write_mask_component_count(write_mask) == 1); -+ assert(vsir_write_mask_component_count(write_mask) == 1); - -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -- component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); -+ component_idx = vsir_swizzle_get_component(swizzle, component_idx); - skipped_component_mask = ~reg_info->write_mask & ((VKD3DSP_WRITEMASK_0 << component_idx) - 1); - if (skipped_component_mask) -- component_idx -= vkd3d_write_mask_component_count(skipped_component_mask); -+ component_idx -= vsir_write_mask_component_count(skipped_component_mask); - component_type = vkd3d_component_type_from_data_type(reg->data_type); - -- reg_component_count = vkd3d_write_mask_component_count(reg_info->write_mask); -+ reg_component_count = vsir_write_mask_component_count(reg_info->write_mask); - -- if (component_idx >= vkd3d_write_mask_component_count(reg_info->write_mask)) -+ if (component_idx >= vsir_write_mask_component_count(reg_info->write_mask)) - { - ERR("Invalid component_idx %u for register %#x, %u (write_mask %#x).\n", - component_idx, reg->type, reg->idx[0].offset, reg_info->write_mask); -@@ -3749,13 +3844,89 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, - - if (component_type != reg_info->component_type) - { -- type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -- val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); -+ if (component_type == VKD3D_SHADER_COMPONENT_BOOL) -+ { -+ if (reg_info->component_type != VKD3D_SHADER_COMPONENT_UINT) -+ { -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); -+ } -+ val_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, -+ VKD3D_DATA_UINT, 1, val_id); -+ } -+ else -+ { -+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); -+ } - } - - return val_id; - } - -+static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler, -+ const struct vkd3d_shader_immediate_constant_buffer *icb, uint32_t *type_id_out) -+{ -+ uint32_t *elements, elem_type_id, length_id, type_id, const_id; -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ enum vkd3d_shader_component_type component_type; -+ unsigned int i, element_count, component_count; -+ -+ element_count = icb->element_count; -+ -+ component_type = vkd3d_component_type_from_data_type(icb->data_type); -+ component_count = icb->component_count; -+ elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, component_count); -+ length_id = spirv_compiler_get_constant_uint(compiler, element_count); -+ type_id = vkd3d_spirv_get_op_type_array(builder, elem_type_id, length_id); -+ -+ if (type_id_out) -+ *type_id_out = type_id; -+ -+ if (icb->is_null) -+ { -+ /* All values are null. Workgroup memory initialisers require OpConstantNull. */ -+ return vkd3d_spirv_get_op_constant_null(builder, type_id); -+ } -+ -+ if (!(elements = vkd3d_calloc(element_count, sizeof(*elements)))) -+ { -+ ERR("Failed to allocate %u elements.", element_count); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY, -+ "Failed to allocate %u constant array elements.", element_count); -+ return 0; -+ } -+ -+ switch (icb->data_type) -+ { -+ case VKD3D_DATA_FLOAT: -+ case VKD3D_DATA_INT: -+ case VKD3D_DATA_UINT: -+ for (i = 0; i < element_count; ++i) -+ elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, -+ &icb->data[component_count * i]); -+ break; -+ case VKD3D_DATA_DOUBLE: -+ case VKD3D_DATA_UINT64: -+ { -+ uint64_t *data = (uint64_t *)icb->data; -+ for (i = 0; i < element_count; ++i) -+ elements[i] = spirv_compiler_get_constant64(compiler, component_type, component_count, -+ &data[component_count * i]); -+ break; -+ } -+ default: -+ FIXME("Unhandled data type %u.\n", icb->data_type); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, -+ "Immediate constant buffer data type %u is unhandled.", icb->data_type); -+ break; -+ } -+ -+ const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count); -+ vkd3d_free(elements); -+ return const_id; -+} -+ - static const struct ssa_register_info *spirv_compiler_get_ssa_register_info(const struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg) - { -@@ -3775,7 +3946,7 @@ static void spirv_compiler_set_ssa_register_info(const struct spirv_compiler *co - - static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, enum vkd3d_shader_component_type component_type, -- unsigned int swizzle) -+ uint32_t swizzle) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type reg_component_type; -@@ -3785,12 +3956,18 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler - - ssa = spirv_compiler_get_ssa_register_info(compiler, reg); - val_id = ssa->id; -- assert(val_id); -- assert(vkd3d_swizzle_is_scalar(swizzle)); -+ if (!val_id) -+ { -+ /* Should only be from a missing instruction implementation. */ -+ assert(compiler->failed); -+ return 0; -+ } -+ assert(vkd3d_swizzle_is_scalar(swizzle, reg)); -+ -+ reg_component_type = vkd3d_component_type_from_data_type(ssa->data_type); - - if (reg->dimension == VSIR_DIMENSION_SCALAR) - { -- reg_component_type = vkd3d_component_type_from_data_type(ssa->data_type); - if (component_type != reg_component_type) - { - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -@@ -3800,20 +3977,28 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler - return val_id; - } - -+ if (component_type != reg_component_type) -+ { -+ /* Required for resource loads with sampled type int, because DXIL has no signedness. -+ * Only 128-bit vector sizes are used. */ -+ type_id = vkd3d_spirv_get_type_id(builder, component_type, VKD3D_VEC4_SIZE); -+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); -+ } -+ - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -- component_idx = vkd3d_swizzle_get_component(swizzle, 0); -+ component_idx = vsir_swizzle_get_component(swizzle, 0); - return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); - } - - static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type component_type; - struct vkd3d_shader_register_info reg_info; - unsigned int component_count; -- unsigned int write_mask32; - uint32_t type_id, val_id; -+ uint32_t write_mask32; - - if (reg->type == VKD3DSPR_IMMCONST) - return spirv_compiler_emit_load_constant(compiler, reg, swizzle, write_mask); -@@ -3822,7 +4007,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, - else if (reg->type == VKD3DSPR_UNDEF) - return spirv_compiler_emit_load_undef(compiler, reg, write_mask); - -- component_count = vkd3d_write_mask_component_count(write_mask); -+ component_count = vsir_write_mask_component_count(write_mask); - component_type = vkd3d_component_type_from_data_type(reg->data_type); - - if (reg->type == VKD3DSPR_SSA) -@@ -3836,31 +4021,45 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, - assert(reg_info.component_type != VKD3D_SHADER_COMPONENT_DOUBLE); - spirv_compiler_emit_dereference_register(compiler, reg, ®_info); - -- write_mask32 = (reg->data_type == VKD3D_DATA_DOUBLE) ? vkd3d_write_mask_32_from_64(write_mask) : write_mask; -+ write_mask32 = data_type_is_64_bit(reg->data_type) ? vsir_write_mask_32_from_64(write_mask) : write_mask; - - /* Intermediate value (no storage class). */ - if (reg_info.storage_class == SpvStorageClassMax) - { - val_id = reg_info.id; - } -- else if (vkd3d_write_mask_component_count(write_mask32) == 1) -+ else if (vsir_write_mask_component_count(write_mask32) == 1) - { - return spirv_compiler_emit_load_scalar(compiler, reg, swizzle, write_mask, ®_info); - } - else - { - type_id = vkd3d_spirv_get_type_id(builder, -- reg_info.component_type, vkd3d_write_mask_component_count(reg_info.write_mask)); -+ reg_info.component_type, vsir_write_mask_component_count(reg_info.write_mask)); - val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone); - } - -+ swizzle = data_type_is_64_bit(reg->data_type) ? vsir_swizzle_32_from_64(swizzle) : swizzle; - val_id = spirv_compiler_emit_swizzle(compiler, - val_id, reg_info.write_mask, reg_info.component_type, swizzle, write_mask32); - - if (component_type != reg_info.component_type) - { -- type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -- val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); -+ if (component_type == VKD3D_SHADER_COMPONENT_BOOL) -+ { -+ if (reg_info.component_type != VKD3D_SHADER_COMPONENT_UINT) -+ { -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); -+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); -+ } -+ val_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, -+ VKD3D_DATA_UINT, component_count, val_id); -+ } -+ else -+ { -+ type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); -+ } - } - - return val_id; -@@ -3882,7 +4081,7 @@ static void spirv_compiler_emit_execution_mode1(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id; -@@ -3896,7 +4095,7 @@ static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id; -@@ -3904,7 +4103,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, - type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); - if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE) - return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id); -- else if (reg->data_type == VKD3D_DATA_INT || reg->data_type == VKD3D_DATA_UINT) -+ else if (data_type_is_integer(reg->data_type)) - return vkd3d_spirv_build_op_snegate(builder, type_id, val_id); - - FIXME("Unhandled data type %#x.\n", reg->data_type); -@@ -3912,7 +4111,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask, -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, - enum vkd3d_shader_src_modifier modifier, uint32_t val_id) - { - switch (modifier) -@@ -3935,7 +4134,7 @@ static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler - } - - static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, -- const struct vkd3d_shader_src_param *src, DWORD write_mask) -+ const struct vkd3d_shader_src_param *src, uint32_t write_mask) - { - uint32_t val_id; - -@@ -3944,7 +4143,7 @@ static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *compiler, -- const struct vkd3d_shader_src_param *src, DWORD write_mask, enum vkd3d_shader_component_type component_type) -+ const struct vkd3d_shader_src_param *src, uint32_t write_mask, enum vkd3d_shader_component_type component_type) - { - struct vkd3d_shader_src_param src_param = *src; - -@@ -3953,19 +4152,19 @@ static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *co - } - - static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, -- uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type, -- SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id) -+ uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, -+ SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, ptr_type_id, index; - unsigned int component_idx; - -- if (vkd3d_write_mask_component_count(dst_write_mask) > 1) -+ if (vsir_write_mask_component_count(dst_write_mask) > 1) - { - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -- component_idx -= vkd3d_write_mask_get_component_idx(dst_write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); -+ component_idx -= vsir_write_mask_get_component_idx(dst_write_mask); - index = spirv_compiler_get_constant_uint(compiler, component_idx); - dst_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, dst_id, index); - } -@@ -3974,8 +4173,8 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, - } - - static void spirv_compiler_emit_store(struct spirv_compiler *compiler, -- uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type, -- SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id) -+ uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, -+ SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - unsigned int component_count, dst_component_count; -@@ -3985,14 +4184,14 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, - - assert(write_mask); - -- component_count = vkd3d_write_mask_component_count(write_mask); -- dst_component_count = vkd3d_write_mask_component_count(dst_write_mask); -+ component_count = vsir_write_mask_component_count(write_mask); -+ dst_component_count = vsir_write_mask_component_count(dst_write_mask); - - if (dst_component_count == 1 && component_count != 1) - { - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, -- vkd3d_write_mask_get_component_idx(dst_write_mask)); -+ vsir_write_mask_get_component_idx(dst_write_mask)); - write_mask &= dst_write_mask; - component_count = 1; - } -@@ -4029,12 +4228,12 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, - } - - static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, unsigned int write_mask, uint32_t val_id) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type component_type; - struct vkd3d_shader_register_info reg_info; -- unsigned int src_write_mask = write_mask; -+ uint32_t src_write_mask = write_mask; - uint32_t type_id; - - assert(!register_is_constant_or_undef(reg)); -@@ -4052,10 +4251,13 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, - component_type = vkd3d_component_type_from_data_type(reg->data_type); - if (component_type != reg_info.component_type) - { -- if (reg->data_type == VKD3D_DATA_DOUBLE) -- src_write_mask = vkd3d_write_mask_32_from_64(write_mask); -+ if (data_type_is_64_bit(reg->data_type)) -+ src_write_mask = vsir_write_mask_32_from_64(write_mask); -+ if (component_type == VKD3D_SHADER_COMPONENT_BOOL) -+ val_id = spirv_compiler_emit_bool_to_int(compiler, -+ vsir_write_mask_component_count(src_write_mask), val_id, false); - type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, -- vkd3d_write_mask_component_count(src_write_mask)); -+ vsir_write_mask_component_count(src_write_mask)); - val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); - component_type = reg_info.component_type; - } -@@ -4065,9 +4267,9 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) - { -- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(write_mask); - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, zero_id, one_id; - -@@ -4102,7 +4304,7 @@ static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler, - - static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst, uint32_t val_id, -- enum vkd3d_shader_component_type component_type, DWORD swizzle) -+ enum vkd3d_shader_component_type component_type, uint32_t swizzle) - { - struct vkd3d_shader_dst_param typed_dst = *dst; - val_id = spirv_compiler_emit_swizzle(compiler, -@@ -4118,7 +4320,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp - const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_component_type component_type, - uint32_t *component_ids) - { -- unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, val_id; - -@@ -4137,16 +4339,16 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp - - static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst, uint32_t val_id, -- enum vkd3d_shader_component_type component_type, DWORD swizzle) -+ enum vkd3d_shader_component_type component_type, uint32_t swizzle) - { -- unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); - uint32_t component_ids[VKD3D_VEC4_SIZE]; - unsigned int component_idx, i; - -- component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask); -+ component_idx = vsir_write_mask_get_component_idx(dst->write_mask); - for (i = 0; i < component_count; ++i) - { -- if (vkd3d_swizzle_get_component(swizzle, component_idx + i)) -+ if (vsir_swizzle_get_component(swizzle, component_idx + i)) - ERR("Invalid swizzle %#x for scalar value, write mask %#x.\n", swizzle, dst->write_mask); - - component_ids[i] = val_id; -@@ -4169,10 +4371,58 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, - spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthReplacing, NULL, 0); - break; - case SpvBuiltInLayer: -- vkd3d_spirv_enable_capability(builder, SpvCapabilityGeometry); -+ switch (compiler->shader_type) -+ { -+ case VKD3D_SHADER_TYPE_PIXEL: -+ case VKD3D_SHADER_TYPE_GEOMETRY: -+ vkd3d_spirv_enable_capability(builder, SpvCapabilityGeometry); -+ break; -+ -+ case VKD3D_SHADER_TYPE_VERTEX: -+ case VKD3D_SHADER_TYPE_DOMAIN: -+ if (!spirv_compiler_is_target_extension_supported(compiler, -+ VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER)) -+ { -+ FIXME("The target environment does not support decoration Layer.\n"); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -+ "Cannot use SV_RenderTargetArrayIndex. " -+ "The target environment does not support decoration Layer."); -+ } -+ vkd3d_spirv_enable_capability(builder, SpvCapabilityShaderViewportIndexLayerEXT); -+ break; -+ -+ default: -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, -+ "Invalid use of SV_RenderTargetArrayIndex."); -+ break; -+ } - break; - case SpvBuiltInViewportIndex: -- vkd3d_spirv_enable_capability(builder, SpvCapabilityMultiViewport); -+ switch (compiler->shader_type) -+ { -+ case VKD3D_SHADER_TYPE_PIXEL: -+ case VKD3D_SHADER_TYPE_GEOMETRY: -+ vkd3d_spirv_enable_capability(builder, SpvCapabilityMultiViewport); -+ break; -+ -+ case VKD3D_SHADER_TYPE_VERTEX: -+ case VKD3D_SHADER_TYPE_DOMAIN: -+ if (!spirv_compiler_is_target_extension_supported(compiler, -+ VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER)) -+ { -+ FIXME("The target environment does not support decoration ViewportIndex.\n"); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -+ "Cannot use SV_ViewportArrayIndex. " -+ "The target environment does not support decoration ViewportIndex."); -+ } -+ vkd3d_spirv_enable_capability(builder, SpvCapabilityShaderViewportIndexLayerEXT); -+ break; -+ -+ default: -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, -+ "Invalid use of SV_ViewportArrayIndex."); -+ break; -+ } - break; - case SpvBuiltInSampleId: - vkd3d_spirv_enable_capability(builder, SpvCapabilitySampleRateShading); -@@ -4191,14 +4441,18 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, - } - - static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler *compiler, -- uint32_t id, enum vkd3d_shader_interpolation_mode mode) -+ enum vkd3d_shader_component_type component_type, uint32_t id, enum vkd3d_shader_interpolation_mode mode) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - - switch (mode) - { - case VKD3DSIM_NONE: -- break; -+ /* VUID-StandaloneSpirv-Flat-04744: integer or double types must be -+ * decorated 'Flat' for fragment shaders. */ -+ if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL || component_type == VKD3D_SHADER_COMPONENT_FLOAT) -+ break; -+ /* fall through */ - case VKD3DSIM_CONSTANT: - vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0); - break; -@@ -4225,87 +4479,36 @@ static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler - } - } - --static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, -- enum vkd3d_shader_conditional_op condition, unsigned int component_count, uint32_t val_id) -+typedef uint32_t (*vkd3d_spirv_builtin_fixup_pfn)(struct spirv_compiler *compiler, -+ uint32_t val_id); -+ -+static uint32_t spirv_compiler_emit_draw_parameter_fixup(struct spirv_compiler *compiler, -+ uint32_t index_id, SpvBuiltIn base) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- uint32_t type_id; -- SpvOp op; -+ uint32_t base_var_id, base_id, type_id; - -- assert(!(condition & ~(VKD3D_SHADER_CONDITIONAL_OP_NZ | VKD3D_SHADER_CONDITIONAL_OP_Z))); -+ vkd3d_spirv_enable_capability(builder, SpvCapabilityDrawParameters); - -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -- op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual; -- return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id, -- spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); --} -+ base_var_id = spirv_compiler_emit_variable(compiler, &builder->global_stream, -+ SpvStorageClassInput, VKD3D_SHADER_COMPONENT_INT, 1); -+ vkd3d_spirv_add_iface_variable(builder, base_var_id); -+ spirv_compiler_decorate_builtin(compiler, base_var_id, base); - --static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, -- unsigned int component_count, uint32_t val_id, bool signedness) --{ -- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- uint32_t type_id, true_id, false_id; -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, 1); -+ base_id = vkd3d_spirv_build_op_load(builder, -+ type_id, base_var_id, SpvMemoryAccessMaskNone); - -- true_id = spirv_compiler_get_constant_uint_vector(compiler, signedness ? 0xffffffff : 1, component_count); -- false_id = spirv_compiler_get_constant_uint_vector(compiler, 0, component_count); -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); -- return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -+ return vkd3d_spirv_build_op_isub(builder, type_id, index_id, base_id); - } - --static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler, -- unsigned int component_count, uint32_t val_id, bool signedness) -+/* Substitute "VertexIndex - BaseVertex" for SV_VertexID. */ -+static uint32_t sv_vertex_id_fixup(struct spirv_compiler *compiler, -+ uint32_t vertex_index_id) - { -- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- uint32_t type_id, true_id, false_id; -- -- true_id = spirv_compiler_get_constant_float_vector(compiler, signedness ? -1.0f : 1.0f, component_count); -- false_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); -- return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); --} -- --static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compiler, -- unsigned int component_count, uint32_t val_id, bool signedness) --{ -- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- uint32_t type_id, true_id, false_id; -- -- true_id = spirv_compiler_get_constant_double_vector(compiler, signedness ? -1.0 : 1.0, component_count); -- false_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_DOUBLE, component_count); -- return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); --} -- --typedef uint32_t (*vkd3d_spirv_builtin_fixup_pfn)(struct spirv_compiler *compiler, -- uint32_t val_id); -- --static uint32_t spirv_compiler_emit_draw_parameter_fixup(struct spirv_compiler *compiler, -- uint32_t index_id, SpvBuiltIn base) --{ -- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- uint32_t base_var_id, base_id, type_id; -- -- vkd3d_spirv_enable_capability(builder, SpvCapabilityDrawParameters); -- -- base_var_id = spirv_compiler_emit_variable(compiler, &builder->global_stream, -- SpvStorageClassInput, VKD3D_SHADER_COMPONENT_INT, 1); -- vkd3d_spirv_add_iface_variable(builder, base_var_id); -- spirv_compiler_decorate_builtin(compiler, base_var_id, base); -- -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, 1); -- base_id = vkd3d_spirv_build_op_load(builder, -- type_id, base_var_id, SpvMemoryAccessMaskNone); -- -- return vkd3d_spirv_build_op_isub(builder, type_id, index_id, base_id); --} -- --/* Substitute "VertexIndex - BaseVertex" for SV_VertexID. */ --static uint32_t sv_vertex_id_fixup(struct spirv_compiler *compiler, -- uint32_t vertex_index_id) --{ -- return spirv_compiler_emit_draw_parameter_fixup(compiler, -- vertex_index_id, SpvBuiltInBaseVertex); --} -+ return spirv_compiler_emit_draw_parameter_fixup(compiler, -+ vertex_index_id, SpvBuiltInBaseVertex); -+} - - /* Substitute "InstanceIndex - BaseInstance" for SV_InstanceID. */ - static uint32_t sv_instance_id_fixup(struct spirv_compiler *compiler, -@@ -4422,9 +4625,9 @@ vkd3d_register_builtins[] = - }; - - static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg) -+ enum vkd3d_shader_register_type type) - { -- switch (reg->type) -+ switch (type) - { - case VKD3DSPR_DEPTHOUTGE: - spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthGreater, NULL, 0); -@@ -4437,9 +4640,9 @@ static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *c - VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT)) - { - FIXME("The target environment does not support stencil export.\n"); -- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED, -- "Cannot export stencil reference value for register id %u. " -- "The target environment does not support stencil export.", reg->idx[0].offset); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -+ "Cannot export stencil reference value. " -+ "The target environment does not support stencil export."); - } - vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityStencilExportEXT); - spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeStencilRefReplacingEXT, NULL, 0); -@@ -4635,7 +4838,7 @@ static uint32_t spirv_compiler_emit_builtin_variable_v(struct spirv_compiler *co - assert(size_count <= ARRAY_SIZE(sizes)); - memcpy(sizes, array_sizes, size_count * sizeof(sizes[0])); - array_sizes = sizes; -- sizes[size_count - 1] = max(sizes[size_count - 1], builtin->spirv_array_size); -+ sizes[0] = max(sizes[0], builtin->spirv_array_size); - - id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, storage_class, - builtin->component_type, builtin->component_count, array_sizes, size_count); -@@ -4674,17 +4877,16 @@ static unsigned int shader_signature_next_location(const struct shader_signature - } - - static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, -- const struct vkd3d_shader_dst_param *dst) -+ enum vkd3d_shader_register_type reg_type, unsigned int element_idx) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- const struct vkd3d_shader_register *reg = &dst->reg; - unsigned int component_idx, input_component_count; - const struct signature_element *signature_element; - const struct shader_signature *shader_signature; - enum vkd3d_shader_component_type component_type; - const struct vkd3d_spirv_builtin *builtin; - enum vkd3d_shader_sysval_semantic sysval; -- unsigned int write_mask, reg_write_mask; -+ uint32_t write_mask, reg_write_mask; - struct vkd3d_symbol *symbol = NULL; - uint32_t val_id, input_id, var_id; - uint32_t type_id, float_type_id; -@@ -4693,31 +4895,26 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - struct rb_entry *entry = NULL; - bool use_private_var = false; - unsigned int array_sizes[2]; -- unsigned int element_idx; -- -- assert(!reg->idx_count || !reg->idx[0].rel_addr); -- assert(reg->idx_count < 2 || !reg->idx[1].rel_addr); - -- shader_signature = reg->type == VKD3DSPR_PATCHCONST -+ shader_signature = reg_type == VKD3DSPR_PATCHCONST - ? &compiler->patch_constant_signature : &compiler->input_signature; - -- element_idx = reg->idx[reg->idx_count - 1].offset; - signature_element = &shader_signature->elements[element_idx]; - sysval = signature_element->sysval_semantic; - /* The Vulkan spec does not explicitly forbid passing varyings from the - * TCS to the TES via builtins. However, Mesa doesn't seem to handle it - * well, and we don't actually need them to be in builtins. */ -- if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg->type != VKD3DSPR_PATCHCONST) -+ if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg_type != VKD3DSPR_PATCHCONST) - sysval = VKD3D_SHADER_SV_NONE; - - builtin = get_spirv_builtin_for_sysval(compiler, sysval); - -- array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); -- array_sizes[1] = signature_element->register_count; -- if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) -- && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[0])) -+ array_sizes[0] = signature_element->register_count; -+ array_sizes[1] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); -+ if (array_sizes[0] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) -+ && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[1])) - { -- array_sizes[1] = 0; -+ array_sizes[0] = 0; - } - - write_mask = signature_element->mask; -@@ -4731,8 +4928,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - else - { - component_type = signature_element->component_type; -- input_component_count = vkd3d_write_mask_component_count(signature_element->mask); -- component_idx = vkd3d_write_mask_get_component_idx(signature_element->mask); -+ input_component_count = vsir_write_mask_component_count(signature_element->mask); -+ component_idx = vsir_write_mask_get_component_idx(signature_element->mask); - } - - if (needs_private_io_variable(builtin)) -@@ -4742,13 +4939,13 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - } - else - { -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); - reg_write_mask = write_mask >> component_idx; - } - - storage_class = SpvStorageClassInput; - -- vkd3d_symbol_make_register(®_symbol, reg); -+ vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); - - if ((entry = rb_get(&compiler->symbol_table, ®_symbol))) - { -@@ -4756,7 +4953,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - * duplicate declarations are: a single register split into multiple declarations having - * different components, which should have been merged, and declarations in one phase - * being repeated in another (i.e. vcp/vocp), which should have been deleted. */ -- if (reg->type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) -+ if (reg_type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) - FIXME("Duplicate input definition found.\n"); - symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); - return symbol->id; -@@ -4765,7 +4962,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - if (builtin) - { - input_id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2); -- if (reg->type == VKD3DSPR_PATCHCONST) -+ if (reg_type == VKD3DSPR_PATCHCONST) - vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); - } - else -@@ -4775,7 +4972,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - input_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, - storage_class, component_type, input_component_count, array_sizes, 2); - vkd3d_spirv_add_iface_variable(builder, input_id); -- if (reg->type == VKD3DSPR_PATCHCONST) -+ if (reg_type == VKD3DSPR_PATCHCONST) - { - vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); - location += shader_signature_next_location(&compiler->input_signature); -@@ -4784,7 +4981,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - if (component_idx) - vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationComponent, component_idx); - -- spirv_compiler_emit_interpolation_decorations(compiler, input_id, signature_element->interpolation_mode); -+ spirv_compiler_emit_interpolation_decorations(compiler, component_type, input_id, -+ signature_element->interpolation_mode); - } - - var_id = input_id; -@@ -4802,12 +5000,14 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - assert(!builtin || !builtin->spirv_array_size || use_private_var || array_sizes[0] || array_sizes[1]); - spirv_compiler_put_symbol(compiler, ®_symbol); - -- spirv_compiler_emit_register_debug_name(builder, var_id, reg); -+ vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "v%u", element_idx); - - if (use_private_var) - { -- struct vkd3d_shader_register dst_reg = *reg; -- dst_reg.data_type = VKD3D_DATA_FLOAT; -+ struct vkd3d_shader_register dst_reg; -+ -+ vsir_register_init(&dst_reg, reg_type, VKD3D_DATA_FLOAT, 1); -+ dst_reg.idx[0].offset = element_idx; - - type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count); - -@@ -4824,9 +5024,9 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - - val_id = spirv_compiler_emit_swizzle(compiler, val_id, - vkd3d_write_mask_from_component_count(input_component_count), -- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, dst->write_mask >> component_idx); -+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, signature_element->mask >> component_idx); - -- spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id); -+ spirv_compiler_emit_store_reg(compiler, &dst_reg, signature_element->mask, val_id); - } - - return input_id; -@@ -4896,7 +5096,7 @@ static void calculate_clip_or_cull_distance_mask(const struct signature_element - return; - } - -- write_mask = e->mask >> vkd3d_write_mask_get_component_idx(e->mask); -+ write_mask = e->mask >> vsir_write_mask_get_component_idx(e->mask); - *mask |= (write_mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index); - } - -@@ -4995,7 +5195,7 @@ static void spirv_compiler_emit_output_register(struct spirv_compiler *compiler, - SpvStorageClassOutput, builtin->component_type, write_mask); - reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size; - spirv_compiler_put_symbol(compiler, ®_symbol); -- spirv_compiler_emit_register_execution_mode(compiler, reg); -+ spirv_compiler_emit_register_execution_mode(compiler, reg->type); - spirv_compiler_emit_register_debug_name(builder, output_id, reg); - } - -@@ -5024,46 +5224,44 @@ static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_c - return id; - } - --static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const struct vkd3d_shader_dst_param *dst) -+static void spirv_compiler_emit_output(struct spirv_compiler *compiler, -+ enum vkd3d_shader_register_type reg_type, unsigned int element_idx) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- const struct vkd3d_shader_register *reg = &dst->reg; - unsigned int component_idx, output_component_count; - const struct signature_element *signature_element; - enum vkd3d_shader_component_type component_type; - const struct shader_signature *shader_signature; - const struct vkd3d_spirv_builtin *builtin; - enum vkd3d_shader_sysval_semantic sysval; -- unsigned int write_mask, reg_write_mask; -+ uint32_t write_mask, reg_write_mask; - bool use_private_variable = false; - struct vkd3d_symbol reg_symbol; - SpvStorageClass storage_class; - unsigned int array_sizes[2]; -- unsigned int element_idx; - bool is_patch_constant; - uint32_t id, var_id; - -- is_patch_constant = is_in_fork_or_join_phase(compiler); -+ is_patch_constant = (reg_type == VKD3DSPR_PATCHCONST); - - shader_signature = is_patch_constant ? &compiler->patch_constant_signature : &compiler->output_signature; - -- element_idx = reg->idx[reg->idx_count - 1].offset; - signature_element = &shader_signature->elements[element_idx]; - sysval = signature_element->sysval_semantic; - /* Don't use builtins for TCS -> TES varyings. See spirv_compiler_emit_input(). */ - if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && !is_patch_constant) - sysval = VKD3D_SHADER_SV_NONE; -- array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); -- array_sizes[1] = signature_element->register_count; -- if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) -- array_sizes[1] = 0; -+ array_sizes[0] = signature_element->register_count; -+ array_sizes[1] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); -+ if (array_sizes[0] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) -+ array_sizes[0] = 0; - -- builtin = vkd3d_get_spirv_builtin(compiler, dst->reg.type, sysval); -+ builtin = vkd3d_get_spirv_builtin(compiler, reg_type, sysval); - - write_mask = signature_element->mask; - -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -- output_component_count = vkd3d_write_mask_component_count(write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); -+ output_component_count = vsir_write_mask_component_count(write_mask); - if (builtin) - { - component_type = builtin->component_type; -@@ -5077,15 +5275,18 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - - storage_class = SpvStorageClassOutput; - -- if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE -- || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask) -- || needs_private_io_variable(builtin)) -+ if (needs_private_io_variable(builtin)) -+ use_private_variable = true; -+ -+ if (!is_patch_constant -+ && (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE -+ || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask))) - { - use_private_variable = true; - } - - reg_write_mask = write_mask >> component_idx; -- vkd3d_symbol_make_register(®_symbol, reg); -+ vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); - - if (rb_get(&compiler->symbol_table, ®_symbol)) - { -@@ -5094,7 +5295,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - return; - } - -- if (compiler->output_info[element_idx].id) -+ if (!is_patch_constant && compiler->output_info[element_idx].id) - { - id = compiler->output_info[element_idx].id; - } -@@ -5105,7 +5306,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - else - id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2); - -- spirv_compiler_emit_register_execution_mode(compiler, &dst->reg); -+ spirv_compiler_emit_register_execution_mode(compiler, reg_type); - } - else if (signature_element->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) - { -@@ -5146,8 +5347,11 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - - spirv_compiler_decorate_xfb_output(compiler, id, output_component_count, signature_element); - -- compiler->output_info[element_idx].id = id; -- compiler->output_info[element_idx].component_type = component_type; -+ if (!is_patch_constant) -+ { -+ compiler->output_info[element_idx].id = id; -+ compiler->output_info[element_idx].component_type = component_type; -+ } - - var_id = id; - if (use_private_variable) -@@ -5165,8 +5369,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - - spirv_compiler_put_symbol(compiler, ®_symbol); - -- if (!is_patch_constant) -- spirv_compiler_emit_register_debug_name(builder, var_id, reg); -+ vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "o%u", element_idx); - - if (use_private_variable) - { -@@ -5198,9 +5401,9 @@ static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *com - static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compiler, - const struct shader_signature *signature, const struct signature_element *output, - const struct vkd3d_shader_output_info *output_info, -- uint32_t output_index_id, uint32_t val_id, unsigned int write_mask) -+ uint32_t output_index_id, uint32_t val_id, uint32_t write_mask) - { -- unsigned int dst_write_mask, use_mask, uninit_mask, swizzle, mask; -+ uint32_t dst_write_mask, use_mask, uninit_mask, swizzle, mask; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id; - const struct signature_element *element; -@@ -5222,7 +5425,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi - use_mask |= element->used_mask; - } - } -- index = vkd3d_write_mask_get_component_idx(output->mask); -+ index = vsir_write_mask_get_component_idx(output->mask); - dst_write_mask >>= index; - use_mask >>= index; - write_mask &= dst_write_mask; -@@ -5246,7 +5449,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi - output_info->component_type, VKD3D_VEC4_SIZE, 0); - val_id = spirv_compiler_emit_vector_shuffle(compiler, - zero_id, val_id, swizzle, uninit_mask, output_info->component_type, -- vkd3d_write_mask_component_count(write_mask)); -+ vsir_write_mask_component_count(write_mask)); - } - else - { -@@ -5258,7 +5461,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi - if (output_index_id) - { - type_id = vkd3d_spirv_get_type_id(builder, -- output_info->component_type, vkd3d_write_mask_component_count(dst_write_mask)); -+ output_info->component_type, vsir_write_mask_component_count(dst_write_mask)); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); - output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); - } -@@ -5412,7 +5615,6 @@ static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *comp - if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) - { - vkd3d_spirv_builder_begin_main_function(builder); -- compiler->main_block_open = true; - } - } - -@@ -5440,10 +5642,34 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler - - if (flags & (VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS)) - { -- vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityFloat64); -+ if (compiler->features & VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLOAT64) -+ { -+ vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityFloat64); -+ } -+ else -+ { -+ WARN("Unsupported 64-bit float ops.\n"); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -+ "The target environment does not support 64-bit floating point."); -+ } - flags &= ~(VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS); - } - -+ if (flags & VKD3DSGF_ENABLE_INT64) -+ { -+ if (compiler->features & VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64) -+ { -+ vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityInt64); -+ } -+ else -+ { -+ WARN("Unsupported 64-bit integer ops.\n"); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -+ "The target environment does not support 64-bit integers."); -+ } -+ flags &= ~VKD3DSGF_ENABLE_INT64; -+ } -+ - if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS)) - FIXME("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags); - else -@@ -5493,39 +5719,43 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil - { - const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t id, type_id, length_id, ptr_type_id, init_id = 0; -+ enum vkd3d_shader_component_type component_type; - struct vkd3d_shader_register reg; - struct vkd3d_symbol reg_symbol; -+ SpvStorageClass storage_class; - size_t function_location; -- uint32_t id; - -- if (temp->component_count != 4) -- FIXME("Unhandled component count %u.\n", temp->component_count); -+ /* Indexable temps may be used by more than one function in hull shaders, and -+ * declarations generally should not occur within VSIR code blocks unless function -+ * scope is specified, e.g. DXIL alloca. */ -+ storage_class = temp->has_function_scope ? SpvStorageClassFunction : SpvStorageClassPrivate; - - vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); - reg.idx[0].offset = temp->register_idx; - - if (temp->alignment) - WARN("Ignoring alignment %u.\n", temp->alignment); -- if (temp->initialiser) -- { -- FIXME("Initialisers are not supported.\n"); -- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -- "Initialisers for indexable temps are not supported."); -- } - - function_location = spirv_compiler_get_current_function_location(compiler); - vkd3d_spirv_begin_function_stream_insertion(builder, function_location); - -- id = spirv_compiler_emit_array_variable(compiler, &builder->function_stream, -- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &temp->register_size, 1); -+ component_type = vkd3d_component_type_from_data_type(temp->data_type); -+ type_id = vkd3d_spirv_get_type_id(builder, component_type, temp->component_count); -+ length_id = spirv_compiler_get_constant_uint(compiler, temp->register_size); -+ type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); -+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); -+ if (temp->initialiser) -+ init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser, NULL); -+ id = vkd3d_spirv_build_op_variable(builder, &builder->function_stream, ptr_type_id, storage_class, init_id); - - spirv_compiler_emit_register_debug_name(builder, id, ®); - - vkd3d_spirv_end_function_stream_insertion(builder); - - vkd3d_symbol_make_register(®_symbol, ®); -- vkd3d_symbol_set_register_info(®_symbol, id, -- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); -+ vkd3d_symbol_set_register_info(®_symbol, id, storage_class, -+ component_type, vkd3d_write_mask_from_component_count(temp->component_count)); - spirv_compiler_put_symbol(compiler, ®_symbol); - } - -@@ -5743,34 +5973,24 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi - const struct vkd3d_shader_instruction *instruction) - { - const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb; -- uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t type_id, const_id, ptr_type_id, icb_id; - struct vkd3d_shader_register reg; - struct vkd3d_symbol reg_symbol; -- unsigned int i; -- -- assert(icb->data_type == VKD3D_DATA_FLOAT); -- assert(icb->component_count == VKD3D_VEC4_SIZE); - -- if (!(elements = vkd3d_calloc(icb->element_count, sizeof(*elements)))) -- return; -- for (i = 0; i < icb->element_count; ++i) -- elements[i] = spirv_compiler_get_constant(compiler, -- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]); -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); -- length_id = spirv_compiler_get_constant_uint(compiler, icb->element_count); -- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); -- const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->element_count); -+ const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); - icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, - ptr_type_id, SpvStorageClassPrivate, const_id); - vkd3d_spirv_build_op_name(builder, icb_id, "icb"); -- vkd3d_free(elements); - -- vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 0); -+ /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */ -+ vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 2); -+ reg.idx[0].offset = icb->register_idx; - vkd3d_symbol_make_register(®_symbol, ®); - vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, -- VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); -+ vkd3d_component_type_from_data_type(icb->data_type), -+ vkd3d_write_mask_from_component_count(icb->component_count)); - spirv_compiler_put_symbol(compiler, ®_symbol); - } - -@@ -6052,6 +6272,9 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp - if (!(d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ)) - vkd3d_spirv_build_op_decorate(builder, var_id, SpvDecorationNonReadable, NULL, 0); - -+ if (d->uav_flags & VKD3DSUF_GLOBALLY_COHERENT) -+ vkd3d_spirv_build_op_decorate(builder, var_id, SpvDecorationCoherent, NULL, 0); -+ - if (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER) - { - assert(structure_stride); /* counters are valid only for structured buffers */ -@@ -6147,37 +6370,22 @@ static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler, - { - const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; - -- /* OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ -- if (dst->reg.type == VKD3DSPR_INPUT || dst->reg.type == VKD3DSPR_PATCHCONST) -- spirv_compiler_emit_input(compiler, dst); -- else if (dst->reg.type != VKD3DSPR_OUTPOINTID) -+ /* INPUT and PATCHCONST are handled in spirv_compiler_emit_io_declarations(). -+ * OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ -+ if (dst->reg.type != VKD3DSPR_INPUT && dst->reg.type != VKD3DSPR_PATCHCONST -+ && dst->reg.type != VKD3DSPR_OUTPOINTID) - spirv_compiler_emit_input_register(compiler, dst); - } - --static void spirv_compiler_emit_dcl_input_sysval(struct spirv_compiler *compiler, -- const struct vkd3d_shader_instruction *instruction) --{ -- spirv_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg); --} -- - static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { - const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; - -- if (dst->reg.type == VKD3DSPR_OUTPUT -- || (is_in_fork_or_join_phase(compiler) && dst->reg.type == VKD3DSPR_PATCHCONST)) -- spirv_compiler_emit_output(compiler, dst); -- else -+ if (dst->reg.type != VKD3DSPR_OUTPUT && dst->reg.type != VKD3DSPR_PATCHCONST) - spirv_compiler_emit_output_register(compiler, dst); - } - --static void spirv_compiler_emit_dcl_output_siv(struct spirv_compiler *compiler, -- const struct vkd3d_shader_instruction *instruction) --{ -- spirv_compiler_emit_output(compiler, &instruction->declaration.register_semantic.reg); --} -- - static void spirv_compiler_emit_dcl_stream(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -@@ -6256,7 +6464,7 @@ static void spirv_compiler_emit_dcl_output_topology(struct spirv_compiler *compi - { - case VKD3D_PT_POINTLIST: - mode = SpvExecutionModeOutputPoints; -- spirv_compiler_emit_point_size(compiler); -+ compiler->emit_point_size = true; - break; - case VKD3D_PT_LINESTRIP: - mode = SpvExecutionModeOutputLineStrip; -@@ -6377,7 +6585,6 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile - - static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) - { -- const struct shader_signature *signature = &compiler->output_signature; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - - if (is_in_control_point_phase(compiler) && compiler->emit_default_control_point_phase) -@@ -6395,7 +6602,6 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) - - /* Fork and join phases share output registers (patch constants). - * Control point phase has separate output registers. */ -- memset(compiler->output_info, 0, signature->element_count * sizeof(*compiler->output_info)); - memset(compiler->private_output_variable, 0, sizeof(compiler->private_output_variable)); - memset(compiler->private_output_variable_write_mask, 0, sizeof(compiler->private_output_variable_write_mask)); - } -@@ -6420,35 +6626,59 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler, - vkd3d_spirv_build_op_function(builder, void_id, function_id, - SpvFunctionControlMaskNone, function_type_id); - -- vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); -- - compiler->phase = instruction->handler_idx; - spirv_compiler_emit_shader_phase_name(compiler, function_id, NULL); - - phase = (instruction->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE) - ? &compiler->control_point_phase : &compiler->patch_constant_phase; - phase->function_id = function_id; -- phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); -+ /* The insertion location must be set after the label is emitted. */ -+ phase->function_location = 0; - - if (instruction->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE) - compiler->emit_default_control_point_phase = instruction->flags; - } - -+static void spirv_compiler_initialise_block(struct spirv_compiler *compiler) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ -+ /* Insertion locations must point immediately after the function's initial label. */ -+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) -+ { -+ struct vkd3d_shader_phase *phase = (compiler->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE) -+ ? &compiler->control_point_phase : &compiler->patch_constant_phase; -+ if (!phase->function_location) -+ phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); -+ } -+ else if (!builder->main_function_location) -+ { -+ builder->main_function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); -+ } -+ -+ /* I/O declarations can result in emission of fixups, which must occur after the initial label. */ -+ if (!compiler->prolog_emitted) -+ { -+ spirv_compiler_emit_main_prolog(compiler); -+ spirv_compiler_emit_io_declarations(compiler); -+ compiler->prolog_emitted = true; -+ } -+} -+ - static void spirv_compiler_emit_default_control_point_phase(struct spirv_compiler *compiler) - { - const struct shader_signature *output_signature = &compiler->output_signature; - const struct shader_signature *input_signature = &compiler->input_signature; -+ uint32_t type_id, output_ptr_type_id, input_id, dst_id, invocation_id; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type component_type; - struct vkd3d_shader_src_param invocation; - struct vkd3d_shader_register input_reg; -- uint32_t type_id, output_ptr_type_id; -- uint32_t input_id, output_id, dst_id; - unsigned int component_count; -- unsigned int array_sizes[2]; -- uint32_t invocation_id; - unsigned int i; - -+ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); -+ spirv_compiler_initialise_block(compiler); - invocation_id = spirv_compiler_emit_load_invocation_id(compiler); - - memset(&invocation, 0, sizeof(invocation)); -@@ -6466,6 +6696,8 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile - { - const struct signature_element *output = &output_signature->elements[i]; - const struct signature_element *input = &input_signature->elements[i]; -+ struct vkd3d_shader_register_info output_reg_info; -+ struct vkd3d_shader_register output_reg; - - assert(input->mask == output->mask); - assert(input->component_type == output->component_type); -@@ -6473,22 +6705,16 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile - input_reg.idx[1].offset = i; - input_id = spirv_compiler_get_register_id(compiler, &input_reg); - -+ vsir_register_init(&output_reg, VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); -+ output_reg.idx[0].offset = i; -+ spirv_compiler_get_register_info(compiler, &output_reg, &output_reg_info); -+ - component_type = output->component_type; -- component_count = vkd3d_write_mask_component_count(output->mask); -+ component_count = vsir_write_mask_component_count(output->mask); - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -- if ((array_sizes[0] = (input->register_count > 1) ? input->register_count : 0)) -- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, spirv_compiler_get_constant_uint(compiler, -- array_sizes[0])); -- -- array_sizes[1] = compiler->output_control_point_count; -- output_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, SpvStorageClassOutput, -- component_type, component_count, array_sizes, 2); -- vkd3d_spirv_add_iface_variable(builder, output_id); -- vkd3d_spirv_build_op_decorate1(builder, output_id, SpvDecorationLocation, output->register_index); -- vkd3d_spirv_build_op_name(builder, output_id, "vocp%u", output->register_index); -- - output_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); -- dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_id, invocation_id); -+ -+ dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_reg_info.id, invocation_id); - - vkd3d_spirv_build_op_copy_memory(builder, dst_id, input_id, SpvMemoryAccessMaskNone); - } -@@ -6547,7 +6773,11 @@ static void spirv_compiler_emit_hull_shader_main(struct spirv_compiler *compiler - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t void_id; - -+ /* If a patch constant function used descriptor indexing the offsets must be reloaded. */ -+ memset(compiler->descriptor_offset_ids, 0, compiler->offset_info.descriptor_table_count -+ * sizeof(*compiler->descriptor_offset_ids)); - vkd3d_spirv_builder_begin_main_function(builder); -+ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); - - void_id = vkd3d_spirv_get_op_type_void(builder); - -@@ -6591,14 +6821,18 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru - {VKD3DSIH_INEG, SpvOpSNegate}, - {VKD3DSIH_ISHL, SpvOpShiftLeftLogical}, - {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic}, -+ {VKD3DSIH_ISINF, SpvOpIsInf}, -+ {VKD3DSIH_ISNAN, SpvOpIsNan}, - {VKD3DSIH_ITOD, SpvOpConvertSToF}, - {VKD3DSIH_ITOF, SpvOpConvertSToF}, -+ {VKD3DSIH_ITOI, SpvOpSConvert}, - {VKD3DSIH_MUL, SpvOpFMul}, - {VKD3DSIH_NOT, SpvOpNot}, - {VKD3DSIH_OR, SpvOpBitwiseOr}, - {VKD3DSIH_USHR, SpvOpShiftRightLogical}, - {VKD3DSIH_UTOD, SpvOpConvertUToF}, - {VKD3DSIH_UTOF, SpvOpConvertUToF}, -+ {VKD3DSIH_UTOU, SpvOpUConvert}, - {VKD3DSIH_XOR, SpvOpBitwiseXor}, - }; - unsigned int i; -@@ -6650,6 +6884,10 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, - { - val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); - } -+ else if (dst->reg.data_type == VKD3D_DATA_UINT64) -+ { -+ val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); -+ } - else - { - WARN("Unhandled data type %u.\n", dst->reg.data_type); -@@ -6715,11 +6953,11 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil - * Microsoft fxc will compile immediate constants larger than 5 bits. - * Fixing up the constants would be more elegant, but the simplest way is - * to let this handle constants too. */ -- if (instruction->handler_idx == VKD3DSIH_ISHL || instruction->handler_idx == VKD3DSIH_ISHR -- || instruction->handler_idx == VKD3DSIH_USHR) -+ if (!(instruction->flags & VKD3DSI_SHIFT_UNMASKED) && (instruction->handler_idx == VKD3DSIH_ISHL -+ || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR)) - { - uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, -- VKD3D_SHADER_COMPONENT_UINT, vkd3d_write_mask_component_count(dst->write_mask), 0x1f); -+ VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f); - src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id); - } - -@@ -6732,6 +6970,23 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil - return VKD3D_OK; - } - -+static void spirv_compiler_emit_isfinite(struct spirv_compiler *compiler, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ const struct vkd3d_shader_dst_param *dst = instruction->dst; -+ const struct vkd3d_shader_src_param *src = instruction->src; -+ uint32_t type_id, src_id, isinf_id, isnan_id, val_id; -+ -+ type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); -+ src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -+ /* OpIsFinite is only available in Kernel mode. */ -+ isinf_id = vkd3d_spirv_build_op_is_inf(builder, type_id, src_id); -+ isnan_id = vkd3d_spirv_build_op_is_nan(builder, type_id, src_id); -+ val_id = vkd3d_spirv_build_op_logical_equal(builder, type_id, isinf_id, isnan_id); -+ spirv_compiler_emit_store_dst(compiler, dst, val_id); -+} -+ - static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( - const struct vkd3d_shader_instruction *instruction) - { -@@ -6742,6 +6997,9 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( - } - glsl_insts[] = - { -+ {VKD3DSIH_ACOS, GLSLstd450Acos}, -+ {VKD3DSIH_ASIN, GLSLstd450Asin}, -+ {VKD3DSIH_ATAN, GLSLstd450Atan}, - {VKD3DSIH_DFMA, GLSLstd450Fma}, - {VKD3DSIH_DMAX, GLSLstd450NMax}, - {VKD3DSIH_DMIN, GLSLstd450NMin}, -@@ -6750,6 +7008,9 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( - {VKD3DSIH_FIRSTBIT_LO, GLSLstd450FindILsb}, - {VKD3DSIH_FIRSTBIT_SHI, GLSLstd450FindSMsb}, - {VKD3DSIH_FRC, GLSLstd450Fract}, -+ {VKD3DSIH_HCOS, GLSLstd450Cosh}, -+ {VKD3DSIH_HSIN, GLSLstd450Sinh}, -+ {VKD3DSIH_HTAN, GLSLstd450Tanh}, - {VKD3DSIH_IMAX, GLSLstd450SMax}, - {VKD3DSIH_IMIN, GLSLstd450SMin}, - {VKD3DSIH_LOG, GLSLstd450Log2}, -@@ -6762,6 +7023,7 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( - {VKD3DSIH_ROUND_Z, GLSLstd450Trunc}, - {VKD3DSIH_RSQ, GLSLstd450InverseSqrt}, - {VKD3DSIH_SQRT, GLSLstd450Sqrt}, -+ {VKD3DSIH_TAN, GLSLstd450Tan}, - {VKD3DSIH_UMAX, GLSLstd450UMax}, - {VKD3DSIH_UMIN, GLSLstd450UMin}, - }; -@@ -6779,13 +7041,13 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( - static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -+ uint32_t instr_set_id, type_id, val_id, rev_val_id, uint_max_id, condition_id; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t src_id[SPIRV_MAX_SRC_COUNT]; -- uint32_t instr_set_id, type_id, val_id; -+ unsigned int i, component_count; - enum GLSLstd450 glsl_inst; -- unsigned int i; - - glsl_inst = spirv_compiler_map_ext_glsl_instruction(instruction); - if (glsl_inst == GLSLstd450Bad) -@@ -6811,8 +7073,13 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp - || instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI) - { - /* In D3D bits are numbered from the most significant bit. */ -- val_id = vkd3d_spirv_build_op_isub(builder, type_id, -- spirv_compiler_get_constant_uint(compiler, 31), val_id); -+ component_count = vsir_write_mask_component_count(dst->write_mask); -+ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT32_MAX, component_count); -+ condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpIEqual, -+ vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), val_id, uint_max_id); -+ rev_val_id = vkd3d_spirv_build_op_isub(builder, type_id, -+ spirv_compiler_get_constant_uint_vector(compiler, 31, component_count), val_id); -+ val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, rev_val_id); - } - - spirv_compiler_emit_store_dst(compiler, dst, val_id); -@@ -6821,11 +7088,11 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp - static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -+ uint32_t val_id, dst_val_id, type_id, dst_id, src_id, write_mask32, swizzle32; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - struct vkd3d_shader_register_info dst_reg_info, src_reg_info; - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; -- uint32_t val_id, dst_val_id, type_id, dst_id, src_id; - uint32_t components[VKD3D_VEC4_SIZE]; - unsigned int i, component_count; - -@@ -6849,7 +7116,9 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, - return; - } - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ write_mask32 = data_type_is_64_bit(dst->reg.data_type) ? vsir_write_mask_32_from_64(dst->write_mask) : dst->write_mask; -+ swizzle32 = data_type_is_64_bit(src->reg.data_type) ? vsir_swizzle_32_from_64(src->swizzle) : src->swizzle; -+ component_count = vsir_write_mask_component_count(write_mask32); - if (component_count != 1 && component_count != VKD3D_VEC4_SIZE - && dst_reg_info.write_mask == VKD3DSP_WRITEMASK_ALL) - { -@@ -6862,8 +7131,8 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, - - for (i = 0; i < ARRAY_SIZE(components); ++i) - { -- if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(src->swizzle, i); -+ if (write_mask32 & (VKD3DSP_WRITEMASK_0 << i)) -+ components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle32, i); - else - components[i] = i; - } -@@ -6877,6 +7146,11 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, - - general_implementation: - val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -+ if (dst->reg.data_type != src->reg.data_type) -+ { -+ val_id = vkd3d_spirv_build_op_bitcast(builder, vkd3d_spirv_get_type_id_for_data_type(builder, -+ dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)), val_id); -+ } - spirv_compiler_emit_store_dst(compiler, dst, val_id); - } - -@@ -6893,12 +7167,12 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); - src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - - if (src[0].reg.data_type != VKD3D_DATA_BOOL) - condition_id = spirv_compiler_emit_int_to_bool(compiler, -- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); - val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id); - - spirv_compiler_emit_store_dst(compiler, dst, val_id); -@@ -6919,11 +7193,11 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); - src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); - - condition_id = spirv_compiler_emit_int_to_bool(compiler, -- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); - - val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src2_id, src1_id); - spirv_compiler_emit_store_dst(compiler, &dst[0], val_id); -@@ -6940,9 +7214,9 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, - enum vkd3d_shader_component_type component_type; - uint32_t type_id, val_id, src_ids[2]; - unsigned int component_count, i; -- DWORD write_mask; -+ uint32_t write_mask; - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); - - if (instruction->handler_idx == VKD3DSIH_DP4) -@@ -6980,7 +7254,7 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, - uint32_t type_id, src_id, val_id, div_id; - unsigned int component_count; - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - - src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -@@ -7060,7 +7334,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, - uint32_t type_id, val_id, src_ids[3]; - unsigned int i, component_count; - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, component_count); - - for (i = 0; i < ARRAY_SIZE(src_ids); ++i) -@@ -7087,16 +7361,18 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, - - if (dst[0].reg.type != VKD3DSPR_NULL) - { -- component_count = vkd3d_write_mask_component_count(dst[0].write_mask); -+ component_count = vsir_write_mask_component_count(dst[0].write_mask); - type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[0]); - - src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[0].write_mask); - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[0].write_mask); - - condition_id = spirv_compiler_emit_int_to_bool(compiler, -- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id); -- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, -- 0xffffffff, component_count); -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id); -+ if (dst[0].reg.data_type == VKD3D_DATA_UINT64) -+ uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); -+ else -+ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); - - val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, div_op, type_id, src0_id, src1_id); - /* The SPIR-V spec says: "The resulting value is undefined if Operand 2 is 0." */ -@@ -7109,16 +7385,18 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, - { - if (!component_count || dst[0].write_mask != dst[1].write_mask) - { -- component_count = vkd3d_write_mask_component_count(dst[1].write_mask); -+ component_count = vsir_write_mask_component_count(dst[1].write_mask); - type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[1]); - - src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask); - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask); - - condition_id = spirv_compiler_emit_int_to_bool(compiler, -- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id); -- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, -- 0xffffffff, component_count); -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id); -+ if (dst[1].reg.data_type == VKD3D_DATA_UINT64) -+ uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); -+ else -+ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); - } - - val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, mod_op, type_id, src0_id, src1_id); -@@ -7147,7 +7425,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, - * as a signed integer, but Direct3D expects the result to saturate, - * and for NaN to yield zero. */ - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); - dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -@@ -7200,7 +7478,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, - * as an unsigned integer, but Direct3D expects the result to saturate, - * and for NaN to yield zero. */ - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); - dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -@@ -7232,13 +7510,13 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, - static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -- uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id; -+ uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id, size_id, max_count_id; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; - enum vkd3d_shader_component_type component_type; -- unsigned int i, j, k, src_count; -- DWORD write_mask; -+ unsigned int i, j, k, src_count, size; -+ uint32_t write_mask; - SpvOp op; - - src_count = instruction->src_count; -@@ -7246,7 +7524,9 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp - - component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -- mask_id = spirv_compiler_get_constant_uint(compiler, 0x1f); -+ size = (src[src_count - 1].reg.data_type == VKD3D_DATA_UINT64) ? 0x40 : 0x20; -+ mask_id = spirv_compiler_get_constant_uint(compiler, size - 1); -+ size_id = spirv_compiler_get_constant_uint(compiler, size); - - switch (instruction->handler_idx) - { -@@ -7275,6 +7555,9 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp - { - src_ids[j] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[j], mask_id); - } -+ max_count_id = vkd3d_spirv_build_op_isub(builder, type_id, size_id, src_ids[src_count - 2]); -+ src_ids[src_count - 1] = vkd3d_spirv_build_op_glsl_std450_umin(builder, type_id, -+ src_ids[src_count - 1], max_count_id); - - constituents[k++] = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, - op, type_id, src_ids, src_count); -@@ -7291,8 +7574,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t components[VKD3D_VEC4_SIZE]; -+ uint32_t write_mask; - unsigned int i, j; -- DWORD write_mask; - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -@@ -7324,8 +7607,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t components[VKD3D_VEC4_SIZE]; -+ uint32_t write_mask; - unsigned int i, j; -- DWORD write_mask; - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -@@ -7387,7 +7670,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co - return; - } - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - - src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); -@@ -7409,7 +7692,7 @@ static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *co - uint32_t condition_id, merge_block_id; - - condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); -- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, condition_id); -+ condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, condition_id); - - merge_block_id = vkd3d_spirv_alloc_id(builder); - -@@ -7445,16 +7728,39 @@ static void spirv_compiler_emit_retc(struct spirv_compiler *compiler, - vkd3d_spirv_build_op_label(builder, merge_block_id); - } - --static void spirv_compiler_emit_kill(struct spirv_compiler *compiler, -- const struct vkd3d_shader_instruction *instruction) -+static uint32_t spirv_compiler_get_discard_function_id(struct spirv_compiler *compiler) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- uint32_t target_id, merge_block_id; - -- target_id = vkd3d_spirv_alloc_id(builder); -- merge_block_id = spirv_compiler_emit_conditional_branch(compiler, instruction, target_id); -+ if (!compiler->discard_function_id) -+ compiler->discard_function_id = vkd3d_spirv_alloc_id(builder); - -- vkd3d_spirv_build_op_label(builder, target_id); -+ return compiler->discard_function_id; -+} -+ -+static void spirv_compiler_emit_discard_function(struct spirv_compiler *compiler) -+{ -+ uint32_t void_id, bool_id, function_type_id, condition_id, target_block_id, merge_block_id; -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ -+ vkd3d_spirv_build_op_name(builder, compiler->discard_function_id, "discard"); -+ -+ void_id = vkd3d_spirv_get_op_type_void(builder); -+ bool_id = vkd3d_spirv_get_op_type_bool(builder); -+ function_type_id = vkd3d_spirv_get_op_type_function(builder, void_id, &bool_id, 1); -+ -+ vkd3d_spirv_build_op_function(builder, void_id, compiler->discard_function_id, -+ SpvFunctionControlMaskNone, function_type_id); -+ condition_id = vkd3d_spirv_build_op_function_parameter(builder, bool_id); -+ -+ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); -+ -+ target_block_id = vkd3d_spirv_alloc_id(builder); -+ merge_block_id = vkd3d_spirv_alloc_id(builder); -+ vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone); -+ vkd3d_spirv_build_op_branch_conditional(builder, condition_id, target_block_id, merge_block_id); -+ -+ vkd3d_spirv_build_op_label(builder, target_block_id); - - if (spirv_compiler_is_target_extension_supported(compiler, - VKD3D_SHADER_SPIRV_EXTENSION_EXT_DEMOTE_TO_HELPER_INVOCATION)) -@@ -7469,381 +7775,158 @@ static void spirv_compiler_emit_kill(struct spirv_compiler *compiler, - } - - vkd3d_spirv_build_op_label(builder, merge_block_id); -+ vkd3d_spirv_build_op_return(builder); -+ vkd3d_spirv_build_op_function_end(builder); - } - --static struct vkd3d_control_flow_info *spirv_compiler_push_control_flow_level( -- struct spirv_compiler *compiler) -+static void spirv_compiler_emit_discard(struct spirv_compiler *compiler, -+ const struct vkd3d_shader_instruction *instruction) - { -- if (!vkd3d_array_reserve((void **)&compiler->control_flow_info, &compiler->control_flow_info_size, -- compiler->control_flow_depth + 1, sizeof(*compiler->control_flow_info))) -- { -- ERR("Failed to allocate control flow info structure.\n"); -- return NULL; -- } -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ const struct vkd3d_shader_src_param *src = instruction->src; -+ uint32_t condition_id, void_id; - -- return &compiler->control_flow_info[compiler->control_flow_depth++]; -+ /* discard is not a block terminator in VSIR, and emitting it as such in SPIR-V would cause -+ * a mismatch between the VSIR structure and the SPIR-V one, which would cause problems if -+ * structurisation is necessary. Therefore we emit it as a function call. */ -+ condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); -+ condition_id = spirv_compiler_emit_int_to_bool(compiler, -+ instruction->flags, src->reg.data_type, 1, condition_id); -+ void_id = vkd3d_spirv_get_op_type_void(builder); -+ vkd3d_spirv_build_op_function_call(builder, void_id, spirv_compiler_get_discard_function_id(compiler), -+ &condition_id, 1); - } - --static void spirv_compiler_pop_control_flow_level(struct spirv_compiler *compiler) -+static bool spirv_compiler_init_blocks(struct spirv_compiler *compiler, unsigned int block_count) - { -- struct vkd3d_control_flow_info *cf_info; -+ compiler->block_count = block_count; - -- assert(compiler->control_flow_depth); -+ if (!(compiler->block_label_ids = vkd3d_calloc(block_count, sizeof(*compiler->block_label_ids)))) -+ return false; - -- cf_info = &compiler->control_flow_info[--compiler->control_flow_depth]; -- memset(cf_info, 0, sizeof(*cf_info)); -+ return true; - } - --static struct vkd3d_control_flow_info *spirv_compiler_find_innermost_loop( -- struct spirv_compiler *compiler) -+static void spirv_compiler_emit_label(struct spirv_compiler *compiler, -+ const struct vkd3d_shader_instruction *instruction) - { -- int depth; -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ const struct vkd3d_shader_src_param *src = instruction->src; -+ unsigned int block_id = src->reg.idx[0].offset; -+ uint32_t label_id; - -- for (depth = compiler->control_flow_depth - 1; depth >= 0; --depth) -- { -- if (compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP) -- return &compiler->control_flow_info[depth]; -- } -+ label_id = spirv_compiler_get_label_id(compiler, block_id); -+ vkd3d_spirv_build_op_label(builder, label_id); - -- return NULL; -+ --block_id; -+ if (block_id < compiler->block_name_count && compiler->block_names[block_id]) -+ vkd3d_spirv_build_op_name(builder, label_id, compiler->block_names[block_id]); -+ -+ spirv_compiler_initialise_block(compiler); - } - --static struct vkd3d_control_flow_info *spirv_compiler_find_innermost_breakable_cf_construct( -- struct spirv_compiler *compiler) -+static void spirv_compiler_emit_merge(struct spirv_compiler *compiler, -+ uint32_t merge_block_id, uint32_t continue_block_id) - { -- int depth; -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ -+ if (!merge_block_id) -+ return; - -- for (depth = compiler->control_flow_depth - 1; depth >= 0; --depth) -+ merge_block_id = spirv_compiler_get_label_id(compiler, merge_block_id); -+ if (!continue_block_id) - { -- if (compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP -- || compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_SWITCH) -- return &compiler->control_flow_info[depth]; -+ vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone); -+ } -+ else -+ { -+ continue_block_id = spirv_compiler_get_label_id(compiler, continue_block_id); -+ vkd3d_spirv_build_op_loop_merge(builder, merge_block_id, continue_block_id, SpvLoopControlMaskNone); - } -- -- return NULL; - } - --static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *compiler, -+static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -- uint32_t loop_header_block_id, loop_body_block_id, continue_block_id; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_src_param *src = instruction->src; -- uint32_t merge_block_id, val_id, condition_id, true_label; -- struct vkd3d_control_flow_info *cf_info; -- -- cf_info = compiler->control_flow_depth -- ? &compiler->control_flow_info[compiler->control_flow_depth - 1] : NULL; -+ uint32_t condition_id; - -- switch (instruction->handler_idx) -+ if (vsir_register_is_label(&src[0].reg)) - { -- case VKD3DSIH_IF: -- if (!(cf_info = spirv_compiler_push_control_flow_level(compiler))) -- return VKD3D_ERROR_OUT_OF_MEMORY; -- -- val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); -- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, val_id); -- -- true_label = vkd3d_spirv_alloc_id(builder); -- merge_block_id = vkd3d_spirv_alloc_id(builder); -- vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone); -- cf_info->u.if_.stream_location = vkd3d_spirv_stream_current_location(&builder->function_stream); -- vkd3d_spirv_build_op_branch_conditional(builder, condition_id, true_label, merge_block_id); -- -- vkd3d_spirv_build_op_label(builder, true_label); -- -- cf_info->u.if_.id = compiler->branch_id; -- cf_info->u.if_.merge_block_id = merge_block_id; -- cf_info->u.if_.else_block_id = 0; -- cf_info->inside_block = true; -- cf_info->current_block = VKD3D_BLOCK_IF; -- -- vkd3d_spirv_build_op_name(builder, merge_block_id, "branch%u_merge", compiler->branch_id); -- vkd3d_spirv_build_op_name(builder, true_label, "branch%u_true", compiler->branch_id); -- ++compiler->branch_id; -- break; -- -- case VKD3DSIH_ELSE: -- assert(compiler->control_flow_depth); -- assert(cf_info->current_block == VKD3D_BLOCK_IF); -- -- if (cf_info->inside_block) -- vkd3d_spirv_build_op_branch(builder, cf_info->u.if_.merge_block_id); -- -- cf_info->u.if_.else_block_id = vkd3d_spirv_alloc_id(builder); -- vkd3d_spirv_as_op_branch_conditional(&builder->function_stream, -- cf_info->u.if_.stream_location)->false_label = cf_info->u.if_.else_block_id; -- vkd3d_spirv_build_op_name(builder, -- cf_info->u.if_.else_block_id, "branch%u_false", cf_info->u.if_.id); -- vkd3d_spirv_build_op_label(builder, cf_info->u.if_.else_block_id); -- cf_info->inside_block = true; -- break; -- -- case VKD3DSIH_ENDIF: -- assert(compiler->control_flow_depth); -- assert(cf_info->current_block == VKD3D_BLOCK_IF); -- -- if (cf_info->inside_block) -- vkd3d_spirv_build_op_branch(builder, cf_info->u.if_.merge_block_id); -- -- vkd3d_spirv_build_op_label(builder, cf_info->u.if_.merge_block_id); -- -- spirv_compiler_pop_control_flow_level(compiler); -- break; -- -- case VKD3DSIH_LOOP: -- if (!(cf_info = spirv_compiler_push_control_flow_level(compiler))) -- return VKD3D_ERROR_OUT_OF_MEMORY; -- -- loop_header_block_id = vkd3d_spirv_alloc_id(builder); -- loop_body_block_id = vkd3d_spirv_alloc_id(builder); -- continue_block_id = vkd3d_spirv_alloc_id(builder); -- merge_block_id = vkd3d_spirv_alloc_id(builder); -- -- vkd3d_spirv_build_op_branch(builder, loop_header_block_id); -- vkd3d_spirv_build_op_label(builder, loop_header_block_id); -- vkd3d_spirv_build_op_loop_merge(builder, merge_block_id, continue_block_id, SpvLoopControlMaskNone); -- vkd3d_spirv_build_op_branch(builder, loop_body_block_id); -- -- vkd3d_spirv_build_op_label(builder, loop_body_block_id); -- -- cf_info->u.loop.header_block_id = loop_header_block_id; -- cf_info->u.loop.continue_block_id = continue_block_id; -- cf_info->u.loop.merge_block_id = merge_block_id; -- cf_info->current_block = VKD3D_BLOCK_LOOP; -- cf_info->inside_block = true; -- -- vkd3d_spirv_build_op_name(builder, loop_header_block_id, "loop%u_header", compiler->loop_id); -- vkd3d_spirv_build_op_name(builder, loop_body_block_id, "loop%u_body", compiler->loop_id); -- vkd3d_spirv_build_op_name(builder, continue_block_id, "loop%u_continue", compiler->loop_id); -- vkd3d_spirv_build_op_name(builder, merge_block_id, "loop%u_merge", compiler->loop_id); -- ++compiler->loop_id; -- break; -- -- case VKD3DSIH_ENDLOOP: -- assert(compiler->control_flow_depth); -- assert(cf_info->current_block == VKD3D_BLOCK_LOOP); -- -- /* The loop block may have already been ended by an unconditional -- * break instruction right before the end of the loop. */ -- if (cf_info->inside_block) -- vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.continue_block_id); -- -- vkd3d_spirv_build_op_label(builder, cf_info->u.loop.continue_block_id); -- vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.header_block_id); -- vkd3d_spirv_build_op_label(builder, cf_info->u.loop.merge_block_id); -- -- spirv_compiler_pop_control_flow_level(compiler); -- break; -- -- case VKD3DSIH_SWITCH: -- if (!(cf_info = spirv_compiler_push_control_flow_level(compiler))) -- return VKD3D_ERROR_OUT_OF_MEMORY; -- -- merge_block_id = vkd3d_spirv_alloc_id(builder); -- -- assert(src->reg.data_type == VKD3D_DATA_INT); -- val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); -- -- vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone); -- -- cf_info->u.switch_.id = compiler->switch_id; -- cf_info->u.switch_.merge_block_id = merge_block_id; -- cf_info->u.switch_.stream_location = vkd3d_spirv_stream_current_location(&builder->function_stream); -- cf_info->u.switch_.selector_id = val_id; -- cf_info->u.switch_.case_blocks = NULL; -- cf_info->u.switch_.case_blocks_size = 0; -- cf_info->u.switch_.case_block_count = 0; -- cf_info->u.switch_.default_block_id = 0; -- cf_info->inside_block = false; -- cf_info->current_block = VKD3D_BLOCK_SWITCH; -- -- vkd3d_spirv_build_op_name(builder, merge_block_id, "switch%u_merge", compiler->switch_id); -- -- ++compiler->switch_id; -- -- if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size, -- 10, sizeof(*cf_info->u.switch_.case_blocks))) -- return VKD3D_ERROR_OUT_OF_MEMORY; -- -- break; -- -- case VKD3DSIH_ENDSWITCH: -- assert(compiler->control_flow_depth); -- assert(cf_info->current_block == VKD3D_BLOCK_SWITCH); -- assert(!cf_info->inside_block); -- -- if (!cf_info->u.switch_.default_block_id) -- cf_info->u.switch_.default_block_id = cf_info->u.switch_.merge_block_id; -- -- vkd3d_spirv_build_op_label(builder, cf_info->u.switch_.merge_block_id); -- -- /* The OpSwitch instruction is inserted when the endswitch -- * instruction is processed because we do not know the number -- * of case statements in advance.*/ -- vkd3d_spirv_begin_function_stream_insertion(builder, cf_info->u.switch_.stream_location); -- vkd3d_spirv_build_op_switch(builder, cf_info->u.switch_.selector_id, -- cf_info->u.switch_.default_block_id, cf_info->u.switch_.case_blocks, -- cf_info->u.switch_.case_block_count); -- vkd3d_spirv_end_function_stream_insertion(builder); -- -- vkd3d_free(cf_info->u.switch_.case_blocks); -- spirv_compiler_pop_control_flow_level(compiler); -- break; -- -- case VKD3DSIH_CASE: -+ if (instruction->src_count > 1) - { -- uint32_t label_id, value; -- -- assert(compiler->control_flow_depth); -- assert(cf_info->current_block == VKD3D_BLOCK_SWITCH); -- -- if (src->swizzle != VKD3D_SHADER_SWIZZLE(X, X, X, X)) -- { -- WARN("Unexpected src swizzle %#x.\n", src->swizzle); -- spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, -- "The swizzle for a switch case value is not scalar."); -- } -- assert(src->reg.type == VKD3DSPR_IMMCONST); -- value = *src->reg.u.immconst_uint; -- -- if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size, -- 2 * (cf_info->u.switch_.case_block_count + 1), sizeof(*cf_info->u.switch_.case_blocks))) -- return VKD3D_ERROR_OUT_OF_MEMORY; -- -- label_id = vkd3d_spirv_alloc_id(builder); -- if (cf_info->inside_block) /* fall-through */ -- vkd3d_spirv_build_op_branch(builder, label_id); -- -- cf_info->u.switch_.case_blocks[2 * cf_info->u.switch_.case_block_count + 0] = value; -- cf_info->u.switch_.case_blocks[2 * cf_info->u.switch_.case_block_count + 1] = label_id; -- ++cf_info->u.switch_.case_block_count; -- -- vkd3d_spirv_build_op_label(builder, label_id); -- cf_info->inside_block = true; -- vkd3d_spirv_build_op_name(builder, label_id, "switch%u_case%u", cf_info->u.switch_.id, value); -- break; -- } -- -- case VKD3DSIH_DEFAULT: -- assert(compiler->control_flow_depth); -- assert(cf_info->current_block == VKD3D_BLOCK_SWITCH); -- assert(!cf_info->u.switch_.default_block_id); -- -- cf_info->u.switch_.default_block_id = vkd3d_spirv_alloc_id(builder); -- if (cf_info->inside_block) /* fall-through */ -- vkd3d_spirv_build_op_branch(builder, cf_info->u.switch_.default_block_id); -- -- vkd3d_spirv_build_op_label(builder, cf_info->u.switch_.default_block_id); -- vkd3d_spirv_build_op_name(builder, cf_info->u.switch_.default_block_id, -- "switch%u_default", cf_info->u.switch_.id); -- cf_info->inside_block = true; -- break; -- -- case VKD3DSIH_BREAK: -- { -- struct vkd3d_control_flow_info *breakable_cf_info; -- -- assert(compiler->control_flow_depth); -- -- if (!(breakable_cf_info = spirv_compiler_find_innermost_breakable_cf_construct(compiler))) -- { -- FIXME("Unhandled break instruction.\n"); -- return VKD3D_ERROR_INVALID_SHADER; -- } -- -- if (breakable_cf_info->current_block == VKD3D_BLOCK_LOOP) -- { -- vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.loop.merge_block_id); -- } -- else if (breakable_cf_info->current_block == VKD3D_BLOCK_SWITCH) -- { -- /* The current case block may have already been ended by an -- * unconditional continue instruction. */ -- if (breakable_cf_info->inside_block) -- vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.switch_.merge_block_id); -- } -- -- cf_info->inside_block = false; -- break; -- } -- -- case VKD3DSIH_BREAKP: -- { -- struct vkd3d_control_flow_info *loop_cf_info; -- -- assert(compiler->control_flow_depth); -- -- if (!(loop_cf_info = spirv_compiler_find_innermost_loop(compiler))) -- { -- ERR("Invalid 'breakc' instruction outside loop.\n"); -- return VKD3D_ERROR_INVALID_SHADER; -- } -- -- merge_block_id = spirv_compiler_emit_conditional_branch(compiler, -- instruction, loop_cf_info->u.loop.merge_block_id); -- vkd3d_spirv_build_op_label(builder, merge_block_id); -- break; -- } -- -- case VKD3DSIH_CONTINUE: -- { -- struct vkd3d_control_flow_info *loop_cf_info; -- -- assert(compiler->control_flow_depth); -- -- if (!(loop_cf_info = spirv_compiler_find_innermost_loop(compiler))) -- { -- ERR("Invalid 'continue' instruction outside loop.\n"); -- return VKD3D_ERROR_INVALID_SHADER; -- } -- -- vkd3d_spirv_build_op_branch(builder, loop_cf_info->u.loop.continue_block_id); -- -- cf_info->inside_block = false; -- break; -+ /* Loop merge only. Must have a merge block and a continue block. */ -+ if (instruction->src_count == 3) -+ spirv_compiler_emit_merge(compiler, src[1].reg.idx[0].offset, src[2].reg.idx[0].offset); -+ else -+ ERR("Invalid branch with %u sources.\n", instruction->src_count); - } -+ vkd3d_spirv_build_op_branch(builder, spirv_compiler_get_label_id(compiler, src[0].reg.idx[0].offset)); -+ return; -+ } - -- case VKD3DSIH_CONTINUEP: -- { -- struct vkd3d_control_flow_info *loop_cf_info; -- -- if (!(loop_cf_info = spirv_compiler_find_innermost_loop(compiler))) -- { -- ERR("Invalid 'continuec' instruction outside loop.\n"); -- return VKD3D_ERROR_INVALID_SHADER; -- } -+ if (!vkd3d_swizzle_is_scalar(src->swizzle, &src->reg)) -+ { -+ WARN("Unexpected src swizzle %#x.\n", src->swizzle); -+ spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, -+ "The swizzle for a branch condition value is not scalar."); -+ } - -- merge_block_id = spirv_compiler_emit_conditional_branch(compiler, -- instruction, loop_cf_info->u.loop.continue_block_id); -- vkd3d_spirv_build_op_label(builder, merge_block_id); -- break; -- } -+ condition_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); -+ if (src[0].reg.data_type != VKD3D_DATA_BOOL) -+ condition_id = spirv_compiler_emit_int_to_bool(compiler, -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, 1, condition_id); -+ /* Emit the merge immediately before the branch instruction. */ -+ if (instruction->src_count >= 4) -+ spirv_compiler_emit_merge(compiler, src[3].reg.idx[0].offset, -+ (instruction->src_count > 4) ? src[4].reg.idx[0].offset : 0); -+ else -+ ERR("Invalid branch with %u sources.\n", instruction->src_count); -+ vkd3d_spirv_build_op_branch_conditional(builder, condition_id, -+ spirv_compiler_get_label_id(compiler, src[1].reg.idx[0].offset), -+ spirv_compiler_get_label_id(compiler, src[2].reg.idx[0].offset)); -+} - -- case VKD3DSIH_RET: -- spirv_compiler_emit_return(compiler, instruction); -+static void spirv_compiler_emit_switch(struct spirv_compiler *compiler, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ const struct vkd3d_shader_src_param *src = instruction->src; -+ uint32_t val_id, default_id; -+ unsigned int i, word_count; -+ uint32_t *cases; - -- if (cf_info) -- cf_info->inside_block = false; -- else -- compiler->main_block_open = false; -- break; -+ if (!vkd3d_swizzle_is_scalar(src[0].swizzle, &src[0].reg)) -+ { -+ WARN("Unexpected src swizzle %#x.\n", src[0].swizzle); -+ spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, -+ "The swizzle for a switch value is not scalar."); -+ } - -- case VKD3DSIH_RETP: -- spirv_compiler_emit_retc(compiler, instruction); -- break; -+ word_count = instruction->src_count - 3; -+ if (!(cases = vkd3d_calloc(word_count, sizeof(*cases)))) -+ { -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY, -+ "Failed to allocate %u words for switch cases.", word_count); -+ return; -+ } - -- case VKD3DSIH_DISCARD: -- case VKD3DSIH_TEXKILL: -- spirv_compiler_emit_kill(compiler, instruction); -- break; -+ val_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); -+ default_id = spirv_compiler_get_label_id(compiler, src[1].reg.idx[0].offset); -+ /* No instructions may occur between the merge and the switch. */ -+ spirv_compiler_emit_merge(compiler, src[2].reg.idx[0].offset, 0); - -- default: -- ERR("Unexpected instruction %#x.\n", instruction->handler_idx); -- break; -+ src = &src[3]; -+ for (i = 0; i < word_count; i += 2) -+ { -+ cases[i] = src[i].reg.u.immconst_u32[0]; -+ cases[i + 1] = spirv_compiler_get_label_id(compiler, src[i + 1].reg.idx[0].offset); - } - -- return VKD3D_OK; -+ vkd3d_spirv_build_op_switch(builder, val_id, default_id, cases, word_count / 2u); -+ -+ vkd3d_free(cases); - } - - static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compiler, -@@ -8090,7 +8173,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, - unsigned int image_operand_count = 0; - struct vkd3d_shader_image image; - uint32_t image_operands[2]; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - bool multisample; - - multisample = instruction->handler_idx == VKD3DSIH_LD2DMS; -@@ -8164,7 +8247,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, - unsigned int image_operand_count = 0; - struct vkd3d_shader_image image; - uint32_t image_operands[3]; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - SpvOp op; - - resource = &src[1]; -@@ -8280,7 +8363,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, - struct vkd3d_shader_image image; - unsigned int component_idx; - uint32_t image_operands[1]; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - bool extended_offset; - - if (instruction->handler_idx == VKD3DSIH_GATHER4_C -@@ -8325,7 +8408,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, - } - else - { -- component_idx = vkd3d_swizzle_get_component(sampler->swizzle, 0); -+ component_idx = vsir_swizzle_get_component(sampler->swizzle, 0); - /* Nvidia driver requires signed integer type. */ - component_id = spirv_compiler_get_constant(compiler, - VKD3D_SHADER_COMPONENT_INT, 1, &component_idx); -@@ -8340,13 +8423,13 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, - - static uint32_t spirv_compiler_emit_raw_structured_addressing( - struct spirv_compiler *compiler, uint32_t type_id, unsigned int stride, -- const struct vkd3d_shader_src_param *src0, DWORD src0_mask, -- const struct vkd3d_shader_src_param *src1, DWORD src1_mask) -+ const struct vkd3d_shader_src_param *src0, uint32_t src0_mask, -+ const struct vkd3d_shader_src_param *src1, uint32_t src1_mask) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_src_param *offset; - uint32_t structure_id = 0, offset_id; -- DWORD offset_write_mask; -+ uint32_t offset_write_mask; - - if (stride) - { -@@ -8403,7 +8486,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler - if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) - continue; - -- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); -+ component_idx = vsir_swizzle_get_component(resource->swizzle, i); - coordinate_id = base_coordinate_id; - if (component_idx) - coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, -@@ -8435,7 +8518,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler - if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) - continue; - -- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); -+ component_idx = vsir_swizzle_get_component(resource->swizzle, i); - coordinate_id = base_coordinate_id; - if (component_idx) - coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, -@@ -8447,7 +8530,6 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler - type_id, val_id, 0); - } - } -- assert(dst->reg.data_type == VKD3D_DATA_UINT); - spirv_compiler_emit_store_dst_components(compiler, dst, VKD3D_SHADER_COMPONENT_UINT, constituents); - } - -@@ -8479,7 +8561,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, - if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) - continue; - -- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); -+ component_idx = vsir_swizzle_get_component(resource->swizzle, i); - coordinate_id = base_coordinate_id; - if (component_idx) - coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, -@@ -8540,7 +8622,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * - assert(data->reg.data_type == VKD3D_DATA_UINT); - val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - for (component_idx = 0; component_idx < component_count; ++component_idx) - { - data_id = component_count > 1 ? -@@ -8569,7 +8651,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * - assert(data->reg.data_type == VKD3D_DATA_UINT); - val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - for (component_idx = 0; component_idx < component_count; ++component_idx) - { - /* Mesa Vulkan drivers require the texel parameter to be a vector. */ -@@ -8613,7 +8695,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, - assert(data->reg.data_type == VKD3D_DATA_UINT); - val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - for (component_idx = 0; component_idx < component_count; ++component_idx) - { - data_id = component_count > 1 ? -@@ -8655,7 +8737,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, - const struct vkd3d_shader_src_param *src = instruction->src; - const struct vkd3d_symbol *resource_symbol; - struct vkd3d_shader_image image; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - uint32_t indices[2]; - - resource_symbol = spirv_compiler_find_resource(compiler, &src[1].reg); -@@ -8698,7 +8780,7 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, - const struct vkd3d_shader_src_param *src = instruction->src; - const struct vkd3d_symbol *resource_symbol; - struct vkd3d_shader_image image; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - uint32_t indices[2]; - - resource_symbol = spirv_compiler_find_resource(compiler, &dst->reg); -@@ -8864,7 +8946,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil - struct vkd3d_shader_register_info reg_info; - struct vkd3d_shader_image image; - unsigned int structure_stride; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - uint32_t operands[6]; - unsigned int i = 0; - SpvScope scope; -@@ -9275,7 +9357,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, - } - - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, -- vkd3d_write_mask_component_count(register_info.write_mask)); -+ vsir_write_mask_component_count(register_info.write_mask)); - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); - val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, op, src_ids, src_count); -@@ -9296,9 +9378,9 @@ static void spirv_compiler_emit_sync(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { - unsigned int memory_semantics = SpvMemorySemanticsAcquireReleaseMask; -- unsigned int flags = instruction->flags; - SpvScope execution_scope = SpvScopeMax; - SpvScope memory_scope = SpvScopeDevice; -+ uint32_t flags = instruction->flags; - - if (flags & VKD3DSSF_GROUP_SHARED_MEMORY) - { -@@ -9313,11 +9395,20 @@ static void spirv_compiler_emit_sync(struct spirv_compiler *compiler, - flags &= ~VKD3DSSF_THREAD_GROUP; - } - -- if (flags & VKD3DSSF_GLOBAL_UAV) -+ if (flags & (VKD3DSSF_THREAD_GROUP_UAV | VKD3DSSF_GLOBAL_UAV)) - { -- memory_scope = SpvScopeDevice; -- memory_semantics |= SpvMemorySemanticsImageMemoryMask; -- flags &= ~VKD3DSSF_GLOBAL_UAV; -+ bool group_uav = flags & VKD3DSSF_THREAD_GROUP_UAV; -+ bool global_uav = flags & VKD3DSSF_GLOBAL_UAV; -+ -+ if (group_uav && global_uav) -+ { -+ WARN("Invalid UAV sync flag combination; assuming global.\n"); -+ spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_UAV_FLAGS, -+ "The flags for a UAV sync instruction are contradictory; assuming global sync."); -+ } -+ memory_scope = global_uav ? SpvScopeDevice : SpvScopeWorkgroup; -+ memory_semantics |= SpvMemorySemanticsUniformMemoryMask | SpvMemorySemanticsImageMemoryMask; -+ flags &= ~(VKD3DSSF_THREAD_GROUP_UAV | VKD3DSSF_GLOBAL_UAV); - } - - if (flags) -@@ -9382,28 +9473,15 @@ static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler) - { - spirv_compiler_emit_push_constant_buffers(compiler); - -- if (compiler->xfb_info && compiler->xfb_info->element_count -- && compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY) -+ if (compiler->emit_point_size) - spirv_compiler_emit_point_size(compiler); - } - --static bool is_dcl_instruction(enum vkd3d_shader_opcode handler_idx) --{ -- return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT) -- || handler_idx == VKD3DSIH_HS_DECLS; --} -- - static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { - int ret = VKD3D_OK; - -- if (!is_dcl_instruction(instruction->handler_idx) && !compiler->after_declarations_section) -- { -- compiler->after_declarations_section = true; -- spirv_compiler_emit_main_prolog(compiler); -- } -- - switch (instruction->handler_idx) - { - case VKD3DSIH_DCL_GLOBAL_FLAGS: -@@ -9425,18 +9503,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_DCL_INPUT: - spirv_compiler_emit_dcl_input(compiler, instruction); - break; -- case VKD3DSIH_DCL_INPUT_PS_SGV: -- case VKD3DSIH_DCL_INPUT_PS_SIV: -- case VKD3DSIH_DCL_INPUT_SGV: -- case VKD3DSIH_DCL_INPUT_SIV: -- spirv_compiler_emit_dcl_input_sysval(compiler, instruction); -- break; - case VKD3DSIH_DCL_OUTPUT: - spirv_compiler_emit_dcl_output(compiler, instruction); - break; -- case VKD3DSIH_DCL_OUTPUT_SIV: -- spirv_compiler_emit_dcl_output_siv(compiler, instruction); -- break; - case VKD3DSIH_DCL_STREAM: - spirv_compiler_emit_dcl_stream(compiler, instruction); - break; -@@ -9500,6 +9569,8 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_INEG: - case VKD3DSIH_ISHL: - case VKD3DSIH_ISHR: -+ case VKD3DSIH_ISINF: -+ case VKD3DSIH_ISNAN: - case VKD3DSIH_ITOD: - case VKD3DSIH_ITOF: - case VKD3DSIH_ITOI: -@@ -9513,6 +9584,15 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_XOR: - ret = spirv_compiler_emit_alu_instruction(compiler, instruction); - break; -+ case VKD3DSIH_ISFINITE: -+ spirv_compiler_emit_isfinite(compiler, instruction); -+ break; -+ case VKD3DSIH_ACOS: -+ case VKD3DSIH_ASIN: -+ case VKD3DSIH_ATAN: -+ case VKD3DSIH_HCOS: -+ case VKD3DSIH_HSIN: -+ case VKD3DSIH_HTAN: - case VKD3DSIH_DFMA: - case VKD3DSIH_DMAX: - case VKD3DSIH_DMIN: -@@ -9533,6 +9613,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_ROUND_Z: - case VKD3DSIH_RSQ: - case VKD3DSIH_SQRT: -+ case VKD3DSIH_TAN: - case VKD3DSIH_UMAX: - case VKD3DSIH_UMIN: - spirv_compiler_emit_ext_glsl_instruction(compiler, instruction); -@@ -9599,24 +9680,23 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_F32TOF16: - spirv_compiler_emit_f32tof16(compiler, instruction); - break; -- case VKD3DSIH_BREAK: -- case VKD3DSIH_BREAKP: -- case VKD3DSIH_CASE: -- case VKD3DSIH_CONTINUE: -- case VKD3DSIH_CONTINUEP: -- case VKD3DSIH_DEFAULT: -- case VKD3DSIH_DISCARD: -- case VKD3DSIH_ELSE: -- case VKD3DSIH_ENDIF: -- case VKD3DSIH_ENDLOOP: -- case VKD3DSIH_ENDSWITCH: -- case VKD3DSIH_IF: -- case VKD3DSIH_LOOP: - case VKD3DSIH_RET: -+ spirv_compiler_emit_return(compiler, instruction); -+ break; - case VKD3DSIH_RETP: -- case VKD3DSIH_SWITCH: -- case VKD3DSIH_TEXKILL: -- ret = spirv_compiler_emit_control_flow_instruction(compiler, instruction); -+ spirv_compiler_emit_retc(compiler, instruction); -+ break; -+ case VKD3DSIH_DISCARD: -+ spirv_compiler_emit_discard(compiler, instruction); -+ break; -+ case VKD3DSIH_LABEL: -+ spirv_compiler_emit_label(compiler, instruction); -+ break; -+ case VKD3DSIH_BRANCH: -+ spirv_compiler_emit_branch(compiler, instruction); -+ break; -+ case VKD3DSIH_SWITCH_MONOLITHIC: -+ spirv_compiler_emit_switch(compiler, instruction); - break; - case VKD3DSIH_DSX: - case VKD3DSIH_DSX_COARSE: -@@ -9719,10 +9799,14 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_DCL_CONSTANT_BUFFER: - case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: - case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT: -+ 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: - case VKD3DSIH_DCL_RESOURCE_RAW: - case VKD3DSIH_DCL_RESOURCE_STRUCTURED: - case VKD3DSIH_DCL_SAMPLER: -- case VKD3DSIH_DCL_TEMPS: - case VKD3DSIH_DCL_UAV_RAW: - case VKD3DSIH_DCL_UAV_STRUCTURED: - case VKD3DSIH_DCL_UAV_TYPED: -@@ -9740,6 +9824,30 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - return ret; - } - -+static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) -+{ -+ for (unsigned int i = 0; i < compiler->input_signature.element_count; ++i) -+ spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, i); -+ -+ for (unsigned int i = 0; i < compiler->output_signature.element_count; ++i) -+ { -+ /* PS outputs other than TARGET have dedicated registers and therefore -+ * go through spirv_compiler_emit_dcl_output() for now. */ -+ if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL -+ && compiler->output_signature.elements[i].sysval_semantic != VKD3D_SHADER_SV_TARGET) -+ continue; -+ spirv_compiler_emit_output(compiler, VKD3DSPR_OUTPUT, i); -+ } -+ -+ for (unsigned int i = 0; i < compiler->patch_constant_signature.element_count; ++i) -+ { -+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) -+ spirv_compiler_emit_output(compiler, VKD3DSPR_PATCHCONST, i); -+ else -+ spirv_compiler_emit_input(compiler, VKD3DSPR_PATCHCONST, i); -+ } -+} -+ - static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler) - { - unsigned int i; -@@ -9793,24 +9901,28 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - struct vkd3d_shader_desc *shader_desc = &parser->shader_desc; - struct vkd3d_shader_instruction_array instructions; -+ struct vsir_program *program = &parser->program; - enum vkd3d_result result = VKD3D_OK; - unsigned int i; - -- if (parser->shader_desc.temp_count) -- spirv_compiler_emit_temps(compiler, parser->shader_desc.temp_count); -- if (parser->shader_desc.ssa_count) -- spirv_compiler_allocate_ssa_register_ids(compiler, parser->shader_desc.ssa_count); -+ if ((result = vkd3d_shader_normalise(parser, compile_info)) < 0) -+ return result; -+ -+ if (program->temp_count) -+ spirv_compiler_emit_temps(compiler, program->temp_count); -+ if (program->ssa_count) -+ spirv_compiler_allocate_ssa_register_ids(compiler, program->ssa_count); - - spirv_compiler_emit_descriptor_declarations(compiler); - - compiler->location.column = 0; - compiler->location.line = 1; - -- if ((result = vkd3d_shader_normalise(parser, compile_info)) < 0) -- return result; -+ if (program->block_count && !spirv_compiler_init_blocks(compiler, program->block_count)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; - -- instructions = parser->instructions; -- memset(&parser->instructions, 0, sizeof(parser->instructions)); -+ instructions = program->instructions; -+ memset(&program->instructions, 0, sizeof(program->instructions)); - - compiler->input_signature = shader_desc->input_signature; - compiler->output_signature = shader_desc->output_signature; -@@ -9818,10 +9930,12 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - memset(&shader_desc->input_signature, 0, sizeof(shader_desc->input_signature)); - memset(&shader_desc->output_signature, 0, sizeof(shader_desc->output_signature)); - memset(&shader_desc->patch_constant_signature, 0, sizeof(shader_desc->patch_constant_signature)); -- compiler->use_vocp = parser->shader_desc.use_vocp; -+ compiler->use_vocp = program->use_vocp; -+ compiler->block_names = program->block_names; -+ compiler->block_name_count = program->block_name_count; - -- compiler->input_control_point_count = shader_desc->input_control_point_count; -- compiler->output_control_point_count = shader_desc->output_control_point_count; -+ compiler->input_control_point_count = program->input_control_point_count; -+ compiler->output_control_point_count = program->output_control_point_count; - - if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) - spirv_compiler_emit_shader_signature_outputs(compiler); -@@ -9837,9 +9951,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - if (result < 0) - return result; - -- if (compiler->main_block_open) -- vkd3d_spirv_build_op_return(builder); -- - if (!is_in_default_phase(compiler)) - spirv_compiler_leave_shader_phase(compiler); - else -@@ -9862,6 +9973,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - } - } - -+ if (compiler->discard_function_id) -+ spirv_compiler_emit_discard_function(compiler); -+ - if (compiler->epilogue_function_id) - { - vkd3d_spirv_build_op_name(builder, compiler->epilogue_function_id, "epilogue"); -@@ -9874,11 +9988,28 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - if (!vkd3d_spirv_compile_module(builder, spirv, spirv_compiler_get_entry_point_name(compiler))) - return VKD3D_ERROR; - -- if (TRACE_ON()) -+ if (TRACE_ON() || parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) - { - enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler); -- vkd3d_spirv_dump(spirv, environment); -- vkd3d_spirv_validate(spirv, environment); -+ struct vkd3d_string_buffer buffer; -+ -+ if (TRACE_ON()) -+ vkd3d_spirv_dump(spirv, environment); -+ -+ vkd3d_string_buffer_init(&buffer); -+ if (!vkd3d_spirv_validate(&buffer, spirv, environment)) -+ { -+ FIXME("Failed to validate SPIR-V binary.\n"); -+ vkd3d_shader_trace_text(buffer.buffer, buffer.content_size); -+ -+ if (compiler->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) -+ { -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, -+ "Execution generated an invalid shader, failing compilation:\n%s", -+ buffer.buffer); -+ } -+ } -+ vkd3d_string_buffer_cleanup(&buffer); - } - - if (compiler->failed) -@@ -9890,6 +10021,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler); - if (vkd3d_spirv_binary_to_text(spirv, environment, compiler->formatting, &text) != VKD3D_OK) - return VKD3D_ERROR; -+ vkd3d_shader_free_shader_code(spirv); - *spirv = text; - } - -@@ -9904,8 +10036,8 @@ int spirv_compile(struct vkd3d_shader_parser *parser, - struct spirv_compiler *spirv_compiler; - int ret; - -- if (!(spirv_compiler = spirv_compiler_create(&parser->shader_version, &parser->shader_desc, -- compile_info, scan_descriptor_info, message_context, &parser->location))) -+ if (!(spirv_compiler = spirv_compiler_create(&parser->program.shader_version, &parser->shader_desc, -+ compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags))) - { - ERR("Failed to create SPIR-V compiler.\n"); - return VKD3D_ERROR; -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 80f8ab98c08..adfddd32036 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -711,7 +711,7 @@ static struct vkd3d_shader_sm4_parser *vkd3d_shader_sm4_parser(struct vkd3d_shad - - static bool shader_is_sm_5_1(const struct vkd3d_shader_sm4_parser *sm4) - { -- const struct vkd3d_shader_version *version = &sm4->p.shader_version; -+ const struct vkd3d_shader_version *version = &sm4->p.program.shader_version; - - return version->major >= 5 && version->minor >= 1; - } -@@ -742,8 +742,7 @@ static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv, - static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins, uint32_t opcode, - uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) - { -- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, -- (struct vkd3d_shader_src_param *)&ins->src[0]); -+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &ins->src[0]); - ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ? - VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z; - } -@@ -751,8 +750,7 @@ static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins, - static void shader_sm4_read_case_condition(struct vkd3d_shader_instruction *ins, uint32_t opcode, - uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) - { -- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, -- (struct vkd3d_shader_src_param *)&ins->src[0]); -+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &ins->src[0]); - if (ins->src[0].reg.type != VKD3DSPR_IMMCONST) - { - FIXME("Switch case value is not a 32-bit constant.\n"); -@@ -792,11 +790,13 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui - ins->handler_idx = VKD3DSIH_INVALID; - return; - } -+ icb->register_idx = 0; - icb->data_type = VKD3D_DATA_FLOAT; - icb->component_count = VKD3D_VEC4_SIZE; - icb->element_count = icb_size / VKD3D_VEC4_SIZE; -+ icb->is_null = false; - memcpy(icb->data, tokens, sizeof(*tokens) * icb_size); -- shader_instruction_array_add_icb(&priv->p.instructions, icb); -+ shader_instruction_array_add_icb(&priv->p.program.instructions, icb); - ins->declaration.icb = icb; - } - -@@ -821,7 +821,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u - const uint32_t *end = &tokens[token_count]; - enum vkd3d_sm4_data_type data_type; - enum vkd3d_data_type reg_data_type; -- DWORD components; -+ uint32_t components; - unsigned int i; - - resource_type = (opcode_token & VKD3D_SM4_RESOURCE_TYPE_MASK) >> VKD3D_SM4_RESOURCE_TYPE_SHIFT; -@@ -918,10 +918,12 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins - uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) - { - struct vkd3d_shader_index_range *index_range = &ins->declaration.index_range; -- unsigned int i, register_idx, register_count, write_mask; -+ unsigned int i, register_idx, register_count; -+ const struct shader_signature *signature; - enum vkd3d_shader_register_type type; - struct sm4_index_range_array *ranges; - unsigned int *io_masks; -+ uint32_t write_mask; - - shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, - &index_range->dst); -@@ -931,40 +933,38 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins - register_count = index_range->register_count; - write_mask = index_range->dst.write_mask; - -- if (vkd3d_write_mask_component_count(write_mask) != 1) -- { -- WARN("Unhandled write mask %#x.\n", write_mask); -- vkd3d_shader_parser_warning(&priv->p, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK, -- "Index range mask %#x is not scalar.", write_mask); -- } -- - switch ((type = index_range->dst.reg.type)) - { - case VKD3DSPR_INPUT: - case VKD3DSPR_INCONTROLPOINT: - io_masks = priv->input_register_masks; - ranges = &priv->input_index_ranges; -+ signature = &priv->p.shader_desc.input_signature; - break; - case VKD3DSPR_OUTPUT: - if (sm4_parser_is_in_fork_or_join_phase(priv)) - { - io_masks = priv->patch_constant_register_masks; - ranges = &priv->patch_constant_index_ranges; -+ signature = &priv->p.shader_desc.patch_constant_signature; - } - else - { - io_masks = priv->output_register_masks; - ranges = &priv->output_index_ranges; -+ signature = &priv->p.shader_desc.output_signature; - } - break; - case VKD3DSPR_COLOROUT: - case VKD3DSPR_OUTCONTROLPOINT: - io_masks = priv->output_register_masks; - ranges = &priv->output_index_ranges; -+ signature = &priv->p.shader_desc.output_signature; - break; - case VKD3DSPR_PATCHCONST: - io_masks = priv->patch_constant_register_masks; - ranges = &priv->patch_constant_index_ranges; -+ signature = &priv->p.shader_desc.patch_constant_signature; - break; - - default: -@@ -1002,6 +1002,18 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins - - for (i = 0; i < register_count; ++i) - { -+ const struct signature_element *e = vsir_signature_find_element_for_reg(signature, register_idx + i, write_mask); -+ /* Index ranges should not contain non-arrayed sysvals. FXC tries to forbid this but it is buggy, -+ * and can emit a range containing a sysval if the sysval is not actually accessed. */ -+ if (e && e->sysval_semantic && register_count > 1 && !vsir_sysval_semantic_is_tess_factor(e->sysval_semantic) -+ && !vsir_sysval_semantic_is_clip_cull(e->sysval_semantic)) -+ { -+ WARN("Sysval %u included in an index range declaration.\n", e->sysval_semantic); -+ vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_INDEX_RANGE_DCL, -+ "Index range base %u, count %u, mask %#x contains sysval %u.", -+ register_idx, register_count, write_mask, e->sysval_semantic); -+ return; -+ } - if ((io_masks[register_idx + i] & write_mask) != write_mask) - { - WARN("No matching declaration for index range base %u, count %u, mask %#x.\n", -@@ -1039,7 +1051,7 @@ static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction - { - ins->declaration.primitive_type.type = VKD3D_PT_PATCH; - ins->declaration.primitive_type.patch_vertex_count = primitive_type - VKD3D_SM5_INPUT_PT_PATCH1 + 1; -- priv->p.shader_desc.input_control_point_count = ins->declaration.primitive_type.patch_vertex_count; -+ priv->p.program.input_control_point_count = ins->declaration.primitive_type.patch_vertex_count; - } - else if (primitive_type >= ARRAY_SIZE(input_primitive_type_table)) - { -@@ -1048,7 +1060,7 @@ static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction - else - { - ins->declaration.primitive_type.type = input_primitive_type_table[primitive_type].vkd3d_type; -- priv->p.shader_desc.input_control_point_count = input_primitive_type_table[primitive_type].control_point_count; -+ priv->p.program.input_control_point_count = input_primitive_type_table[primitive_type].control_point_count; - } - - if (ins->declaration.primitive_type.type == VKD3D_PT_UNDEFINED) -@@ -1060,7 +1072,7 @@ static void shader_sm4_read_declaration_count(struct vkd3d_shader_instruction *i - { - ins->declaration.count = *tokens; - if (opcode == VKD3D_SM4_OP_DCL_TEMPS) -- priv->p.shader_desc.temp_count = max(priv->p.shader_desc.temp_count, *tokens); -+ priv->p.program.temp_count = max(priv->p.program.temp_count, *tokens); - } - - static void shader_sm4_read_declaration_dst(struct vkd3d_shader_instruction *ins, uint32_t opcode, -@@ -1116,6 +1128,7 @@ static void shader_sm4_read_dcl_indexable_temp(struct vkd3d_shader_instruction * - ins->declaration.indexable_temp.alignment = 0; - ins->declaration.indexable_temp.data_type = VKD3D_DATA_FLOAT; - ins->declaration.indexable_temp.component_count = *tokens; -+ ins->declaration.indexable_temp.has_function_scope = false; - } - - static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *ins, uint32_t opcode, -@@ -1127,9 +1140,8 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in - static void shader_sm5_read_fcall(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, - const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) - { -- struct vkd3d_shader_src_param *src_params = (struct vkd3d_shader_src_param *)ins->src; -- src_params[0].reg.u.fp_body_idx = *tokens++; -- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &src_params[0]); -+ ins->src[0].reg.u.fp_body_idx = *tokens++; -+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &ins->src[0]); - } - - static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode, -@@ -1162,9 +1174,9 @@ static void shader_sm5_read_control_point_count(struct vkd3d_shader_instruction - >> VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT; - - if (opcode == VKD3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT) -- priv->p.shader_desc.input_control_point_count = ins->declaration.count; -+ priv->p.program.input_control_point_count = ins->declaration.count; - else -- priv->p.shader_desc.output_control_point_count = ins->declaration.count; -+ priv->p.program.output_control_point_count = ins->declaration.count; - } - - static void shader_sm5_read_dcl_tessellator_domain(struct vkd3d_shader_instruction *ins, uint32_t opcode, -@@ -1720,7 +1732,7 @@ static void shader_sm4_destroy(struct vkd3d_shader_parser *parser) - { - struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser); - -- shader_instruction_array_destroy(&parser->instructions); -+ vsir_program_cleanup(&parser->program); - free_shader_desc(&parser->shader_desc); - vkd3d_free(sm4); - } -@@ -1730,7 +1742,7 @@ static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const - { - if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE) - { -- struct vkd3d_shader_src_param *rel_addr = shader_parser_get_src_params(&priv->p, 1); -+ struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(&priv->p.program, 1); - - if (!(reg_idx->rel_addr = rel_addr)) - { -@@ -1759,11 +1771,11 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - const struct vkd3d_sm4_register_type_info *register_type_info; - enum vkd3d_shader_register_type vsir_register_type; - enum vkd3d_sm4_register_precision precision; -+ uint32_t token, order, extended, addressing; - enum vkd3d_sm4_register_type register_type; - enum vkd3d_sm4_extended_operand_type type; -- enum vkd3d_sm4_register_modifier m; - enum vkd3d_sm4_dimension sm4_dimension; -- uint32_t token, order, extended; -+ enum vkd3d_sm4_register_modifier m; - - if (*ptr >= end) - { -@@ -1861,7 +1873,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - - if (order >= 1) - { -- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0; -+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0; - if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[0]))) - { - ERR("Failed to read register index.\n"); -@@ -1871,7 +1883,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - - if (order >= 2) - { -- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1; -+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1; - if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[1]))) - { - ERR("Failed to read register index.\n"); -@@ -1881,7 +1893,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - - if (order >= 3) - { -- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2; -+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2; - if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[2]))) - { - ERR("Failed to read register index.\n"); -@@ -1900,19 +1912,19 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - - if (register_type == VKD3D_SM4_RT_IMMCONST || register_type == VKD3D_SM4_RT_IMMCONST64) - { -- unsigned int dword_count; -+ unsigned int u32_count; - - switch (param->dimension) - { - case VSIR_DIMENSION_SCALAR: -- dword_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); -- if (end - *ptr < dword_count) -+ u32_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); -+ if (end - *ptr < u32_count) - { - WARN("Invalid ptr %p, end %p.\n", *ptr, end); - return false; - } -- memcpy(param->u.immconst_uint, *ptr, dword_count * sizeof(DWORD)); -- *ptr += dword_count; -+ memcpy(param->u.immconst_u32, *ptr, u32_count * sizeof(uint32_t)); -+ *ptr += u32_count; - break; - - case VSIR_DIMENSION_VEC4: -@@ -1921,7 +1933,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - WARN("Invalid ptr %p, end %p.\n", *ptr, end); - return false; - } -- memcpy(param->u.immconst_uint, *ptr, VKD3D_VEC4_SIZE * sizeof(DWORD)); -+ memcpy(param->u.immconst_u32, *ptr, VKD3D_VEC4_SIZE * sizeof(uint32_t)); - *ptr += 4; - break; - -@@ -1930,6 +1942,15 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - break; - } - } -+ else if (register_type == VKD3D_SM4_RT_IMMCONSTBUFFER) -+ { -+ if (param->idx_count != 1) -+ { -+ WARN("Unexpected idx count %u.\n", param->idx_count); -+ vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT, -+ "Invalid index count %u for immediate const buffer register; expected count 1.", param->idx_count); -+ } -+ } - else if (!shader_is_sm_5_1(priv) && vsir_register_is_descriptor(param)) - { - /* SM5.1 places a symbol identifier in idx[0] and moves -@@ -1970,10 +1991,10 @@ static uint32_t swizzle_from_sm4(uint32_t s) - static uint32_t swizzle_to_sm4(uint32_t s) - { - uint32_t ret = 0; -- ret |= ((vkd3d_swizzle_get_component(s, 0)) & 0x3); -- ret |= ((vkd3d_swizzle_get_component(s, 1)) & 0x3) << 2; -- ret |= ((vkd3d_swizzle_get_component(s, 2)) & 0x3) << 4; -- ret |= ((vkd3d_swizzle_get_component(s, 3)) & 0x3) << 6; -+ ret |= ((vsir_swizzle_get_component(s, 0)) & 0x3); -+ ret |= ((vsir_swizzle_get_component(s, 1)) & 0x3) << 2; -+ ret |= ((vsir_swizzle_get_component(s, 2)) & 0x3) << 4; -+ ret |= ((vsir_swizzle_get_component(s, 3)) & 0x3) << 6; - return ret; - } - -@@ -1999,15 +2020,15 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register * - { - return reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT - || (reg->type == VKD3DSPR_INPUT && (priv->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE -- || priv->p.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY)); -+ || priv->p.program.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY)); - } - --static unsigned int mask_from_swizzle(unsigned int swizzle) -+static uint32_t mask_from_swizzle(uint32_t swizzle) - { -- return (1u << vkd3d_swizzle_get_component(swizzle, 0)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 1)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 2)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 3)); -+ return (1u << vsir_swizzle_get_component(swizzle, 0)) -+ | (1u << vsir_swizzle_get_component(swizzle, 1)) -+ | (1u << vsir_swizzle_get_component(swizzle, 2)) -+ | (1u << vsir_swizzle_get_component(swizzle, 3)); - } - - static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_parser *priv, -@@ -2066,7 +2087,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons - const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param) - { - unsigned int dimension, mask; -- DWORD token; -+ uint32_t token; - - if (*ptr >= end) - { -@@ -2140,6 +2161,9 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons - break; - } - -+ if (data_type_is_64_bit(data_type)) -+ src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); -+ - if (register_is_input_output(&src_param->reg) && !shader_sm4_validate_input_output_register(priv, - &src_param->reg, mask_from_swizzle(src_param->swizzle))) - return false; -@@ -2153,7 +2177,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons - enum vkd3d_sm4_swizzle_type swizzle_type; - enum vkd3d_shader_src_modifier modifier; - unsigned int dimension, swizzle; -- DWORD token; -+ uint32_t token; - - if (*ptr >= end) - { -@@ -2219,7 +2243,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons - } - - if (data_type == VKD3D_DATA_DOUBLE) -- dst_param->write_mask = vkd3d_write_mask_64_from_32(dst_param->write_mask); -+ dst_param->write_mask = vsir_write_mask_64_from_32(dst_param->write_mask); - /* Some scalar registers are declared with no write mask in shader bytecode. */ - if (!dst_param->write_mask && shader_sm4_is_scalar_register(&dst_param->reg)) - dst_param->write_mask = VKD3DSP_WRITEMASK_0; -@@ -2233,7 +2257,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons - return true; - } - --static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_shader_instruction *ins) -+static void shader_sm4_read_instruction_modifier(uint32_t modifier, struct vkd3d_shader_instruction *ins) - { - enum vkd3d_sm4_instruction_modifier modifier_type = modifier & VKD3D_SM4_MODIFIER_MASK; - -@@ -2241,7 +2265,7 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh - { - case VKD3D_SM4_MODIFIER_AOFFIMMI: - { -- static const DWORD recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER -+ static const uint32_t recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER - | VKD3D_SM4_MODIFIER_MASK - | VKD3D_SM4_AOFFIMMI_U_MASK - | VKD3D_SM4_AOFFIMMI_V_MASK -@@ -2269,7 +2293,7 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh - - case VKD3D_SM5_MODIFIER_DATA_TYPE: - { -- DWORD components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT; -+ uint32_t components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT; - unsigned int i; - - for (i = 0; i < VKD3D_VEC4_SIZE; i++) -@@ -2320,14 +2344,15 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh - static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, struct vkd3d_shader_instruction *ins) - { - const struct vkd3d_sm4_opcode_info *opcode_info; -+ struct vsir_program *program = &sm4->p.program; - uint32_t opcode_token, opcode, previous_token; - struct vkd3d_shader_dst_param *dst_params; - struct vkd3d_shader_src_param *src_params; - const uint32_t **ptr = &sm4->ptr; - unsigned int i, len; -- size_t remaining; - const uint32_t *p; -- DWORD precise; -+ uint32_t precise; -+ size_t remaining; - - if (*ptr >= sm4->end) - { -@@ -2378,7 +2403,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str - ins->predicate = NULL; - ins->dst_count = strnlen(opcode_info->dst_info, SM4_MAX_DST_COUNT); - ins->src_count = strnlen(opcode_info->src_info, SM4_MAX_SRC_COUNT); -- ins->src = src_params = shader_parser_get_src_params(&sm4->p, ins->src_count); -+ ins->src = src_params = vsir_program_get_src_params(program, ins->src_count); - if (!src_params && ins->src_count) - { - ERR("Failed to allocate src parameters.\n"); -@@ -2420,7 +2445,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str - precise = (opcode_token & VKD3D_SM5_PRECISE_MASK) >> VKD3D_SM5_PRECISE_SHIFT; - ins->flags |= precise << VKD3DSI_PRECISE_SHIFT; - -- ins->dst = dst_params = shader_parser_get_dst_params(&sm4->p, ins->dst_count); -+ ins->dst = dst_params = vsir_program_get_dst_params(program, ins->dst_count); - if (!dst_params && ins->dst_count) - { - ERR("Failed to allocate dst parameters.\n"); -@@ -2533,6 +2558,16 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t - return true; - } - -+static void uninvert_used_masks(struct shader_signature *signature) -+{ -+ for (unsigned int i = 0; i < signature->element_count; ++i) -+ { -+ struct signature_element *e = &signature->elements[i]; -+ -+ e->used_mask = e->mask & ~e->used_mask; -+ } -+} -+ - static bool shader_sm4_parser_validate_signature(struct vkd3d_shader_sm4_parser *sm4, - const struct shader_signature *signature, unsigned int *masks, const char *name) - { -@@ -2628,6 +2663,12 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi - return VKD3D_ERROR_INVALID_ARGUMENT; - } - -+ /* DXBC stores used masks inverted for output signatures, for some reason. -+ * We return them un-inverted. */ -+ uninvert_used_masks(&shader_desc->output_signature); -+ if (sm4->p.program.shader_version.type == VKD3D_SHADER_TYPE_HULL) -+ uninvert_used_masks(&shader_desc->patch_constant_signature); -+ - if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature, - sm4->input_register_masks, "Input") - || !shader_sm4_parser_validate_signature(sm4, &shader_desc->output_signature, -@@ -2639,7 +2680,7 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi - return VKD3D_ERROR_INVALID_SHADER; - } - -- instructions = &sm4->p.instructions; -+ instructions = &sm4->p.program.instructions; - while (sm4->ptr != sm4->end) - { - if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) -@@ -2660,7 +2701,8 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi - } - ++instructions->count; - } -- if (sm4->p.shader_version.type == VKD3D_SHADER_TYPE_HULL && !sm4->has_control_point_phase && !sm4->p.failed) -+ if (sm4->p.program.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) -@@ -2769,6 +2811,8 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant - {"position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, - {"sv_position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, - {"sv_isfrontface", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_IS_FRONT_FACE}, -+ {"sv_rendertargetarrayindex", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_RENDER_TARGET_ARRAY_INDEX}, -+ {"sv_viewportarrayindex", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_VIEWPORT_ARRAY_INDEX}, - - {"color", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_TARGET}, - {"depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH}, -@@ -2777,9 +2821,12 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant - - {"sv_position", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_UNDEFINED}, - {"sv_vertexid", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_VERTEX_ID}, -+ {"sv_instanceid", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_INSTANCE_ID}, - - {"position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, - {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, -+ {"sv_rendertargetarrayindex", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_RENDER_TARGET_ARRAY_INDEX}, -+ {"sv_viewportarrayindex", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_VIEWPORT_ARRAY_INDEX}, - }; - bool needs_compat_mapping = ascii_strncasecmp(semantic->name, "sv_", 3); - -@@ -3842,7 +3889,7 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src, - if (width == 1) - { - src->reg.dimension = VSIR_DIMENSION_SCALAR; -- src->reg.u.immconst_uint[0] = value->u[0].u; -+ src->reg.u.immconst_u32[0] = value->u[0].u; - } - else - { -@@ -3852,9 +3899,9 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src, - for (i = 0; i < 4; ++i) - { - if ((map_writemask & (1u << i)) && (j < width)) -- src->reg.u.immconst_uint[i] = value->u[j++].u; -+ src->reg.u.immconst_u32[i] = value->u[j++].u; - else -- src->reg.u.immconst_uint[i] = 0; -+ src->reg.u.immconst_u32[i] = 0; - } - } - } -@@ -4049,12 +4096,12 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk - - if (src->reg.type == VKD3DSPR_IMMCONST) - { -- put_u32(buffer, src->reg.u.immconst_uint[0]); -+ put_u32(buffer, src->reg.u.immconst_u32[0]); - if (src->reg.dimension == VSIR_DIMENSION_VEC4) - { -- put_u32(buffer, src->reg.u.immconst_uint[1]); -- put_u32(buffer, src->reg.u.immconst_uint[2]); -- put_u32(buffer, src->reg.u.immconst_uint[3]); -+ put_u32(buffer, src->reg.u.immconst_u32[1]); -+ put_u32(buffer, src->reg.u.immconst_u32[2]); -+ put_u32(buffer, src->reg.u.immconst_u32[3]); - } - } - } -@@ -4589,7 +4636,7 @@ static void write_sm4_ld(const struct tpf_writer *tpf, const struct hlsl_ir_node - memset(&instr.srcs[2], 0, sizeof(instr.srcs[2])); - reg->type = VKD3DSPR_IMMCONST; - reg->dimension = VSIR_DIMENSION_SCALAR; -- reg->u.immconst_uint[0] = index->value.u[0].u; -+ reg->u.immconst_u32[0] = index->value.u[0].u; - } - else if (tpf->ctx->profile->major_version == 4 && tpf->ctx->profile->minor_version == 0) - { -@@ -4750,7 +4797,7 @@ static void write_sm4_cast_from_bool(const struct tpf_writer *tpf, const struct - sm4_src_from_node(tpf, &instr.srcs[0], arg, instr.dsts[0].write_mask); - instr.srcs[1].reg.type = VKD3DSPR_IMMCONST; - instr.srcs[1].reg.dimension = VSIR_DIMENSION_SCALAR; -- instr.srcs[1].reg.u.immconst_uint[0] = mask; -+ instr.srcs[1].reg.u.immconst_u32[0] = mask; - instr.src_count = 2; - - write_sm4_instruction(tpf, &instr); -@@ -5460,7 +5507,7 @@ static void write_sm4_loop(const struct tpf_writer *tpf, const struct hlsl_ir_lo - - static void write_sm4_gather(const struct tpf_writer *tpf, const struct hlsl_ir_node *dst, - const struct hlsl_deref *resource, const struct hlsl_deref *sampler, -- const struct hlsl_ir_node *coords, DWORD swizzle, const struct hlsl_ir_node *texel_offset) -+ const struct hlsl_ir_node *coords, uint32_t swizzle, const struct hlsl_ir_node *texel_offset) - { - struct vkd3d_shader_src_param *src; - struct sm4_instruction instr; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 8fd8945151f..d0fd6b047b1 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -23,6 +23,8 @@ - #include - #include - -+/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */ -+ - static inline int char_to_int(char c) - { - if ('0' <= c && c <= '9') -@@ -305,6 +307,16 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s - vkd3d_string_buffer_printf(&context->messages, "\n"); - } - -+void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, -+ enum vkd3d_shader_error error, const char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ vkd3d_shader_vwarning(context, location, error, format, args); -+ va_end(args); -+} -+ - void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, - enum vkd3d_shader_error error, const char *format, va_list args) - { -@@ -371,24 +383,53 @@ size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *byte - return offset; - } - --void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) -+size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size) -+{ -+ size_t offset = bytecode_align(buffer); -+ -+ if (buffer->status) -+ return offset; -+ -+ if (!vkd3d_array_reserve((void **)&buffer->data, &buffer->capacity, offset + size, 1)) -+ { -+ buffer->status = VKD3D_ERROR_OUT_OF_MEMORY; -+ return offset; -+ } -+ -+ memset(buffer->data + offset, 0, size); -+ buffer->size = offset + size; -+ return offset; -+} -+ -+static void bytecode_set_bytes(struct vkd3d_bytecode_buffer *buffer, size_t offset, -+ const void *value, size_t size) - { - if (buffer->status) - return; - -- assert(vkd3d_bound_range(offset, sizeof(value), buffer->size)); -- memcpy(buffer->data + offset, &value, sizeof(value)); -+ assert(vkd3d_bound_range(offset, size, buffer->size)); -+ memcpy(buffer->data + offset, value, size); -+} -+ -+void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) -+{ -+ bytecode_set_bytes(buffer, offset, &value, sizeof(value)); -+} -+ -+void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length) -+{ -+ bytecode_set_bytes(buffer, offset, string, length); - } - - static void vkd3d_shader_dump_blob(const char *path, const char *profile, - const char *suffix, const void *data, size_t size) - { -- static LONG shader_id = 0; -+ static unsigned int shader_id = 0; - char filename[1024]; - unsigned int id; - FILE *f; - -- id = InterlockedIncrement(&shader_id) - 1; -+ id = vkd3d_atomic_increment_u32(&shader_id) - 1; - - if (profile) - snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u-%s.%s", path, id, profile, suffix); -@@ -498,10 +539,9 @@ bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, - parser->location.source_name = source_name; - parser->location.line = 1; - 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); -+ return vsir_program_init(&parser->program, version, instruction_reserve); - } - - void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser, -@@ -888,6 +928,21 @@ static void vkd3d_shader_scan_combined_sampler_declaration( - &semantic->resource.range, semantic->resource_type, VKD3D_SHADER_RESOURCE_DATA_FLOAT); - } - -+static const struct vkd3d_shader_descriptor_info1 *find_descriptor( -+ const struct vkd3d_shader_scan_descriptor_info1 *info, -+ enum vkd3d_shader_descriptor_type type, unsigned int register_id) -+{ -+ for (unsigned int i = 0; i < info->descriptor_count; ++i) -+ { -+ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; -+ -+ if (d->type == type && d->register_id == register_id) -+ return d; -+ } -+ -+ return NULL; -+} -+ - static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_context *context, - const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler) - { -@@ -913,7 +968,6 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co - - if (vkd3d_shader_ver_ge(context->version, 5, 1)) - { -- const struct vkd3d_shader_scan_descriptor_info1 *info = context->scan_descriptor_info; - const struct vkd3d_shader_descriptor_info1 *d; - bool dynamic_resource, dynamic_sampler; - -@@ -928,30 +982,13 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co - if (dynamic_resource || dynamic_sampler) - return; - -- for (i = 0; i < info->descriptor_count; ++i) -- { -- d = &info->descriptors[i]; -- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV) -- continue; -- if (d->register_id != resource->idx[0].offset) -- continue; -+ if ((d = find_descriptor(context->scan_descriptor_info, -+ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource->idx[0].offset))) - resource_space = d->register_space; -- break; -- } - -- if (sampler) -- { -- for (i = 0; i < info->descriptor_count; ++i) -- { -- d = &info->descriptors[i]; -- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) -- continue; -- if (d->register_id != sampler->idx[0].offset) -- continue; -- sampler_space = d->register_space; -- break; -- } -- } -+ if (sampler && (d = find_descriptor(context->scan_descriptor_info, -+ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler->idx[0].offset))) -+ sampler_space = d->register_space; - } - - for (i = 0; i < info->combined_sampler_count; ++i) -@@ -979,7 +1016,7 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co - static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_context *context, - const struct vkd3d_shader_resource *resource, enum vkd3d_shader_resource_type resource_type, - enum vkd3d_shader_resource_data_type resource_data_type, -- unsigned int sample_count, unsigned int structure_stride, bool raw) -+ unsigned int sample_count, unsigned int structure_stride, bool raw, uint32_t flags) - { - struct vkd3d_shader_descriptor_info1 *d; - enum vkd3d_shader_descriptor_type type; -@@ -995,6 +1032,8 @@ static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_cont - d->structure_stride = structure_stride; - if (raw) - d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_RAW_BUFFER; -+ if (type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) -+ d->uav_flags = flags; - } - - static void vkd3d_shader_scan_typed_resource_declaration(struct vkd3d_shader_scan_context *context, -@@ -1053,7 +1092,7 @@ static void vkd3d_shader_scan_typed_resource_declaration(struct vkd3d_shader_sca - } - - vkd3d_shader_scan_resource_declaration(context, &semantic->resource, -- semantic->resource_type, resource_data_type, semantic->sample_count, 0, false); -+ semantic->resource_type, resource_data_type, semantic->sample_count, 0, false, instruction->flags); - } - - static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *context, -@@ -1074,6 +1113,9 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte - vkd3d_shader_scan_sampler_declaration(context, instruction); - break; - case VKD3DSIH_DCL: -+ if (instruction->declaration.semantic.resource_type == VKD3D_SHADER_RESOURCE_NONE) -+ break; -+ - if (instruction->declaration.semantic.resource.reg.reg.type == VKD3DSPR_COMBINED_SAMPLER) - { - vkd3d_shader_scan_combined_sampler_declaration(context, &instruction->declaration.semantic); -@@ -1086,15 +1128,16 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte - case VKD3DSIH_DCL_RESOURCE_RAW: - case VKD3DSIH_DCL_UAV_RAW: - vkd3d_shader_scan_resource_declaration(context, &instruction->declaration.raw_resource.resource, -- VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0, 0, true); -+ VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0, 0, true, instruction->flags); - break; - case VKD3DSIH_DCL_RESOURCE_STRUCTURED: - case VKD3DSIH_DCL_UAV_STRUCTURED: - vkd3d_shader_scan_resource_declaration(context, &instruction->declaration.structured_resource.resource, - VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0, -- instruction->declaration.structured_resource.byte_stride, false); -+ instruction->declaration.structured_resource.byte_stride, false, instruction->flags); - break; - case VKD3DSIH_IF: -+ case VKD3DSIH_IFC: - cf_info = vkd3d_shader_scan_push_cf_info(context); - cf_info->type = VKD3D_SHADER_BLOCK_IF; - cf_info->inside_block = true; -@@ -1361,17 +1404,15 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info - descriptor_info1 = &local_descriptor_info1; - } - -- vkd3d_shader_scan_context_init(&context, &parser->shader_version, compile_info, -+ vkd3d_shader_scan_context_init(&context, &parser->program.shader_version, compile_info, - descriptor_info1, combined_sampler_info, message_context); - - if (TRACE_ON()) -- { -- vkd3d_shader_trace(&parser->instructions, &parser->shader_version); -- } -+ vkd3d_shader_trace(&parser->program); - -- for (i = 0; i < parser->instructions.count; ++i) -+ for (i = 0; i < parser->program.instructions.count; ++i) - { -- instruction = &parser->instructions.elements[i]; -+ instruction = &parser->program.instructions.elements[i]; - if ((ret = vkd3d_shader_scan_instruction(&context, instruction)) < 0) - break; - } -@@ -1541,17 +1582,16 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, - - scan_info = *compile_info; - -- if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) -- return ret; -- - switch (compile_info->target_type) - { - case VKD3D_SHADER_TARGET_D3D_ASM: -- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); -+ ret = vkd3d_dxbc_binary_to_text(&parser->program, compile_info, out, VSIR_ASM_D3D); - break; - - case VKD3D_SHADER_TARGET_GLSL: -- if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->shader_version, -+ if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) -+ return ret; -+ if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->program.shader_version, - message_context, &parser->location))) - { - ERR("Failed to create GLSL generator.\n"); -@@ -1559,21 +1599,24 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, - return VKD3D_ERROR; - } - -- ret = vkd3d_glsl_generator_generate(glsl_generator, parser, out); -+ ret = vkd3d_glsl_generator_generate(glsl_generator, &parser->program, out); - vkd3d_glsl_generator_destroy(glsl_generator); -+ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); - break; - - case VKD3D_SHADER_TARGET_SPIRV_BINARY: - case VKD3D_SHADER_TARGET_SPIRV_TEXT: -+ if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) -+ return ret; - ret = spirv_compile(parser, &scan_descriptor_info, compile_info, out, message_context); -+ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); - break; - - default: - /* Validation should prevent us from reaching this. */ -- assert(0); -+ vkd3d_unreachable(); - } - -- vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); - return ret; - } - -@@ -1622,14 +1665,10 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_ - return ret; - } - -- if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) -- { -- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); -- vkd3d_shader_parser_destroy(parser); -- return ret; -- } -+ ret = vkd3d_shader_parser_compile(parser, compile_info, out, message_context); - -- return VKD3D_ERROR; -+ vkd3d_shader_parser_destroy(parser); -+ return ret; - } - - static int compile_dxbc_dxil(const struct vkd3d_shader_compile_info *compile_info, -@@ -1903,10 +1942,15 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( - { - VKD3D_SHADER_TARGET_D3D_BYTECODE, - VKD3D_SHADER_TARGET_DXBC_TPF, -+ VKD3D_SHADER_TARGET_FX, - }; - - static const enum vkd3d_shader_target_type d3dbc_types[] = - { -+ VKD3D_SHADER_TARGET_SPIRV_BINARY, -+#ifdef HAVE_SPIRV_TOOLS -+ VKD3D_SHADER_TARGET_SPIRV_TEXT, -+#endif - VKD3D_SHADER_TARGET_D3D_ASM, - }; - -@@ -2043,6 +2087,23 @@ bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *ins - return true; - } - -+bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, -+ unsigned int idx, unsigned int count) -+{ -+ assert(idx <= instructions->count); -+ -+ if (!shader_instruction_array_reserve(instructions, instructions->count + count)) -+ return false; -+ -+ memmove(&instructions->elements[idx + count], &instructions->elements[idx], -+ (instructions->count - idx) * sizeof(*instructions->elements)); -+ memset(&instructions->elements[idx], 0, count * sizeof(*instructions->elements)); -+ -+ instructions->count += count; -+ -+ return true; -+} -+ - bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, - struct vkd3d_shader_immediate_constant_buffer *icb) - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index a93fa7160f7..acfd39b7643 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -91,13 +91,15 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001, - VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING = 2002, - VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003, -- VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004, -+ VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE = 2004, - VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY = 2005, - VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006, - VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007, - VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED = 2008, -+ VKD3D_SHADER_ERROR_SPV_INVALID_SHADER = 2009, - - VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300, -+ VKD3D_SHADER_WARNING_SPV_INVALID_UAV_FLAGS = 2301, - - VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY = 3000, - VKD3D_SHADER_ERROR_RS_INVALID_VERSION = 3001, -@@ -196,6 +198,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306, - VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307, - VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, -+ VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309, - - VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, - VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001, -@@ -213,7 +216,8 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS = 9013, - VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS = 9014, - VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9015, -- VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING = 9016, -+ VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW = 9016, -+ VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017, - - VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, - }; -@@ -221,8 +225,11 @@ enum vkd3d_shader_error - enum vkd3d_shader_opcode - { - VKD3DSIH_ABS, -+ VKD3DSIH_ACOS, - VKD3DSIH_ADD, - VKD3DSIH_AND, -+ VKD3DSIH_ASIN, -+ VKD3DSIH_ATAN, - VKD3DSIH_ATOMIC_AND, - VKD3DSIH_ATOMIC_CMP_STORE, - VKD3DSIH_ATOMIC_IADD, -@@ -235,6 +242,7 @@ enum vkd3d_shader_opcode - VKD3DSIH_BEM, - VKD3DSIH_BFI, - VKD3DSIH_BFREV, -+ VKD3DSIH_BRANCH, - VKD3DSIH_BREAK, - VKD3DSIH_BREAKC, - VKD3DSIH_BREAKP, -@@ -358,10 +366,13 @@ enum vkd3d_shader_opcode - VKD3DSIH_GATHER4_S, - VKD3DSIH_GEO, - VKD3DSIH_GEU, -+ VKD3DSIH_HCOS, - VKD3DSIH_HS_CONTROL_POINT_PHASE, - VKD3DSIH_HS_DECLS, - VKD3DSIH_HS_FORK_PHASE, - VKD3DSIH_HS_JOIN_PHASE, -+ VKD3DSIH_HSIN, -+ VKD3DSIH_HTAN, - VKD3DSIH_IADD, - VKD3DSIH_IBFE, - VKD3DSIH_IDIV, -@@ -388,8 +399,11 @@ enum vkd3d_shader_opcode - VKD3DSIH_IMUL, - VKD3DSIH_INE, - VKD3DSIH_INEG, -+ VKD3DSIH_ISFINITE, - VKD3DSIH_ISHL, - VKD3DSIH_ISHR, -+ VKD3DSIH_ISINF, -+ VKD3DSIH_ISNAN, - VKD3DSIH_ITOD, - VKD3DSIH_ITOF, - VKD3DSIH_ITOI, -@@ -432,6 +446,7 @@ enum vkd3d_shader_opcode - VKD3DSIH_NRM, - VKD3DSIH_OR, - VKD3DSIH_PHASE, -+ VKD3DSIH_PHI, - VKD3DSIH_POW, - VKD3DSIH_RCP, - VKD3DSIH_REP, -@@ -469,7 +484,9 @@ enum vkd3d_shader_opcode - VKD3DSIH_SUB, - VKD3DSIH_SWAPC, - VKD3DSIH_SWITCH, -+ VKD3DSIH_SWITCH_MONOLITHIC, - VKD3DSIH_SYNC, -+ VKD3DSIH_TAN, - VKD3DSIH_TEX, - VKD3DSIH_TEXBEM, - VKD3DSIH_TEXBEML, -@@ -618,6 +635,11 @@ static inline bool data_type_is_bool(enum vkd3d_data_type data_type) - return data_type == VKD3D_DATA_BOOL; - } - -+static inline bool data_type_is_64_bit(enum vkd3d_data_type data_type) -+{ -+ return data_type == VKD3D_DATA_DOUBLE || data_type == VKD3D_DATA_UINT64; -+} -+ - enum vsir_dimension - { - VSIR_DIMENSION_NONE, -@@ -716,6 +738,7 @@ enum vkd3d_shader_sync_flags - { - VKD3DSSF_THREAD_GROUP = 0x1, - VKD3DSSF_GROUP_SHARED_MEMORY = 0x2, -+ VKD3DSSF_THREAD_GROUP_UAV = 0x4, - VKD3DSSF_GLOBAL_UAV = 0x8, - }; - -@@ -740,6 +763,7 @@ enum vkd3d_tessellator_domain - #define VKD3DSI_RESINFO_UINT 0x2 - #define VKD3DSI_SAMPLE_INFO_UINT 0x1 - #define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1 -+#define VKD3DSI_SHIFT_UNMASKED 0x1 - - #define VKD3DSI_PRECISE_X 0x100 - #define VKD3DSI_PRECISE_Y 0x200 -@@ -793,10 +817,12 @@ struct vkd3d_shader_version - - struct vkd3d_shader_immediate_constant_buffer - { -+ unsigned int register_idx; - enum vkd3d_data_type data_type; - /* total count is element_count * component_count */ - unsigned int element_count; - unsigned int component_count; -+ bool is_null; - uint32_t data[]; - }; - -@@ -807,12 +833,13 @@ struct vkd3d_shader_indexable_temp - unsigned int alignment; - enum vkd3d_data_type data_type; - unsigned int component_count; -+ bool has_function_scope; - const struct vkd3d_shader_immediate_constant_buffer *initialiser; - }; - - struct vkd3d_shader_register_index - { -- const struct vkd3d_shader_src_param *rel_addr; -+ struct vkd3d_shader_src_param *rel_addr; - unsigned int offset; - /* address is known to fall within the object (for optimisation) */ - bool is_in_bounds; -@@ -831,10 +858,10 @@ struct vkd3d_shader_register - unsigned int alignment; - union - { -- DWORD immconst_uint[VKD3D_VEC4_SIZE]; -- float immconst_float[VKD3D_VEC4_SIZE]; -- uint64_t immconst_uint64[VKD3D_DVEC2_SIZE]; -- double immconst_double[VKD3D_DVEC2_SIZE]; -+ uint32_t immconst_u32[VKD3D_VEC4_SIZE]; -+ float immconst_f32[VKD3D_VEC4_SIZE]; -+ uint64_t immconst_u64[VKD3D_DVEC2_SIZE]; -+ double immconst_f64[VKD3D_DVEC2_SIZE]; - unsigned fp_body_idx; - } u; - }; -@@ -861,17 +888,23 @@ struct vkd3d_shader_dst_param - { - struct vkd3d_shader_register reg; - uint32_t write_mask; -- DWORD modifiers; -- DWORD shift; -+ uint32_t modifiers; -+ unsigned int shift; - }; - - struct vkd3d_shader_src_param - { - struct vkd3d_shader_register reg; -- DWORD swizzle; -+ uint32_t swizzle; - enum vkd3d_shader_src_modifier modifiers; - }; - -+void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader_register_type reg_type, -+ enum vkd3d_data_type data_type, unsigned int idx_count); -+void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, -+ enum vkd3d_data_type data_type, unsigned int idx_count); -+void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id); -+ - struct vkd3d_shader_index_range - { - struct vkd3d_shader_dst_param dst; -@@ -945,6 +978,9 @@ enum vkd3d_shader_input_sysval_semantic - VKD3D_SIV_LINE_DENSITY_TESS_FACTOR = 22, - }; - -+#define SM1_COLOR_REGISTER_OFFSET 8 -+#define SM1_RASTOUT_REGISTER_OFFSET 10 -+ - #define SIGNATURE_TARGET_LOCATION_UNUSED (~0u) - - struct signature_element -@@ -998,17 +1034,10 @@ struct vkd3d_shader_desc - struct shader_signature output_signature; - struct shader_signature patch_constant_signature; - -- unsigned int input_control_point_count, output_control_point_count; -- -- uint32_t temp_count; -- unsigned int ssa_count; -- - struct - { - uint32_t used, external; - } flat_constant_count[3]; -- -- bool use_vocp; - }; - - struct vkd3d_shader_register_semantic -@@ -1110,11 +1139,11 @@ struct vkd3d_shader_instruction - { - struct vkd3d_shader_location location; - enum vkd3d_shader_opcode handler_idx; -- DWORD flags; -+ uint32_t flags; - unsigned int dst_count; - unsigned int src_count; -- const struct vkd3d_shader_dst_param *dst; -- const struct vkd3d_shader_src_param *src; -+ struct vkd3d_shader_dst_param *dst; -+ struct vkd3d_shader_src_param *src; - struct vkd3d_shader_texel_offset texel_offset; - enum vkd3d_shader_resource_type resource_type; - unsigned int resource_stride; -@@ -1171,6 +1200,32 @@ static inline bool register_is_constant(const struct vkd3d_shader_register *reg) - return (reg->type == VKD3DSPR_IMMCONST || reg->type == VKD3DSPR_IMMCONST64); - } - -+static inline bool register_is_undef(const struct vkd3d_shader_register *reg) -+{ -+ return reg->type == VKD3DSPR_UNDEF; -+} -+ -+static inline bool register_is_constant_or_undef(const struct vkd3d_shader_register *reg) -+{ -+ return register_is_constant(reg) || register_is_undef(reg); -+} -+ -+static inline bool register_is_scalar_constant_zero(const struct vkd3d_shader_register *reg) -+{ -+ return register_is_constant(reg) && reg->dimension == VSIR_DIMENSION_SCALAR -+ && (data_type_is_64_bit(reg->data_type) ? !reg->u.immconst_u64[0] : !reg->u.immconst_u32[0]); -+} -+ -+static inline bool vsir_register_is_label(const struct vkd3d_shader_register *reg) -+{ -+ return reg->type == VKD3DSPR_LABEL; -+} -+ -+static inline bool register_is_ssa(const struct vkd3d_shader_register *reg) -+{ -+ return reg->type == VKD3DSPR_SSA; -+} -+ - struct vkd3d_shader_param_node - { - struct vkd3d_shader_param_node *next; -@@ -1217,6 +1272,8 @@ struct vkd3d_shader_instruction_array - - bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); - bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); -+bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, -+ unsigned int idx, unsigned int count); - bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, - struct vkd3d_shader_immediate_constant_buffer *icb); - bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, -@@ -1228,6 +1285,36 @@ enum vkd3d_shader_config_flags - VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION = 0x00000001, - }; - -+struct vsir_program -+{ -+ struct vkd3d_shader_version shader_version; -+ struct vkd3d_shader_instruction_array instructions; -+ -+ unsigned int input_control_point_count, output_control_point_count; -+ unsigned int block_count; -+ unsigned int temp_count; -+ unsigned int ssa_count; -+ bool use_vocp; -+ -+ const char **block_names; -+ size_t block_name_count; -+}; -+ -+bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve); -+void vsir_program_cleanup(struct vsir_program *program); -+ -+static inline struct vkd3d_shader_dst_param *vsir_program_get_dst_params( -+ struct vsir_program *program, unsigned int count) -+{ -+ return shader_dst_param_allocator_get(&program->instructions.dst_params, count); -+} -+ -+static inline struct vkd3d_shader_src_param *vsir_program_get_src_params( -+ struct vsir_program *program, unsigned int count) -+{ -+ return shader_src_param_allocator_get(&program->instructions.src_params, count); -+} -+ - struct vkd3d_shader_parser - { - struct vkd3d_shader_message_context *message_context; -@@ -1235,9 +1322,8 @@ struct vkd3d_shader_parser - bool failed; - - struct vkd3d_shader_desc shader_desc; -- struct vkd3d_shader_version shader_version; - const struct vkd3d_shader_parser_ops *ops; -- struct vkd3d_shader_instruction_array instructions; -+ struct vsir_program program; - - uint64_t config_flags; - }; -@@ -1256,18 +1342,6 @@ bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, - void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, - enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); - --static inline struct vkd3d_shader_dst_param *shader_parser_get_dst_params( -- struct vkd3d_shader_parser *parser, unsigned int count) --{ -- return shader_dst_param_allocator_get(&parser->instructions.dst_params, count); --} -- --static inline struct vkd3d_shader_src_param *shader_parser_get_src_params( -- struct vkd3d_shader_parser *parser, unsigned int count) --{ -- return shader_src_param_allocator_get(&parser->instructions.src_params, count); --} -- - static inline void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser) - { - parser->ops->parser_destroy(parser); -@@ -1286,6 +1360,7 @@ struct vkd3d_shader_descriptor_info1 - unsigned int buffer_size; - unsigned int structure_stride; - unsigned int count; -+ uint32_t uav_flags; - }; - - struct vkd3d_shader_scan_descriptor_info1 -@@ -1294,8 +1369,7 @@ struct vkd3d_shader_scan_descriptor_info1 - unsigned int descriptor_count; - }; - --void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instructions, -- const struct vkd3d_shader_version *shader_version); -+void vkd3d_shader_trace(const struct vsir_program *program); - - const char *shader_get_type_prefix(enum vkd3d_shader_type type); - -@@ -1311,9 +1385,15 @@ struct vkd3d_string_buffer_cache - size_t count, max_count, capacity; - }; - --enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, -- const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info, -- struct vkd3d_shader_code *out); -+enum vsir_asm_dialect -+{ -+ VSIR_ASM_VSIR, -+ VSIR_ASM_D3D, -+}; -+ -+enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, -+ const struct vkd3d_shader_compile_info *compile_info, -+ struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect); - void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); - struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list); - void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer); -@@ -1338,7 +1418,9 @@ struct vkd3d_bytecode_buffer - /* Align to the next 4-byte offset, and return that offset. */ - size_t bytecode_align(struct vkd3d_bytecode_buffer *buffer); - size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size); -+size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size); - void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value); -+void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length); - - static inline size_t put_u32(struct vkd3d_bytecode_buffer *buffer, uint32_t value) - { -@@ -1382,6 +1464,8 @@ void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const str - enum vkd3d_shader_error error, const char *format, va_list args); - void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, - enum vkd3d_shader_log_level level, const char *format, va_list args); -+void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, -+ enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(4, 5); - void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, - enum vkd3d_shader_error error, const char *format, va_list args); - -@@ -1409,7 +1493,7 @@ struct vkd3d_glsl_generator; - struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version, - struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location); - int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, -- struct vkd3d_shader_parser *parser, struct vkd3d_shader_code *out); -+ struct vsir_program *program, struct vkd3d_shader_code *out); - void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator); - - #define SPIRV_MAX_SRC_COUNT 6 -@@ -1427,7 +1511,7 @@ 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); -+enum vkd3d_result 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) -@@ -1444,6 +1528,8 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty - return VKD3D_SHADER_COMPONENT_INT; - case VKD3D_DATA_DOUBLE: - return VKD3D_SHADER_COMPONENT_DOUBLE; -+ case VKD3D_DATA_UINT64: -+ return VKD3D_SHADER_COMPONENT_UINT64; - case VKD3D_DATA_BOOL: - return VKD3D_SHADER_COMPONENT_BOOL; - default: -@@ -1505,7 +1591,7 @@ static inline enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum - return vkd3d_siv_from_sysval_indexed(sysval, 0); - } - --static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask) -+static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask) - { - unsigned int i; - -@@ -1520,7 +1606,7 @@ static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask) - return 0; - } - --static inline unsigned int vkd3d_write_mask_component_count(DWORD write_mask) -+static inline unsigned int vsir_write_mask_component_count(uint32_t write_mask) - { - unsigned int count = vkd3d_popcount(write_mask & VKD3DSP_WRITEMASK_ALL); - assert(1 <= count && count <= VKD3D_VEC4_SIZE); -@@ -1533,32 +1619,94 @@ static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int co - return (VKD3DSP_WRITEMASK_0 << component_count) - 1; - } - --static inline unsigned int vkd3d_write_mask_64_from_32(DWORD write_mask32) -+static inline uint32_t vsir_write_mask_64_from_32(uint32_t write_mask32) - { -- unsigned int write_mask64 = write_mask32 | (write_mask32 >> 1); -- return (write_mask64 & VKD3DSP_WRITEMASK_0) | ((write_mask64 & VKD3DSP_WRITEMASK_2) >> 1); -+ switch (write_mask32) -+ { -+ case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1: -+ return VKD3DSP_WRITEMASK_0; -+ -+ case VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3: -+ return VKD3DSP_WRITEMASK_1; -+ -+ case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3: -+ return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; -+ -+ default: -+ ERR("Invalid 32 bit writemask when converting to 64 bit: %#x.\n", write_mask32); -+ return VKD3DSP_WRITEMASK_0; -+ } - } - --static inline unsigned int vkd3d_write_mask_32_from_64(unsigned int write_mask64) -+static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) - { -- unsigned int write_mask32 = (write_mask64 | (write_mask64 << 1)) -- & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_2); -- return write_mask32 | (write_mask32 << 1); -+ switch (write_mask64) -+ { -+ case VKD3DSP_WRITEMASK_0: -+ return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; -+ -+ case VKD3DSP_WRITEMASK_1: -+ return VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; -+ -+ case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1: -+ return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; -+ -+ default: -+ ERR("Invalid 64 bit writemask: %#x.\n", write_mask64); -+ return VKD3DSP_WRITEMASK_0; -+ } - } - --static inline unsigned int vkd3d_swizzle_get_component(DWORD swizzle, -- unsigned int idx) -+static inline uint32_t vsir_swizzle_64_from_32(uint32_t swizzle32) - { -- return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; -+ switch (swizzle32) -+ { -+ case VKD3D_SHADER_SWIZZLE(X, Y, X, Y): -+ return VKD3D_SHADER_SWIZZLE(X, X, X, X); -+ -+ case VKD3D_SHADER_SWIZZLE(X, Y, Z, W): -+ return VKD3D_SHADER_SWIZZLE(X, Y, X, X); -+ -+ case VKD3D_SHADER_SWIZZLE(Z, W, X, Y): -+ return VKD3D_SHADER_SWIZZLE(Y, X, X, X); -+ -+ case VKD3D_SHADER_SWIZZLE(Z, W, Z, W): -+ return VKD3D_SHADER_SWIZZLE(Y, Y, X, X); -+ -+ default: -+ ERR("Invalid 32 bit swizzle when converting to 64 bit: %#x.\n", swizzle32); -+ return VKD3D_SHADER_SWIZZLE(X, X, X, X); -+ } - } - --static inline unsigned int vkd3d_swizzle_get_component64(DWORD swizzle, -- unsigned int idx) -+static inline uint32_t vsir_swizzle_32_from_64(uint32_t swizzle64) - { -- return ((swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx * 2)) & VKD3D_SHADER_SWIZZLE_MASK) / 2u; -+ switch (swizzle64) -+ { -+ case VKD3D_SHADER_SWIZZLE(X, X, X, X): -+ return VKD3D_SHADER_SWIZZLE(X, Y, X, Y); -+ -+ case VKD3D_SHADER_SWIZZLE(X, Y, X, X): -+ return VKD3D_SHADER_SWIZZLE(X, Y, Z, W); -+ -+ case VKD3D_SHADER_SWIZZLE(Y, X, X, X): -+ return VKD3D_SHADER_SWIZZLE(Z, W, X, Y); -+ -+ case VKD3D_SHADER_SWIZZLE(Y, Y, X, X): -+ return VKD3D_SHADER_SWIZZLE(Z, W, Z, W); -+ -+ default: -+ ERR("Invalid 64 bit swizzle: %#x.\n", swizzle64); -+ return VKD3D_SHADER_SWIZZLE(X, Y, X, Y); -+ } -+} -+ -+static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx) -+{ -+ return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; - } - --static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned int write_mask) -+static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask) - { - unsigned int i, compacted_swizzle = 0; - -@@ -1567,7 +1715,7 @@ static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - { - compacted_swizzle <<= VKD3D_SHADER_SWIZZLE_SHIFT(1); -- compacted_swizzle |= vkd3d_swizzle_get_component(swizzle, i); -+ compacted_swizzle |= vsir_swizzle_get_component(swizzle, i); - } - } - -diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c -index 15c8317b191..8a47dc494f7 100644 ---- a/libs/vkd3d/libs/vkd3d/command.c -+++ b/libs/vkd3d/libs/vkd3d/command.c -@@ -313,7 +313,7 @@ static void vkd3d_wait_for_gpu_fence(struct vkd3d_fence_worker *worker, - - TRACE("Signaling fence %p value %#"PRIx64".\n", waiting_fence->fence, waiting_fence->value); - if (FAILED(hr = d3d12_fence_signal(waiting_fence->fence, waiting_fence->value, waiting_fence->u.vk_fence, false))) -- ERR("Failed to signal D3D12 fence, hr %#x.\n", hr); -+ ERR("Failed to signal d3d12 fence, hr %s.\n", debugstr_hresult(hr)); - - d3d12_fence_decref(waiting_fence->fence); - -@@ -926,7 +926,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_QueryInterface(ID3D12Fence1 *iface, - static ULONG STDMETHODCALLTYPE d3d12_fence_AddRef(ID3D12Fence1 *iface) - { - struct d3d12_fence *fence = impl_from_ID3D12Fence1(iface); -- ULONG refcount = InterlockedIncrement(&fence->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&fence->refcount); - - TRACE("%p increasing refcount to %u.\n", fence, refcount); - -@@ -935,13 +935,13 @@ static ULONG STDMETHODCALLTYPE d3d12_fence_AddRef(ID3D12Fence1 *iface) - - static void d3d12_fence_incref(struct d3d12_fence *fence) - { -- InterlockedIncrement(&fence->internal_refcount); -+ vkd3d_atomic_increment_u32(&fence->internal_refcount); - } - - static ULONG STDMETHODCALLTYPE d3d12_fence_Release(ID3D12Fence1 *iface) - { - struct d3d12_fence *fence = impl_from_ID3D12Fence1(iface); -- ULONG refcount = InterlockedDecrement(&fence->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&fence->refcount); - - TRACE("%p decreasing refcount to %u.\n", fence, refcount); - -@@ -953,24 +953,24 @@ static ULONG STDMETHODCALLTYPE d3d12_fence_Release(ID3D12Fence1 *iface) - - static void d3d12_fence_decref(struct d3d12_fence *fence) - { -- ULONG internal_refcount = InterlockedDecrement(&fence->internal_refcount); -+ struct d3d12_device *device; - -- if (!internal_refcount) -- { -- struct d3d12_device *device = fence->device; -+ if (vkd3d_atomic_decrement_u32(&fence->internal_refcount)) -+ return; - -- vkd3d_private_store_destroy(&fence->private_store); -+ device = fence->device; - -- d3d12_fence_destroy_vk_objects(fence); -+ vkd3d_private_store_destroy(&fence->private_store); - -- vkd3d_free(fence->events); -- vkd3d_free(fence->semaphores); -- vkd3d_mutex_destroy(&fence->mutex); -- vkd3d_cond_destroy(&fence->null_event_cond); -- vkd3d_free(fence); -+ d3d12_fence_destroy_vk_objects(fence); - -- d3d12_device_release(device); -- } -+ vkd3d_free(fence->events); -+ vkd3d_free(fence->semaphores); -+ vkd3d_mutex_destroy(&fence->mutex); -+ vkd3d_cond_destroy(&fence->null_event_cond); -+ vkd3d_free(fence); -+ -+ d3d12_device_release(device); - } - - static HRESULT STDMETHODCALLTYPE d3d12_fence_GetPrivateData(ID3D12Fence1 *iface, -@@ -1635,7 +1635,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_QueryInterface(ID3D12Co - static ULONG STDMETHODCALLTYPE d3d12_command_allocator_AddRef(ID3D12CommandAllocator *iface) - { - struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface); -- ULONG refcount = InterlockedIncrement(&allocator->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&allocator->refcount); - - TRACE("%p increasing refcount to %u.\n", allocator, refcount); - -@@ -1645,7 +1645,7 @@ static ULONG STDMETHODCALLTYPE d3d12_command_allocator_AddRef(ID3D12CommandAlloc - static ULONG STDMETHODCALLTYPE d3d12_command_allocator_Release(ID3D12CommandAllocator *iface) - { - struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface); -- ULONG refcount = InterlockedDecrement(&allocator->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&allocator->refcount); - - TRACE("%p decreasing refcount to %u.\n", allocator, refcount); - -@@ -1921,12 +1921,12 @@ HRESULT d3d12_command_allocator_create(struct d3d12_device *device, - - static void d3d12_command_signature_incref(struct d3d12_command_signature *signature) - { -- vkd3d_atomic_increment(&signature->internal_refcount); -+ vkd3d_atomic_increment_u32(&signature->internal_refcount); - } - - static void d3d12_command_signature_decref(struct d3d12_command_signature *signature) - { -- unsigned int refcount = vkd3d_atomic_decrement(&signature->internal_refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&signature->internal_refcount); - - if (!refcount) - { -@@ -2320,7 +2320,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(ID3D12Graphic - static ULONG STDMETHODCALLTYPE d3d12_command_list_AddRef(ID3D12GraphicsCommandList5 *iface) - { - struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList5(iface); -- ULONG refcount = InterlockedIncrement(&list->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&list->refcount); - - TRACE("%p increasing refcount to %u.\n", list, refcount); - -@@ -2335,7 +2335,7 @@ static void vkd3d_pipeline_bindings_cleanup(struct vkd3d_pipeline_bindings *bind - static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(ID3D12GraphicsCommandList5 *iface) - { - struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList5(iface); -- ULONG refcount = InterlockedDecrement(&list->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&list->refcount); - - TRACE("%p decreasing refcount to %u.\n", list, refcount); - -@@ -2644,6 +2644,8 @@ static bool d3d12_command_list_update_compute_pipeline(struct d3d12_command_list - { - const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; - -+ vkd3d_cond_signal(&list->device->worker_cond); -+ - if (list->current_pipeline != VK_NULL_HANDLE) - return true; - -@@ -2665,6 +2667,8 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis - VkRenderPass vk_render_pass; - VkPipeline vk_pipeline; - -+ vkd3d_cond_signal(&list->device->worker_cond); -+ - if (list->current_pipeline != VK_NULL_HANDLE) - return true; - -@@ -3266,7 +3270,8 @@ static void d3d12_command_list_bind_descriptor_heap(struct d3d12_command_list *l - { - VkDescriptorSet vk_descriptor_set = heap->vk_descriptor_sets[set].vk_set; - -- if (!vk_descriptor_set) -+ /* Null vk_set_layout means set 0 uses mutable descriptors, and this set is unused. */ -+ if (!vk_descriptor_set || !list->device->vk_descriptor_heap_layouts[set].vk_set_layout) - continue; - - VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point, rs->vk_pipeline_layout, -@@ -3701,7 +3706,7 @@ static void d3d12_command_list_copy_incompatible_texture_region(struct d3d12_com - buffer_image_copy.imageExtent.height * buffer_image_copy.imageExtent.depth * layer_count; - if (FAILED(hr = d3d12_command_list_allocate_transfer_buffer(list, buffer_size, &transfer_buffer))) - { -- ERR("Failed to allocate transfer buffer, hr %#x.\n", hr); -+ ERR("Failed to allocate transfer buffer, hr %s.\n", debugstr_hresult(hr)); - return; - } - -@@ -4494,8 +4499,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_SetComputeRootDescriptorTable(I - { - struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList5(iface); - -- TRACE("iface %p, root_parameter_index %u, base_descriptor %#"PRIx64".\n", -- iface, root_parameter_index, base_descriptor.ptr); -+ TRACE("iface %p, root_parameter_index %u, base_descriptor %s.\n", -+ iface, root_parameter_index, debug_gpu_handle(base_descriptor)); - - d3d12_command_list_set_descriptor_table(list, VKD3D_PIPELINE_BIND_POINT_COMPUTE, - root_parameter_index, base_descriptor); -@@ -4506,8 +4511,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRootDescriptorTable( - { - struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList5(iface); - -- TRACE("iface %p, root_parameter_index %u, base_descriptor %#"PRIx64".\n", -- iface, root_parameter_index, base_descriptor.ptr); -+ TRACE("iface %p, root_parameter_index %u, base_descriptor %s.\n", -+ iface, root_parameter_index, debug_gpu_handle(base_descriptor)); - - d3d12_command_list_set_descriptor_table(list, VKD3D_PIPELINE_BIND_POINT_GRAPHICS, - root_parameter_index, base_descriptor); -@@ -5127,8 +5132,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearDepthStencilView(ID3D12Gra - struct VkAttachmentDescription attachment_desc; - struct VkAttachmentReference ds_reference; - -- TRACE("iface %p, dsv %#lx, flags %#x, depth %.8e, stencil 0x%02x, rect_count %u, rects %p.\n", -- iface, dsv.ptr, flags, depth, stencil, rect_count, rects); -+ TRACE("iface %p, dsv %s, flags %#x, depth %.8e, stencil 0x%02x, rect_count %u, rects %p.\n", -+ iface, debug_cpu_handle(dsv), flags, depth, stencil, rect_count, rects); - - d3d12_command_list_track_resource_usage(list, dsv_desc->resource); - -@@ -5175,8 +5180,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12Gra - struct VkAttachmentReference color_reference; - VkClearValue clear_value; - -- TRACE("iface %p, rtv %#lx, color %p, rect_count %u, rects %p.\n", -- iface, rtv.ptr, color, rect_count, rects); -+ TRACE("iface %p, rtv %s, color %p, rect_count %u, rects %p.\n", -+ iface, debug_cpu_handle(rtv), color, rect_count, rects); - - d3d12_command_list_track_resource_usage(list, rtv_desc->resource); - -@@ -5427,8 +5432,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID - struct d3d12_resource *resource_impl; - VkClearColorValue colour; - -- TRACE("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p.\n", -- iface, gpu_handle.ptr, cpu_handle.ptr, resource, values, rect_count, rects); -+ TRACE("iface %p, gpu_handle %s, cpu_handle %s, resource %p, values %p, rect_count %u, rects %p.\n", -+ iface, debug_gpu_handle(gpu_handle), debug_cpu_handle(cpu_handle), resource, values, rect_count, rects); - - resource_impl = unsafe_impl_from_ID3D12Resource(resource); - if (!(descriptor = d3d12_desc_from_cpu_handle(cpu_handle)->s.u.view)) -@@ -5491,8 +5496,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewFloat(I - VkClearColorValue colour; - struct vkd3d_view *view; - -- TRACE("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p.\n", -- iface, gpu_handle.ptr, cpu_handle.ptr, resource, values, rect_count, rects); -+ TRACE("iface %p, gpu_handle %s, cpu_handle %s, resource %p, values %p, rect_count %u, rects %p.\n", -+ iface, debug_gpu_handle(gpu_handle), debug_cpu_handle(cpu_handle), resource, values, rect_count, rects); - - resource_impl = unsafe_impl_from_ID3D12Resource(resource); - if (!(view = d3d12_desc_from_cpu_handle(cpu_handle)->s.u.view)) -@@ -5958,15 +5963,15 @@ static void STDMETHODCALLTYPE d3d12_command_list_EndRenderPass(ID3D12GraphicsCom - static void STDMETHODCALLTYPE d3d12_command_list_InitializeMetaCommand(ID3D12GraphicsCommandList5 *iface, - ID3D12MetaCommand *meta_command, const void *parameters_data, SIZE_T data_size_in_bytes) - { -- FIXME("iface %p, meta_command %p, parameters_data %p, data_size_in_bytes %lu stub!\n", iface, -- meta_command, parameters_data, data_size_in_bytes); -+ FIXME("iface %p, meta_command %p, parameters_data %p, data_size_in_bytes %"PRIuPTR" stub!\n", iface, -+ meta_command, parameters_data, (uintptr_t)data_size_in_bytes); - } - - static void STDMETHODCALLTYPE d3d12_command_list_ExecuteMetaCommand(ID3D12GraphicsCommandList5 *iface, - ID3D12MetaCommand *meta_command, const void *parameters_data, SIZE_T data_size_in_bytes) - { -- FIXME("iface %p, meta_command %p, parameters_data %p, data_size_in_bytes %lu stub!\n", iface, -- meta_command, parameters_data, data_size_in_bytes); -+ FIXME("iface %p, meta_command %p, parameters_data %p, data_size_in_bytes %"PRIuPTR" stub!\n", iface, -+ meta_command, parameters_data, (uintptr_t)data_size_in_bytes); - } - - static void STDMETHODCALLTYPE d3d12_command_list_BuildRaytracingAccelerationStructure(ID3D12GraphicsCommandList5 *iface, -@@ -6225,7 +6230,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_QueryInterface(ID3D12Comman - static ULONG STDMETHODCALLTYPE d3d12_command_queue_AddRef(ID3D12CommandQueue *iface) - { - struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface); -- ULONG refcount = InterlockedIncrement(&command_queue->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&command_queue->refcount); - - TRACE("%p increasing refcount to %u.\n", command_queue, refcount); - -@@ -6267,7 +6272,7 @@ static void d3d12_command_queue_op_array_destroy(struct d3d12_command_queue_op_a - static ULONG STDMETHODCALLTYPE d3d12_command_queue_Release(ID3D12CommandQueue *iface) - { - struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface); -- ULONG refcount = InterlockedDecrement(&command_queue->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&command_queue->refcount); - - TRACE("%p decreasing refcount to %u.\n", command_queue, refcount); - -@@ -6508,7 +6513,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command - if (!(op = d3d12_command_queue_op_array_require_space(&command_queue->op_queue))) - { - ERR("Failed to add op.\n"); -- return; -+ goto unlock_mutex; - } - op->opcode = VKD3D_CS_OP_COPY_MAPPINGS; - op->u.copy_mappings.dst_resource = dst_resource_impl; -@@ -6520,6 +6525,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command - - d3d12_command_queue_submit_locked(command_queue); - -+unlock_mutex: - vkd3d_mutex_unlock(&command_queue->op_mutex); - } - -@@ -6558,7 +6564,7 @@ static void d3d12_command_queue_submit_locked(struct d3d12_command_queue *queue) - if (queue->op_queue.count == 1 && !queue->is_flushing) - { - if (FAILED(hr = d3d12_command_queue_flush_ops_locked(queue, &flushed_any))) -- ERR("Cannot flush queue, hr %#x.\n", hr); -+ ERR("Failed to flush queue, hr %s.\n", debugstr_hresult(hr)); - } - } - -@@ -7436,7 +7442,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_signature_QueryInterface(ID3D12Co - static ULONG STDMETHODCALLTYPE d3d12_command_signature_AddRef(ID3D12CommandSignature *iface) - { - struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface); -- ULONG refcount = InterlockedIncrement(&signature->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&signature->refcount); - - TRACE("%p increasing refcount to %u.\n", signature, refcount); - -@@ -7446,7 +7452,7 @@ static ULONG STDMETHODCALLTYPE d3d12_command_signature_AddRef(ID3D12CommandSigna - static ULONG STDMETHODCALLTYPE d3d12_command_signature_Release(ID3D12CommandSignature *iface) - { - struct d3d12_command_signature *signature = impl_from_ID3D12CommandSignature(iface); -- ULONG refcount = InterlockedDecrement(&signature->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&signature->refcount); - - TRACE("%p decreasing refcount to %u.\n", signature, refcount); - -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 5c801ca4676..90272818b3d 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -94,9 +94,11 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = - VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), - VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable), - VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), -+ VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type), - VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), - VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), - VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), -+ VK_EXTENSION(EXT_SHADER_VIEWPORT_INDEX_LAYER, EXT_shader_viewport_index_layer), - VK_EXTENSION(EXT_TEXEL_BUFFER_ALIGNMENT, EXT_texel_buffer_alignment), - VK_EXTENSION(EXT_TRANSFORM_FEEDBACK, EXT_transform_feedback), - VK_EXTENSION(EXT_VERTEX_ATTRIBUTE_DIVISOR, EXT_vertex_attribute_divisor), -@@ -106,13 +108,32 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic - { - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - VkDescriptorSetLayoutBindingFlagsCreateInfoEXT flags_info; -+ VkMutableDescriptorTypeCreateInfoEXT mutable_info; -+ VkMutableDescriptorTypeListEXT type_list; - VkDescriptorSetLayoutCreateInfo set_desc; - VkDescriptorBindingFlagsEXT set_flags; - VkDescriptorSetLayoutBinding binding; - VkResult vr; - -+ static const VkDescriptorType descriptor_types[] = -+ { -+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, -+ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, -+ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, -+ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, -+ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, -+ }; -+ -+ if (device->vk_info.EXT_mutable_descriptor_type && index && index != VKD3D_SET_INDEX_UAV_COUNTER -+ && device->vk_descriptor_heap_layouts[index].applicable_heap_type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) -+ { -+ device->vk_descriptor_heap_layouts[index].vk_set_layout = VK_NULL_HANDLE; -+ return S_OK; -+ } -+ - binding.binding = 0; -- binding.descriptorType = device->vk_descriptor_heap_layouts[index].type; -+ binding.descriptorType = (device->vk_info.EXT_mutable_descriptor_type && !index) -+ ? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[index].type; - binding.descriptorCount = device->vk_descriptor_heap_layouts[index].count; - binding.stageFlags = VK_SHADER_STAGE_ALL; - binding.pImmutableSamplers = NULL; -@@ -132,6 +153,17 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic - flags_info.bindingCount = 1; - flags_info.pBindingFlags = &set_flags; - -+ if (binding.descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_EXT) -+ { -+ type_list.descriptorTypeCount = ARRAY_SIZE(descriptor_types); -+ type_list.pDescriptorTypes = descriptor_types; -+ mutable_info.sType = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT; -+ mutable_info.pNext = NULL; -+ mutable_info.mutableDescriptorTypeListCount = 1; -+ mutable_info.pMutableDescriptorTypeLists = &type_list; -+ flags_info.pNext = &mutable_info; -+ } -+ - if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device->vk_device, &set_desc, NULL, - &device->vk_descriptor_heap_layouts[index].vk_set_layout))) < 0) - { -@@ -562,7 +594,7 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance, - - if (FAILED(hr = vkd3d_init_vk_global_procs(instance, create_info->pfn_vkGetInstanceProcAddr))) - { -- ERR("Failed to initialize Vulkan global procs, hr %#x.\n", hr); -+ ERR("Failed to initialise Vulkan global procs, hr %s.\n", debugstr_hresult(hr)); - return hr; - } - -@@ -642,7 +674,7 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance, - - if (FAILED(hr = vkd3d_load_vk_instance_procs(&instance->vk_procs, vk_global_procs, vk_instance))) - { -- ERR("Failed to load instance procs, hr %#x.\n", hr); -+ ERR("Failed to load instance procs, hr %s.\n", debugstr_hresult(hr)); - if (instance->vk_procs.vkDestroyInstance) - instance->vk_procs.vkDestroyInstance(vk_instance, NULL); - if (instance->libvulkan) -@@ -718,7 +750,7 @@ static void vkd3d_destroy_instance(struct vkd3d_instance *instance) - - ULONG vkd3d_instance_incref(struct vkd3d_instance *instance) - { -- ULONG refcount = InterlockedIncrement(&instance->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&instance->refcount); - - TRACE("%p increasing refcount to %u.\n", instance, refcount); - -@@ -727,7 +759,7 @@ ULONG vkd3d_instance_incref(struct vkd3d_instance *instance) - - ULONG vkd3d_instance_decref(struct vkd3d_instance *instance) - { -- ULONG refcount = InterlockedDecrement(&instance->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&instance->refcount); - - TRACE("%p decreasing refcount to %u.\n", instance, refcount); - -@@ -763,6 +795,7 @@ struct vkd3d_physical_device_info - VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features; - VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features; - VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timeline_semaphore_features; -+ VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT mutable_features; - - VkPhysicalDeviceFeatures2 features2; - }; -@@ -780,6 +813,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i - VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features; - VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features; - VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *timeline_semaphore_features; -+ VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *mutable_features; - VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_features; - VkPhysicalDeviceMaintenance3Properties *maintenance3_properties; - VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb_properties; -@@ -800,6 +834,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i - vertex_divisor_features = &info->vertex_divisor_features; - vertex_divisor_properties = &info->vertex_divisor_properties; - timeline_semaphore_features = &info->timeline_semaphore_features; -+ mutable_features = &info->mutable_features; - xfb_features = &info->xfb_features; - xfb_properties = &info->xfb_properties; - -@@ -823,6 +858,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i - vk_prepend_struct(&info->features2, vertex_divisor_features); - timeline_semaphore_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR; - vk_prepend_struct(&info->features2, timeline_semaphore_features); -+ mutable_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT; -+ vk_prepend_struct(&info->features2, mutable_features); - - if (vulkan_info->KHR_get_physical_device_properties2) - VK_CALL(vkGetPhysicalDeviceFeatures2KHR(physical_device, &info->features2)); -@@ -1510,8 +1547,6 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, - device->feature_options.StandardSwizzle64KBSupported = FALSE; - device->feature_options.CrossNodeSharingTier = D3D12_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED; - device->feature_options.CrossAdapterRowMajorTextureSupported = FALSE; -- /* SPV_EXT_shader_viewport_index_layer */ -- device->feature_options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = FALSE; - device->feature_options.ResourceHeapTier = D3D12_RESOURCE_HEAP_TIER_2; - - /* Shader Model 6 support. */ -@@ -1594,6 +1629,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, - vulkan_info->EXT_shader_demote_to_helper_invocation = false; - if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment) - vulkan_info->EXT_texel_buffer_alignment = false; -+ if (!physical_device_info->mutable_features.mutableDescriptorType) -+ vulkan_info->EXT_mutable_descriptor_type = false; - if (!physical_device_info->timeline_semaphore_features.timelineSemaphore) - vulkan_info->KHR_timeline_semaphore = false; - -@@ -1615,6 +1652,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, - vkd3d_free(vk_extensions); - - device->feature_options.PSSpecifiedStencilRefSupported = vulkan_info->EXT_shader_stencil_export; -+ device->feature_options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = -+ vulkan_info->EXT_shader_viewport_index_layer; - - vkd3d_init_feature_level(vulkan_info, features, &device->feature_options); - if (vulkan_info->max_feature_level < create_info->minimum_feature_level) -@@ -1640,6 +1679,10 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, - vulkan_info->shader_extensions[vulkan_info->shader_extension_count++] - = VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT; - -+ if (vulkan_info->EXT_shader_viewport_index_layer) -+ vulkan_info->shader_extensions[vulkan_info->shader_extension_count++] -+ = VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER; -+ - /* Disable unused Vulkan features. */ - features->shaderTessellationAndGeometryPointSize = VK_FALSE; - -@@ -1926,7 +1969,7 @@ static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance, - * which applies to resources of a total size of 4 MiB or less. */ - static bool d3d12_is_64k_msaa_supported(struct d3d12_device *device) - { -- D3D12_RESOURCE_ALLOCATION_INFO info; -+ struct vkd3d_resource_allocation_info info; - D3D12_RESOURCE_DESC resource_desc; - - memset(&resource_desc, 0, sizeof(resource_desc)); -@@ -1943,7 +1986,7 @@ static bool d3d12_is_64k_msaa_supported(struct d3d12_device *device) - * resources, which must have 0x10000 in their description, so we might - * reasonably return true here for 0x20000 or 0x40000. */ - return SUCCEEDED(vkd3d_get_image_allocation_info(device, &resource_desc, &info)) -- && info.Alignment <= 0x10000; -+ && info.alignment <= 0x10000; - } - - static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, -@@ -2028,7 +2071,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, - - if (FAILED(hr = vkd3d_load_vk_device_procs(&device->vk_procs, vk_procs, vk_device))) - { -- ERR("Failed to load device procs, hr %#x.\n", hr); -+ ERR("Failed to load device procs, hr %s.\n", debugstr_hresult(hr)); - if (device->vk_procs.vkDestroyDevice) - device->vk_procs.vkDestroyDevice(vk_device, NULL); - return hr; -@@ -2038,7 +2081,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, - - if (FAILED(hr = d3d12_device_create_vkd3d_queues(device, &device_queue_info))) - { -- ERR("Failed to create queues, hr %#x.\n", hr); -+ ERR("Failed to create queues, hr %s.\n", debugstr_hresult(hr)); - device->vk_procs.vkDestroyDevice(vk_device, NULL); - return hr; - } -@@ -2056,7 +2099,7 @@ static HRESULT d3d12_device_init_pipeline_cache(struct d3d12_device *device) - VkPipelineCacheCreateInfo cache_info; - VkResult vr; - -- vkd3d_mutex_init(&device->mutex); -+ vkd3d_mutex_init(&device->pipeline_cache_mutex); - - cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - cache_info.pNext = NULL; -@@ -2080,7 +2123,7 @@ static void d3d12_device_destroy_pipeline_cache(struct d3d12_device *device) - if (device->vk_pipeline_cache) - VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL)); - -- vkd3d_mutex_destroy(&device->mutex); -+ vkd3d_mutex_destroy(&device->pipeline_cache_mutex); - } - - #define VKD3D_VA_FALLBACK_BASE 0x8000000000000000ull -@@ -2090,7 +2133,7 @@ static void d3d12_device_destroy_pipeline_cache(struct d3d12_device *device) - #define VKD3D_VA_SLAB_COUNT (64 * 1024) - - static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_slab(struct vkd3d_gpu_va_allocator *allocator, -- size_t aligned_size, void *ptr) -+ uint64_t aligned_size, void *ptr) - { - struct vkd3d_gpu_va_slab *slab; - D3D12_GPU_VIRTUAL_ADDRESS address; -@@ -2106,13 +2149,13 @@ static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_slab(struct vkd - slab_idx = slab - allocator->slabs; - address = VKD3D_VA_SLAB_BASE + slab_idx * VKD3D_VA_SLAB_SIZE; - -- TRACE("Allocated address %#"PRIx64", slab %u, size %zu.\n", address, slab_idx, aligned_size); -+ TRACE("Allocated address %#"PRIx64", slab %u, size %"PRIu64".\n", address, slab_idx, aligned_size); - - return address; - } - - static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_fallback(struct vkd3d_gpu_va_allocator *allocator, -- size_t alignment, size_t aligned_size, void *ptr) -+ size_t alignment, uint64_t aligned_size, void *ptr) - { - struct vkd3d_gpu_va_allocation *allocation; - D3D12_GPU_VIRTUAL_ADDRESS base, ceiling; -@@ -2138,17 +2181,17 @@ static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_fallback(struct - * only fail once we have exhausted 63 bits of address space. */ - allocator->fallback_floor = base + aligned_size; - -- TRACE("Allocated address %#"PRIx64", size %zu.\n", base, aligned_size); -+ TRACE("Allocated address %#"PRIx64", size %"PRIu64".\n", base, aligned_size); - - return base; - } - - D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator, -- size_t alignment, size_t size, void *ptr) -+ size_t alignment, uint64_t size, void *ptr) - { - D3D12_GPU_VIRTUAL_ADDRESS address; - -- if (size > ~(size_t)0 - (alignment - 1)) -+ if (size > ~(uint64_t)0 - (alignment - 1)) - return 0; - size = align(size, alignment); - -@@ -2184,7 +2227,7 @@ static void *vkd3d_gpu_va_allocator_dereference_slab(struct vkd3d_gpu_va_allocat - base_offset -= slab_idx * VKD3D_VA_SLAB_SIZE; - if (base_offset >= slab->size) - { -- ERR("Address %#"PRIx64" is %#"PRIx64" bytes into slab %u of size %zu.\n", -+ ERR("Address %#"PRIx64" is %#"PRIx64" bytes into slab %u of size %"PRIu64".\n", - address, base_offset, slab_idx, slab->size); - return NULL; - } -@@ -2455,17 +2498,19 @@ static void vkd3d_desc_object_cache_cleanup(struct vkd3d_desc_object_cache *cach - } - - /* ID3D12Device */ --static inline struct d3d12_device *impl_from_ID3D12Device5(ID3D12Device5 *iface) -+static inline struct d3d12_device *impl_from_ID3D12Device7(ID3D12Device7 *iface) - { -- return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12Device5_iface); -+ return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12Device7_iface); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device7 *iface, - REFIID riid, void **object) - { - TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); - -- if (IsEqualGUID(riid, &IID_ID3D12Device5) -+ if (IsEqualGUID(riid, &IID_ID3D12Device7) -+ || IsEqualGUID(riid, &IID_ID3D12Device6) -+ || IsEqualGUID(riid, &IID_ID3D12Device5) - || IsEqualGUID(riid, &IID_ID3D12Device4) - || IsEqualGUID(riid, &IID_ID3D12Device3) - || IsEqualGUID(riid, &IID_ID3D12Device2) -@@ -2485,20 +2530,42 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device5 *ifac - return E_NOINTERFACE; - } - --static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device5 *iface) -+static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device7 *iface) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -- ULONG refcount = InterlockedIncrement(&device->refcount); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&device->refcount); - - TRACE("%p increasing refcount to %u.\n", device, refcount); - - return refcount; - } - --static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) -+static HRESULT device_worker_stop(struct d3d12_device *device) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -- ULONG refcount = InterlockedDecrement(&device->refcount); -+ HRESULT hr; -+ -+ TRACE("device %p.\n", device); -+ -+ vkd3d_mutex_lock(&device->worker_mutex); -+ -+ device->worker_should_exit = true; -+ vkd3d_cond_signal(&device->worker_cond); -+ -+ vkd3d_mutex_unlock(&device->worker_mutex); -+ -+ if (FAILED(hr = vkd3d_join_thread(device->vkd3d_instance, &device->worker_thread))) -+ return hr; -+ -+ vkd3d_mutex_destroy(&device->worker_mutex); -+ vkd3d_cond_destroy(&device->worker_cond); -+ -+ return S_OK; -+} -+ -+static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device7 *iface) -+{ -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&device->refcount); - - TRACE("%p decreasing refcount to %u.\n", device, refcount); - -@@ -2520,6 +2587,9 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) - d3d12_device_destroy_vkd3d_queues(device); - vkd3d_desc_object_cache_cleanup(&device->view_desc_cache); - vkd3d_desc_object_cache_cleanup(&device->cbuffer_desc_cache); -+ if (device->use_vk_heaps) -+ device_worker_stop(device); -+ vkd3d_free(device->heaps); - VK_CALL(vkDestroyDevice(device->vk_device, NULL)); - if (device->parent) - IUnknown_Release(device->parent); -@@ -2531,10 +2601,10 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) - return refcount; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_GetPrivateData(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_GetPrivateData(ID3D12Device7 *iface, - REFGUID guid, UINT *data_size, void *data) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - TRACE("iface %p, guid %s, data_size %p, data %p.\n", - iface, debugstr_guid(guid), data_size, data); -@@ -2542,10 +2612,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_GetPrivateData(ID3D12Device5 *ifac - return vkd3d_get_private_data(&device->private_store, guid, data_size, data); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateData(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateData(ID3D12Device7 *iface, - REFGUID guid, UINT data_size, const void *data) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - TRACE("iface %p, guid %s, data_size %u, data %p.\n", - iface, debugstr_guid(guid), data_size, data); -@@ -2553,19 +2623,19 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateData(ID3D12Device5 *ifac - return vkd3d_set_private_data(&device->private_store, guid, data_size, data); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateDataInterface(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_SetPrivateDataInterface(ID3D12Device7 *iface, - REFGUID guid, const IUnknown *data) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(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(ID3D12Device5 *iface, const WCHAR *name) -+static HRESULT STDMETHODCALLTYPE d3d12_device_SetName(ID3D12Device7 *iface, const WCHAR *name) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - TRACE("iface %p, name %s.\n", iface, debugstr_w(name, device->wchar_size)); - -@@ -2573,17 +2643,17 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetName(ID3D12Device5 *iface, cons - VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, name); - } - --static UINT STDMETHODCALLTYPE d3d12_device_GetNodeCount(ID3D12Device5 *iface) -+static UINT STDMETHODCALLTYPE d3d12_device_GetNodeCount(ID3D12Device7 *iface) - { - TRACE("iface %p.\n", iface); - - return 1; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandQueue(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandQueue(ID3D12Device7 *iface, - const D3D12_COMMAND_QUEUE_DESC *desc, REFIID riid, void **command_queue) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_command_queue *object; - HRESULT hr; - -@@ -2597,10 +2667,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandQueue(ID3D12Device5 * - riid, command_queue); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Device7 *iface, - D3D12_COMMAND_LIST_TYPE type, REFIID riid, void **command_allocator) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_command_allocator *object; - HRESULT hr; - -@@ -2614,10 +2684,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandAllocator(ID3D12Devic - riid, command_allocator); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12Device7 *iface, - const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, REFIID riid, void **pipeline_state) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_pipeline_state *object; - HRESULT hr; - -@@ -2631,10 +2701,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateGraphicsPipelineState(ID3D12 - &IID_ID3D12PipelineState, riid, pipeline_state); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateComputePipelineState(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateComputePipelineState(ID3D12Device7 *iface, - const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, REFIID riid, void **pipeline_state) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_pipeline_state *object; - HRESULT hr; - -@@ -2648,11 +2718,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateComputePipelineState(ID3D12D - &IID_ID3D12PipelineState, riid, pipeline_state); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device7 *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_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_command_list *object; - HRESULT hr; - -@@ -2775,10 +2845,10 @@ bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent) - return true; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device7 *iface, - D3D12_FEATURE feature, void *feature_data, UINT feature_data_size) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - TRACE("iface %p, feature %#x, feature_data %p, feature_data_size %u.\n", - iface, feature, feature_data, feature_data_size); -@@ -3278,16 +3348,101 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device5 - return S_OK; - } - -+ case D3D12_FEATURE_D3D12_OPTIONS6: -+ { -+ D3D12_FEATURE_DATA_D3D12_OPTIONS6 *data = feature_data; -+ -+ if (feature_data_size != sizeof(*data)) -+ { -+ WARN("Invalid size %u.\n", feature_data_size); -+ return E_INVALIDARG; -+ } -+ -+ data->AdditionalShadingRatesSupported = FALSE; -+ data->PerPrimitiveShadingRateSupportedWithViewportIndexing = FALSE; -+ data->VariableShadingRateTier = D3D12_VARIABLE_SHADING_RATE_TIER_NOT_SUPPORTED; -+ data->ShadingRateImageTileSize = 0; -+ data->BackgroundProcessingSupported = FALSE; -+ -+ TRACE("Additional shading rates support %#x.\n", data->AdditionalShadingRatesSupported); -+ TRACE("Per-primitive shading rates with viewport indexing %#x.\n", -+ data->PerPrimitiveShadingRateSupportedWithViewportIndexing); -+ TRACE("Variable shading rate tier %#x.\n", data->VariableShadingRateTier); -+ TRACE("Shading rate image tile size %#x.\n", data->ShadingRateImageTileSize); -+ TRACE("Background processing support %#x.\n", data->BackgroundProcessingSupported); -+ return S_OK; -+ } -+ -+ case D3D12_FEATURE_D3D12_OPTIONS7: -+ { -+ D3D12_FEATURE_DATA_D3D12_OPTIONS7 *data = feature_data; -+ -+ if (feature_data_size != sizeof(*data)) -+ { -+ WARN("Invalid size %u.\n", feature_data_size); -+ return E_INVALIDARG; -+ } -+ -+ data->MeshShaderTier = D3D12_MESH_SHADER_TIER_NOT_SUPPORTED; -+ data->SamplerFeedbackTier = D3D12_SAMPLER_FEEDBACK_TIER_NOT_SUPPORTED; -+ -+ TRACE("Mesh shading tier %#x.\n", data->MeshShaderTier); -+ TRACE("Sampler feedback tier %#x.\n", data->SamplerFeedbackTier); -+ return S_OK; -+ } -+ -+ case D3D12_FEATURE_D3D12_OPTIONS8: -+ { -+ D3D12_FEATURE_DATA_D3D12_OPTIONS8 *data = feature_data; -+ -+ if (feature_data_size != sizeof(*data)) -+ { -+ WARN("Invalid size %u.\n", feature_data_size); -+ return E_INVALIDARG; -+ } -+ -+ data->UnalignedBlockTexturesSupported = FALSE; -+ -+ TRACE("Unaligned block texture support %#x.\n", data->UnalignedBlockTexturesSupported); -+ return S_OK; -+ } -+ -+ case D3D12_FEATURE_D3D12_OPTIONS9: -+ { -+ D3D12_FEATURE_DATA_D3D12_OPTIONS9 *data = feature_data; -+ -+ if (feature_data_size != sizeof(*data)) -+ { -+ WARN("Invalid size %u.\n", feature_data_size); -+ return E_INVALIDARG; -+ } -+ -+ data->MeshShaderPipelineStatsSupported = FALSE; -+ data->MeshShaderSupportsFullRangeRenderTargetArrayIndex = FALSE; -+ data->AtomicInt64OnTypedResourceSupported = FALSE; -+ data->AtomicInt64OnGroupSharedSupported = FALSE; -+ data->DerivativesInMeshAndAmplificationShadersSupported = FALSE; -+ data->WaveMMATier = D3D12_WAVE_MMA_TIER_NOT_SUPPORTED; -+ -+ TRACE("Mesh shader pipeline stats support %#x.\n", data->MeshShaderPipelineStatsSupported); -+ TRACE("Mesh shader RT array index full range %#x.\n", data->MeshShaderSupportsFullRangeRenderTargetArrayIndex); -+ TRACE("Atomic int64 on typed resource %#x.\n", data->AtomicInt64OnTypedResourceSupported); -+ TRACE("Atomic int64 on group shared mem %#x.\n", data->AtomicInt64OnGroupSharedSupported); -+ TRACE("Derivatives in mesh and amp shaders %#x.\n", data->DerivativesInMeshAndAmplificationShadersSupported); -+ TRACE("Wave MMA tier %#x.\n", data->WaveMMATier); -+ return S_OK; -+ } -+ - default: - FIXME("Unhandled feature %#x.\n", feature); - return E_NOTIMPL; - } - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateDescriptorHeap(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateDescriptorHeap(ID3D12Device7 *iface, - const D3D12_DESCRIPTOR_HEAP_DESC *desc, REFIID riid, void **descriptor_heap) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_descriptor_heap *object; - HRESULT hr; - -@@ -3301,7 +3456,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateDescriptorHeap(ID3D12Device5 - &IID_ID3D12DescriptorHeap, riid, descriptor_heap); - } - --static UINT STDMETHODCALLTYPE d3d12_device_GetDescriptorHandleIncrementSize(ID3D12Device5 *iface, -+static UINT STDMETHODCALLTYPE d3d12_device_GetDescriptorHandleIncrementSize(ID3D12Device7 *iface, - D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) - { - TRACE("iface %p, descriptor_heap_type %#x.\n", iface, descriptor_heap_type); -@@ -3324,16 +3479,16 @@ static UINT STDMETHODCALLTYPE d3d12_device_GetDescriptorHandleIncrementSize(ID3D - } - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateRootSignature(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateRootSignature(ID3D12Device7 *iface, - UINT node_mask, const void *bytecode, SIZE_T bytecode_length, - REFIID riid, void **root_signature) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_root_signature *object; - HRESULT hr; - -- TRACE("iface %p, node_mask 0x%08x, bytecode %p, bytecode_length %lu, riid %s, root_signature %p.\n", -- iface, node_mask, bytecode, bytecode_length, debugstr_guid(riid), root_signature); -+ TRACE("iface %p, node_mask 0x%08x, bytecode %p, bytecode_length %"PRIuPTR", riid %s, root_signature %p.\n", -+ iface, node_mask, bytecode, (uintptr_t)bytecode_length, debugstr_guid(riid), root_signature); - - debug_ignored_node_mask(node_mask); - -@@ -3344,89 +3499,89 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateRootSignature(ID3D12Device5 - &IID_ID3D12RootSignature, riid, root_signature); - } - --static void STDMETHODCALLTYPE d3d12_device_CreateConstantBufferView(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_CreateConstantBufferView(ID3D12Device7 *iface, - const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_desc tmp = {0}; - -- TRACE("iface %p, desc %p, descriptor %#lx.\n", iface, desc, descriptor.ptr); -+ TRACE("iface %p, desc %p, descriptor %s.\n", iface, desc, debug_cpu_handle(descriptor)); - - d3d12_desc_create_cbv(&tmp, device, desc); - d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device); - } - --static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(ID3D12Device7 *iface, - ID3D12Resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc, - D3D12_CPU_DESCRIPTOR_HANDLE descriptor) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_desc tmp = {0}; - -- TRACE("iface %p, resource %p, desc %p, descriptor %#lx.\n", -- iface, resource, desc, descriptor.ptr); -+ TRACE("iface %p, resource %p, desc %p, descriptor %s.\n", -+ iface, resource, desc, debug_cpu_handle(descriptor)); - - d3d12_desc_create_srv(&tmp, device, unsafe_impl_from_ID3D12Resource(resource), desc); - d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device); - } - --static void STDMETHODCALLTYPE d3d12_device_CreateUnorderedAccessView(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_CreateUnorderedAccessView(ID3D12Device7 *iface, - ID3D12Resource *resource, ID3D12Resource *counter_resource, - const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_desc tmp = {0}; - -- TRACE("iface %p, resource %p, counter_resource %p, desc %p, descriptor %#lx.\n", -- iface, resource, counter_resource, desc, descriptor.ptr); -+ TRACE("iface %p, resource %p, counter_resource %p, desc %p, descriptor %s.\n", -+ iface, resource, counter_resource, desc, debug_cpu_handle(descriptor)); - - d3d12_desc_create_uav(&tmp, device, unsafe_impl_from_ID3D12Resource(resource), - unsafe_impl_from_ID3D12Resource(counter_resource), desc); - d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device); - } - --static void STDMETHODCALLTYPE d3d12_device_CreateRenderTargetView(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_CreateRenderTargetView(ID3D12Device7 *iface, - ID3D12Resource *resource, const D3D12_RENDER_TARGET_VIEW_DESC *desc, - D3D12_CPU_DESCRIPTOR_HANDLE descriptor) - { -- TRACE("iface %p, resource %p, desc %p, descriptor %#lx.\n", -- iface, resource, desc, descriptor.ptr); -+ TRACE("iface %p, resource %p, desc %p, descriptor %s.\n", -+ iface, resource, desc, debug_cpu_handle(descriptor)); - - d3d12_rtv_desc_create_rtv(d3d12_rtv_desc_from_cpu_handle(descriptor), -- impl_from_ID3D12Device5(iface), unsafe_impl_from_ID3D12Resource(resource), desc); -+ impl_from_ID3D12Device7(iface), unsafe_impl_from_ID3D12Resource(resource), desc); - } - --static void STDMETHODCALLTYPE d3d12_device_CreateDepthStencilView(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_CreateDepthStencilView(ID3D12Device7 *iface, - ID3D12Resource *resource, const D3D12_DEPTH_STENCIL_VIEW_DESC *desc, - D3D12_CPU_DESCRIPTOR_HANDLE descriptor) - { -- TRACE("iface %p, resource %p, desc %p, descriptor %#lx.\n", -- iface, resource, desc, descriptor.ptr); -+ TRACE("iface %p, resource %p, desc %p, descriptor %s.\n", -+ iface, resource, desc, debug_cpu_handle(descriptor)); - - d3d12_dsv_desc_create_dsv(d3d12_dsv_desc_from_cpu_handle(descriptor), -- impl_from_ID3D12Device5(iface), unsafe_impl_from_ID3D12Resource(resource), desc); -+ impl_from_ID3D12Device7(iface), unsafe_impl_from_ID3D12Resource(resource), desc); - } - --static void STDMETHODCALLTYPE d3d12_device_CreateSampler(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_CreateSampler(ID3D12Device7 *iface, - const D3D12_SAMPLER_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_desc tmp = {0}; - -- TRACE("iface %p, desc %p, descriptor %#lx.\n", iface, desc, descriptor.ptr); -+ TRACE("iface %p, desc %p, descriptor %s.\n", iface, desc, debug_cpu_handle(descriptor)); - - d3d12_desc_create_sampler(&tmp, device, desc); - d3d12_desc_write_atomic(d3d12_desc_from_cpu_handle(descriptor), &tmp, device); - } - --static void STDMETHODCALLTYPE d3d12_device_CopyDescriptors(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_CopyDescriptors(ID3D12Device7 *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_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(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; -@@ -3482,101 +3637,126 @@ static void STDMETHODCALLTYPE d3d12_device_CopyDescriptors(ID3D12Device5 *iface, - } - } - --static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device7 *iface, - UINT descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE dst_descriptor_range_offset, - const D3D12_CPU_DESCRIPTOR_HANDLE src_descriptor_range_offset, - D3D12_DESCRIPTOR_HEAP_TYPE descriptor_heap_type) - { -- TRACE("iface %p, descriptor_count %u, dst_descriptor_range_offset %#lx, " -- "src_descriptor_range_offset %#lx, descriptor_heap_type %#x.\n", -- iface, descriptor_count, dst_descriptor_range_offset.ptr, src_descriptor_range_offset.ptr, -- descriptor_heap_type); -+ TRACE("iface %p, descriptor_count %u, dst_descriptor_range_offset %s, " -+ "src_descriptor_range_offset %s, descriptor_heap_type %#x.\n", -+ iface, descriptor_count, debug_cpu_handle(dst_descriptor_range_offset), -+ debug_cpu_handle(src_descriptor_range_offset), descriptor_heap_type); - - d3d12_device_CopyDescriptors(iface, 1, &dst_descriptor_range_offset, &descriptor_count, - 1, &src_descriptor_range_offset, &descriptor_count, descriptor_heap_type); - } - --static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo( -- ID3D12Device5 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask, -- UINT count, const D3D12_RESOURCE_DESC *resource_descs) -+static void d3d12_resource_allocation_info1_from_vkd3d(D3D12_RESOURCE_ALLOCATION_INFO1 *result, -+ const struct vkd3d_resource_allocation_info *info) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ result->Offset = info->offset; -+ result->Alignment = info->alignment; -+ result->SizeInBytes = info->size_in_bytes; -+} -+ -+static void d3d12_device_get_resource_allocation_info(struct d3d12_device *device, -+ D3D12_RESOURCE_ALLOCATION_INFO1 *infos1, unsigned int count, const D3D12_RESOURCE_DESC *resource_descs, -+ D3D12_RESOURCE_ALLOCATION_INFO *result) -+{ -+ struct vkd3d_resource_allocation_info info; - const D3D12_RESOURCE_DESC *desc; - uint64_t requested_alignment; -+ unsigned int i; - -- TRACE("iface %p, info %p, visible_mask 0x%08x, count %u, resource_descs %p.\n", -- iface, info, visible_mask, count, resource_descs); -- -- debug_ignored_node_mask(visible_mask); -- -- info->SizeInBytes = 0; -- info->Alignment = 0; -+ result->Alignment = 0; -+ result->SizeInBytes = 0; - -- if (count != 1) -- { -- FIXME("Multiple resource descriptions not supported.\n"); -- return info; -- } -+ info.offset = 0; - -- desc = &resource_descs[0]; -- -- if (FAILED(d3d12_resource_validate_desc(desc, device))) -+ for (i = 0; i < count; ++i) - { -- WARN("Invalid resource desc.\n"); -- goto invalid; -- } -+ desc = &resource_descs[i]; - -- if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) -- { -- info->SizeInBytes = align(desc->Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); -- info->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; -- } -- else -- { -- if (FAILED(vkd3d_get_image_allocation_info(device, desc, info))) -+ if (FAILED(d3d12_resource_validate_desc(desc, device))) - { -- WARN("Failed to get allocation info for texture.\n"); -+ WARN("Invalid resource desc.\n"); - goto invalid; - } - -- requested_alignment = desc->Alignment -- ? desc->Alignment : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; -- info->Alignment = max(info->Alignment, requested_alignment); -+ if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) -+ { -+ info.alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; -+ info.offset = align(info.offset, info.alignment); -+ info.size_in_bytes = align(desc->Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); -+ } -+ else -+ { -+ if (FAILED(vkd3d_get_image_allocation_info(device, desc, &info))) -+ { -+ WARN("Failed to get allocation info for texture.\n"); -+ goto invalid; -+ } - -- info->SizeInBytes = align(info->SizeInBytes, info->Alignment); -+ requested_alignment = desc->Alignment -+ ? desc->Alignment : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; -+ info.alignment = max(info.alignment, requested_alignment); -+ info.size_in_bytes = align(info.size_in_bytes, info.alignment); - -- /* Pad by the maximum heap offset increase which may be needed to align to a higher -- * Vulkan requirement an offset supplied by the calling application. This allows -- * us to return the standard D3D12 alignment and adjust resource placement later. */ -- if (info->Alignment > requested_alignment) -- { -- info->SizeInBytes += info->Alignment - requested_alignment; -- info->Alignment = requested_alignment; -+ /* Pad by the maximum heap offset increase which may be needed to align to a higher -+ * Vulkan requirement an offset supplied by the calling application. This allows -+ * us to return the standard D3D12 alignment and adjust resource placement later. */ -+ if (info.alignment > requested_alignment) -+ { -+ info.size_in_bytes += info.alignment - requested_alignment; -+ info.alignment = requested_alignment; -+ } -+ -+ info.offset = align(info.offset, info.alignment); - } -- } - -- TRACE("Size %#"PRIx64", alignment %#"PRIx64".\n", info->SizeInBytes, info->Alignment); -+ if (infos1) -+ d3d12_resource_allocation_info1_from_vkd3d(&infos1[i], &info); - -- return info; -+ info.offset += info.size_in_bytes; -+ -+ result->Alignment = max(result->Alignment, info.alignment); -+ result->SizeInBytes = info.offset; -+ } -+ -+ return; - - invalid: -- info->SizeInBytes = ~(uint64_t)0; -+ result->SizeInBytes = UINT64_MAX; - -- /* FIXME: Should we support D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT for small MSSA resources? */ -+ /* FIXME: Should we support D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT for small MSAA resources? */ - if (desc->SampleDesc.Count != 1) -- info->Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; -+ result->Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; - else -- info->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; -+ result->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; -+ -+ TRACE("Alignment %#"PRIx64".\n", result->Alignment); -+} -+ -+static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo( -+ ID3D12Device7 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask, -+ UINT count, const D3D12_RESOURCE_DESC *resource_descs) -+{ -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - -- TRACE("Alignment %#"PRIx64".\n", info->Alignment); -+ TRACE("iface %p, info %p, visible_mask 0x%08x, count %u, resource_descs %p.\n", -+ iface, info, visible_mask, count, resource_descs); -+ -+ debug_ignored_node_mask(visible_mask); -+ -+ d3d12_device_get_resource_allocation_info(device, NULL, count, resource_descs, info); - - return info; - } - --static D3D12_HEAP_PROPERTIES * STDMETHODCALLTYPE d3d12_device_GetCustomHeapProperties(ID3D12Device5 *iface, -+static D3D12_HEAP_PROPERTIES * STDMETHODCALLTYPE d3d12_device_GetCustomHeapProperties(ID3D12Device7 *iface, - D3D12_HEAP_PROPERTIES *heap_properties, UINT node_mask, D3D12_HEAP_TYPE heap_type) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - bool coherent; - - TRACE("iface %p, heap_properties %p, node_mask 0x%08x, heap_type %#x.\n", -@@ -3616,12 +3796,12 @@ static D3D12_HEAP_PROPERTIES * STDMETHODCALLTYPE d3d12_device_GetCustomHeapPrope - return heap_properties; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Device7 *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_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_resource *object; - HRESULT hr; - -@@ -3640,10 +3820,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Devi - return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device7 *iface, - const D3D12_HEAP_DESC *desc, REFIID iid, void **heap) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_heap *object; - HRESULT hr; - -@@ -3659,12 +3839,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device5 *iface, - return return_interface(&object->ID3D12Heap_iface, &IID_ID3D12Heap, iid, heap); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device7 *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_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_heap *heap_object; - struct d3d12_resource *object; - HRESULT hr; -@@ -3683,11 +3863,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device5 - return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Device7 *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_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_resource *object; - HRESULT hr; - -@@ -3701,11 +3881,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Devic - return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device7 *iface, - ID3D12DeviceChild *object, const SECURITY_ATTRIBUTES *attributes, DWORD access, - const WCHAR *name, HANDLE *handle) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(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); -@@ -3713,7 +3893,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device5 * - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandle(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandle(ID3D12Device7 *iface, - HANDLE handle, REFIID riid, void **object) - { - FIXME("iface %p, handle %p, riid %s, object %p stub!\n", -@@ -3722,10 +3902,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandle(ID3D12Device5 *if - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandleByName(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandleByName(ID3D12Device7 *iface, - const WCHAR *name, DWORD access, HANDLE *handle) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - FIXME("iface %p, name %s, access %#x, handle %p stub!\n", - iface, debugstr_w(name, device->wchar_size), access, handle); -@@ -3733,7 +3913,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandleByName(ID3D12Devic - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_MakeResident(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_MakeResident(ID3D12Device7 *iface, - UINT object_count, ID3D12Pageable * const *objects) - { - ID3D12Fence *fence; -@@ -3741,17 +3921,17 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_MakeResident(ID3D12Device5 *iface, - - TRACE("iface %p, object_count %u, objects %p.\n", iface, object_count, objects); - -- if (FAILED(hr = ID3D12Device5_CreateFence(iface, 0, 0, &IID_ID3D12Fence, (void **)&fence))) -+ if (FAILED(hr = ID3D12Device7_CreateFence(iface, 0, 0, &IID_ID3D12Fence, (void **)&fence))) - return hr; - -- hr = ID3D12Device5_EnqueueMakeResident(iface, 0, object_count, objects, fence, 1); -+ hr = ID3D12Device7_EnqueueMakeResident(iface, 0, object_count, objects, fence, 1); - if (SUCCEEDED(hr)) - ID3D12Fence_SetEventOnCompletion(fence, 1, NULL); - ID3D12Fence_Release(fence); - return hr; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_Evict(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_Evict(ID3D12Device7 *iface, - UINT object_count, ID3D12Pageable * const *objects) - { - FIXME_ONCE("iface %p, object_count %u, objects %p stub!\n", -@@ -3760,10 +3940,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_Evict(ID3D12Device5 *iface, - return S_OK; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device7 *iface, - UINT64 initial_value, D3D12_FENCE_FLAGS flags, REFIID riid, void **fence) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_fence *object; - HRESULT hr; - -@@ -3776,21 +3956,21 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateFence(ID3D12Device5 *iface, - return return_interface(&object->ID3D12Fence1_iface, &IID_ID3D12Fence1, riid, fence); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_GetDeviceRemovedReason(ID3D12Device5 *iface) -+static HRESULT STDMETHODCALLTYPE d3d12_device_GetDeviceRemovedReason(ID3D12Device7 *iface) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - TRACE("iface %p.\n", iface); - - return device->removed_reason; - } - --static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device7 *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_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(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; -@@ -3870,10 +4050,10 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device5 * - *total_bytes = total; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateQueryHeap(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateQueryHeap(ID3D12Device7 *iface, - const D3D12_QUERY_HEAP_DESC *desc, REFIID iid, void **heap) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_query_heap *object; - HRESULT hr; - -@@ -3886,18 +4066,18 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateQueryHeap(ID3D12Device5 *ifa - return return_interface(&object->ID3D12QueryHeap_iface, &IID_ID3D12QueryHeap, iid, heap); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_SetStablePowerState(ID3D12Device5 *iface, BOOL enable) -+static HRESULT STDMETHODCALLTYPE d3d12_device_SetStablePowerState(ID3D12Device7 *iface, BOOL enable) - { - FIXME("iface %p, enable %#x stub!\n", iface, enable); - - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(ID3D12Device7 *iface, - const D3D12_COMMAND_SIGNATURE_DESC *desc, ID3D12RootSignature *root_signature, - REFIID iid, void **command_signature) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_command_signature *object; - HRESULT hr; - -@@ -3911,14 +4091,14 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(ID3D12Devic - &IID_ID3D12CommandSignature, iid, command_signature); - } - --static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device7 *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_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - TRACE("iface %p, resource %p, total_tile_count %p, packed_mip_info %p, " - "standard_title_shape %p, sub_resource_tiling_count %p, " -@@ -3931,9 +4111,9 @@ static void STDMETHODCALLTYPE d3d12_device_GetResourceTiling(ID3D12Device5 *ifac - sub_resource_tiling_count, first_sub_resource_tiling, sub_resource_tilings); - } - --static LUID * STDMETHODCALLTYPE d3d12_device_GetAdapterLuid(ID3D12Device5 *iface, LUID *luid) -+static LUID * STDMETHODCALLTYPE d3d12_device_GetAdapterLuid(ID3D12Device7 *iface, LUID *luid) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - TRACE("iface %p, luid %p.\n", iface, luid); - -@@ -3942,15 +4122,16 @@ static LUID * STDMETHODCALLTYPE d3d12_device_GetAdapterLuid(ID3D12Device5 *iface - return luid; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineLibrary(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineLibrary(ID3D12Device7 *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); -+ FIXME("iface %p, blob %p, blob_size %"PRIuPTR", iid %s, lib %p stub!\n", -+ iface, blob, (uintptr_t)blob_size, debugstr_guid(iid), lib); - - return DXGI_ERROR_UNSUPPORTED; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(ID3D12Device7 *iface, - ID3D12Fence *const *fences, const UINT64 *values, UINT fence_count, - D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags, HANDLE event) - { -@@ -3960,7 +4141,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion( - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_SetResidencyPriority(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_SetResidencyPriority(ID3D12Device7 *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); -@@ -3968,10 +4149,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetResidencyPriority(ID3D12Device5 - return S_OK; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineState(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineState(ID3D12Device7 *iface, - const D3D12_PIPELINE_STATE_STREAM_DESC *desc, REFIID iid, void **pipeline_state) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_pipeline_state *object; - HRESULT hr; - -@@ -3983,7 +4164,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineState(ID3D12Device5 - return return_interface(&object->ID3D12PipelineState_iface, &IID_ID3D12PipelineState, iid, pipeline_state); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_OpenExistingHeapFromAddress(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_OpenExistingHeapFromAddress(ID3D12Device7 *iface, - const void *address, REFIID iid, void **heap) - { - FIXME("iface %p, address %p, iid %s, heap %p stub!\n", iface, address, debugstr_guid(iid), heap); -@@ -3991,7 +4172,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_OpenExistingHeapFromAddress(ID3D12 - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_OpenExistingHeapFromFileMapping(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_OpenExistingHeapFromFileMapping(ID3D12Device7 *iface, - HANDLE file_mapping, REFIID iid, void **heap) - { - FIXME("iface %p, file_mapping %p, iid %s, heap %p stub!\n", iface, file_mapping, debugstr_guid(iid), heap); -@@ -3999,7 +4180,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_OpenExistingHeapFromFileMapping(ID - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_EnqueueMakeResident(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_EnqueueMakeResident(ID3D12Device7 *iface, - D3D12_RESIDENCY_FLAGS flags, UINT num_objects, ID3D12Pageable *const *objects, - ID3D12Fence *fence, UINT64 fence_value) - { -@@ -4010,7 +4191,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_EnqueueMakeResident(ID3D12Device5 - return S_OK; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList1(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList1(ID3D12Device7 *iface, - UINT node_mask, D3D12_COMMAND_LIST_TYPE type, D3D12_COMMAND_LIST_FLAGS flags, - REFIID iid, void **command_list) - { -@@ -4020,7 +4201,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList1(ID3D12Device5 * - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateProtectedResourceSession(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateProtectedResourceSession(ID3D12Device7 *iface, - const D3D12_PROTECTED_RESOURCE_SESSION_DESC *desc, REFIID iid, void **session) - { - FIXME("iface %p, desc %p, iid %s, session %p stub!\n", iface, desc, debugstr_guid(iid), session); -@@ -4028,13 +4209,13 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateProtectedResourceSession(ID3 - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource1(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource1(ID3D12Device7 *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, - ID3D12ProtectedResourceSession *protected_session, REFIID iid, void **resource) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_resource *object; - HRESULT hr; - -@@ -4053,11 +4234,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource1(ID3D12Dev - return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap1(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap1(ID3D12Device7 *iface, - const D3D12_HEAP_DESC *desc, ID3D12ProtectedResourceSession *protected_session, - REFIID iid, void **heap) - { -- struct d3d12_device *device = impl_from_ID3D12Device5(iface); -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); - struct d3d12_heap *object; - HRESULT hr; - -@@ -4073,7 +4254,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap1(ID3D12Device5 *iface, - return return_interface(&object->ID3D12Heap_iface, &IID_ID3D12Heap, iid, heap); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource1(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource1(ID3D12Device7 *iface, - const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, - ID3D12ProtectedResourceSession *protected_session, REFIID iid, void **resource) -@@ -4087,17 +4268,23 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource1(ID3D12Devi - } - - static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo1( -- ID3D12Device5 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask, -+ ID3D12Device7 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask, - UINT count, const D3D12_RESOURCE_DESC *resource_descs, - D3D12_RESOURCE_ALLOCATION_INFO1 *info1) - { -- FIXME("iface %p, info %p, visible_mask 0x%08x, count %u, resource_descs %p, info1 %p stub!\n", -+ struct d3d12_device *device = impl_from_ID3D12Device7(iface); -+ -+ TRACE("iface %p, info %p, visible_mask 0x%08x, count %u, resource_descs %p, info1 %p.\n", - iface, info, visible_mask, count, resource_descs, info1); - -+ debug_ignored_node_mask(visible_mask); -+ -+ d3d12_device_get_resource_allocation_info(device, info1, count, resource_descs, info); -+ - return info; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateLifetimeTracker(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateLifetimeTracker(ID3D12Device7 *iface, - ID3D12LifetimeOwner *owner, REFIID iid, void **tracker) - { - FIXME("iface %p, owner %p, iid %s, tracker %p stub!\n", iface, owner, debugstr_guid(iid), tracker); -@@ -4105,12 +4292,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateLifetimeTracker(ID3D12Device - return E_NOTIMPL; - } - --static void STDMETHODCALLTYPE d3d12_device_RemoveDevice(ID3D12Device5 *iface) -+static void STDMETHODCALLTYPE d3d12_device_RemoveDevice(ID3D12Device7 *iface) - { - FIXME("iface %p stub!\n", iface); - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_EnumerateMetaCommands(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_EnumerateMetaCommands(ID3D12Device7 *iface, - UINT *num_meta_commands, D3D12_META_COMMAND_DESC *command_desc) - { - FIXME("iface %p, num_meta_commands %p, command_desc %p stub!\n", iface, -@@ -4119,7 +4306,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_EnumerateMetaCommands(ID3D12Device - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_EnumerateMetaCommandParameters(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_EnumerateMetaCommandParameters(ID3D12Device7 *iface, - REFGUID command_id, D3D12_META_COMMAND_PARAMETER_STAGE stage, - UINT *size_in_bytes, UINT *parameter_count, - D3D12_META_COMMAND_PARAMETER_DESC *parameter_desc) -@@ -4131,19 +4318,19 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_EnumerateMetaCommandParameters(ID3 - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateMetaCommand(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateMetaCommand(ID3D12Device7 *iface, - REFGUID command_id, UINT node_mask, const void *parameters_data, - SIZE_T data_size_in_bytes, REFIID iid, void **meta_command) - { - FIXME("iface %p, command_id %s, node_mask %#x, parameters_data %p, " -- "data_size_in_bytes %lu, iid %s, meta_command %p stub!\n", iface, -+ "data_size_in_bytes %"PRIuPTR", iid %s, meta_command %p stub!\n", iface, - debugstr_guid(command_id), node_mask, parameters_data, -- data_size_in_bytes, debugstr_guid(iid), meta_command); -+ (uintptr_t)data_size_in_bytes, debugstr_guid(iid), meta_command); - - return E_NOTIMPL; - } - --static HRESULT STDMETHODCALLTYPE d3d12_device_CreateStateObject(ID3D12Device5 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateStateObject(ID3D12Device7 *iface, - const D3D12_STATE_OBJECT_DESC *desc, REFIID iid, void **state_object) - { - FIXME("iface %p, desc %p, iid %s, state_object %p stub!\n", iface, desc, debugstr_guid(iid), state_object); -@@ -4151,14 +4338,14 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateStateObject(ID3D12Device5 *i - return E_NOTIMPL; - } - --static void STDMETHODCALLTYPE d3d12_device_GetRaytracingAccelerationStructurePrebuildInfo(ID3D12Device5 *iface, -+static void STDMETHODCALLTYPE d3d12_device_GetRaytracingAccelerationStructurePrebuildInfo(ID3D12Device7 *iface, - const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS *desc, - D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO *info) - { - FIXME("iface %p, desc %p, info %p stub!\n", iface, desc, info); - } - --static D3D12_DRIVER_MATCHING_IDENTIFIER_STATUS STDMETHODCALLTYPE d3d12_device_CheckDriverMatchingIdentifier(ID3D12Device5 *iface, -+static D3D12_DRIVER_MATCHING_IDENTIFIER_STATUS STDMETHODCALLTYPE d3d12_device_CheckDriverMatchingIdentifier(ID3D12Device7 *iface, - D3D12_SERIALIZED_DATA_TYPE data_type, const D3D12_SERIALIZED_DATA_DRIVER_MATCHING_IDENTIFIER *identifier) - { - FIXME("iface %p, data_type %u, identifier %p stub!\n", iface, data_type, identifier); -@@ -4166,7 +4353,35 @@ static D3D12_DRIVER_MATCHING_IDENTIFIER_STATUS STDMETHODCALLTYPE d3d12_device_Ch - return D3D12_DRIVER_MATCHING_IDENTIFIER_UNRECOGNIZED; - } - --static const struct ID3D12Device5Vtbl d3d12_device_vtbl = -+static HRESULT STDMETHODCALLTYPE d3d12_device_SetBackgroundProcessingMode(ID3D12Device7 *iface, -+ D3D12_BACKGROUND_PROCESSING_MODE mode, D3D12_MEASUREMENTS_ACTION action, HANDLE event, -+ BOOL *further_measurements_desired) -+{ -+ FIXME("iface %p, mode %#x, action %#x, event %p, further_measurements_desired %p stub!\n", -+ iface, mode, action, event, further_measurements_desired); -+ -+ return E_NOTIMPL; -+} -+ -+static HRESULT STDMETHODCALLTYPE d3d12_device_AddToStateObject(ID3D12Device7 *iface, -+ const D3D12_STATE_OBJECT_DESC *addition, ID3D12StateObject *state_object_to_grow_from, -+ REFIID riid, void **new_state_object) -+{ -+ FIXME("iface %p, addition %p, state_object_to_grow_from %p, riid %s, new_state_object %p stub!\n", -+ iface, addition, state_object_to_grow_from, debugstr_guid(riid), new_state_object); -+ -+ return E_NOTIMPL; -+} -+ -+static HRESULT STDMETHODCALLTYPE d3d12_device_CreateProtectedResourceSession1(ID3D12Device7 *iface, -+ const D3D12_PROTECTED_RESOURCE_SESSION_DESC1 *desc, REFIID riid, void **session) -+{ -+ FIXME("iface %p, desc %p, riid %s, session %p stub!\n", iface, desc, debugstr_guid(riid), session); -+ -+ return E_NOTIMPL; -+} -+ -+static const struct ID3D12Device7Vtbl d3d12_device_vtbl = - { - /* IUnknown methods */ - d3d12_device_QueryInterface, -@@ -4241,14 +4456,53 @@ static const struct ID3D12Device5Vtbl d3d12_device_vtbl = - d3d12_device_CreateStateObject, - d3d12_device_GetRaytracingAccelerationStructurePrebuildInfo, - d3d12_device_CheckDriverMatchingIdentifier, -+ /* ID3D12Device6 methods */ -+ d3d12_device_SetBackgroundProcessingMode, -+ /* ID3D12Device7 methods */ -+ d3d12_device_AddToStateObject, -+ d3d12_device_CreateProtectedResourceSession1, - }; - --struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface) -+struct d3d12_device *unsafe_impl_from_ID3D12Device7(ID3D12Device7 *iface) - { - if (!iface) - return NULL; - assert(iface->lpVtbl == &d3d12_device_vtbl); -- return impl_from_ID3D12Device5(iface); -+ return impl_from_ID3D12Device7(iface); -+} -+ -+static void *device_worker_main(void *arg) -+{ -+ struct d3d12_descriptor_heap *heap; -+ struct d3d12_device *device = arg; -+ size_t i; -+ -+ vkd3d_set_thread_name("device_worker"); -+ -+ vkd3d_mutex_lock(&device->worker_mutex); -+ -+ while (!device->worker_should_exit) -+ { -+ for (i = 0; i < device->heap_count; ++i) -+ { -+ /* Descriptor updates are not written to Vulkan descriptor sets until a command list -+ * is submitted to a queue, while the client is free to write d3d12 descriptors earlier, -+ * from any thread. This causes a delay right before command list execution, so -+ * handling these updates in a worker thread can speed up execution significantly. */ -+ heap = device->heaps[i]; -+ if (heap->dirty_list_head == UINT_MAX) -+ continue; -+ vkd3d_mutex_lock(&heap->vk_sets_mutex); -+ d3d12_desc_flush_vk_heap_updates_locked(heap, device); -+ vkd3d_mutex_unlock(&heap->vk_sets_mutex); -+ } -+ -+ vkd3d_cond_wait(&device->worker_cond, &device->worker_mutex); -+ } -+ -+ vkd3d_mutex_unlock(&device->worker_mutex); -+ -+ return NULL; - } - - static HRESULT d3d12_device_init(struct d3d12_device *device, -@@ -4257,7 +4511,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, - const struct vkd3d_vk_device_procs *vk_procs; - HRESULT hr; - -- device->ID3D12Device5_iface.lpVtbl = &d3d12_device_vtbl; -+ device->ID3D12Device7_iface.lpVtbl = &d3d12_device_vtbl; - device->refcount = 1; - - vkd3d_instance_incref(device->vkd3d_instance = instance); -@@ -4270,6 +4524,14 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, - - device->vk_device = VK_NULL_HANDLE; - -+ device->heaps = NULL; -+ device->heap_capacity = 0; -+ device->heap_count = 0; -+ memset(&device->worker_thread, 0, sizeof(device->worker_thread)); -+ device->worker_should_exit = false; -+ vkd3d_mutex_init(&device->worker_mutex); -+ vkd3d_cond_init(&device->worker_cond); -+ - if (FAILED(hr = vkd3d_create_vk_device(device, create_info))) - goto out_free_instance; - -@@ -4291,6 +4553,13 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, - if (FAILED(hr = vkd3d_vk_descriptor_heap_layouts_init(device))) - goto out_cleanup_uav_clear_state; - -+ if (device->use_vk_heaps && FAILED(hr = vkd3d_create_thread(device->vkd3d_instance, -+ device_worker_main, device, &device->worker_thread))) -+ { -+ WARN("Failed to create worker thread, hr %s.\n", debugstr_hresult(hr)); -+ goto out_cleanup_descriptor_heap_layouts; -+ } -+ - vkd3d_render_pass_cache_init(&device->render_pass_cache); - vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator); - vkd3d_time_domains_init(device); -@@ -4308,6 +4577,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, - - return S_OK; - -+out_cleanup_descriptor_heap_layouts: -+ vkd3d_vk_descriptor_heap_layouts_cleanup(device); - out_cleanup_uav_clear_state: - vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device); - out_destroy_null_resources: -@@ -4354,13 +4625,47 @@ void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, - va_list args; - - va_start(args, message); -- WARN("Device %p is lost (reason %#x, \"%s\").\n", -- device, reason, vkd3d_dbg_vsprintf(message, args)); -+ WARN("Device %p is lost (reason %s, \"%s\").\n", -+ device, debugstr_hresult(reason), vkd3d_dbg_vsprintf(message, args)); - va_end(args); - - device->removed_reason = reason; - } - -+HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap) -+{ -+ vkd3d_mutex_lock(&device->worker_mutex); -+ -+ if (!vkd3d_array_reserve((void **)&device->heaps, &device->heap_capacity, device->heap_count + 1, -+ sizeof(*device->heaps))) -+ { -+ vkd3d_mutex_unlock(&device->worker_mutex); -+ return E_OUTOFMEMORY; -+ } -+ device->heaps[device->heap_count++] = heap; -+ -+ vkd3d_mutex_unlock(&device->worker_mutex); -+ -+ return S_OK; -+} -+ -+void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap) -+{ -+ size_t i; -+ -+ vkd3d_mutex_lock(&device->worker_mutex); -+ -+ for (i = 0; i < device->heap_count; ++i) -+ { -+ if (device->heaps[i] == heap) -+ { -+ device->heaps[i] = device->heaps[--device->heap_count]; -+ break; -+ } -+ } -+ -+ vkd3d_mutex_unlock(&device->worker_mutex); -+} - - #ifdef _WIN32 - struct thread_data -@@ -4403,7 +4708,7 @@ HRESULT vkd3d_create_thread(struct vkd3d_instance *instance, - thread_data->data = data; - if (!(thread->handle = CreateThread(NULL, 0, call_thread_main, thread_data, 0, NULL))) - { -- ERR("Failed to create thread, error %d.\n", GetLastError()); -+ ERR("Failed to create thread, error %lu.\n", GetLastError()); - vkd3d_free(thread_data); - hr = E_FAIL; - } -@@ -4429,7 +4734,7 @@ HRESULT vkd3d_join_thread(struct vkd3d_instance *instance, union vkd3d_thread_ha - if (instance->join_thread) - { - if (FAILED(hr = instance->join_thread(thread->handle))) -- ERR("Failed to join thread, hr %#x.\n", hr); -+ ERR("Failed to join thread, hr %s.\n", debugstr_hresult(hr)); - } - else - { -@@ -4454,28 +4759,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_ID3D12Device5((ID3D12Device5 *)device); -+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device7((ID3D12Device7 *)device); - - return d3d12_device->parent; - } - - VkDevice vkd3d_get_vk_device(ID3D12Device *device) - { -- struct d3d12_device *d3d12_device = impl_from_ID3D12Device5((ID3D12Device5 *)device); -+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device7((ID3D12Device7 *)device); - - return d3d12_device->vk_device; - } - - VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device) - { -- struct d3d12_device *d3d12_device = impl_from_ID3D12Device5((ID3D12Device5 *)device); -+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device7((ID3D12Device7 *)device); - - return d3d12_device->vk_physical_device; - } - - struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device) - { -- struct d3d12_device *d3d12_device = impl_from_ID3D12Device5((ID3D12Device5 *)device); -+ struct d3d12_device *d3d12_device = impl_from_ID3D12Device7((ID3D12Device7 *)device); - - return d3d12_device->vkd3d_instance; - } -diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c -index abbdfbe2015..8f4d18358d2 100644 ---- a/libs/vkd3d/libs/vkd3d/resource.c -+++ b/libs/vkd3d/libs/vkd3d/resource.c -@@ -22,7 +22,7 @@ - #define VKD3D_NULL_BUFFER_SIZE 16 - #define VKD3D_NULL_VIEW_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM - --LONG64 object_global_serial_id; -+uint64_t object_global_serial_id; - - static inline bool is_cpu_accessible_heap(const D3D12_HEAP_PROPERTIES *properties) - { -@@ -308,7 +308,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_heap_QueryInterface(ID3D12Heap *iface, - static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface) - { - struct d3d12_heap *heap = impl_from_ID3D12Heap(iface); -- ULONG refcount = InterlockedIncrement(&heap->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&heap->refcount); - - TRACE("%p increasing refcount to %u.\n", heap, refcount); - -@@ -345,7 +345,7 @@ static void d3d12_heap_destroy(struct d3d12_heap *heap) - static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface) - { - struct d3d12_heap *heap = impl_from_ID3D12Heap(iface); -- ULONG refcount = InterlockedDecrement(&heap->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&heap->refcount); - - TRACE("%p decreasing refcount to %u.\n", heap, refcount); - -@@ -358,7 +358,7 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface) - - static void d3d12_heap_resource_destroyed(struct d3d12_heap *heap) - { -- if (!InterlockedDecrement(&heap->resource_count) && (!heap->refcount || heap->is_private)) -+ if (!vkd3d_atomic_decrement_u32(&heap->resource_count) && (!heap->refcount || heap->is_private)) - d3d12_heap_destroy(heap); - } - -@@ -940,7 +940,7 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, - } - - HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_ALLOCATION_INFO *allocation_info) -+ const D3D12_RESOURCE_DESC *desc, struct vkd3d_resource_allocation_info *allocation_info) - { - static const D3D12_HEAP_PROPERTIES heap_properties = {D3D12_HEAP_TYPE_DEFAULT}; - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; -@@ -968,8 +968,8 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, - VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, &requirements)); - VK_CALL(vkDestroyImage(device->vk_device, vk_image, NULL)); - -- allocation_info->SizeInBytes = requirements.size; -- allocation_info->Alignment = requirements.alignment; -+ allocation_info->size_in_bytes = requirements.size; -+ allocation_info->alignment = requirements.alignment; - } - - return hr; -@@ -1003,7 +1003,7 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12 - - static ULONG d3d12_resource_incref(struct d3d12_resource *resource) - { -- ULONG refcount = InterlockedIncrement(&resource->internal_refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&resource->internal_refcount); - - TRACE("%p increasing refcount to %u.\n", resource, refcount); - -@@ -1012,7 +1012,7 @@ static ULONG d3d12_resource_incref(struct d3d12_resource *resource) - - static ULONG d3d12_resource_decref(struct d3d12_resource *resource) - { -- ULONG refcount = InterlockedDecrement(&resource->internal_refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&resource->internal_refcount); - - TRACE("%p decreasing refcount to %u.\n", resource, refcount); - -@@ -1284,7 +1284,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource1 * - static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource1 *iface) - { - struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -- ULONG refcount = InterlockedIncrement(&resource->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&resource->refcount); - - TRACE("%p increasing refcount to %u.\n", resource, refcount); - -@@ -1302,7 +1302,7 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource1 *iface) - static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource1 *iface) - { - struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -- ULONG refcount = InterlockedDecrement(&resource->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&resource->refcount); - - TRACE("%p decreasing refcount to %u.\n", resource, refcount); - -@@ -2174,7 +2174,7 @@ static HRESULT vkd3d_bind_heap_memory(struct d3d12_device *device, - { - resource->heap = heap; - resource->heap_offset = heap_offset; -- InterlockedIncrement(&heap->resource_count); -+ vkd3d_atomic_increment_u32(&heap->resource_count); - } - else - { -@@ -2239,7 +2239,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_ID3D12Device5((ID3D12Device5 *)device); -+ struct d3d12_device *d3d12_device = unsafe_impl_from_ID3D12Device7((ID3D12Device7 *)device); - struct d3d12_resource *object; - HRESULT hr; - -@@ -2314,14 +2314,14 @@ static void *vkd3d_desc_object_cache_get(struct vkd3d_desc_object_cache *cache) - - STATIC_ASSERT(!(ARRAY_SIZE(cache->heads) & HEAD_INDEX_MASK)); - -- i = (vkd3d_atomic_increment(&cache->next_index)) & HEAD_INDEX_MASK; -+ i = vkd3d_atomic_increment_u32(&cache->next_index) & HEAD_INDEX_MASK; - for (;;) - { - if (vkd3d_atomic_compare_exchange(&cache->heads[i].spinlock, 0, 1)) - { - if ((u.object = cache->heads[i].head)) - { -- vkd3d_atomic_decrement(&cache->free_count); -+ vkd3d_atomic_decrement_u32(&cache->free_count); - cache->heads[i].head = u.header->next; - vkd3d_atomic_exchange(&cache->heads[i].spinlock, 0); - return u.object; -@@ -2345,7 +2345,7 @@ static void vkd3d_desc_object_cache_push(struct vkd3d_desc_object_cache *cache, - - /* Using the same index as above may result in a somewhat uneven distribution, - * but the main objective is to avoid costly spinlock contention. */ -- i = (vkd3d_atomic_increment(&cache->next_index)) & HEAD_INDEX_MASK; -+ i = vkd3d_atomic_increment_u32(&cache->next_index) & HEAD_INDEX_MASK; - for (;;) - { - if (vkd3d_atomic_compare_exchange(&cache->heads[i].spinlock, 0, 1)) -@@ -2357,7 +2357,7 @@ static void vkd3d_desc_object_cache_push(struct vkd3d_desc_object_cache *cache, - u.header->next = head; - cache->heads[i].head = u.object; - vkd3d_atomic_exchange(&cache->heads[i].spinlock, 0); -- vkd3d_atomic_increment(&cache->free_count); -+ vkd3d_atomic_increment_u32(&cache->free_count); - } - - #undef HEAD_INDEX_MASK -@@ -2429,7 +2429,7 @@ void vkd3d_view_decref(void *view, struct d3d12_device *device) - { - union d3d12_desc_object u = {view}; - -- if (vkd3d_atomic_decrement(&u.header->refcount)) -+ if (vkd3d_atomic_decrement_u32(&u.header->refcount)) - return; - - if (u.header->magic != VKD3D_DESCRIPTOR_MAGIC_CBV) -@@ -2470,12 +2470,14 @@ static void d3d12_desc_write_vk_heap_null_descriptor(struct d3d12_descriptor_hea - { - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - struct d3d12_descriptor_heap_vk_set *descriptor_set; -- enum vkd3d_vk_descriptor_set_index set; -+ enum vkd3d_vk_descriptor_set_index set, end; - unsigned int i = writes->count; - -+ end = device->vk_info.EXT_mutable_descriptor_type ? VKD3D_SET_INDEX_UNIFORM_BUFFER -+ : VKD3D_SET_INDEX_STORAGE_IMAGE; - /* Binding a shader with the wrong null descriptor type works in Windows. - * To support that here we must write one to all applicable Vulkan sets. */ -- for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= VKD3D_SET_INDEX_STORAGE_IMAGE; ++set) -+ for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= end; ++set) - { - descriptor_set = &descriptor_heap->vk_descriptor_sets[set]; - writes->vk_descriptor_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; -@@ -2632,20 +2634,18 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr - for (; i != UINT_MAX; i = next) - { - src = &descriptors[i]; -- next = (int)src->next >> 1; -+ next = vkd3d_atomic_exchange(&src->next, 0); -+ next = (int)next >> 1; - -+ /* A race exists here between updating src->next and getting the current object. The best -+ * we can do is get the object last, which may result in a harmless rewrite later. */ - u.object = d3d12_desc_get_object_ref(src, device); - - if (!u.object) -- { -- vkd3d_atomic_exchange(&src->next, 0); - continue; -- } - - writes.held_refs[writes.held_ref_count++] = u.object; - d3d12_desc_write_vk_heap(descriptor_heap, i, &writes, u.object, device); -- -- vkd3d_atomic_exchange(&src->next, 0); - } - - /* Avoid thunk calls wherever possible. */ -@@ -3446,6 +3446,7 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor, - vkd3d_desc.miplevel_count = 1; - vkd3d_desc.layer_idx = 0; - vkd3d_desc.layer_count = 1; -+ vkd3d_desc.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT; - vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_R; - vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_G; - vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_B; -@@ -3663,11 +3664,27 @@ static VkSamplerAddressMode vk_address_mode_from_d3d12(const struct d3d12_device - } - } - -+static VkBorderColor vk_border_colour_from_d3d12(D3D12_STATIC_BORDER_COLOR colour) -+{ -+ switch (colour) -+ { -+ case D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK: -+ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; -+ case D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK: -+ return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; -+ case D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE: -+ return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; -+ default: -+ FIXME("Unhandled border colour %#x.\n", colour); -+ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; -+ } -+} -+ - static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER filter, - D3D12_TEXTURE_ADDRESS_MODE address_u, D3D12_TEXTURE_ADDRESS_MODE address_v, - D3D12_TEXTURE_ADDRESS_MODE address_w, float mip_lod_bias, unsigned int max_anisotropy, -- D3D12_COMPARISON_FUNC comparison_func, float min_lod, float max_lod, -- VkSampler *vk_sampler) -+ D3D12_COMPARISON_FUNC comparison_func, D3D12_STATIC_BORDER_COLOR border_colour, -+ float min_lod, float max_lod, VkSampler *vk_sampler) - { - const struct vkd3d_vk_device_procs *vk_procs; - struct VkSamplerCreateInfo sampler_desc; -@@ -3697,15 +3714,48 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f - sampler_desc.maxLod = max_lod; - sampler_desc.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - sampler_desc.unnormalizedCoordinates = VK_FALSE; -+ -+ if (address_u == D3D12_TEXTURE_ADDRESS_MODE_BORDER || address_v == D3D12_TEXTURE_ADDRESS_MODE_BORDER -+ || address_w == D3D12_TEXTURE_ADDRESS_MODE_BORDER) -+ sampler_desc.borderColor = vk_border_colour_from_d3d12(border_colour); -+ - if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0) - WARN("Failed to create Vulkan sampler, vr %d.\n", vr); - - return vr; - } - -+static D3D12_STATIC_BORDER_COLOR d3d12_static_border_colour(const float *colour) -+{ -+ unsigned int i; -+ -+ static const struct -+ { -+ float colour[4]; -+ D3D12_STATIC_BORDER_COLOR static_colour; -+ } -+ colours[] = -+ { -+ {{0.0f, 0.0f, 0.0f, 0.0f}, D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK}, -+ {{0.0f, 0.0f, 0.0f, 1.0f}, D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK}, -+ {{1.0f, 1.0f, 1.0f, 1.0f}, D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE}, -+ }; -+ -+ for (i = 0; i < ARRAY_SIZE(colours); ++i) -+ { -+ if (!memcmp(colour, colours[i].colour, sizeof(colours[i].colour))) -+ return colours[i].static_colour; -+ } -+ -+ FIXME("Unhandled border colour {%.8e, %.8e, %.8e, %.8e}.\n", colour[0], colour[1], colour[2], colour[3]); -+ -+ return D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; -+} -+ - void d3d12_desc_create_sampler(struct d3d12_desc *sampler, - struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc) - { -+ D3D12_STATIC_BORDER_COLOR static_colour = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; - struct vkd3d_view *view; - - if (!desc) -@@ -3717,8 +3767,7 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, - if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER - || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER - || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER) -- FIXME("Ignoring border color {%.8e, %.8e, %.8e, %.8e}.\n", -- desc->BorderColor[0], desc->BorderColor[1], desc->BorderColor[2], desc->BorderColor[3]); -+ static_colour = d3d12_static_border_colour(desc->BorderColor); - - if (!(view = vkd3d_view_create(VKD3D_DESCRIPTOR_MAGIC_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER, - VKD3D_VIEW_TYPE_SAMPLER, device))) -@@ -3726,9 +3775,9 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, - view->v.u.vk_sampler = VK_NULL_HANDLE; - view->v.format = NULL; - -- if (d3d12_create_sampler(device, desc->Filter, desc->AddressU, -- desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, -- desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, &view->v.u.vk_sampler) < 0) -+ if (d3d12_create_sampler(device, desc->Filter, desc->AddressU, desc->AddressV, -+ desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, desc->ComparisonFunc, -+ static_colour, desc->MinLOD, desc->MaxLOD, &view->v.u.vk_sampler) < 0) - { - vkd3d_view_decref(view, device); - return; -@@ -3742,14 +3791,9 @@ HRESULT vkd3d_create_static_sampler(struct d3d12_device *device, - { - VkResult vr; - -- if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER -- || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER -- || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER) -- FIXME("Ignoring border %#x.\n", desc->BorderColor); -- -- vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU, -- desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, -- desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, vk_sampler); -+ vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU, desc->AddressV, -+ desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, desc->ComparisonFunc, -+ desc->BorderColor, desc->MinLOD, desc->MaxLOD, vk_sampler); - return hresult_from_vk_result(vr); - } - -@@ -3966,7 +4010,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_QueryInterface(ID3D12Desc - static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_AddRef(ID3D12DescriptorHeap *iface) - { - struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface); -- ULONG refcount = InterlockedIncrement(&heap->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&heap->refcount); - - TRACE("%p increasing refcount to %u.\n", heap, refcount); - -@@ -3976,7 +4020,7 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_AddRef(ID3D12DescriptorHeap - static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHeap *iface) - { - struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface); -- ULONG refcount = InterlockedDecrement(&heap->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&heap->refcount); - - TRACE("%p decreasing refcount to %u.\n", heap, refcount); - -@@ -3997,6 +4041,9 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHea - { - struct d3d12_desc *descriptors = (struct d3d12_desc *)heap->descriptors; - -+ if (heap->use_vk_heaps) -+ d3d12_device_remove_descriptor_heap(device, heap); -+ - for (i = 0; i < heap->desc.NumDescriptors; ++i) - { - d3d12_desc_destroy(&descriptors[i], device); -@@ -4175,9 +4222,11 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_pool(struct d3d12_descrip - - for (set = 0, pool_desc.poolSizeCount = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set) - { -- if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type) -+ if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type -+ && device->vk_descriptor_heap_layouts[set].vk_set_layout) - { -- pool_sizes[pool_desc.poolSizeCount].type = device->vk_descriptor_heap_layouts[set].type; -+ pool_sizes[pool_desc.poolSizeCount].type = (device->vk_info.EXT_mutable_descriptor_type && !set) -+ ? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[set].type; - pool_sizes[pool_desc.poolSizeCount++].descriptorCount = desc->NumDescriptors; - } - } -@@ -4203,6 +4252,16 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_set(struct d3d12_descript - VkDescriptorSetAllocateInfo set_desc; - VkResult vr; - -+ if (!device->vk_descriptor_heap_layouts[set].vk_set_layout) -+ { -+ /* Set 0 uses mutable descriptors, and this set is unused. */ -+ if (!descriptor_heap->vk_descriptor_sets[0].vk_set) -+ d3d12_descriptor_heap_create_descriptor_set(descriptor_heap, device, 0); -+ descriptor_set->vk_set = descriptor_heap->vk_descriptor_sets[0].vk_set; -+ descriptor_set->vk_type = device->vk_descriptor_heap_layouts[set].type; -+ return S_OK; -+ } -+ - set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - set_desc.pNext = &set_size; - set_desc.descriptorPool = descriptor_heap->vk_descriptor_pool; -@@ -4255,7 +4314,7 @@ static HRESULT d3d12_descriptor_heap_init(struct d3d12_descriptor_heap *descript - - descriptor_heap->ID3D12DescriptorHeap_iface.lpVtbl = &d3d12_descriptor_heap_vtbl; - descriptor_heap->refcount = 1; -- descriptor_heap->serial_id = InterlockedIncrement64(&object_global_serial_id); -+ descriptor_heap->serial_id = vkd3d_atomic_increment_u64(&object_global_serial_id); - - descriptor_heap->desc = *desc; - -@@ -4320,6 +4379,12 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, - dst[i].next = 0; - } - object->dirty_list_head = UINT_MAX; -+ -+ if (object->use_vk_heaps && FAILED(hr = d3d12_device_add_descriptor_heap(device, object))) -+ { -+ vkd3d_free(object); -+ return hr; -+ } - } - else - { -@@ -4364,7 +4429,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_query_heap_QueryInterface(ID3D12QueryHeap - static ULONG STDMETHODCALLTYPE d3d12_query_heap_AddRef(ID3D12QueryHeap *iface) - { - struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface); -- ULONG refcount = InterlockedIncrement(&heap->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&heap->refcount); - - TRACE("%p increasing refcount to %u.\n", heap, refcount); - -@@ -4374,7 +4439,7 @@ static ULONG STDMETHODCALLTYPE d3d12_query_heap_AddRef(ID3D12QueryHeap *iface) - static ULONG STDMETHODCALLTYPE d3d12_query_heap_Release(ID3D12QueryHeap *iface) - { - struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface); -- ULONG refcount = InterlockedDecrement(&heap->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&heap->refcount); - - TRACE("%p decreasing refcount to %u.\n", heap, refcount); - -@@ -4858,7 +4923,7 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources, - return vkd3d_init_null_resources_data(null_resources, device); - - fail: -- ERR("Failed to initialize NULL resources, hr %#x.\n", hr); -+ ERR("Failed to initialise NULL resources, hr %s.\n", debugstr_hresult(hr)); - vkd3d_destroy_null_resources(null_resources, device); - return hr; - } -diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c -index fc3187f4bea..3428742dd7f 100644 ---- a/libs/vkd3d/libs/vkd3d/state.c -+++ b/libs/vkd3d/libs/vkd3d/state.c -@@ -52,7 +52,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_root_signature_QueryInterface(ID3D12RootS - static ULONG STDMETHODCALLTYPE d3d12_root_signature_AddRef(ID3D12RootSignature *iface) - { - struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface); -- ULONG refcount = InterlockedIncrement(&root_signature->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&root_signature->refcount); - - TRACE("%p increasing refcount to %u.\n", root_signature, refcount); - -@@ -110,7 +110,7 @@ static void d3d12_root_signature_cleanup(struct d3d12_root_signature *root_signa - static ULONG STDMETHODCALLTYPE d3d12_root_signature_Release(ID3D12RootSignature *iface) - { - struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(iface); -- ULONG refcount = InterlockedDecrement(&root_signature->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&root_signature->refcount); - - TRACE("%p decreasing refcount to %u.\n", root_signature, refcount); - -@@ -515,7 +515,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat - assert(p->ShaderVisibility <= D3D12_SHADER_VISIBILITY_PIXEL); - push_constants[p->ShaderVisibility].stageFlags = use_vk_heaps ? VK_SHADER_STAGE_ALL - : stage_flags_from_visibility(p->ShaderVisibility); -- push_constants[p->ShaderVisibility].size += p->u.Constants.Num32BitValues * sizeof(uint32_t); -+ push_constants[p->ShaderVisibility].size += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t); - } - if (push_constants[D3D12_SHADER_VISIBILITY_ALL].size) - { -@@ -564,7 +564,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat - - idx = push_constant_count == 1 ? 0 : p->ShaderVisibility; - offset = push_constants_offset[idx]; -- push_constants_offset[idx] += p->u.Constants.Num32BitValues * sizeof(uint32_t); -+ push_constants_offset[idx] += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t); - - root_signature->parameters[i].parameter_type = p->ParameterType; - root_constant->stage_flags = push_constant_count == 1 -@@ -848,7 +848,20 @@ static void vkd3d_descriptor_heap_binding_from_descriptor_range(const struct d3d - const struct vkd3d_device_descriptor_limits *descriptor_limits = &root_signature->device->vk_info.descriptor_limits; - unsigned int descriptor_set_size; - -- switch (range->type) -+ if (root_signature->device->vk_info.EXT_mutable_descriptor_type) -+ { -+ if (range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) -+ { -+ binding->set = VKD3D_SET_INDEX_SAMPLER; -+ descriptor_set_size = descriptor_limits->sampler_max_descriptors; -+ } -+ else -+ { -+ binding->set = 0; -+ descriptor_set_size = descriptor_limits->sampled_image_max_descriptors; -+ } -+ } -+ else switch (range->type) - { - case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: - binding->set = is_buffer ? VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER : VKD3D_SET_INDEX_SAMPLED_IMAGE; -@@ -1368,8 +1381,14 @@ static unsigned int d3d12_root_signature_copy_descriptor_set_layouts(const struc - - if (device->use_vk_heaps) - { -+ VkDescriptorSetLayout mutable_layout = device->vk_descriptor_heap_layouts[0].vk_set_layout; -+ - for (set = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set) -- vk_set_layouts[i++] = device->vk_descriptor_heap_layouts[set].vk_set_layout; -+ { -+ VkDescriptorSetLayout vk_set_layout = device->vk_descriptor_heap_layouts[set].vk_set_layout; -+ /* All layouts must be valid, so if null, just set it to the mutable one. */ -+ vk_set_layouts[i++] = vk_set_layout ? vk_set_layout : mutable_layout; -+ } - } - - return i; -@@ -1691,7 +1710,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache, - HRESULT hr = S_OK; - unsigned int i; - -- vkd3d_mutex_lock(&device->mutex); -+ vkd3d_mutex_lock(&device->pipeline_cache_mutex); - - for (i = 0; i < cache->render_pass_count; ++i) - { -@@ -1708,7 +1727,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache, - if (!found) - hr = vkd3d_render_pass_cache_create_pass_locked(cache, device, key, vk_render_pass); - -- vkd3d_mutex_unlock(&device->mutex); -+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); - - return hr; - } -@@ -1965,7 +1984,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_pipeline_state_QueryInterface(ID3D12Pipel - static ULONG STDMETHODCALLTYPE d3d12_pipeline_state_AddRef(ID3D12PipelineState *iface) - { - struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface); -- ULONG refcount = InterlockedIncrement(&state->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&state->refcount); - - TRACE("%p increasing refcount to %u.\n", state, refcount); - -@@ -2008,7 +2027,7 @@ static void d3d12_pipeline_uav_counter_state_cleanup(struct d3d12_pipeline_uav_c - static ULONG STDMETHODCALLTYPE d3d12_pipeline_state_Release(ID3D12PipelineState *iface) - { - struct d3d12_pipeline_state *state = impl_from_ID3D12PipelineState(iface); -- ULONG refcount = InterlockedDecrement(&state->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&state->refcount); - - TRACE("%p decreasing refcount to %u.\n", state, refcount); - -@@ -2129,6 +2148,18 @@ static inline unsigned int typed_uav_compile_option(const struct d3d12_device *d - : VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_R32; - } - -+static unsigned int feature_flags_compile_option(const struct d3d12_device *device) -+{ -+ unsigned int flags = 0; -+ -+ if (device->feature_options1.Int64ShaderOps) -+ flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64; -+ if (device->feature_options.DoublePrecisionFloatShaderOps) -+ flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLOAT64; -+ -+ return flags; -+} -+ - static HRESULT create_shader_stage(struct d3d12_device *device, - struct VkPipelineShaderStageCreateInfo *stage_desc, enum VkShaderStageFlagBits stage, - const D3D12_SHADER_BYTECODE *code, const struct vkd3d_shader_interface_info *shader_interface) -@@ -2145,6 +2176,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, - {VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_10}, - {VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)}, - {VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE, 0}, -+ {VKD3D_SHADER_COMPILE_OPTION_FEATURE, feature_flags_compile_option(device)}, - }; - - stage_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; -@@ -2240,7 +2272,7 @@ static HRESULT vkd3d_create_compute_pipeline(struct d3d12_device *device, - VK_CALL(vkDestroyShaderModule(device->vk_device, pipeline_info.stage.module, NULL)); - if (vr < 0) - { -- WARN("Failed to create Vulkan compute pipeline, hr %#x.\n", hr); -+ WARN("Failed to create Vulkan compute pipeline, hr %s.\n", debugstr_hresult(hr)); - return hresult_from_vk_result(vr); - } - -@@ -2368,7 +2400,7 @@ static HRESULT d3d12_pipeline_state_find_and_init_uav_counters(struct d3d12_pipe - } - - if (FAILED(hr = d3d12_pipeline_state_init_uav_counters(state, device, root_signature, &shader_info, stage_flags))) -- WARN("Failed to create descriptor set layout for UAV counters, hr %#x.\n", hr); -+ WARN("Failed to create descriptor set layout for UAV counters, hr %s.\n", debugstr_hresult(hr)); - - vkd3d_shader_free_scan_descriptor_info(&shader_info); - -@@ -2442,7 +2474,7 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st - if (FAILED(hr = vkd3d_create_compute_pipeline(device, &desc->cs, &shader_interface, - vk_pipeline_layout, &state->u.compute.vk_pipeline))) - { -- WARN("Failed to create Vulkan compute pipeline, hr %#x.\n", hr); -+ WARN("Failed to create Vulkan compute pipeline, hr %s.\n", debugstr_hresult(hr)); - d3d12_pipeline_uav_counter_state_cleanup(&state->uav_counters, device); - return hr; - } -@@ -3615,7 +3647,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12 - - *vk_render_pass = VK_NULL_HANDLE; - -- vkd3d_mutex_lock(&device->mutex); -+ vkd3d_mutex_lock(&device->pipeline_cache_mutex); - - LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry) - { -@@ -3627,7 +3659,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12 - } - } - -- vkd3d_mutex_unlock(&device->mutex); -+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); - - return vk_pipeline; - } -@@ -3646,7 +3678,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta - compiled_pipeline->vk_pipeline = vk_pipeline; - compiled_pipeline->vk_render_pass = vk_render_pass; - -- vkd3d_mutex_lock(&device->mutex); -+ vkd3d_mutex_lock(&device->pipeline_cache_mutex); - - LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry) - { -@@ -3661,7 +3693,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta - if (compiled_pipeline) - list_add_tail(&graphics->compiled_pipelines, &compiled_pipeline->entry); - -- vkd3d_mutex_unlock(&device->mutex); -+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); - return compiled_pipeline; - } - -@@ -3996,14 +4028,14 @@ HRESULT vkd3d_uav_clear_state_init(struct vkd3d_uav_clear_state *state, struct d - if (FAILED(hr = vkd3d_create_descriptor_set_layout(device, 0, - 1, false, &set_binding, set_layouts[i].set_layout))) - { -- ERR("Failed to create descriptor set layout %u, hr %#x.\n", i, hr); -+ ERR("Failed to create descriptor set layout %u, hr %s.\n", i, debugstr_hresult(hr)); - goto fail; - } - - if (FAILED(hr = vkd3d_create_pipeline_layout(device, 1, set_layouts[i].set_layout, - 1, &push_constant_range, set_layouts[i].pipeline_layout))) - { -- ERR("Failed to create pipeline layout %u, hr %#x.\n", i, hr); -+ ERR("Failed to create pipeline layout %u, hr %s.\n", i, debugstr_hresult(hr)); - goto fail; - } - } -@@ -4041,7 +4073,7 @@ HRESULT vkd3d_uav_clear_state_init(struct vkd3d_uav_clear_state *state, struct d - vkd3d_shader_free_shader_code(&dxbc); - if (FAILED(hr)) - { -- ERR("Failed to create compute pipeline %u, hr %#x.\n", i, hr); -+ ERR("Failed to create compute pipeline %u, hr %s.\n", i, debugstr_hresult(hr)); - goto fail; - } - } -diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c -index 9b28068be51..ac79ae5ddff 100644 ---- a/libs/vkd3d/libs/vkd3d/utils.c -+++ b/libs/vkd3d/libs/vkd3d/utils.c -@@ -539,6 +539,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) - { - static const D3D_FEATURE_LEVEL valid_feature_levels[] = - { -+ D3D_FEATURE_LEVEL_12_2, - D3D_FEATURE_LEVEL_12_1, - D3D_FEATURE_LEVEL_12_0, - D3D_FEATURE_LEVEL_11_1, -@@ -548,6 +549,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) - D3D_FEATURE_LEVEL_9_3, - D3D_FEATURE_LEVEL_9_2, - D3D_FEATURE_LEVEL_9_1, -+ D3D_FEATURE_LEVEL_1_0_CORE, - }; - unsigned int i; - -@@ -630,6 +632,11 @@ HRESULT return_interface(void *iface, REFIID iface_iid, - return hr; - } - -+const char *debug_cpu_handle(D3D12_CPU_DESCRIPTOR_HANDLE handle) -+{ -+ return vkd3d_dbg_sprintf("{%#"PRIxPTR"}", (uintptr_t)handle.ptr); -+} -+ - const char *debug_d3d12_box(const D3D12_BOX *box) - { - if (!box) -@@ -671,6 +678,11 @@ const char *debug_d3d12_shader_component_mapping(unsigned int mapping) - debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(3, mapping))); - } - -+const char *debug_gpu_handle(D3D12_GPU_DESCRIPTOR_HANDLE handle) -+{ -+ return vkd3d_dbg_sprintf("{%#"PRIx64"}", handle.ptr); -+} -+ - const char *debug_vk_extent_3d(VkExtent3D extent) - { - return vkd3d_dbg_sprintf("(%u, %u, %u)", -@@ -681,7 +693,7 @@ const char *debug_vk_extent_3d(VkExtent3D extent) - - const char *debug_vk_queue_flags(VkQueueFlags flags) - { -- char buffer[120]; -+ char buffer[159]; - - buffer[0] = '\0'; - #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; } -@@ -689,6 +701,10 @@ const char *debug_vk_queue_flags(VkQueueFlags flags) - FLAG_TO_STR(VK_QUEUE_COMPUTE_BIT) - FLAG_TO_STR(VK_QUEUE_TRANSFER_BIT) - FLAG_TO_STR(VK_QUEUE_SPARSE_BINDING_BIT) -+ FLAG_TO_STR(VK_QUEUE_PROTECTED_BIT) -+#undef FLAG_TO_STR -+#define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; } -+ FLAG_TO_STR(0x20, VK_QUEUE_VIDEO_DECODE_BIT_KHR) - #undef FLAG_TO_STR - if (flags) - FIXME("Unrecognized flag(s) %#x.\n", flags); -@@ -727,10 +743,8 @@ const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags) - FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_CACHED_BIT) - FLAG_TO_STR(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) - FLAG_TO_STR(VK_MEMORY_PROPERTY_PROTECTED_BIT) --#undef FLAG_TO_STR --#define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; } -- FLAG_TO_STR(0x40, VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) -- FLAG_TO_STR(0x80, VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD) -+ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) -+ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD) - #undef FLAG_TO_STR - if (flags) - FIXME("Unrecognized flag(s) %#x.\n", flags); -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/libs/vkd3d/vkd3d_main.c -index 245edb5aeac..7919b7d8760 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_main.c -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_main.c -@@ -60,7 +60,7 @@ HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info, - } - else if (FAILED(hr = vkd3d_create_instance(create_info->instance_create_info, &instance))) - { -- WARN("Failed to create instance, hr %#x.\n", hr); -+ WARN("Failed to create instance, hr %s.\n", debugstr_hresult(hr)); - return E_FAIL; - } - -@@ -71,18 +71,18 @@ HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info, - - if (!device) - { -- ID3D12Device_Release(&object->ID3D12Device5_iface); -+ ID3D12Device_Release(&object->ID3D12Device7_iface); - return S_FALSE; - } - -- return return_interface(&object->ID3D12Device5_iface, &IID_ID3D12Device, iid, device); -+ return return_interface(&object->ID3D12Device7_iface, &IID_ID3D12Device, iid, device); - } - - /* ID3D12RootSignatureDeserializer */ - struct d3d12_root_signature_deserializer - { - ID3D12RootSignatureDeserializer ID3D12RootSignatureDeserializer_iface; -- LONG refcount; -+ unsigned int refcount; - - union - { -@@ -123,7 +123,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_root_signature_deserializer_QueryInterfac - static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_AddRef(ID3D12RootSignatureDeserializer *iface) - { - struct d3d12_root_signature_deserializer *deserializer = impl_from_ID3D12RootSignatureDeserializer(iface); -- ULONG refcount = InterlockedIncrement(&deserializer->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&deserializer->refcount); - - TRACE("%p increasing refcount to %u.\n", deserializer, refcount); - -@@ -133,7 +133,7 @@ static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_AddRef(ID3D12Ro - static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_Release(ID3D12RootSignatureDeserializer *iface) - { - struct d3d12_root_signature_deserializer *deserializer = impl_from_ID3D12RootSignatureDeserializer(iface); -- ULONG refcount = InterlockedDecrement(&deserializer->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&deserializer->refcount); - - TRACE("%p decreasing refcount to %u.\n", deserializer, refcount); - -@@ -222,8 +222,8 @@ HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_s - struct d3d12_root_signature_deserializer *object; - HRESULT hr; - -- TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n", -- data, data_size, debugstr_guid(iid), deserializer); -+ TRACE("data %p, data_size %"PRIuPTR", iid %s, deserializer %p.\n", -+ data, (uintptr_t)data_size, debugstr_guid(iid), deserializer); - - if (!(object = vkd3d_malloc(sizeof(*object)))) - return E_OUTOFMEMORY; -@@ -242,7 +242,7 @@ HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_s - struct d3d12_versioned_root_signature_deserializer - { - ID3D12VersionedRootSignatureDeserializer ID3D12VersionedRootSignatureDeserializer_iface; -- LONG refcount; -+ unsigned int refcount; - - union - { -@@ -284,7 +284,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_Que - static ULONG STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_AddRef(ID3D12VersionedRootSignatureDeserializer *iface) - { - struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface); -- ULONG refcount = InterlockedIncrement(&deserializer->refcount); -+ unsigned int refcount = vkd3d_atomic_increment_u32(&deserializer->refcount); - - TRACE("%p increasing refcount to %u.\n", deserializer, refcount); - -@@ -294,7 +294,7 @@ static ULONG STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_AddRe - static ULONG STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_Release(ID3D12VersionedRootSignatureDeserializer *iface) - { - struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface); -- ULONG refcount = InterlockedDecrement(&deserializer->refcount); -+ unsigned int refcount = vkd3d_atomic_decrement_u32(&deserializer->refcount); - - TRACE("%p decreasing refcount to %u.\n", deserializer, refcount); - -@@ -406,8 +406,8 @@ HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZ - struct vkd3d_shader_code dxbc = {data, data_size}; - HRESULT hr; - -- TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n", -- data, data_size, debugstr_guid(iid), deserializer); -+ TRACE("data %p, data_size %"PRIuPTR", iid %s, deserializer %p.\n", -+ data, (uintptr_t)data_size, debugstr_guid(iid), deserializer); - - if (!(object = vkd3d_malloc(sizeof(*object)))) - return E_OUTOFMEMORY; -@@ -456,7 +456,7 @@ HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc, - if (error_blob && messages) - { - if (FAILED(hr = vkd3d_blob_create(messages, strlen(messages), error_blob))) -- ERR("Failed to create error blob, hr %#x.\n", hr); -+ ERR("Failed to create error blob, hr %s.\n", debugstr_hresult(hr)); - } - return hresult_from_vkd3d_result(ret); - } -@@ -464,7 +464,7 @@ HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc, - - if (FAILED(hr = vkd3d_blob_create((void *)dxbc.code, dxbc.size, blob))) - { -- WARN("Failed to create blob object, hr %#x.\n", hr); -+ WARN("Failed to create blob object, hr %s.\n", debugstr_hresult(hr)); - vkd3d_shader_free_shader_code(&dxbc); - } - return hr; -@@ -497,7 +497,7 @@ HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGN - if (error_blob && messages) - { - if (FAILED(hr = vkd3d_blob_create(messages, strlen(messages), error_blob))) -- ERR("Failed to create error blob, hr %#x.\n", hr); -+ ERR("Failed to create error blob, hr %s.\n", debugstr_hresult(hr)); - } - return hresult_from_vkd3d_result(ret); - } -@@ -505,7 +505,7 @@ HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGN - - if (FAILED(hr = vkd3d_blob_create((void *)dxbc.code, dxbc.size, blob))) - { -- WARN("Failed to create blob object, hr %#x.\n", hr); -+ WARN("Failed to create blob object, hr %s.\n", debugstr_hresult(hr)); - vkd3d_shader_free_shader_code(&dxbc); - } - return hr; -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index f06f564d6ea..78f4f3514e2 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -@@ -55,7 +55,7 @@ - - #define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u - #define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u --#define VKD3D_MAX_SHADER_EXTENSIONS 3u -+#define VKD3D_MAX_SHADER_EXTENSIONS 4u - #define VKD3D_MAX_SHADER_STAGES 5u - #define VKD3D_MAX_VK_SYNC_OBJECTS 4u - #define VKD3D_MAX_DEVICE_BLOCKED_QUEUES 16u -@@ -67,7 +67,7 @@ - * this number to prevent excessive pool memory use. */ - #define VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE (16 * 1024u) - --extern LONG64 object_global_serial_id; -+extern uint64_t object_global_serial_id; - - struct d3d12_command_list; - struct d3d12_device; -@@ -133,9 +133,11 @@ struct vkd3d_vulkan_info - bool EXT_debug_marker; - bool EXT_depth_clip_enable; - bool EXT_descriptor_indexing; -+ bool EXT_mutable_descriptor_type; - bool EXT_robustness2; - bool EXT_shader_demote_to_helper_invocation; - bool EXT_shader_stencil_export; -+ bool EXT_shader_viewport_index_layer; - bool EXT_texel_buffer_alignment; - bool EXT_transform_feedback; - bool EXT_vertex_attribute_divisor; -@@ -190,7 +192,7 @@ struct vkd3d_instance - - uint64_t host_ticks_per_second; - -- LONG refcount; -+ unsigned int refcount; - }; - - #ifdef _WIN32 -@@ -248,23 +250,13 @@ static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond) - static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock) - { - if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE)) -- ERR("Could not sleep on the condition variable, error %u.\n", GetLastError()); -+ ERR("Could not sleep on the condition variable, error %lu.\n", GetLastError()); - } - - static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond) - { - } - --static inline unsigned int vkd3d_atomic_increment(unsigned int volatile *x) --{ -- return InterlockedIncrement((LONG volatile *)x); --} -- --static inline unsigned int vkd3d_atomic_decrement(unsigned int volatile *x) --{ -- return InterlockedDecrement((LONG volatile *)x); --} -- - static inline bool vkd3d_atomic_compare_exchange(unsigned int volatile *x, unsigned int cmp, unsigned int xchg) - { - return InterlockedCompareExchange((LONG volatile *)x, xchg, cmp) == cmp; -@@ -387,24 +379,6 @@ static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond) - ERR("Could not destroy the condition variable, error %d.\n", ret); - } - --# if HAVE_SYNC_SUB_AND_FETCH --static inline unsigned int vkd3d_atomic_decrement(unsigned int volatile *x) --{ -- return __sync_sub_and_fetch(x, 1); --} --# else --# error "vkd3d_atomic_decrement() not implemented for this platform" --# endif /* HAVE_SYNC_SUB_AND_FETCH */ -- --# if HAVE_SYNC_ADD_AND_FETCH --static inline unsigned int vkd3d_atomic_increment(unsigned int volatile *x) --{ -- return __sync_add_and_fetch(x, 1); --} --# else --# error "vkd3d_atomic_increment() not implemented for this platform" --# endif /* HAVE_SYNC_ADD_AND_FETCH */ -- - # if HAVE_SYNC_BOOL_COMPARE_AND_SWAP - static inline bool vkd3d_atomic_compare_exchange(unsigned int volatile *x, unsigned int cmp, unsigned int xchg) - { -@@ -491,13 +465,13 @@ struct vkd3d_fence_worker - struct vkd3d_gpu_va_allocation - { - D3D12_GPU_VIRTUAL_ADDRESS base; -- size_t size; -+ uint64_t size; - void *ptr; - }; - - struct vkd3d_gpu_va_slab - { -- size_t size; -+ uint64_t size; - void *ptr; - }; - -@@ -515,7 +489,7 @@ struct vkd3d_gpu_va_allocator - }; - - D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_allocator *allocator, -- size_t alignment, size_t size, void *ptr); -+ size_t alignment, uint64_t size, void *ptr); - void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address); - void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address); - -@@ -619,8 +593,8 @@ struct vkd3d_signaled_semaphore - struct d3d12_fence - { - ID3D12Fence1 ID3D12Fence1_iface; -- LONG internal_refcount; -- LONG refcount; -+ unsigned int internal_refcount; -+ unsigned int refcount; - - D3D12_FENCE_FLAGS flags; - -@@ -663,8 +637,8 @@ VkResult vkd3d_create_timeline_semaphore(const struct d3d12_device *device, uint - struct d3d12_heap - { - ID3D12Heap ID3D12Heap_iface; -- LONG refcount; -- LONG resource_count; -+ unsigned int refcount; -+ unsigned int resource_count; - - bool is_private; - D3D12_HEAP_DESC desc; -@@ -719,8 +693,8 @@ struct d3d12_resource_tile_info - struct d3d12_resource - { - ID3D12Resource1 ID3D12Resource1_iface; -- LONG refcount; -- LONG internal_refcount; -+ unsigned int refcount; -+ unsigned int internal_refcount; - - D3D12_RESOURCE_DESC desc; - const struct vkd3d_format *format; -@@ -768,6 +742,13 @@ static inline bool d3d12_resource_is_texture(const struct d3d12_resource *resour - return resource->desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER; - } - -+struct vkd3d_resource_allocation_info -+{ -+ uint64_t offset; -+ uint64_t alignment; -+ uint64_t size_in_bytes; -+}; -+ - bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource); - HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device); - void d3d12_resource_get_tiling(struct d3d12_device *device, const struct d3d12_resource *resource, -@@ -795,7 +776,7 @@ HRESULT vkd3d_create_buffer(struct d3d12_device *device, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, - const D3D12_RESOURCE_DESC *desc, VkBuffer *vk_buffer); - HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_ALLOCATION_INFO *allocation_info); -+ const D3D12_RESOURCE_DESC *desc, struct vkd3d_resource_allocation_info *allocation_info); - - enum vkd3d_view_type - { -@@ -1044,7 +1025,7 @@ struct d3d12_descriptor_heap_vk_set - struct d3d12_descriptor_heap - { - ID3D12DescriptorHeap ID3D12DescriptorHeap_iface; -- LONG refcount; -+ unsigned int refcount; - uint64_t serial_id; - - D3D12_DESCRIPTOR_HEAP_DESC desc; -@@ -1083,7 +1064,7 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, - struct d3d12_query_heap - { - ID3D12QueryHeap ID3D12QueryHeap_iface; -- LONG refcount; -+ unsigned int refcount; - - VkQueryPool vk_query_pool; - -@@ -1170,7 +1151,7 @@ struct d3d12_descriptor_set_layout - struct d3d12_root_signature - { - ID3D12RootSignature ID3D12RootSignature_iface; -- LONG refcount; -+ unsigned int refcount; - - VkPipelineLayout vk_pipeline_layout; - struct d3d12_descriptor_set_layout descriptor_set_layouts[VKD3D_MAX_DESCRIPTOR_SETS]; -@@ -1279,7 +1260,7 @@ struct d3d12_pipeline_uav_counter_state - struct d3d12_pipeline_state - { - ID3D12PipelineState ID3D12PipelineState_iface; -- LONG refcount; -+ unsigned int refcount; - - union - { -@@ -1363,7 +1344,7 @@ struct vkd3d_buffer - struct d3d12_command_allocator - { - ID3D12CommandAllocator ID3D12CommandAllocator_iface; -- LONG refcount; -+ unsigned int refcount; - - D3D12_COMMAND_LIST_TYPE type; - VkQueueFlags vk_queue_flags; -@@ -1464,7 +1445,7 @@ enum vkd3d_pipeline_bind_point - struct d3d12_command_list - { - ID3D12GraphicsCommandList5 ID3D12GraphicsCommandList5_iface; -- LONG refcount; -+ unsigned int refcount; - - D3D12_COMMAND_LIST_TYPE type; - VkQueueFlags vk_queue_flags; -@@ -1620,7 +1601,7 @@ struct d3d12_command_queue_op_array - struct d3d12_command_queue - { - ID3D12CommandQueue ID3D12CommandQueue_iface; -- LONG refcount; -+ unsigned int refcount; - - D3D12_COMMAND_QUEUE_DESC desc; - -@@ -1655,7 +1636,7 @@ HRESULT d3d12_command_queue_create(struct d3d12_device *device, - struct d3d12_command_signature - { - ID3D12CommandSignature ID3D12CommandSignature_iface; -- LONG refcount; -+ unsigned int refcount; - unsigned int internal_refcount; - - D3D12_COMMAND_SIGNATURE_DESC desc; -@@ -1746,8 +1727,8 @@ struct vkd3d_desc_object_cache - /* ID3D12Device */ - struct d3d12_device - { -- ID3D12Device5 ID3D12Device5_iface; -- LONG refcount; -+ ID3D12Device7 ID3D12Device7_iface; -+ unsigned int refcount; - - VkDevice vk_device; - VkPhysicalDevice vk_physical_device; -@@ -1757,9 +1738,23 @@ struct d3d12_device - - struct vkd3d_gpu_va_allocator gpu_va_allocator; - -- struct vkd3d_mutex mutex; - struct vkd3d_desc_object_cache view_desc_cache; - struct vkd3d_desc_object_cache cbuffer_desc_cache; -+ -+ VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT]; -+ unsigned int vk_pool_count; -+ struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT]; -+ bool use_vk_heaps; -+ -+ struct d3d12_descriptor_heap **heaps; -+ size_t heap_capacity; -+ size_t heap_count; -+ union vkd3d_thread_handle worker_thread; -+ struct vkd3d_mutex worker_mutex; -+ struct vkd3d_cond worker_cond; -+ bool worker_should_exit; -+ -+ struct vkd3d_mutex pipeline_cache_mutex; - struct vkd3d_render_pass_cache render_pass_cache; - VkPipelineCache vk_pipeline_cache; - -@@ -1799,11 +1794,6 @@ struct d3d12_device - const struct vkd3d_format_compatibility_list *format_compatibility_lists; - struct vkd3d_null_resources null_resources; - struct vkd3d_uav_clear_state uav_clear_state; -- -- VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT]; -- unsigned int vk_pool_count; -- struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT]; -- bool use_vk_heaps; - }; - - HRESULT d3d12_device_create(struct vkd3d_instance *instance, -@@ -1812,27 +1802,29 @@ 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_ID3D12Device5(ID3D12Device5 *iface); -+struct d3d12_device *unsafe_impl_from_ID3D12Device7(ID3D12Device7 *iface); -+HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap); -+void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap); - - static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object) - { -- return ID3D12Device5_QueryInterface(&device->ID3D12Device5_iface, iid, object); -+ return ID3D12Device7_QueryInterface(&device->ID3D12Device7_iface, iid, object); - } - - static inline ULONG d3d12_device_add_ref(struct d3d12_device *device) - { -- return ID3D12Device5_AddRef(&device->ID3D12Device5_iface); -+ return ID3D12Device7_AddRef(&device->ID3D12Device7_iface); - } - - static inline ULONG d3d12_device_release(struct d3d12_device *device) - { -- return ID3D12Device5_Release(&device->ID3D12Device5_iface); -+ return ID3D12Device7_Release(&device->ID3D12Device7_iface); - } - - static inline unsigned int d3d12_device_get_descriptor_handle_increment_size(struct d3d12_device *device, - D3D12_DESCRIPTOR_HEAP_TYPE descriptor_type) - { -- return ID3D12Device5_GetDescriptorHandleIncrementSize(&device->ID3D12Device5_iface, descriptor_type); -+ return ID3D12Device7_GetDescriptorHandleIncrementSize(&device->ID3D12Device7_iface, descriptor_type); - } - - /* utils */ -@@ -1940,8 +1932,10 @@ bool is_write_resource_state(D3D12_RESOURCE_STATES state); - - HRESULT return_interface(void *iface, REFIID iface_iid, REFIID requested_iid, void **object); - -+const char *debug_cpu_handle(D3D12_CPU_DESCRIPTOR_HANDLE handle); - const char *debug_d3d12_box(const D3D12_BOX *box); - const char *debug_d3d12_shader_component_mapping(unsigned int mapping); -+const char *debug_gpu_handle(D3D12_GPU_DESCRIPTOR_HANDLE handle); - const char *debug_vk_extent_3d(VkExtent3D extent); - const char *debug_vk_memory_heap_flags(VkMemoryHeapFlags flags); - const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags); --- -2.43.0 - diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-628acb6b96eaae24861402dfa2be641c44c.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-628acb6b96eaae24861402dfa2be641c44c.patch deleted file mode 100644 index c6fd29f3..00000000 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-628acb6b96eaae24861402dfa2be641c44c.patch +++ /dev/null @@ -1,638 +0,0 @@ -From 18cc9a5fae9ba51354b6febe00f5a52587255d02 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Thu, 15 Feb 2024 11:01:11 +1100 -Subject: [PATCH] Updated vkd3d to 628acb6b96eaae24861402dfa2be641c44ce2480. - ---- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 221 ++++++++++++++++-- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 18 +- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 7 +- - libs/vkd3d/libs/vkd3d/device.c | 85 ++++++- - 4 files changed, 304 insertions(+), 27 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index a001f6f0642..33d30aef08e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -33,7 +33,7 @@ static const uint64_t ALLOCA_FLAG_IN_ALLOCA = 0x20; - static const uint64_t ALLOCA_FLAG_EXPLICIT_TYPE = 0x40; - static const uint64_t ALLOCA_ALIGNMENT_MASK = ALLOCA_FLAG_IN_ALLOCA - 1; - static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4; --static const size_t MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION = 5; -+static const size_t MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION = 11; - - static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; - -@@ -228,6 +228,13 @@ enum dxil_component_type - COMPONENT_TYPE_PACKEDU8X32 = 18, - }; - -+enum dxil_sampler_kind -+{ -+ SAMPLER_KIND_DEFAULT = 0, -+ SAMPLER_KIND_COMPARISON = 1, -+ SAMPLER_KIND_MONO = 2, -+}; -+ - enum dxil_semantic_kind - { - SEMANTIC_KIND_ARBITRARY = 0, -@@ -369,6 +376,8 @@ enum dx_intrinsic_opcode - DX_UBFE = 52, - DX_CREATE_HANDLE = 57, - DX_CBUFFER_LOAD_LEGACY = 59, -+ DX_SAMPLE = 60, -+ DX_SAMPLE_GRAD = 63, - DX_TEXTURE_LOAD = 66, - DX_TEXTURE_STORE = 67, - DX_BUFFER_LOAD = 68, -@@ -2421,6 +2430,26 @@ static bool sm6_value_validate_is_texture_handle(const struct sm6_value *value, - return true; - } - -+static bool sm6_value_validate_is_sampler_handle(const struct sm6_value *value, enum dx_intrinsic_opcode op, -+ struct sm6_parser *sm6) -+{ -+ enum dxil_resource_kind kind; -+ -+ if (!sm6_value_validate_is_handle(value, sm6)) -+ return false; -+ -+ kind = value->u.handle.d->kind; -+ if (kind != RESOURCE_KIND_SAMPLER) -+ { -+ WARN("Resource kind %u for op %u is not a sampler.\n", kind, op); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE, -+ "Resource kind %u for sample operation %u is not a sampler.", kind, op); -+ return false; -+ } -+ -+ return true; -+} -+ - static bool sm6_value_validate_is_pointer(const struct sm6_value *value, struct sm6_parser *sm6) - { - if (!sm6_type_is_pointer(value->type)) -@@ -3500,7 +3529,8 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - "Ignoring flags %#"PRIx64" for a binary operation.", flags); - } - -- src_params = instruction_src_params_alloc(ins, 2, sm6); -+ if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) -+ return; - src_param_init_from_value(&src_params[0], a); - src_param_init_from_value(&src_params[1], b); - if (code == BINOP_SUB) -@@ -3654,11 +3684,10 @@ static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const st - } - - static bool sm6_parser_emit_coordinate_construct(struct sm6_parser *sm6, const struct sm6_value **operands, -- const struct sm6_value *z_operand, struct function_emission_state *state, -+ unsigned int max_operands, const struct sm6_value *z_operand, struct function_emission_state *state, - struct vkd3d_shader_register *reg) - { - const struct vkd3d_shader_register *operand_regs[VKD3D_VEC4_SIZE]; -- const unsigned int max_operands = 3; - unsigned int component_count; - - for (component_count = 0; component_count < max_operands; ++component_count) -@@ -3751,7 +3780,8 @@ static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_o - struct vkd3d_shader_src_param *src_param; - - vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param_init_from_value(src_param, operands[0]); - - instruction_dst_param_init_ssa_scalar(ins, sm6); -@@ -3785,7 +3815,8 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ - struct vkd3d_shader_src_param *src_params; - - vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type)); -- src_params = instruction_src_params_alloc(ins, 2, sm6); -+ if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) -+ return; - src_param_init_from_value(&src_params[0], operands[0]); - src_param_init_from_value(&src_params[1], operands[1]); - -@@ -3807,7 +3838,8 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param_init_vector_from_reg(src_param, &buffer->u.handle.reg); - register_index_address_init(&src_param->reg.idx[2], operands[1], sm6); - assert(src_param->reg.idx_count == 3); -@@ -3903,7 +3935,8 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi - unsigned int i; - - vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_tertiary_op(op)); -- src_params = instruction_src_params_alloc(ins, 3, sm6); -+ if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) -+ return; - for (i = 0; i < 3; ++i) - src_param_init_from_value(&src_params[i], operands[i]); - -@@ -3934,7 +3967,8 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin - } - e = &signature->elements[row_index]; - -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param->reg = sm6->input_params[row_index].reg; - src_param_init_scalar(src_param, column_index); - if (e->register_count > 1) -@@ -4013,7 +4047,8 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri - instruction_init_with_resource(ins, (resource->u.handle.d->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) - ? VKD3DSIH_LD_UAV_TYPED : VKD3DSIH_LD, resource, sm6); - -- src_params = instruction_src_params_alloc(ins, 2, sm6); -+ if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) -+ return; - src_param_init_from_value(&src_params[0], operands[1]); - if (!sm6_value_is_undef(operands[2])) - { -@@ -4040,6 +4075,71 @@ static void instruction_set_texel_offset(struct vkd3d_shader_instruction *ins, - ins->texel_offset.w = sm6_value_get_texel_offset(operands[2]); - } - -+static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_register coord, ddx, ddy; -+ const struct sm6_value *resource, *sampler; -+ struct vkd3d_shader_src_param *src_params; -+ struct vkd3d_shader_instruction *ins; -+ unsigned int clamp_idx; -+ -+ resource = operands[0]; -+ sampler = operands[1]; -+ if (!sm6_value_validate_is_texture_handle(resource, op, sm6) -+ || !sm6_value_validate_is_sampler_handle(sampler, op, sm6)) -+ { -+ return; -+ } -+ -+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], VKD3D_VEC4_SIZE, NULL, state, &coord)) -+ return; -+ -+ if (op == DX_SAMPLE_GRAD) -+ { -+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[9], 3, NULL, state, &ddx)) -+ return; -+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[12], 3, NULL, state, &ddy)) -+ return; -+ } -+ -+ ins = state->ins; -+ switch (op) -+ { -+ case DX_SAMPLE: -+ instruction_init_with_resource(ins, VKD3DSIH_SAMPLE, resource, sm6); -+ src_params = instruction_src_params_alloc(ins, 3, sm6); -+ clamp_idx = 9; -+ break; -+ case DX_SAMPLE_GRAD: -+ instruction_init_with_resource(ins, VKD3DSIH_SAMPLE_GRAD, resource, sm6); -+ src_params = instruction_src_params_alloc(ins, 5, sm6); -+ src_param_init_vector_from_reg(&src_params[3], &ddx); -+ src_param_init_vector_from_reg(&src_params[4], &ddy); -+ clamp_idx = 15; -+ break; -+ default: -+ vkd3d_unreachable(); -+ } -+ -+ if (!src_params) -+ return; -+ -+ if (!sm6_value_is_undef(operands[clamp_idx])) -+ { -+ FIXME("Ignoring LOD clamp value.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring LOD clamp value for a sample operation."); -+ } -+ -+ src_param_init_vector_from_reg(&src_params[0], &coord); -+ src_param_init_vector_from_reg(&src_params[1], &resource->u.handle.reg); -+ src_param_init_vector_from_reg(&src_params[2], &sampler->u.handle.reg); -+ instruction_set_texel_offset(ins, &operands[6], sm6); -+ -+ instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); -+} -+ - static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, - const struct sm6_value **operands, struct function_emission_state *state) - { -@@ -4050,7 +4150,8 @@ static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_ - unsigned int index; - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SINCOS); -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param_init_from_value(src_param, operands[0]); - - index = op == DX_COS; -@@ -4069,7 +4170,8 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr - struct vkd3d_shader_src_param *src_param; - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param_init_from_value(src_param, operands[0]); - - instruction_dst_param_init_ssa_vector(ins, 2, sm6); -@@ -4150,7 +4252,7 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr - is_uav = resource->u.handle.d->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; - - mip_level_or_sample_count = (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) ? operands[1] : NULL; -- if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], -+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], 3, - is_multisample ? NULL : mip_level_or_sample_count, state, &coord)) - { - return; -@@ -4164,7 +4266,8 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr - for (i = 0; i < VKD3D_VEC4_SIZE; ++i) - ins->resource_data_type[i] = resource->u.handle.d->resource_data_type; - -- src_params = instruction_src_params_alloc(ins, 2 + is_multisample, sm6); -+ if (!(src_params = instruction_src_params_alloc(ins, 2 + is_multisample, sm6))) -+ return; - src_param_init_vector_from_reg(&src_params[0], &coord); - src_param_init_vector_from_reg(&src_params[1], &resource->u.handle.reg); - if (is_multisample) -@@ -4187,7 +4290,7 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int - if (!sm6_value_validate_is_texture_handle(resource, op, sm6)) - return; - -- if (!sm6_parser_emit_coordinate_construct(sm6, &operands[1], NULL, state, &coord)) -+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[1], 3, NULL, state, &coord)) - return; - - write_mask = sm6_value_get_constant_uint(operands[8]); -@@ -4290,6 +4393,8 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - [DX_ROUND_PI ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_ROUND_Z ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_RSQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_SAMPLE ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, -+ [DX_SAMPLE_GRAD ] = {"o", "HHffffiiifffffff", sm6_parser_emit_dx_sample}, - [DX_SIN ] = {"g", "R", sm6_parser_emit_dx_sincos}, - [DX_SPLIT_DOUBLE ] = {"S", "d", sm6_parser_emit_dx_split_double}, - [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, -@@ -4661,7 +4766,8 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - return; - } - -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param_init_from_value(src_param, value); - - instruction_dst_param_init_ssa_scalar(ins, sm6); -@@ -4797,7 +4903,8 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor - "Ignoring flags %#"PRIx64" for a comparison operation.", flags); - } - -- src_params = instruction_src_params_alloc(ins, 2, sm6); -+ if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) -+ return; - src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a); - src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b); - -@@ -4855,7 +4962,8 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param->reg = src->u.reg; - src_param_init_scalar(src_param, elem_idx); - -@@ -5006,7 +5114,8 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param_init_from_value(&src_param[0], ptr); - src_param->reg.alignment = alignment; - -@@ -5165,7 +5274,8 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - -- src_param = instruction_src_params_alloc(ins, 1, sm6); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ return; - src_param_init_from_value(&src_param[0], src); - - dst_param = instruction_dst_params_alloc(ins, 1, sm6); -@@ -5285,7 +5395,8 @@ static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_re - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOVC); - -- src_params = instruction_src_params_alloc(ins, 3, sm6); -+ if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) -+ return; - for (i = 0; i < 3; ++i) - src_param_init_from_value(&src_params[i], src[i]); - -@@ -6755,6 +6866,70 @@ static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6, - return VKD3D_OK; - } - -+static enum vkd3d_result sm6_parser_resources_load_sampler(struct sm6_parser *sm6, -+ const struct sm6_metadata_node *node, struct sm6_descriptor_info *d, struct vkd3d_shader_instruction *ins) -+{ -+ struct vkd3d_shader_register *reg; -+ unsigned int kind; -+ -+ if (node->operand_count < 7) -+ { -+ WARN("Invalid operand count %u.\n", node->operand_count); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Invalid operand count %u for a sampler descriptor.", node->operand_count); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ if (node->operand_count > 7 && node->operands[7]) -+ { -+ WARN("Ignoring %u extra operands.\n", node->operand_count - 7); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring %u extra operands for a sampler descriptor.", node->operand_count - 7); -+ } -+ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_DCL_SAMPLER); -+ ins->resource_type = VKD3D_SHADER_RESOURCE_NONE; -+ -+ if (!sm6_metadata_get_uint_value(sm6, node->operands[6], &kind)) -+ { -+ WARN("Failed to load sampler mode.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Sampler mode metadata value is not an integer."); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ switch (kind) -+ { -+ case SAMPLER_KIND_DEFAULT: -+ break; -+ case SAMPLER_KIND_COMPARISON: -+ ins->flags = VKD3DSI_SAMPLER_COMPARISON_MODE; -+ break; -+ default: -+ FIXME("Ignoring sampler kind %u.\n", kind); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring sampler kind %u.", kind); -+ break; -+ } -+ -+ ins->declaration.sampler.src.swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ ins->declaration.sampler.src.modifiers = VKD3DSPSM_NONE; -+ -+ reg = &ins->declaration.sampler.src.reg; -+ vsir_register_init(reg, VKD3DSPR_SAMPLER, VKD3D_DATA_UNUSED, 3); -+ reg->idx[0].offset = d->id; -+ reg->idx[1].offset = d->range.first; -+ reg->idx[2].offset = d->range.last; -+ -+ ins->declaration.sampler.range = d->range; -+ -+ d->resource_type = ins->resource_type; -+ d->kind = RESOURCE_KIND_SAMPLER; -+ d->reg_type = VKD3DSPR_SAMPLER; -+ d->reg_data_type = VKD3D_DATA_UNUSED; -+ d->resource_data_type = VKD3D_DATA_UNUSED; -+ -+ return VKD3D_OK; -+} -+ - static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, - enum vkd3d_shader_descriptor_type type, const struct sm6_metadata_node *descriptor_node) - { -@@ -6831,6 +7006,10 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, - if ((ret = sm6_parser_resources_load_uav(sm6, node, d, ins)) < 0) - return ret; - break; -+ case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: -+ if ((ret = sm6_parser_resources_load_sampler(sm6, node, d, ins)) < 0) -+ return ret; -+ break; - default: - FIXME("Unsupported descriptor type %u.\n", type); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 8dc353e11c0..5f6334a4d19 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -5572,11 +5572,11 @@ attribute: - $$->name = $2; - hlsl_block_init(&$$->instrs); - hlsl_block_add_block(&$$->instrs, $4.instrs); -- vkd3d_free($4.instrs); - $$->loc = @$; - $$->args_count = $4.args_count; - for (i = 0; i < $4.args_count; ++i) - hlsl_src_from_node(&$$->args[i], $4.args[i]); -+ free_parse_initializer(&$4); - } - - attribute_list: -@@ -5807,7 +5807,11 @@ func_prototype: - } - else - { -- free($1.attrs); -+ unsigned int i; -+ -+ for (i = 0; i < $1.count; ++i) -+ hlsl_free_attribute((void *)$1.attrs[i]); -+ vkd3d_free($1.attrs); - } - $$ = $2; - } -@@ -6992,8 +6996,10 @@ primary_expr: - if (!(var = hlsl_get_var(ctx->cur_scope, $1))) - { - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Variable \"%s\" is not defined.", $1); -+ vkd3d_free($1); - YYABORT; - } -+ vkd3d_free($1); - if (!(load = hlsl_new_var_load(ctx, var, &@1))) - YYABORT; - if (!($$ = make_block(ctx, &load->node))) -@@ -7067,12 +7073,17 @@ postfix_expr: - if (!(field = get_struct_field(type->e.record.fields, type->e.record.field_count, $3))) - { - hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Field \"%s\" is not defined.", $3); -+ vkd3d_free($3); - YYABORT; - } - - field_idx = field - type->e.record.fields; - if (!add_record_access(ctx, $1, node, field_idx, &@2)) -+ { -+ vkd3d_free($3); - YYABORT; -+ } -+ vkd3d_free($3); - $$ = $1; - } - else if (hlsl_is_numeric_type(node->data_type)) -@@ -7082,14 +7093,17 @@ postfix_expr: - if (!(swizzle = get_swizzle(ctx, node, $3, &@3))) - { - hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Invalid swizzle \"%s\".", $3); -+ vkd3d_free($3); - YYABORT; - } - hlsl_block_add_instr($1, swizzle); -+ vkd3d_free($3); - $$ = $1; - } - else - { - hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Invalid subscript \"%s\".", $3); -+ vkd3d_free($3); - YYABORT; - } - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index d0fd6b047b1..1557fb3ea7f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -2048,9 +2048,12 @@ void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, - - if (count > allocator->count - allocator->index) - { -- struct vkd3d_shader_param_node *next = shader_param_allocator_node_create(allocator); -+ struct vkd3d_shader_param_node *next; - -- if (!next) -+ /* Monolithic switch has no definite parameter count limit. */ -+ allocator->count = max(allocator->count, count); -+ -+ if (!(next = shader_param_allocator_node_create(allocator))) - return NULL; - if (allocator->current) - allocator->current->next = next; -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 90272818b3d..f5a57ad31b7 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -3433,6 +3433,87 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device7 - return S_OK; - } - -+ case D3D12_FEATURE_D3D12_OPTIONS10: -+ { -+ D3D12_FEATURE_DATA_D3D12_OPTIONS10 *data = feature_data; -+ -+ if (feature_data_size != sizeof(*data)) -+ { -+ WARN("Invalid size %u.\n", feature_data_size); -+ return E_INVALIDARG; -+ } -+ -+ data->VariableRateShadingSumCombinerSupported = FALSE; -+ data->MeshShaderPerPrimitiveShadingRateSupported = FALSE; -+ -+ TRACE("Variable rate shading sum combiner %#x.\n", data->VariableRateShadingSumCombinerSupported); -+ TRACE("Mesh shader per primitive shading rate %#x.\n", data->MeshShaderPerPrimitiveShadingRateSupported); -+ return S_OK; -+ } -+ -+ case D3D12_FEATURE_D3D12_OPTIONS11: -+ { -+ D3D12_FEATURE_DATA_D3D12_OPTIONS11 *data = feature_data; -+ -+ if (feature_data_size != sizeof(*data)) -+ { -+ WARN("Invalid size %u.\n", feature_data_size); -+ return E_INVALIDARG; -+ } -+ -+ data->AtomicInt64OnDescriptorHeapResourceSupported = FALSE; -+ -+ TRACE("Atomic int64 on descriptor heap resource %#x.\n", data->AtomicInt64OnDescriptorHeapResourceSupported); -+ return S_OK; -+ } -+ -+ case D3D12_FEATURE_D3D12_OPTIONS12: -+ { -+ D3D12_FEATURE_DATA_D3D12_OPTIONS12 *data = feature_data; -+ -+ if (feature_data_size != sizeof(*data)) -+ { -+ WARN("Invalid size %u.\n", feature_data_size); -+ return E_INVALIDARG; -+ } -+ -+ data->MSPrimitivesPipelineStatisticIncludesCulledPrimitives = D3D12_TRI_STATE_UNKNOWN; -+ data->EnhancedBarriersSupported = FALSE; -+ data->RelaxedFormatCastingSupported = FALSE; -+ -+ TRACE("Mesh shader primitives pipeline stats include cull primitives %#x.\n", -+ data->MSPrimitivesPipelineStatisticIncludesCulledPrimitives); -+ TRACE("Enhanced barriers %#x.\n", data->EnhancedBarriersSupported); -+ TRACE("Relaxed format casting %#x.\n", data->RelaxedFormatCastingSupported); -+ return S_OK; -+ } -+ -+ case D3D12_FEATURE_D3D12_OPTIONS13: -+ { -+ D3D12_FEATURE_DATA_D3D12_OPTIONS13 *data = feature_data; -+ -+ if (feature_data_size != sizeof(*data)) -+ { -+ WARN("Invalid size %u.\n", feature_data_size); -+ return E_INVALIDARG; -+ } -+ -+ data->UnrestrictedBufferTextureCopyPitchSupported = FALSE; -+ data->UnrestrictedVertexElementAlignmentSupported = FALSE; -+ data->InvertedViewportHeightFlipsYSupported = FALSE; -+ data->InvertedViewportDepthFlipsZSupported = FALSE; -+ data->TextureCopyBetweenDimensionsSupported = FALSE; -+ data->AlphaBlendFactorSupported = FALSE; -+ -+ TRACE("Unrestricted buffer-texture copy pitch %#x.\n", data->UnrestrictedBufferTextureCopyPitchSupported); -+ TRACE("Unrestricted vertex element alignment %#x.\n", data->UnrestrictedVertexElementAlignmentSupported); -+ TRACE("Inverted viewport height flips Y %#x.\n", data->InvertedViewportHeightFlipsYSupported); -+ TRACE("Inverted viewport depth flips Z %#x.\n", data->InvertedViewportDepthFlipsZSupported); -+ TRACE("Texture copy between dimensions %#x.\n", data->TextureCopyBetweenDimensionsSupported); -+ TRACE("Alpha blend factor support %#x.\n", data->AlphaBlendFactorSupported); -+ return S_OK; -+ } -+ - default: - FIXME("Unhandled feature %#x.\n", feature); - return E_NOTIMPL; -@@ -3888,7 +3969,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device7 * - struct d3d12_device *device = impl_from_ID3D12Device7(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); -+ iface, object, attributes, (uint32_t)access, debugstr_w(name, device->wchar_size), handle); - - return E_NOTIMPL; - } -@@ -3908,7 +3989,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandleByName(ID3D12Devic - struct d3d12_device *device = impl_from_ID3D12Device7(iface); - - FIXME("iface %p, name %s, access %#x, handle %p stub!\n", -- iface, debugstr_w(name, device->wchar_size), access, handle); -+ iface, debugstr_w(name, device->wchar_size), (uint32_t)access, handle); - - return E_NOTIMPL; - } --- -2.43.0 - diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-4735ff48d17258fa996a9df954dde289348.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-4735ff48d17258fa996a9df954dde289348.patch deleted file mode 100644 index 4522872c..00000000 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-4735ff48d17258fa996a9df954dde289348.patch +++ /dev/null @@ -1,1331 +0,0 @@ -From 81992c5cacdc26f851bce3fac5a4f091c0674313 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Fri, 16 Feb 2024 13:32:12 +1100 -Subject: [PATCH] Updated vkd3d to 4735ff48d17258fa996a9df954dde2893482aefb. - ---- - libs/vkd3d/include/private/vkd3d_test.h | 1 + - libs/vkd3d/include/vkd3d.h | 2 +- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 82 +++++++++++++ - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 4 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 40 +++--- - libs/vkd3d/libs/vkd3d-shader/hlsl.l | 7 ++ - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 127 ++++++++++++++------ - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 34 ++++++ - libs/vkd3d/libs/vkd3d-shader/tpf.c | 3 + - libs/vkd3d/libs/vkd3d/command.c | 14 +-- - libs/vkd3d/libs/vkd3d/device.c | 107 +++++++++++++---- - libs/vkd3d/libs/vkd3d/resource.c | 127 +++++++++++--------- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 34 +++--- - 13 files changed, 418 insertions(+), 164 deletions(-) - -diff --git a/libs/vkd3d/include/private/vkd3d_test.h b/libs/vkd3d/include/private/vkd3d_test.h -index a337ac07269..bd6bafa9049 100644 ---- a/libs/vkd3d/include/private/vkd3d_test.h -+++ b/libs/vkd3d/include/private/vkd3d_test.h -@@ -277,6 +277,7 @@ int main(int argc, char **argv) - char *test_platform = getenv("VKD3D_TEST_PLATFORM"); - const char *bug = getenv("VKD3D_TEST_BUG"); - -+ setvbuf(stdout, NULL, _IONBF, 0); - 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; -diff --git a/libs/vkd3d/include/vkd3d.h b/libs/vkd3d/include/vkd3d.h -index 8a8389f02a4..df361f90177 100644 ---- a/libs/vkd3d/include/vkd3d.h -+++ b/libs/vkd3d/include/vkd3d.h -@@ -182,7 +182,7 @@ struct vkd3d_image_resource_create_info - const void *next; - - VkImage vk_image; -- D3D12_RESOURCE_DESC desc; -+ D3D12_RESOURCE_DESC1 desc; - unsigned int flags; - D3D12_RESOURCE_STATES present_state; - }; -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 9ad9f735dd1..27f5c810436 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -1958,6 +1958,82 @@ static void write_sm1_unary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe - write_sm1_instruction(ctx, buffer, &instr); - } - -+static void write_sm1_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, -+ const struct hlsl_ir_node *instr) -+{ -+ struct hlsl_ir_expr *expr = hlsl_ir_expr(instr); -+ const struct hlsl_ir_node *arg1 = expr->operands[0].node; -+ const struct hlsl_type *dst_type = expr->node.data_type; -+ const struct hlsl_type *src_type = arg1->data_type; -+ -+ /* Narrowing casts were already lowered. */ -+ assert(src_type->dimx == dst_type->dimx); -+ -+ switch (dst_type->base_type) -+ { -+ case HLSL_TYPE_HALF: -+ case HLSL_TYPE_FLOAT: -+ switch (src_type->base_type) -+ { -+ case HLSL_TYPE_INT: -+ case HLSL_TYPE_UINT: -+ /* Integers are internally represented as floats, so no change is necessary.*/ -+ case HLSL_TYPE_HALF: -+ case HLSL_TYPE_FLOAT: -+ write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, 0); -+ break; -+ -+ case HLSL_TYPE_BOOL: -+ hlsl_fixme(ctx, &instr->loc, "SM1 cast from bool to float."); -+ break; -+ -+ case HLSL_TYPE_DOUBLE: -+ hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to float."); -+ break; -+ -+ default: -+ vkd3d_unreachable(); -+ } -+ break; -+ -+ case HLSL_TYPE_INT: -+ case HLSL_TYPE_UINT: -+ switch(src_type->base_type) -+ { -+ case HLSL_TYPE_HALF: -+ case HLSL_TYPE_FLOAT: -+ /* A compilation pass applies a FLOOR operation to casts to int, so no change is necessary. */ -+ case HLSL_TYPE_INT: -+ case HLSL_TYPE_UINT: -+ write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, 0); -+ break; -+ -+ case HLSL_TYPE_BOOL: -+ hlsl_fixme(ctx, &instr->loc, "SM1 cast from bool to integer."); -+ break; -+ -+ case HLSL_TYPE_DOUBLE: -+ hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to integer."); -+ break; -+ -+ default: -+ vkd3d_unreachable(); -+ } -+ break; -+ -+ case HLSL_TYPE_DOUBLE: -+ hlsl_fixme(ctx, &instr->loc, "SM1 cast to double."); -+ break; -+ -+ case HLSL_TYPE_BOOL: -+ /* Casts to bool should have already been lowered. */ -+ default: -+ hlsl_fixme(ctx, &expr->node.loc, "SM1 cast from %s to %s.\n", -+ debug_hlsl_type(ctx, src_type), debug_hlsl_type(ctx, dst_type)); -+ break; -+ } -+} -+ - static void write_sm1_constant_defs(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer) - { - unsigned int i, x; -@@ -2166,6 +2242,12 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b - - assert(instr->reg.allocated); - -+ if (expr->op == HLSL_OP1_CAST) -+ { -+ write_sm1_cast(ctx, buffer, instr); -+ return; -+ } -+ - if (instr->data_type->base_type != HLSL_TYPE_FLOAT) - { - /* These need to be lowered. */ -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 04c37498d84..3d068ac6d3b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -758,7 +758,8 @@ struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_ - return type; - } - --struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format) -+struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, -+ enum hlsl_sampler_dim dim, struct hlsl_type *format, uint32_t modifiers) - { - struct hlsl_type *type; - -@@ -769,6 +770,7 @@ struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim - type->dimx = format->dimx; - type->dimy = 1; - type->sampler_dim = dim; -+ type->modifiers = modifiers; - type->e.resource_format = format; - hlsl_type_calculate_reg_size(ctx, type); - list_add_tail(&ctx->types, &type->entry); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index 984ac7e4883..974a5dd7aee 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -348,27 +348,28 @@ struct hlsl_attribute - struct hlsl_src args[]; - }; - --#define HLSL_STORAGE_EXTERN 0x00000001 --#define HLSL_STORAGE_NOINTERPOLATION 0x00000002 --#define HLSL_MODIFIER_PRECISE 0x00000004 --#define HLSL_STORAGE_SHARED 0x00000008 --#define HLSL_STORAGE_GROUPSHARED 0x00000010 --#define HLSL_STORAGE_STATIC 0x00000020 --#define HLSL_STORAGE_UNIFORM 0x00000040 --#define HLSL_MODIFIER_VOLATILE 0x00000080 --#define HLSL_MODIFIER_CONST 0x00000100 --#define HLSL_MODIFIER_ROW_MAJOR 0x00000200 --#define HLSL_MODIFIER_COLUMN_MAJOR 0x00000400 --#define HLSL_STORAGE_IN 0x00000800 --#define HLSL_STORAGE_OUT 0x00001000 --#define HLSL_MODIFIER_INLINE 0x00002000 --#define HLSL_STORAGE_CENTROID 0x00004000 --#define HLSL_STORAGE_NOPERSPECTIVE 0x00008000 --#define HLSL_STORAGE_LINEAR 0x00010000 -+#define HLSL_STORAGE_EXTERN 0x00000001 -+#define HLSL_STORAGE_NOINTERPOLATION 0x00000002 -+#define HLSL_MODIFIER_PRECISE 0x00000004 -+#define HLSL_STORAGE_SHARED 0x00000008 -+#define HLSL_STORAGE_GROUPSHARED 0x00000010 -+#define HLSL_STORAGE_STATIC 0x00000020 -+#define HLSL_STORAGE_UNIFORM 0x00000040 -+#define HLSL_MODIFIER_VOLATILE 0x00000080 -+#define HLSL_MODIFIER_CONST 0x00000100 -+#define HLSL_MODIFIER_ROW_MAJOR 0x00000200 -+#define HLSL_MODIFIER_COLUMN_MAJOR 0x00000400 -+#define HLSL_STORAGE_IN 0x00000800 -+#define HLSL_STORAGE_OUT 0x00001000 -+#define HLSL_MODIFIER_INLINE 0x00002000 -+#define HLSL_STORAGE_CENTROID 0x00004000 -+#define HLSL_STORAGE_NOPERSPECTIVE 0x00008000 -+#define HLSL_STORAGE_LINEAR 0x00010000 -+#define HLSL_MODIFIER_RASTERIZER_ORDERED 0x00020000 - - #define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_MODIFIER_VOLATILE | \ - HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \ -- HLSL_MODIFIER_COLUMN_MAJOR) -+ HLSL_MODIFIER_COLUMN_MAJOR | HLSL_MODIFIER_RASTERIZER_ORDERED) - - #define HLSL_INTERPOLATION_MODIFIERS_MASK (HLSL_STORAGE_NOINTERPOLATION | HLSL_STORAGE_CENTROID | \ - HLSL_STORAGE_NOPERSPECTIVE | HLSL_STORAGE_LINEAR) -@@ -1270,7 +1271,8 @@ struct hlsl_ir_var *hlsl_new_synthetic_var_named(struct hlsl_ctx *ctx, const cha - struct hlsl_type *type, const struct vkd3d_shader_location *loc, bool dummy_scope); - struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format, - unsigned int sample_count); --struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format); -+struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, -+ enum hlsl_sampler_dim dim, struct hlsl_type *format, uint32_t modifiers); - struct hlsl_ir_node *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n, - const struct vkd3d_shader_location *loc); - struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -index 6cef0e02eff..558506db108 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -@@ -106,6 +106,13 @@ packoffset {return KW_PACKOFFSET; } - pass {return KW_PASS; } - PixelShader {return KW_PIXELSHADER; } - precise {return KW_PRECISE; } -+RasterizerOrderedBuffer {return KW_RASTERIZERORDEREDBUFFER; } -+RasterizerOrderedStructuredBuffer {return KW_RASTERIZERORDEREDSTRUCTUREDBUFFER; } -+RasterizerOrderedTexture1D {return KW_RASTERIZERORDEREDTEXTURE1D; } -+RasterizerOrderedTexture1DArray {return KW_RASTERIZERORDEREDTEXTURE1DARRAY; } -+RasterizerOrderedTexture2D {return KW_RASTERIZERORDEREDTEXTURE2D; } -+RasterizerOrderedTexture2DArray {return KW_RASTERIZERORDEREDTEXTURE2DARRAY; } -+RasterizerOrderedTexture3D {return KW_RASTERIZERORDEREDTEXTURE3D; } - RasterizerState {return KW_RASTERIZERSTATE; } - register {return KW_REGISTER; } - RenderTargetView {return KW_RENDERTARGETVIEW; } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 5f6334a4d19..37a372893df 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -5005,6 +5005,48 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - } - } - -+static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, -+ struct hlsl_type *format, const struct vkd3d_shader_location* loc) -+{ -+ struct vkd3d_string_buffer *string = hlsl_type_to_string(ctx, format); -+ -+ if (!type_contains_only_numerics(format)) -+ { -+ if (string) -+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "UAV type %s is not numeric.", string->buffer); -+ } -+ -+ switch (dim) -+ { -+ case HLSL_SAMPLER_DIM_BUFFER: -+ case HLSL_SAMPLER_DIM_1D: -+ case HLSL_SAMPLER_DIM_1DARRAY: -+ case HLSL_SAMPLER_DIM_2D: -+ case HLSL_SAMPLER_DIM_2DARRAY: -+ case HLSL_SAMPLER_DIM_3D: -+ if (format->class == HLSL_CLASS_ARRAY) -+ { -+ if (string) -+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "This type of UAV does not support array type."); -+ } -+ else if (hlsl_type_component_count(format) > 4) -+ { -+ if (string) -+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "UAV data type %s size exceeds maximum size.", string->buffer); -+ } -+ break; -+ case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: -+ break; -+ default: -+ vkd3d_unreachable(); -+ } -+ -+ hlsl_release_string_buffer(ctx, string); -+} -+ - } - - %locations -@@ -5084,6 +5126,13 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - %token KW_PASS - %token KW_PIXELSHADER - %token KW_PRECISE -+%token KW_RASTERIZERORDEREDBUFFER -+%token KW_RASTERIZERORDEREDSTRUCTUREDBUFFER -+%token KW_RASTERIZERORDEREDTEXTURE1D -+%token KW_RASTERIZERORDEREDTEXTURE1DARRAY -+%token KW_RASTERIZERORDEREDTEXTURE2D -+%token KW_RASTERIZERORDEREDTEXTURE2DARRAY -+%token KW_RASTERIZERORDEREDTEXTURE3D - %token KW_RASTERIZERSTATE - %token KW_RENDERTARGETVIEW - %token KW_RETURN -@@ -5244,7 +5293,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - %type register_opt - %type packoffset_opt - --%type texture_type texture_ms_type uav_type -+%type texture_type texture_ms_type uav_type rov_type - - %type semantic - -@@ -6057,6 +6106,36 @@ uav_type: - $$ = HLSL_SAMPLER_DIM_3D; - } - -+rov_type: -+ KW_RASTERIZERORDEREDBUFFER -+ { -+ $$ = HLSL_SAMPLER_DIM_BUFFER; -+ } -+ | KW_RASTERIZERORDEREDSTRUCTUREDBUFFER -+ { -+ $$ = HLSL_SAMPLER_DIM_STRUCTURED_BUFFER; -+ } -+ | KW_RASTERIZERORDEREDTEXTURE1D -+ { -+ $$ = HLSL_SAMPLER_DIM_1D; -+ } -+ | KW_RASTERIZERORDEREDTEXTURE1DARRAY -+ { -+ $$ = HLSL_SAMPLER_DIM_1DARRAY; -+ } -+ | KW_RASTERIZERORDEREDTEXTURE2D -+ { -+ $$ = HLSL_SAMPLER_DIM_2D; -+ } -+ | KW_RASTERIZERORDEREDTEXTURE2DARRAY -+ { -+ $$ = HLSL_SAMPLER_DIM_2DARRAY; -+ } -+ | KW_RASTERIZERORDEREDTEXTURE3D -+ { -+ $$ = HLSL_SAMPLER_DIM_3D; -+ } -+ - type_no_void: - KW_VECTOR '<' type ',' C_INTEGER '>' - { -@@ -6185,45 +6264,13 @@ type_no_void: - } - | uav_type '<' type '>' - { -- struct vkd3d_string_buffer *string = hlsl_type_to_string(ctx, $3); -- -- if (!type_contains_only_numerics($3)) -- { -- if (string) -- hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -- "UAV type %s is not numeric.", string->buffer); -- } -- -- switch ($1) -- { -- case HLSL_SAMPLER_DIM_BUFFER: -- case HLSL_SAMPLER_DIM_1D: -- case HLSL_SAMPLER_DIM_1DARRAY: -- case HLSL_SAMPLER_DIM_2D: -- case HLSL_SAMPLER_DIM_2DARRAY: -- case HLSL_SAMPLER_DIM_3D: -- if ($3->class == HLSL_CLASS_ARRAY) -- { -- if (string) -- hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -- "This type of UAV does not support array type."); -- } -- else if (hlsl_type_component_count($3) > 4) -- { -- if (string) -- hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -- "UAV data type %s size exceeds maximum size.", string->buffer); -- } -- break; -- case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: -- break; -- default: -- vkd3d_unreachable(); -- } -- -- hlsl_release_string_buffer(ctx, string); -- -- $$ = hlsl_new_uav_type(ctx, $1, $3); -+ validate_uav_type(ctx, $1, $3, &@3); -+ $$ = hlsl_new_uav_type(ctx, $1, $3, 0); -+ } -+ | rov_type '<' type '>' -+ { -+ validate_uav_type(ctx, $1, $3, &@3); -+ $$ = hlsl_new_uav_type(ctx, $1, $3, HLSL_MODIFIER_RASTERIZER_ORDERED); - } - | TYPE_IDENTIFIER - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 6ad60e4c6c2..4121fadf333 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -2647,6 +2647,39 @@ static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx) - return false; - } - -+/* Append a FLOOR before a CAST to int or uint (which is written as a mere MOV). */ -+static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) -+{ -+ struct hlsl_ir_node *arg, *floor, *cast2; -+ struct hlsl_ir_expr *expr; -+ -+ if (instr->type != HLSL_IR_EXPR) -+ return false; -+ expr = hlsl_ir_expr(instr); -+ if (expr->op != HLSL_OP1_CAST) -+ return false; -+ -+ arg = expr->operands[0].node; -+ if (instr->data_type->base_type != HLSL_TYPE_INT && instr->data_type->base_type != HLSL_TYPE_UINT) -+ return false; -+ if (arg->data_type->base_type != HLSL_TYPE_FLOAT && arg->data_type->base_type != HLSL_TYPE_HALF) -+ return false; -+ -+ /* Check that the argument is not already a FLOOR */ -+ if (arg->type == HLSL_IR_EXPR && hlsl_ir_expr(arg)->op == HLSL_OP1_FLOOR) -+ return false; -+ -+ if (!(floor = hlsl_new_unary_expr(ctx, HLSL_OP1_FLOOR, arg, &instr->loc))) -+ return false; -+ hlsl_block_add_instr(block, floor); -+ -+ if (!(cast2 = hlsl_new_cast(ctx, floor, instr->data_type, &instr->loc))) -+ return false; -+ hlsl_block_add_instr(block, cast2); -+ -+ return true; -+} -+ - /* Lower DIV to RCP + MUL. */ - static bool lower_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) - { -@@ -5060,6 +5093,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry - lower_ir(ctx, lower_ternary, body); - if (profile->major_version < 4) - { -+ lower_ir(ctx, lower_casts_to_int, body); - lower_ir(ctx, lower_division, body); - lower_ir(ctx, lower_sqrt, body); - lower_ir(ctx, lower_dot, body); -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index adfddd32036..f70606e6f22 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -4271,6 +4271,9 @@ static void write_sm4_dcl_textures(const struct tpf_writer *tpf, const struct ex - instr.extra_bits |= component_type->sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; - } - -+ if (resource->data_type->modifiers & HLSL_MODIFIER_RASTERIZER_ORDERED) -+ instr.opcode |= VKD3DSUF_RASTERISER_ORDERED_VIEW << VKD3D_SM5_UAV_FLAGS_SHIFT; -+ - write_sm4_instruction(tpf, &instr); - } - } -diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c -index 8a47dc494f7..7115a74a6f2 100644 ---- a/libs/vkd3d/libs/vkd3d/command.c -+++ b/libs/vkd3d/libs/vkd3d/command.c -@@ -3508,7 +3508,7 @@ static void vk_image_subresource_layers_from_d3d12(VkImageSubresourceLayers *sub - } - - static void vk_extent_3d_from_d3d12_miplevel(VkExtent3D *extent, -- const D3D12_RESOURCE_DESC *resource_desc, unsigned int miplevel_idx) -+ const D3D12_RESOURCE_DESC1 *resource_desc, unsigned int miplevel_idx) - { - extent->width = d3d12_resource_desc_get_width(resource_desc, miplevel_idx); - extent->height = d3d12_resource_desc_get_height(resource_desc, miplevel_idx); -@@ -3517,7 +3517,7 @@ static void vk_extent_3d_from_d3d12_miplevel(VkExtent3D *extent, - - static void vk_buffer_image_copy_from_d3d12(VkBufferImageCopy *copy, - const D3D12_PLACED_SUBRESOURCE_FOOTPRINT *footprint, unsigned int sub_resource_idx, -- const D3D12_RESOURCE_DESC *image_desc, const struct vkd3d_format *format, -+ const D3D12_RESOURCE_DESC1 *image_desc, const struct vkd3d_format *format, - const D3D12_BOX *src_box, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z) - { - copy->bufferOffset = footprint->Offset; -@@ -3558,7 +3558,7 @@ static void vk_buffer_image_copy_from_d3d12(VkBufferImageCopy *copy, - - static void vk_image_buffer_copy_from_d3d12(VkBufferImageCopy *copy, - const D3D12_PLACED_SUBRESOURCE_FOOTPRINT *footprint, unsigned int sub_resource_idx, -- const D3D12_RESOURCE_DESC *image_desc, const struct vkd3d_format *format, -+ const D3D12_RESOURCE_DESC1 *image_desc, const struct vkd3d_format *format, - const D3D12_BOX *src_box, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z) - { - VkDeviceSize row_count = footprint->Footprint.Height / format->block_height; -@@ -3588,7 +3588,7 @@ static void vk_image_buffer_copy_from_d3d12(VkBufferImageCopy *copy, - - static void vk_image_copy_from_d3d12(VkImageCopy *image_copy, - unsigned int src_sub_resource_idx, unsigned int dst_sub_resource_idx, -- const D3D12_RESOURCE_DESC *src_desc, const D3D12_RESOURCE_DESC *dst_desc, -+ const D3D12_RESOURCE_DESC1 *src_desc, const D3D12_RESOURCE_DESC1 *dst_desc, - const struct vkd3d_format *src_format, const struct vkd3d_format *dst_format, - const D3D12_BOX *src_box, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z) - { -@@ -3621,7 +3621,7 @@ static HRESULT d3d12_command_list_allocate_transfer_buffer(struct d3d12_command_ - const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; - struct d3d12_device *device = list->device; - D3D12_HEAP_PROPERTIES heap_properties; -- D3D12_RESOURCE_DESC buffer_desc; -+ D3D12_RESOURCE_DESC1 buffer_desc; - HRESULT hr; - - memset(&heap_properties, 0, sizeof(heap_properties)); -@@ -3671,8 +3671,8 @@ static void d3d12_command_list_copy_incompatible_texture_region(struct d3d12_com - unsigned int src_sub_resource_idx, const struct vkd3d_format *src_format, unsigned int layer_count) - { - const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; -- const D3D12_RESOURCE_DESC *dst_desc = &dst_resource->desc; -- const D3D12_RESOURCE_DESC *src_desc = &src_resource->desc; -+ const D3D12_RESOURCE_DESC1 *dst_desc = &dst_resource->desc; -+ const D3D12_RESOURCE_DESC1 *src_desc = &src_resource->desc; - unsigned int dst_miplevel_idx, src_miplevel_idx; - struct vkd3d_buffer transfer_buffer; - VkBufferImageCopy buffer_image_copy; -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index f5a57ad31b7..01818458e97 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -1970,7 +1970,7 @@ static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance, - static bool d3d12_is_64k_msaa_supported(struct d3d12_device *device) - { - struct vkd3d_resource_allocation_info info; -- D3D12_RESOURCE_DESC resource_desc; -+ D3D12_RESOURCE_DESC1 resource_desc; - - memset(&resource_desc, 0, sizeof(resource_desc)); - resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; -@@ -3732,6 +3732,14 @@ static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device7 * - 1, &src_descriptor_range_offset, &descriptor_count, descriptor_heap_type); - } - -+static void d3d12_resource_desc1_from_desc(D3D12_RESOURCE_DESC1 *desc1, const D3D12_RESOURCE_DESC *desc) -+{ -+ memcpy(desc1, desc, sizeof(*desc)); -+ desc1->SamplerFeedbackMipRegion.Width = 0; -+ desc1->SamplerFeedbackMipRegion.Height = 0; -+ desc1->SamplerFeedbackMipRegion.Depth = 0; -+} -+ - static void d3d12_resource_allocation_info1_from_vkd3d(D3D12_RESOURCE_ALLOCATION_INFO1 *result, - const struct vkd3d_resource_allocation_info *info) - { -@@ -3740,12 +3748,12 @@ static void d3d12_resource_allocation_info1_from_vkd3d(D3D12_RESOURCE_ALLOCATION - result->SizeInBytes = info->size_in_bytes; - } - --static void d3d12_device_get_resource_allocation_info(struct d3d12_device *device, -- D3D12_RESOURCE_ALLOCATION_INFO1 *infos1, unsigned int count, const D3D12_RESOURCE_DESC *resource_descs, -+static void d3d12_device_get_resource1_allocation_info(struct d3d12_device *device, -+ D3D12_RESOURCE_ALLOCATION_INFO1 *infos1, unsigned int count, const D3D12_RESOURCE_DESC1 *resource_descs, - D3D12_RESOURCE_ALLOCATION_INFO *result) - { - struct vkd3d_resource_allocation_info info; -- const D3D12_RESOURCE_DESC *desc; -+ const D3D12_RESOURCE_DESC1 *desc; - uint64_t requested_alignment; - unsigned int i; - -@@ -3818,6 +3826,36 @@ invalid: - TRACE("Alignment %#"PRIx64".\n", result->Alignment); - } - -+static void d3d12_device_get_resource_allocation_info(struct d3d12_device *device, -+ D3D12_RESOURCE_ALLOCATION_INFO1 *infos1, unsigned int count, const D3D12_RESOURCE_DESC *resource_descs, -+ D3D12_RESOURCE_ALLOCATION_INFO *result) -+{ -+ /* Avoid spurious compiler warning for uninitialized use. */ -+ D3D12_RESOURCE_DESC1 resource_descs1[4] = {0}; -+ D3D12_RESOURCE_DESC1 *descs1; -+ unsigned int i; -+ -+ if (count <= ARRAY_SIZE(resource_descs1)) -+ { -+ descs1 = resource_descs1; -+ } -+ else if (!(descs1 = vkd3d_calloc(count, sizeof(*descs1)))) -+ { -+ ERR("Failed to allocate %u resource descriptions.\n", count); -+ result->SizeInBytes = UINT64_MAX; -+ result->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; -+ return; -+ } -+ -+ for (i = 0; i < count; ++i) -+ d3d12_resource_desc1_from_desc(&descs1[i], &resource_descs[i]); -+ -+ d3d12_device_get_resource1_allocation_info(device, infos1, count, descs1, result); -+ -+ if (descs1 != resource_descs1) -+ vkd3d_free(descs1); -+} -+ - static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo( - ID3D12Device7 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask, - UINT count, const D3D12_RESOURCE_DESC *resource_descs) -@@ -3883,6 +3921,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Devi - const D3D12_CLEAR_VALUE *optimized_clear_value, REFIID iid, void **resource) - { - struct d3d12_device *device = impl_from_ID3D12Device7(iface); -+ D3D12_RESOURCE_DESC1 resource_desc; - struct d3d12_resource *object; - HRESULT hr; - -@@ -3891,14 +3930,16 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Devi - iface, heap_properties, heap_flags, desc, initial_state, - optimized_clear_value, debugstr_guid(iid), resource); - -+ d3d12_resource_desc1_from_desc(&resource_desc, desc); -+ - if (FAILED(hr = d3d12_committed_resource_create(device, heap_properties, heap_flags, -- desc, initial_state, optimized_clear_value, NULL, &object))) -+ &resource_desc, initial_state, optimized_clear_value, NULL, &object))) - { - *resource = NULL; - return hr; - } - -- return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource); -+ return return_interface(&object->ID3D12Resource2_iface, &IID_ID3D12Resource2, iid, resource); - } - - static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device7 *iface, -@@ -3926,6 +3967,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device7 - const D3D12_CLEAR_VALUE *optimized_clear_value, REFIID iid, void **resource) - { - struct d3d12_device *device = impl_from_ID3D12Device7(iface); -+ D3D12_RESOURCE_DESC1 resource_desc; - struct d3d12_heap *heap_object; - struct d3d12_resource *object; - HRESULT hr; -@@ -3936,12 +3978,13 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device7 - optimized_clear_value, debugstr_guid(iid), resource); - - heap_object = unsafe_impl_from_ID3D12Heap(heap); -+ d3d12_resource_desc1_from_desc(&resource_desc, desc); - - if (FAILED(hr = d3d12_placed_resource_create(device, heap_object, heap_offset, -- desc, initial_state, optimized_clear_value, &object))) -+ &resource_desc, initial_state, optimized_clear_value, &object))) - return hr; - -- return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource); -+ return return_interface(&object->ID3D12Resource2_iface, &IID_ID3D12Resource2, iid, resource); - } - - static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Device7 *iface, -@@ -3949,17 +3992,20 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Devic - const D3D12_CLEAR_VALUE *optimized_clear_value, REFIID iid, void **resource) - { - struct d3d12_device *device = impl_from_ID3D12Device7(iface); -+ D3D12_RESOURCE_DESC1 resource_desc; - struct d3d12_resource *object; - HRESULT hr; - - TRACE("iface %p, desc %p, initial_state %#x, optimized_clear_value %p, iid %s, resource %p.\n", - iface, desc, initial_state, optimized_clear_value, debugstr_guid(iid), resource); - -+ d3d12_resource_desc1_from_desc(&resource_desc, desc); -+ - if (FAILED(hr = d3d12_reserved_resource_create(device, -- desc, initial_state, optimized_clear_value, &object))) -+ &resource_desc, initial_state, optimized_clear_value, &object))) - return hr; - -- return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource); -+ return return_interface(&object->ID3D12Resource2_iface, &IID_ID3D12Resource2, iid, resource); - } - - static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device7 *iface, -@@ -4046,23 +4092,16 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_GetDeviceRemovedReason(ID3D12Devic - return device->removed_reason; - } - --static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device7 *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) -+static void d3d12_device_get_copyable_footprints(struct d3d12_device *device, -+ const D3D12_RESOURCE_DESC1 *desc, unsigned int first_sub_resource, unsigned int sub_resource_count, -+ uint64_t base_offset, D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts, UINT *row_counts, -+ UINT64 *row_sizes, UINT64 *total_bytes) - { -- struct d3d12_device *device = impl_from_ID3D12Device7(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; - const struct vkd3d_format *format; - uint64_t offset, size, total; - -- TRACE("iface %p, desc %p, first_sub_resource %u, sub_resource_count %u, base_offset %#"PRIx64", " -- "layouts %p, row_counts %p, row_sizes %p, total_bytes %p.\n", -- iface, desc, first_sub_resource, sub_resource_count, base_offset, -- layouts, row_counts, row_sizes, total_bytes); -- - if (layouts) - memset(layouts, 0xff, sizeof(*layouts) * sub_resource_count); - if (row_counts) -@@ -4131,6 +4170,25 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device7 * - *total_bytes = total; - } - -+static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device7 *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_ID3D12Device7(iface); -+ D3D12_RESOURCE_DESC1 resource_desc; -+ -+ TRACE("iface %p, desc %p, first_sub_resource %u, sub_resource_count %u, base_offset %#"PRIx64", " -+ "layouts %p, row_counts %p, row_sizes %p, total_bytes %p.\n", -+ iface, desc, first_sub_resource, sub_resource_count, base_offset, -+ layouts, row_counts, row_sizes, total_bytes); -+ -+ d3d12_resource_desc1_from_desc(&resource_desc, desc); -+ -+ d3d12_device_get_copyable_footprints(device, &resource_desc, first_sub_resource, sub_resource_count, -+ base_offset, layouts, row_counts, row_sizes, total_bytes); -+} -+ - static HRESULT STDMETHODCALLTYPE d3d12_device_CreateQueryHeap(ID3D12Device7 *iface, - const D3D12_QUERY_HEAP_DESC *desc, REFIID iid, void **heap) - { -@@ -4297,6 +4355,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource1(ID3D12Dev - ID3D12ProtectedResourceSession *protected_session, REFIID iid, void **resource) - { - struct d3d12_device *device = impl_from_ID3D12Device7(iface); -+ D3D12_RESOURCE_DESC1 resource_desc; - struct d3d12_resource *object; - HRESULT hr; - -@@ -4305,14 +4364,16 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource1(ID3D12Dev - iface, heap_properties, heap_flags, desc, initial_state, - optimized_clear_value, protected_session, debugstr_guid(iid), resource); - -+ d3d12_resource_desc1_from_desc(&resource_desc, desc); -+ - if (FAILED(hr = d3d12_committed_resource_create(device, heap_properties, heap_flags, -- desc, initial_state, optimized_clear_value, protected_session, &object))) -+ &resource_desc, initial_state, optimized_clear_value, protected_session, &object))) - { - *resource = NULL; - return hr; - } - -- return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource); -+ return return_interface(&object->ID3D12Resource2_iface, &IID_ID3D12Resource2, iid, resource); - } - - static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap1(ID3D12Device7 *iface, -diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c -index 8f4d18358d2..fc05fce14f3 100644 ---- a/libs/vkd3d/libs/vkd3d/resource.c -+++ b/libs/vkd3d/libs/vkd3d/resource.c -@@ -651,7 +651,7 @@ VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_DESC *d - - HRESULT vkd3d_create_buffer(struct d3d12_device *device, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, -- const D3D12_RESOURCE_DESC *desc, VkBuffer *vk_buffer) -+ const D3D12_RESOURCE_DESC1 *desc, VkBuffer *vk_buffer) - { - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - const bool sparse_resource = !heap_properties; -@@ -731,7 +731,7 @@ HRESULT vkd3d_create_buffer(struct d3d12_device *device, - return hresult_from_vk_result(vr); - } - --static unsigned int max_miplevel_count(const D3D12_RESOURCE_DESC *desc) -+static unsigned int max_miplevel_count(const D3D12_RESOURCE_DESC1 *desc) - { - unsigned int size = max(desc->Width, desc->Height); - size = max(size, d3d12_resource_desc_get_depth(desc, 0)); -@@ -775,7 +775,7 @@ static bool vkd3d_is_linear_tiling_supported(const struct d3d12_device *device, - - static HRESULT vkd3d_create_image(struct d3d12_device *device, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, -- const D3D12_RESOURCE_DESC *desc, struct d3d12_resource *resource, VkImage *vk_image) -+ const D3D12_RESOURCE_DESC1 *desc, struct d3d12_resource *resource, VkImage *vk_image) - { - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - const struct vkd3d_format_compatibility_list *compat_list; -@@ -940,11 +940,11 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, - } - - HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, -- const D3D12_RESOURCE_DESC *desc, struct vkd3d_resource_allocation_info *allocation_info) -+ const D3D12_RESOURCE_DESC1 *desc, struct vkd3d_resource_allocation_info *allocation_info) - { - static const D3D12_HEAP_PROPERTIES heap_properties = {D3D12_HEAP_TYPE_DEFAULT}; - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; -- D3D12_RESOURCE_DESC validated_desc; -+ D3D12_RESOURCE_DESC1 validated_desc; - VkMemoryRequirements requirements; - VkImage vk_image; - bool tiled; -@@ -1069,7 +1069,7 @@ static void d3d12_resource_get_level_box(const struct d3d12_resource *resource, - } - - static void compute_image_subresource_size_in_tiles(const VkExtent3D *tile_extent, -- const struct D3D12_RESOURCE_DESC *desc, unsigned int miplevel_idx, -+ const struct D3D12_RESOURCE_DESC1 *desc, unsigned int miplevel_idx, - struct vkd3d_tiled_region_extent *size) - { - unsigned int width, height, depth; -@@ -1258,12 +1258,13 @@ static bool d3d12_resource_init_tiles(struct d3d12_resource *resource, struct d3 - } - - /* ID3D12Resource */ --static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource1 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource2 *iface, - REFIID riid, void **object) - { - TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); - -- if (IsEqualGUID(riid, &IID_ID3D12Resource1) -+ if (IsEqualGUID(riid, &IID_ID3D12Resource2) -+ || IsEqualGUID(riid, &IID_ID3D12Resource1) - || IsEqualGUID(riid, &IID_ID3D12Resource) - || IsEqualGUID(riid, &IID_ID3D12Pageable) - || IsEqualGUID(riid, &IID_ID3D12DeviceChild) -@@ -1281,9 +1282,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource1 * - return E_NOINTERFACE; - } - --static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource1 *iface) -+static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource2 *iface) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - unsigned int refcount = vkd3d_atomic_increment_u32(&resource->refcount); - - TRACE("%p increasing refcount to %u.\n", resource, refcount); -@@ -1299,9 +1300,9 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource1 *iface) - return refcount; - } - --static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource1 *iface) -+static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource2 *iface) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - unsigned int refcount = vkd3d_atomic_decrement_u32(&resource->refcount); - - TRACE("%p decreasing refcount to %u.\n", resource, refcount); -@@ -1318,39 +1319,39 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource1 *iface) - return refcount; - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_GetPrivateData(ID3D12Resource1 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetPrivateData(ID3D12Resource2 *iface, - REFGUID guid, UINT *data_size, void *data) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - - TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data); - - return vkd3d_get_private_data(&resource->private_store, guid, data_size, data); - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateData(ID3D12Resource1 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateData(ID3D12Resource2 *iface, - REFGUID guid, UINT data_size, const void *data) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - - TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data); - - return vkd3d_set_private_data(&resource->private_store, guid, data_size, data); - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateDataInterface(ID3D12Resource1 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateDataInterface(ID3D12Resource2 *iface, - REFGUID guid, const IUnknown *data) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - - TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data); - - return vkd3d_set_private_data_interface(&resource->private_store, guid, data); - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource1 *iface, const WCHAR *name) -+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource2 *iface, const WCHAR *name) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - HRESULT hr; - - TRACE("iface %p, name %s.\n", iface, debugstr_w(name, resource->device->wchar_size)); -@@ -1369,9 +1370,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource1 *iface, - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, name); - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_GetDevice(ID3D12Resource1 *iface, REFIID iid, void **device) -+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetDevice(ID3D12Resource2 *iface, REFIID iid, void **device) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - - TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device); - -@@ -1422,10 +1423,10 @@ static void d3d12_resource_flush(struct d3d12_resource *resource, uint64_t offse - ERR("Failed to flush memory, vr %d.\n", vr); - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource1 *iface, UINT sub_resource, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource2 *iface, UINT sub_resource, - const D3D12_RANGE *read_range, void **data) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - unsigned int sub_resource_count; - - TRACE("iface %p, sub_resource %u, read_range %p, data %p.\n", -@@ -1471,10 +1472,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource1 *iface, UINT - return S_OK; - } - --static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource1 *iface, UINT sub_resource, -+static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource2 *iface, UINT sub_resource, - const D3D12_RANGE *written_range) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - unsigned int sub_resource_count; - - TRACE("iface %p, sub_resource %u, written_range %p.\n", -@@ -1493,31 +1494,31 @@ static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource1 *iface, UINT - d3d12_resource_flush(resource, written_range->Begin, written_range->End - written_range->Begin); - } - --static D3D12_RESOURCE_DESC * STDMETHODCALLTYPE d3d12_resource_GetDesc(ID3D12Resource1 *iface, -+static D3D12_RESOURCE_DESC * STDMETHODCALLTYPE d3d12_resource_GetDesc(ID3D12Resource2 *iface, - D3D12_RESOURCE_DESC *resource_desc) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - - TRACE("iface %p, resource_desc %p.\n", iface, resource_desc); - -- *resource_desc = resource->desc; -+ memcpy(resource_desc, &resource->desc, sizeof(*resource_desc)); - return resource_desc; - } - --static D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE d3d12_resource_GetGPUVirtualAddress(ID3D12Resource1 *iface) -+static D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE d3d12_resource_GetGPUVirtualAddress(ID3D12Resource2 *iface) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - - TRACE("iface %p.\n", iface); - - return resource->gpu_address; - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resource1 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resource2 *iface, - UINT dst_sub_resource, const D3D12_BOX *dst_box, const void *src_data, - UINT src_row_pitch, UINT src_slice_pitch) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - const struct vkd3d_vk_device_procs *vk_procs; - VkImageSubresource vk_sub_resource; - const struct vkd3d_format *format; -@@ -1598,11 +1599,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resourc - return S_OK; - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resource1 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resource2 *iface, - void *dst_data, UINT dst_row_pitch, UINT dst_slice_pitch, - UINT src_sub_resource, const D3D12_BOX *src_box) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - const struct vkd3d_vk_device_procs *vk_procs; - VkImageSubresource vk_sub_resource; - const struct vkd3d_format *format; -@@ -1683,10 +1684,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour - return S_OK; - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource1 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource2 *iface, - D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS *flags) - { -- struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); - struct d3d12_heap *heap; - - TRACE("iface %p, heap_properties %p, flags %p.\n", -@@ -1720,15 +1721,26 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource - return S_OK; - } - --static HRESULT STDMETHODCALLTYPE d3d12_resource_GetProtectedResourceSession(ID3D12Resource1 *iface, -+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetProtectedResourceSession(ID3D12Resource2 *iface, - REFIID iid, void **session) - { - FIXME("iface %p, iid %s, session %p stub!\n", iface, debugstr_guid(iid), session); - -- return E_NOTIMPL; -+ return DXGI_ERROR_NOT_FOUND; -+} -+ -+static D3D12_RESOURCE_DESC1 * STDMETHODCALLTYPE d3d12_resource_GetDesc1(ID3D12Resource2 *iface, -+ D3D12_RESOURCE_DESC1 *resource_desc) -+{ -+ struct d3d12_resource *resource = impl_from_ID3D12Resource2(iface); -+ -+ TRACE("iface %p, resource_desc %p.\n", iface, resource_desc); -+ -+ *resource_desc = resource->desc; -+ return resource_desc; - } - --static const struct ID3D12Resource1Vtbl d3d12_resource_vtbl = -+static const struct ID3D12Resource2Vtbl d3d12_resource_vtbl = - { - /* IUnknown methods */ - d3d12_resource_QueryInterface, -@@ -1751,6 +1763,8 @@ static const struct ID3D12Resource1Vtbl d3d12_resource_vtbl = - d3d12_resource_GetHeapProperties, - /* ID3D12Resource1 methods */ - d3d12_resource_GetProtectedResourceSession, -+ /* ID3D12Resource2 methods */ -+ d3d12_resource_GetDesc1, - }; - - struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface) -@@ -1777,7 +1791,7 @@ static void d3d12_validate_resource_flags(D3D12_RESOURCE_FLAGS flags) - FIXME("Ignoring D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER.\n"); - } - --static bool d3d12_resource_validate_texture_format(const D3D12_RESOURCE_DESC *desc, -+static bool d3d12_resource_validate_texture_format(const D3D12_RESOURCE_DESC1 *desc, - const struct vkd3d_format *format) - { - if (desc->Format == DXGI_FORMAT_UNKNOWN) -@@ -1806,7 +1820,7 @@ static bool d3d12_resource_validate_texture_format(const D3D12_RESOURCE_DESC *de - return true; - } - --static bool d3d12_resource_validate_texture_alignment(const D3D12_RESOURCE_DESC *desc, -+static bool d3d12_resource_validate_texture_alignment(const D3D12_RESOURCE_DESC1 *desc, - const struct vkd3d_format *format) - { - uint64_t estimated_size; -@@ -1841,7 +1855,7 @@ static bool d3d12_resource_validate_texture_alignment(const D3D12_RESOURCE_DESC - return true; - } - --HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device) -+HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC1 *desc, struct d3d12_device *device) - { - const struct vkd3d_format *format; - -@@ -1950,12 +1964,12 @@ static bool d3d12_resource_validate_heap_properties(const struct d3d12_resource - - static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12_device *device, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, -+ const D3D12_RESOURCE_DESC1 *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value) - { - HRESULT hr; - -- resource->ID3D12Resource1_iface.lpVtbl = &d3d12_resource_vtbl; -+ resource->ID3D12Resource2_iface.lpVtbl = &d3d12_resource_vtbl; - resource->refcount = 1; - resource->internal_refcount = 1; - -@@ -2047,7 +2061,7 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12 - - static HRESULT d3d12_resource_create(struct d3d12_device *device, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, -+ const D3D12_RESOURCE_DESC1 *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource) - { - struct d3d12_resource *object; -@@ -2086,7 +2100,7 @@ static HRESULT vkd3d_allocate_resource_memory( - - HRESULT d3d12_committed_resource_create(struct d3d12_device *device, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, -+ const D3D12_RESOURCE_DESC1 *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, ID3D12ProtectedResourceSession *protected_session, - struct d3d12_resource **resource) - { -@@ -2108,7 +2122,7 @@ HRESULT d3d12_committed_resource_create(struct d3d12_device *device, - - if (FAILED(hr = vkd3d_allocate_resource_memory(device, object, heap_properties, heap_flags))) - { -- d3d12_resource_Release(&object->ID3D12Resource1_iface); -+ d3d12_resource_Release(&object->ID3D12Resource2_iface); - return hr; - } - -@@ -2189,7 +2203,7 @@ allocate_memory: - } - - HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_heap *heap, uint64_t heap_offset, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, -+ const D3D12_RESOURCE_DESC1 *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource) - { - struct d3d12_resource *object; -@@ -2201,7 +2215,7 @@ HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_h - - if (FAILED(hr = vkd3d_bind_heap_memory(device, object, heap, heap_offset))) - { -- d3d12_resource_Release(&object->ID3D12Resource1_iface); -+ d3d12_resource_Release(&object->ID3D12Resource2_iface); - return hr; - } - -@@ -2213,7 +2227,7 @@ HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_h - } - - HRESULT d3d12_reserved_resource_create(struct d3d12_device *device, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, -+ const D3D12_RESOURCE_DESC1 *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource) - { - struct d3d12_resource *object; -@@ -2225,7 +2239,7 @@ HRESULT d3d12_reserved_resource_create(struct d3d12_device *device, - - if (!d3d12_resource_init_tiles(object, device)) - { -- d3d12_resource_Release(&object->ID3D12Resource1_iface); -+ d3d12_resource_Release(&object->ID3D12Resource2_iface); - return E_OUTOFMEMORY; - } - -@@ -2260,7 +2274,7 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, - - memset(object, 0, sizeof(*object)); - -- object->ID3D12Resource1_iface.lpVtbl = &d3d12_resource_vtbl; -+ object->ID3D12Resource2_iface.lpVtbl = &d3d12_resource_vtbl; - object->refcount = 1; - object->internal_refcount = 1; - object->desc = create_info->desc; -@@ -2284,7 +2298,7 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, - - TRACE("Created resource %p.\n", object); - -- *resource = (ID3D12Resource *)&object->ID3D12Resource1_iface; -+ *resource = (ID3D12Resource *)&object->ID3D12Resource2_iface; - - return S_OK; - } -@@ -3022,7 +3036,7 @@ static bool init_default_texture_view_desc(struct vkd3d_texture_view_desc *desc, - } - - static void vkd3d_texture_view_desc_normalise(struct vkd3d_texture_view_desc *desc, -- const D3D12_RESOURCE_DESC *resource_desc) -+ const D3D12_RESOURCE_DESC1 *resource_desc) - { - unsigned int max_layer_count; - -@@ -4815,7 +4829,7 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources, - { - const bool use_sparse_resources = device->vk_info.sparse_properties.residencyNonResidentStrict; - D3D12_HEAP_PROPERTIES heap_properties; -- D3D12_RESOURCE_DESC resource_desc; -+ D3D12_RESOURCE_DESC1 resource_desc; - HRESULT hr; - - TRACE("Creating resources for NULL views.\n"); -@@ -4840,6 +4854,7 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources, - resource_desc.SampleDesc.Quality = 0; - resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE; -+ memset(&resource_desc.SamplerFeedbackMipRegion, 0, sizeof(resource_desc.SamplerFeedbackMipRegion)); - - if (FAILED(hr = vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_NONE, - &resource_desc, &null_resources->vk_buffer))) -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index 78f4f3514e2..ed331ccbcc5 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -@@ -692,11 +692,11 @@ struct d3d12_resource_tile_info - /* ID3D12Resource */ - struct d3d12_resource - { -- ID3D12Resource1 ID3D12Resource1_iface; -+ ID3D12Resource2 ID3D12Resource2_iface; - unsigned int refcount; - unsigned int internal_refcount; - -- D3D12_RESOURCE_DESC desc; -+ D3D12_RESOURCE_DESC1 desc; - const struct vkd3d_format *format; - - D3D12_GPU_VIRTUAL_ADDRESS gpu_address; -@@ -724,12 +724,12 @@ struct d3d12_resource - - static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface) - { -- return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource1_iface); -+ return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource2_iface); - } - --static inline struct d3d12_resource *impl_from_ID3D12Resource1(ID3D12Resource1 *iface) -+static inline struct d3d12_resource *impl_from_ID3D12Resource2(ID3D12Resource2 *iface) - { -- return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource1_iface); -+ return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource2_iface); - } - - static inline bool d3d12_resource_is_buffer(const struct d3d12_resource *resource) -@@ -750,7 +750,7 @@ struct vkd3d_resource_allocation_info - }; - - bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource); --HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device); -+HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC1 *desc, struct d3d12_device *device); - void d3d12_resource_get_tiling(struct d3d12_device *device, const struct d3d12_resource *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, -@@ -758,14 +758,14 @@ void d3d12_resource_get_tiling(struct d3d12_device *device, const struct d3d12_r - - HRESULT d3d12_committed_resource_create(struct d3d12_device *device, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, -+ const D3D12_RESOURCE_DESC1 *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, ID3D12ProtectedResourceSession *protected_session, - struct d3d12_resource **resource); - HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_heap *heap, uint64_t heap_offset, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, -+ const D3D12_RESOURCE_DESC1 *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource); - HRESULT d3d12_reserved_resource_create(struct d3d12_device *device, -- const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state, -+ const D3D12_RESOURCE_DESC1 *desc, D3D12_RESOURCE_STATES initial_state, - const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource); - struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface); - -@@ -774,9 +774,9 @@ HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_bu - VkDeviceMemory *vk_memory, uint32_t *vk_memory_type, VkDeviceSize *vk_memory_size); - HRESULT vkd3d_create_buffer(struct d3d12_device *device, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, -- const D3D12_RESOURCE_DESC *desc, VkBuffer *vk_buffer); -+ const D3D12_RESOURCE_DESC1 *desc, VkBuffer *vk_buffer); - HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, -- const D3D12_RESOURCE_DESC *desc, struct vkd3d_resource_allocation_info *allocation_info); -+ const D3D12_RESOURCE_DESC1 *desc, struct vkd3d_resource_allocation_info *allocation_info); - - enum vkd3d_view_type - { -@@ -1876,7 +1876,7 @@ HRESULT vkd3d_init_format_info(struct d3d12_device *device); - void vkd3d_cleanup_format_info(struct d3d12_device *device); - - static inline const struct vkd3d_format *vkd3d_format_from_d3d12_resource_desc( -- const struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc, DXGI_FORMAT view_format) -+ const struct d3d12_device *device, const D3D12_RESOURCE_DESC1 *desc, DXGI_FORMAT view_format) - { - return vkd3d_get_format(device, view_format ? view_format : desc->Format, - desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL); -@@ -1887,31 +1887,31 @@ static inline bool d3d12_box_is_empty(const D3D12_BOX *box) - return box->right <= box->left || box->bottom <= box->top || box->back <= box->front; - } - --static inline unsigned int d3d12_resource_desc_get_width(const D3D12_RESOURCE_DESC *desc, -+static inline unsigned int d3d12_resource_desc_get_width(const D3D12_RESOURCE_DESC1 *desc, - unsigned int miplevel_idx) - { - return max(1, desc->Width >> miplevel_idx); - } - --static inline unsigned int d3d12_resource_desc_get_height(const D3D12_RESOURCE_DESC *desc, -+static inline unsigned int d3d12_resource_desc_get_height(const D3D12_RESOURCE_DESC1 *desc, - unsigned int miplevel_idx) - { - return max(1, desc->Height >> miplevel_idx); - } - --static inline unsigned int d3d12_resource_desc_get_depth(const D3D12_RESOURCE_DESC *desc, -+static inline unsigned int d3d12_resource_desc_get_depth(const D3D12_RESOURCE_DESC1 *desc, - unsigned int miplevel_idx) - { - unsigned int d = desc->Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? 1 : desc->DepthOrArraySize; - return max(1, d >> miplevel_idx); - } - --static inline unsigned int d3d12_resource_desc_get_layer_count(const D3D12_RESOURCE_DESC *desc) -+static inline unsigned int d3d12_resource_desc_get_layer_count(const D3D12_RESOURCE_DESC1 *desc) - { - return desc->Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? desc->DepthOrArraySize : 1; - } - --static inline unsigned int d3d12_resource_desc_get_sub_resource_count(const D3D12_RESOURCE_DESC *desc) -+static inline unsigned int d3d12_resource_desc_get_sub_resource_count(const D3D12_RESOURCE_DESC1 *desc) - { - return d3d12_resource_desc_get_layer_count(desc) * desc->MipLevels; - } --- -2.43.0 - diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-d9c68ee481367d90da949cbd41b09ceb4b6.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-d9c68ee481367d90da949cbd41b09ceb4b6.patch deleted file mode 100644 index c41c1f28..00000000 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-d9c68ee481367d90da949cbd41b09ceb4b6.patch +++ /dev/null @@ -1,1511 +0,0 @@ -From a42ba588e5eda7f2f182aa3a2dd0ab527e1a39b3 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 21 Feb 2024 15:11:16 +1100 -Subject: [PATCH] Updated vkd3d to d9c68ee481367d90da949cbd41b09ceb4b6a3823. - ---- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 284 ++++++++++--- - libs/vkd3d/libs/vkd3d-shader/fx.c | 379 ++++++++++++++++-- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 20 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 16 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 130 +++--- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 48 ++- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 8 + - .../libs/vkd3d-shader/vkd3d_shader_main.c | 10 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 1 + - 9 files changed, 712 insertions(+), 184 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 33d30aef08e..2ca3aa955e7 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -199,10 +199,12 @@ enum dxil_resource_kind - RESOURCE_KIND_FEEDBACKTEXTURE2DARRAY = 18, - }; - --enum dxil_resource_type -+enum dxil_resource_tag - { -- RESOURCE_TYPE_NON_RAW_STRUCTURED = 0, -- RESOURCE_TYPE_RAW_STRUCTURED = 1, -+ RESOURCE_TAG_ELEMENT_TYPE = 0, -+ RESOURCE_TAG_ELEMENT_STRIDE = 1, -+ RESOURCE_TAG_SAMPLER_FEEDBACK_KIND = 2, -+ RESOURCE_TAG_ENABLE_ATOMIC_64 = 3, - }; - - enum dxil_component_type -@@ -381,6 +383,8 @@ enum dx_intrinsic_opcode - DX_TEXTURE_LOAD = 66, - DX_TEXTURE_STORE = 67, - DX_BUFFER_LOAD = 68, -+ DX_ATOMIC_BINOP = 78, -+ DX_ATOMIC_CMP_XCHG = 79, - DX_DERIV_COARSEX = 83, - DX_DERIV_COARSEY = 84, - DX_DERIV_FINEX = 85, -@@ -438,6 +442,20 @@ enum dxil_predicate - ICMP_SLE = 41, - }; - -+enum dxil_atomic_binop_code -+{ -+ ATOMIC_BINOP_ADD, -+ ATOMIC_BINOP_AND, -+ ATOMIC_BINOP_OR, -+ ATOMIC_BINOP_XOR, -+ ATOMIC_BINOP_IMIN, -+ ATOMIC_BINOP_IMAX, -+ ATOMIC_BINOP_UMIN, -+ ATOMIC_BINOP_UMAX, -+ ATOMIC_BINOP_XCHG, -+ ATOMIC_BINOP_INVALID, -+}; -+ - struct sm6_pointer_info - { - const struct sm6_type *type; -@@ -2275,7 +2293,7 @@ static void src_param_init_from_value(struct vkd3d_shader_src_param *param, cons - static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, - const struct vkd3d_shader_register *reg) - { -- param->swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ param->swizzle = (reg->dimension == VSIR_DIMENSION_VEC4) ? VKD3D_SHADER_NO_SWIZZLE : VKD3D_SHADER_SWIZZLE(X, X, X, X); - param->modifiers = VKD3DSPSM_NONE; - param->reg = *reg; - } -@@ -3823,6 +3841,105 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ - instruction_dst_param_init_ssa_scalar(ins, sm6); - } - -+static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6) -+{ -+ uint64_t code = sm6_value_get_constant_uint(operand); -+ -+ switch (code) -+ { -+ case ATOMIC_BINOP_ADD: -+ return VKD3DSIH_IMM_ATOMIC_IADD; -+ case ATOMIC_BINOP_AND: -+ return VKD3DSIH_IMM_ATOMIC_AND; -+ case ATOMIC_BINOP_IMAX: -+ return VKD3DSIH_IMM_ATOMIC_IMAX; -+ case ATOMIC_BINOP_IMIN: -+ return VKD3DSIH_IMM_ATOMIC_IMIN; -+ case ATOMIC_BINOP_OR: -+ return VKD3DSIH_IMM_ATOMIC_OR; -+ case ATOMIC_BINOP_UMAX: -+ return VKD3DSIH_IMM_ATOMIC_UMAX; -+ case ATOMIC_BINOP_UMIN: -+ return VKD3DSIH_IMM_ATOMIC_UMIN; -+ case ATOMIC_BINOP_XCHG: -+ return VKD3DSIH_IMM_ATOMIC_EXCH; -+ case ATOMIC_BINOP_XOR: -+ return VKD3DSIH_IMM_ATOMIC_XOR; -+ /* DXIL currently doesn't use SUB and NAND. */ -+ default: -+ FIXME("Unhandled atomic binop %"PRIu64".\n", code); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Operation %"PRIu64" for an atomic binop instruction is unhandled.", code); -+ return VKD3DSIH_INVALID; -+ } -+} -+ -+static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct sm6_value *dst = sm6_parser_get_current_value(sm6); -+ enum vkd3d_shader_resource_type resource_type; -+ bool is_cmp_xchg = op == DX_ATOMIC_CMP_XCHG; -+ unsigned int i, coord_idx, coord_count = 1; -+ struct vkd3d_shader_dst_param *dst_params; -+ struct vkd3d_shader_src_param *src_params; -+ enum vkd3d_shader_opcode handler_idx; -+ struct vkd3d_shader_instruction *ins; -+ const struct sm6_value *resource; -+ struct vkd3d_shader_register reg; -+ -+ resource = operands[0]; -+ if (!sm6_value_validate_is_handle(resource, sm6)) -+ return; -+ -+ if (is_cmp_xchg) -+ handler_idx = VKD3DSIH_IMM_ATOMIC_CMP_EXCH; -+ else if ((handler_idx = map_dx_atomic_binop(operands[1], sm6)) == VKD3DSIH_INVALID) -+ return; -+ -+ coord_idx = 2 - is_cmp_xchg; -+ resource_type = resource->u.handle.d->resource_type; -+ if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER || resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER) -+ { -+ coord_count = 2 + (resource_type != VKD3D_SHADER_RESOURCE_BUFFER); -+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[coord_idx], coord_count, NULL, state, ®)) -+ return; -+ } -+ else -+ { -+ reg = operands[coord_idx]->u.reg; -+ } -+ -+ for (i = coord_idx + coord_count; i < coord_idx + 3; ++i) -+ { -+ if (!operands[i]->is_undefined) -+ { -+ WARN("Ignoring unexpected operand.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring an unexpected defined operand value for atomic instruction %u.", handler_idx); -+ break; -+ } -+ } -+ -+ ins = state->ins; -+ vsir_instruction_init(ins, &sm6->p.location, handler_idx); -+ -+ if (!(src_params = instruction_src_params_alloc(ins, 2 + is_cmp_xchg, sm6))) -+ return; -+ src_param_init_vector_from_reg(&src_params[0], ®); -+ if (is_cmp_xchg) -+ src_param_init_from_value(&src_params[1], operands[4]); -+ src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5]); -+ -+ dst_params = instruction_dst_params_alloc(ins, 2, sm6); -+ dst_param_init(&dst_params[0]); -+ register_init_ssa_scalar(&dst_params[0].reg, dst->type, dst, sm6); -+ dst_param_init(&dst_params[1]); -+ dst_params[1].reg = resource->u.handle.reg; -+ -+ dst->u.reg = dst_params[0].reg; -+} -+ - static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, - const struct sm6_value **operands, struct function_emission_state *state) - { -@@ -4357,6 +4474,8 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - [DX_ACOS ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_ASIN ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_ATAN ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_ATOMIC_BINOP ] = {"o", "HciiiR", sm6_parser_emit_dx_atomic_binop}, -+ [DX_ATOMIC_CMP_XCHG ] = {"o", "HiiiRR", sm6_parser_emit_dx_atomic_binop}, - [DX_BFREV ] = {"m", "R", sm6_parser_emit_dx_unary}, - [DX_BUFFER_LOAD ] = {"o", "Hii", sm6_parser_emit_dx_buffer_load}, - [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, -@@ -6556,15 +6675,97 @@ static enum vkd3d_data_type vkd3d_data_type_from_dxil_component_type(enum dxil_c - return data_type; - } - -+struct resource_additional_values -+{ -+ enum vkd3d_data_type data_type; -+ unsigned int byte_stride; -+}; -+ -+static bool resources_load_additional_values(struct resource_additional_values *info, -+ const struct sm6_metadata_node *node, enum dxil_resource_kind kind, struct sm6_parser *sm6) -+{ -+ unsigned int i, operand_count, tag, value; -+ -+ info->data_type = VKD3D_DATA_UNUSED; -+ info->byte_stride = 0; -+ -+ if (node->operand_count & 1) -+ { -+ WARN("Operand count is not even.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Operand count for resource descriptor tag/value pairs is not even."); -+ } -+ operand_count = node->operand_count & ~1u; -+ -+ for (i = 0; i < operand_count; i += 2) -+ { -+ if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &tag) -+ || !sm6_metadata_get_uint_value(sm6, node->operands[i + 1], &value)) -+ { -+ WARN("Failed to load tag/value pair at index %u.\n", i); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Resource descriptor tag/value pair at index %u is not an integer pair.", i); -+ return false; -+ } -+ -+ switch (tag) -+ { -+ case RESOURCE_TAG_ELEMENT_TYPE: -+ if (value && kind != RESOURCE_KIND_TYPEDBUFFER && !resource_kind_is_texture(kind)) -+ { -+ WARN("Invalid type %u for an untyped resource.\n", value); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "An untyped resource has type %u.", value); -+ return false; -+ } -+ info->data_type = vkd3d_data_type_from_dxil_component_type(value, sm6); -+ break; -+ -+ case RESOURCE_TAG_ELEMENT_STRIDE: -+ if (value && kind != RESOURCE_KIND_STRUCTUREDBUFFER) -+ { -+ WARN("Invalid stride %u for an unstructured resource.\n", value); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "An unstructured resource has a byte stride."); -+ return false; -+ } -+ info->byte_stride = value; -+ break; -+ -+ case RESOURCE_TAG_SAMPLER_FEEDBACK_KIND: -+ /* MinMip = 0, MipRegionUsed = 1 */ -+ FIXME("Unhandled sampler feedback kind %u.\n", value); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "Sampler feedback kind %u is unhandled.", value); -+ break; -+ -+ case RESOURCE_TAG_ENABLE_ATOMIC_64: -+ if (value) -+ { -+ FIXME("Unsupported 64-bit atomic ops.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -+ "64-bit atomic ops on resources are not supported."); -+ } -+ break; -+ -+ default: -+ FIXME("Unhandled tag %u, value %u.\n", tag, value); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Tag %u for resource descriptor additional value %u is unhandled.", tag, value); -+ break; -+ } -+ } -+ -+ return true; -+} -+ - static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struct sm6_parser *sm6, - const struct sm6_metadata_value *type_value, bool is_uav, enum dxil_resource_kind kind, - const struct sm6_metadata_value *m, struct vkd3d_shader_instruction *ins) - { -+ struct resource_additional_values resource_values; - enum vkd3d_shader_resource_type resource_type; -- enum dxil_resource_type dxil_resource_type; -- const struct sm6_metadata_node *node; -- enum vkd3d_data_type data_type; -- unsigned int i, values[2]; -+ unsigned int i; - - if (!(resource_type = shader_resource_type_from_dxil_resource_kind(kind))) - { -@@ -6590,72 +6791,37 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc - return NULL; - } - -- node = m->u.node; -- -- if (node->operand_count < 2) -- { -- WARN("Invalid operand count %u.\n", node->operand_count); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -- "Invalid operand count %u for a resource descriptor.", node->operand_count); -+ if (!resources_load_additional_values(&resource_values, m->u.node, kind, sm6)) - return NULL; -- } -- if (node->operand_count > 2) -- { -- WARN("Ignoring %u extra operands.\n", node->operand_count - 2); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -- "Ignoring %u extra operands for a resource descriptor.", node->operand_count - 2); -- } -- -- for (i = 0; i < 2; ++i) -- { -- if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &values[i])) -- { -- WARN("Failed to load uint value at index %u.\n", i); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -- "A resource descriptor operand metadata value is not an integer."); -- return NULL; -- } -- } - -- if ((dxil_resource_type = values[0]) == RESOURCE_TYPE_NON_RAW_STRUCTURED) -+ if (kind == RESOURCE_KIND_TYPEDBUFFER || resource_kind_is_texture(kind)) - { -- if (kind != RESOURCE_KIND_TYPEDBUFFER && !resource_kind_is_texture(kind)) -+ if (resource_values.data_type == VKD3D_DATA_UNUSED) - { -- WARN("Unhandled resource kind %u.\n", kind); -+ WARN("No data type defined.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -- "Resource kind %u for a typed resource is unhandled.", kind); -- return NULL; -+ "A typed resource has no data type."); - } - -- data_type = vkd3d_data_type_from_dxil_component_type(values[1], sm6); - ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_TYPED : VKD3DSIH_DCL; - for (i = 0; i < VKD3D_VEC4_SIZE; ++i) -- ins->declaration.semantic.resource_data_type[i] = data_type; -+ ins->declaration.semantic.resource_data_type[i] = resource_values.data_type; - ins->declaration.semantic.resource_type = resource_type; - ins->declaration.semantic.resource.reg.write_mask = VKD3DSP_WRITEMASK_ALL; - - return &ins->declaration.semantic.resource; - } -- else if (dxil_resource_type == RESOURCE_TYPE_RAW_STRUCTURED) -+ else if (kind == RESOURCE_KIND_RAWBUFFER) - { -- if (kind == RESOURCE_KIND_RAWBUFFER) -- { -- ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; -- ins->declaration.raw_resource.resource.reg.write_mask = 0; -- -- return &ins->declaration.raw_resource.resource; -- } -- -- if (kind != RESOURCE_KIND_STRUCTUREDBUFFER) -- { -- WARN("Unhandled resource kind %u.\n", kind); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -- "Resource kind %u for a raw or structured buffer is unhandled.", kind); -- return NULL; -- } -+ ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; -+ ins->declaration.raw_resource.resource.reg.write_mask = 0; - -+ return &ins->declaration.raw_resource.resource; -+ } -+ else if (kind == RESOURCE_KIND_STRUCTUREDBUFFER) -+ { - ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_STRUCTURED : VKD3DSIH_DCL_RESOURCE_STRUCTURED; -- ins->declaration.structured_resource.byte_stride = values[1]; -+ ins->declaration.structured_resource.byte_stride = resource_values.byte_stride; - ins->declaration.structured_resource.resource.reg.write_mask = 0; - - /* TODO: 16-bit resources. */ -@@ -6671,9 +6837,9 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc - } - else - { -- FIXME("Unhandled resource type %u.\n", dxil_resource_type); -+ FIXME("Unhandled resource kind %u.\n", kind); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, -- "Resource type %u is unhandled.", dxil_resource_type); -+ "Resource kind %u is unhandled.", kind); - } - - return NULL; -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index e1459f76c14..11dee4ba9d7 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -20,6 +20,11 @@ - - #include "hlsl.h" - -+static inline size_t put_u32_unaligned(struct vkd3d_bytecode_buffer *buffer, uint32_t value) -+{ -+ return bytecode_put_bytes_unaligned(buffer, &value, sizeof(value)); -+} -+ - struct string_entry - { - struct rb_entry entry; -@@ -28,6 +33,14 @@ struct string_entry - uint32_t offset; - }; - -+struct type_entry -+{ -+ struct list entry; -+ const char *name; -+ uint32_t elements_count; -+ uint32_t offset; -+}; -+ - static int string_storage_compare(const void *key, const struct rb_entry *entry) - { - struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); -@@ -48,6 +61,7 @@ struct fx_write_context; - struct fx_write_context_ops - { - uint32_t (*write_string)(const char *string, struct fx_write_context *fx); -+ uint32_t (*write_type)(const struct hlsl_type *type, struct fx_write_context *fx); - void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx); - void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx); - }; -@@ -60,17 +74,28 @@ struct fx_write_context - struct vkd3d_bytecode_buffer structured; - - struct rb_tree strings; -+ struct list types; - - unsigned int min_technique_version; - unsigned int max_technique_version; - - uint32_t technique_count; - uint32_t group_count; -+ uint32_t buffer_count; -+ uint32_t numeric_variable_count; - int status; - - const struct fx_write_context_ops *ops; - }; - -+static void set_status(struct fx_write_context *fx, int status) -+{ -+ if (fx->status < 0) -+ return; -+ if (status < 0) -+ fx->status = status; -+} -+ - static uint32_t write_string(const char *string, struct fx_write_context *fx) - { - return fx->ops->write_string(string, fx); -@@ -81,6 +106,46 @@ static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) - fx->ops->write_pass(var, fx); - } - -+static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx) -+{ -+ struct type_entry *type_entry; -+ unsigned int elements_count; -+ const char *name; -+ -+ if (type->class == HLSL_CLASS_ARRAY) -+ { -+ name = hlsl_get_multiarray_element_type(type)->name; -+ elements_count = hlsl_get_multiarray_size(type); -+ } -+ else -+ { -+ name = type->name; -+ elements_count = 0; -+ } -+ -+ LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) -+ { -+ if (strcmp(type_entry->name, name)) -+ continue; -+ -+ if (type_entry->elements_count != elements_count) -+ continue; -+ -+ return type_entry->offset; -+ } -+ -+ if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry)))) -+ return 0; -+ -+ type_entry->offset = fx->ops->write_type(type, fx); -+ type_entry->name = name; -+ type_entry->elements_count = elements_count; -+ -+ list_add_tail(&fx->types, &type_entry->entry); -+ -+ return type_entry->offset; -+} -+ - static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_context_ops *ops, - struct fx_write_context *fx) - { -@@ -107,13 +172,22 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co - } - - rb_init(&fx->strings, string_storage_compare); -+ list_init(&fx->types); - } - - static int fx_write_context_cleanup(struct fx_write_context *fx) - { -+ struct type_entry *type, *next_type; - int status = fx->status; -+ - rb_destroy(&fx->strings, string_storage_destroy, NULL); - -+ LIST_FOR_EACH_ENTRY_SAFE(type, next_type, &fx->types, struct type_entry, entry) -+ { -+ list_remove(&type->entry); -+ vkd3d_free(type); -+ } -+ - return status; - } - -@@ -145,7 +219,7 @@ static uint32_t write_fx_4_string(const char *string, struct fx_write_context *f - if (!(string_entry = hlsl_alloc(fx->ctx, sizeof(*string_entry)))) - return 0; - -- string_entry->offset = put_string(&fx->unstructured, string); -+ string_entry->offset = bytecode_put_bytes_unaligned(&fx->unstructured, string, strlen(string) + 1); - string_entry->string = string; - - rb_put(&fx->strings, string, &string_entry->entry); -@@ -181,6 +255,156 @@ static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx - /* TODO: assignments */ - } - -+static uint32_t get_fx_4_type_size(const struct hlsl_type *type) -+{ -+ uint32_t elements_count; -+ -+ elements_count = hlsl_get_multiarray_size(type); -+ type = hlsl_get_multiarray_element_type(type); -+ -+ return type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float) * elements_count; -+} -+ -+static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, struct fx_write_context *fx) -+{ -+ static const unsigned int NUMERIC_BASE_TYPE_SHIFT = 3; -+ static const unsigned int NUMERIC_ROWS_SHIFT = 8; -+ static const unsigned int NUMERIC_COLUMNS_SHIFT = 11; -+ static const unsigned int NUMERIC_COLUMN_MAJOR_MASK = 0x4000; -+ static const uint32_t numeric_type_class[] = -+ { -+ [HLSL_CLASS_SCALAR] = 1, -+ [HLSL_CLASS_VECTOR] = 2, -+ [HLSL_CLASS_MATRIX] = 3, -+ }; -+ static const uint32_t numeric_base_type[] = -+ { -+ [HLSL_TYPE_FLOAT] = 1, -+ [HLSL_TYPE_INT ] = 2, -+ [HLSL_TYPE_UINT ] = 3, -+ [HLSL_TYPE_BOOL ] = 4, -+ }; -+ uint32_t value = 0; -+ -+ switch (type->class) -+ { -+ case HLSL_CLASS_SCALAR: -+ case HLSL_CLASS_VECTOR: -+ case HLSL_CLASS_MATRIX: -+ value |= numeric_type_class[type->class]; -+ break; -+ default: -+ FIXME("Unexpected type class %u.\n", type->class); -+ set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED); -+ return 0; -+ } -+ -+ switch (type->base_type) -+ { -+ case HLSL_TYPE_FLOAT: -+ case HLSL_TYPE_INT: -+ case HLSL_TYPE_UINT: -+ case HLSL_TYPE_BOOL: -+ value |= (numeric_base_type[type->base_type] << NUMERIC_BASE_TYPE_SHIFT); -+ break; -+ default: -+ FIXME("Unexpected base type %u.\n", type->base_type); -+ set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED); -+ return 0; -+ } -+ -+ value |= (type->dimy & 0x7) << NUMERIC_ROWS_SHIFT; -+ value |= (type->dimx & 0x7) << NUMERIC_COLUMNS_SHIFT; -+ if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR) -+ value |= NUMERIC_COLUMN_MAJOR_MASK; -+ -+ return value; -+} -+ -+static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; -+ uint32_t name_offset, offset, size, stride, numeric_desc; -+ uint32_t elements_count = 0; -+ static const uint32_t variable_type[] = -+ { -+ [HLSL_CLASS_SCALAR] = 1, -+ [HLSL_CLASS_VECTOR] = 1, -+ [HLSL_CLASS_MATRIX] = 1, -+ [HLSL_CLASS_OBJECT] = 2, -+ [HLSL_CLASS_STRUCT] = 3, -+ }; -+ -+ /* Resolve arrays to element type and number of elements. */ -+ if (type->class == HLSL_CLASS_ARRAY) -+ { -+ elements_count = hlsl_get_multiarray_size(type); -+ type = hlsl_get_multiarray_element_type(type); -+ } -+ -+ name_offset = write_string(type->name, fx); -+ offset = put_u32_unaligned(buffer, name_offset); -+ -+ switch (type->class) -+ { -+ case HLSL_CLASS_SCALAR: -+ case HLSL_CLASS_VECTOR: -+ case HLSL_CLASS_MATRIX: -+ case HLSL_CLASS_OBJECT: -+ case HLSL_CLASS_STRUCT: -+ put_u32_unaligned(buffer, variable_type[type->class]); -+ break; -+ default: -+ FIXME("Writing type class %u is not implemented.\n", type->class); -+ set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED); -+ return 0; -+ } -+ -+ size = stride = type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float); -+ if (elements_count) -+ size *= elements_count; -+ stride = align(stride, 4 * sizeof(float)); -+ -+ put_u32_unaligned(buffer, elements_count); -+ put_u32_unaligned(buffer, size); /* Total size. */ -+ put_u32_unaligned(buffer, stride); /* Stride. */ -+ put_u32_unaligned(buffer, size); -+ -+ if (type->class == HLSL_CLASS_STRUCT) -+ { -+ size_t i; -+ -+ put_u32_unaligned(buffer, type->e.record.field_count); -+ for (i = 0; i < type->e.record.field_count; ++i) -+ { -+ const struct hlsl_struct_field *field = &type->e.record.fields[i]; -+ uint32_t semantic_offset, field_type_offset; -+ -+ name_offset = write_string(field->name, fx); -+ semantic_offset = write_string(field->semantic.name, fx); -+ field_type_offset = write_type(field->type, fx); -+ -+ put_u32_unaligned(buffer, name_offset); -+ put_u32_unaligned(buffer, semantic_offset); -+ put_u32_unaligned(buffer, field->reg_offset[HLSL_REGSET_NUMERIC]); -+ put_u32_unaligned(buffer, field_type_offset); -+ } -+ } -+ else if (type->class == HLSL_CLASS_OBJECT) -+ { -+ FIXME("Object types are not supported.\n"); -+ set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED); -+ return 0; -+ } -+ else /* Numeric type */ -+ { -+ numeric_desc = get_fx_4_numeric_type_description(type, fx); -+ put_u32_unaligned(buffer, numeric_desc); -+ } -+ -+ return offset; -+} -+ - static void write_fx_4_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) - { - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -@@ -202,14 +426,6 @@ static void write_fx_4_technique(struct hlsl_ir_var *var, struct fx_write_contex - set_u32(buffer, count_offset, count); - } - --static void set_status(struct fx_write_context *fx, int status) --{ -- if (fx->status < 0) -- return; -- if (status < 0) -- fx->status = status; --} -- - static void write_techniques(struct hlsl_scope *scope, struct fx_write_context *fx) - { - struct hlsl_ir_var *var; -@@ -227,10 +443,10 @@ static void write_techniques(struct hlsl_scope *scope, struct fx_write_context * - set_status(fx, fx->structured.status); - } - --static void write_group(struct hlsl_scope *scope, const char *name, struct fx_write_context *fx) -+static void write_group(struct hlsl_ir_var *var, struct fx_write_context *fx) - { - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -- uint32_t name_offset = write_string(name, fx); -+ uint32_t name_offset = write_string(var ? var->name : NULL, fx); - uint32_t count_offset, count; - - put_u32(buffer, name_offset); -@@ -238,14 +454,15 @@ static void write_group(struct hlsl_scope *scope, const char *name, struct fx_wr - put_u32(buffer, 0); /* Annotation count */ - - count = fx->technique_count; -- write_techniques(scope, fx); -+ write_techniques(var ? var->scope : fx->ctx->globals, fx); - set_u32(buffer, count_offset, fx->technique_count - count); - - ++fx->group_count; - } - --static void write_groups(struct hlsl_scope *scope, struct fx_write_context *fx) -+static void write_groups(struct fx_write_context *fx) - { -+ struct hlsl_scope *scope = fx->ctx->globals; - bool needs_default_group = false; - struct hlsl_ir_var *var; - -@@ -259,13 +476,13 @@ static void write_groups(struct hlsl_scope *scope, struct fx_write_context *fx) - } - - if (needs_default_group) -- write_group(scope, NULL, fx); -+ write_group(NULL, fx); - LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) - { - const struct hlsl_type *type = var->data_type; - - if (type->base_type == HLSL_TYPE_EFFECT_GROUP) -- write_group(var->scope, var->name, fx); -+ write_group(var, fx); - } - } - -@@ -366,21 +583,121 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - static const struct fx_write_context_ops fx_4_ops = - { - .write_string = write_fx_4_string, -+ .write_type = write_fx_4_type, - .write_technique = write_fx_4_technique, - .write_pass = write_fx_4_pass, - }; - -+static void write_fx_4_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t semantic_offset, flags = 0; -+ uint32_t name_offset, type_offset; -+ enum fx_4_variable_flags -+ { -+ HAS_EXPLICIT_BIND_POINT = 0x4, -+ }; -+ -+ /* Explicit bind point. */ -+ if (var->reg_reservation.reg_type) -+ flags |= HAS_EXPLICIT_BIND_POINT; -+ -+ type_offset = write_type(var->data_type, fx); -+ name_offset = write_string(var->name, fx); -+ semantic_offset = write_string(var->semantic.name, fx); -+ -+ put_u32(buffer, name_offset); -+ put_u32(buffer, type_offset); -+ -+ semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */ -+ put_u32(buffer, var->buffer_offset); /* Offset in the constant buffer */ -+ put_u32(buffer, 0); /* FIXME: default value offset */ -+ put_u32(buffer, flags); /* Flags */ -+ -+ put_u32(buffer, 0); /* Annotations count */ -+ /* FIXME: write annotations */ -+} -+ -+static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx) -+{ -+ enum fx_4_buffer_flags -+ { -+ IS_TBUFFER = 0x1, -+ IS_SINGLE = 0x2, -+ }; -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t count = 0, bind_point = ~0u, flags = 0, size; -+ uint32_t name_offset, size_offset; -+ struct hlsl_ctx *ctx = fx->ctx; -+ struct hlsl_ir_var *var; -+ uint32_t count_offset; -+ -+ if (b->reservation.reg_type) -+ bind_point = b->reservation.reg_index; -+ if (b->type == HLSL_BUFFER_TEXTURE) -+ flags |= IS_TBUFFER; -+ /* FIXME: set 'single' flag for fx_5_0 */ -+ -+ name_offset = write_string(b->name, fx); -+ -+ put_u32(buffer, name_offset); /* Name */ -+ size_offset = put_u32(buffer, 0); /* Data size */ -+ put_u32(buffer, flags); /* Flags */ -+ count_offset = put_u32(buffer, 0); -+ put_u32(buffer, bind_point); /* Bind point */ -+ -+ put_u32(buffer, 0); /* Annotations count */ -+ /* FIXME: write annotations */ -+ -+ count = 0; -+ size = 0; -+ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) -+ { -+ if (var->buffer != b) -+ continue; -+ -+ write_fx_4_variable(var, fx); -+ size += get_fx_4_type_size(var->data_type); -+ ++count; -+ } -+ -+ set_u32(buffer, count_offset, count); -+ set_u32(buffer, size_offset, align(size, 16)); -+ -+ fx->numeric_variable_count += count; -+} -+ -+static void write_buffers(struct fx_write_context *fx) -+{ -+ struct hlsl_buffer *buffer; -+ struct hlsl_block block; -+ -+ hlsl_block_init(&block); -+ hlsl_prepend_global_uniform_copy(fx->ctx, &block); -+ hlsl_block_init(&block); -+ hlsl_calculate_buffer_offsets(fx->ctx); -+ -+ LIST_FOR_EACH_ENTRY(buffer, &fx->ctx->buffers, struct hlsl_buffer, entry) -+ { -+ if (!buffer->size) -+ continue; -+ -+ write_fx_4_buffer(buffer, fx); -+ ++fx->buffer_count; -+ } -+} -+ - static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - { - struct vkd3d_bytecode_buffer buffer = { 0 }; - struct fx_write_context fx; -- uint32_t size_offset, size; -+ uint32_t size_offset; - - fx_write_context_init(ctx, &fx_4_ops, &fx); - - put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ - -- /* TODO: buffers */ -+ write_buffers(&fx); - /* TODO: objects */ - /* TODO: shared buffers */ - /* TODO: shared objects */ -@@ -388,9 +705,9 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - write_techniques(ctx->globals, &fx); - - put_u32(&buffer, ctx->profile->minor_version == 0 ? 0xfeff1001 : 0xfeff1011); /* Version. */ -- put_u32(&buffer, 0); /* Buffer count. */ -- put_u32(&buffer, 0); /* Variable count. */ -- put_u32(&buffer, 0); /* Object count. */ -+ put_u32(&buffer, fx.buffer_count); /* Buffer count. */ -+ put_u32(&buffer, fx.numeric_variable_count); /* Numeric variable count. */ -+ put_u32(&buffer, 0); /* Object variable count. */ - put_u32(&buffer, 0); /* Pool buffer count. */ - put_u32(&buffer, 0); /* Pool variable count. */ - put_u32(&buffer, 0); /* Pool object count. */ -@@ -407,11 +724,10 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - put_u32(&buffer, 0); /* Shader count. */ - put_u32(&buffer, 0); /* Inline shader count. */ - -- size = align(fx.unstructured.size, 4); -- set_u32(&buffer, size_offset, size); -+ set_u32(&buffer, size_offset, fx.unstructured.size); - - bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); -- bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); -+ bytecode_put_bytes_unaligned(&buffer, fx.structured.data, fx.structured.size); - - vkd3d_free(fx.unstructured.data); - vkd3d_free(fx.structured.data); -@@ -434,22 +750,22 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - { - struct vkd3d_bytecode_buffer buffer = { 0 }; - struct fx_write_context fx; -- uint32_t size_offset, size; -+ uint32_t size_offset; - - fx_write_context_init(ctx, &fx_4_ops, &fx); - - put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ - -- /* TODO: buffers */ -+ write_buffers(&fx); - /* TODO: objects */ - /* TODO: interface variables */ - -- write_groups(ctx->globals, &fx); -+ write_groups(&fx); - - put_u32(&buffer, 0xfeff2001); /* Version. */ -- put_u32(&buffer, 0); /* Buffer count. */ -- put_u32(&buffer, 0); /* Variable count. */ -- put_u32(&buffer, 0); /* Object count. */ -+ put_u32(&buffer, fx.buffer_count); /* Buffer count. */ -+ put_u32(&buffer, fx.numeric_variable_count); /* Numeric variable count. */ -+ put_u32(&buffer, 0); /* Object variable count. */ - put_u32(&buffer, 0); /* Pool buffer count. */ - put_u32(&buffer, 0); /* Pool variable count. */ - put_u32(&buffer, 0); /* Pool object count. */ -@@ -471,11 +787,10 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - put_u32(&buffer, 0); /* Interface variable element count. */ - put_u32(&buffer, 0); /* Class instance elements count. */ - -- size = align(fx.unstructured.size, 4); -- set_u32(&buffer, size_offset, size); -+ set_u32(&buffer, size_offset, fx.unstructured.size); - - bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); -- bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); -+ bytecode_put_bytes_unaligned(&buffer, fx.structured.data, fx.structured.size); - - vkd3d_free(fx.unstructured.data); - vkd3d_free(fx.structured.data); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 3d068ac6d3b..edd99238d59 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -1554,6 +1554,15 @@ bool hlsl_index_is_resource_access(struct hlsl_ir_index *index) - return index->val.node->data_type->class == HLSL_CLASS_OBJECT; - } - -+bool hlsl_index_chain_has_resource_access(struct hlsl_ir_index *index) -+{ -+ if (hlsl_index_is_resource_access(index)) -+ return true; -+ if (index->val.node->type == HLSL_IR_INDEX) -+ return hlsl_index_chain_has_resource_access(hlsl_ir_index(index->val.node)); -+ return false; -+} -+ - struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *val, - struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc) - { -@@ -2192,9 +2201,16 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru - return string; - } - -- assert(type->sampler_dim < ARRAY_SIZE(dimensions)); - assert(type->e.resource_format->base_type < ARRAY_SIZE(base_types)); -- vkd3d_string_buffer_printf(string, "Texture%s", dimensions[type->sampler_dim]); -+ if (type->sampler_dim == HLSL_SAMPLER_DIM_BUFFER) -+ { -+ vkd3d_string_buffer_printf(string, "Buffer"); -+ } -+ else -+ { -+ assert(type->sampler_dim < ARRAY_SIZE(dimensions)); -+ vkd3d_string_buffer_printf(string, "Texture%s", dimensions[type->sampler_dim]); -+ } - if ((inner_string = hlsl_type_to_string(ctx, type->e.resource_format))) - { - vkd3d_string_buffer_printf(string, "<%s>", inner_string->buffer); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index 974a5dd7aee..91500ed8b8b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -104,7 +104,7 @@ enum hlsl_base_type - - enum hlsl_sampler_dim - { -- HLSL_SAMPLER_DIM_GENERIC, -+ HLSL_SAMPLER_DIM_GENERIC = 0, - HLSL_SAMPLER_DIM_COMPARISON, - HLSL_SAMPLER_DIM_1D, - HLSL_SAMPLER_DIM_2D, -@@ -116,10 +116,10 @@ enum hlsl_sampler_dim - HLSL_SAMPLER_DIM_2DMS, - HLSL_SAMPLER_DIM_2DMSARRAY, - HLSL_SAMPLER_DIM_CUBEARRAY, -- HLSL_SAMPLER_DIM_LAST_TEXTURE = HLSL_SAMPLER_DIM_CUBEARRAY, - HLSL_SAMPLER_DIM_BUFFER, - HLSL_SAMPLER_DIM_STRUCTURED_BUFFER, - HLSL_SAMPLER_DIM_MAX = HLSL_SAMPLER_DIM_STRUCTURED_BUFFER, -+ /* NOTE: Remember to update object_methods[] in hlsl.y if this enum is modified. */ - }; - - enum hlsl_regset -@@ -149,7 +149,8 @@ struct hlsl_type - enum hlsl_base_type base_type; - - /* If base_type is HLSL_TYPE_SAMPLER, then sampler_dim is <= HLSL_SAMPLER_DIM_LAST_SAMPLER. -- * If base_type is HLSL_TYPE_TEXTURE, then sampler_dim is <= HLSL_SAMPLER_DIM_LAST_TEXTURE. -+ * If base_type is HLSL_TYPE_TEXTURE, then sampler_dim can be any value of the enum except -+ * HLSL_SAMPLER_DIM_GENERIC and HLSL_SAMPLER_DIM_COMPARISON. - * If base_type is HLSL_TYPE_UAV, then sampler_dim must be one of HLSL_SAMPLER_DIM_1D, - * HLSL_SAMPLER_DIM_2D, HLSL_SAMPLER_DIM_3D, HLSL_SAMPLER_DIM_1DARRAY, HLSL_SAMPLER_DIM_2DARRAY, - * HLSL_SAMPLER_DIM_BUFFER, or HLSL_SAMPLER_DIM_STRUCTURED_BUFFER. -@@ -1147,6 +1148,11 @@ static inline unsigned int hlsl_sampler_dim_count(enum hlsl_sampler_dim dim) - } - } - -+static inline bool hlsl_var_has_buffer_offset_register_reservation(struct hlsl_ctx *ctx, const struct hlsl_ir_var *var) -+{ -+ return var->reg_reservation.reg_type == 'c' && var->buffer == ctx->globals_buffer; -+} -+ - char *hlsl_sprintf_alloc(struct hlsl_ctx *ctx, const char *fmt, ...) VKD3D_PRINTF_FUNC(2, 3); - - const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op); -@@ -1252,6 +1258,7 @@ bool hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl_block *block, - - bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index); - bool hlsl_index_is_resource_access(struct hlsl_ir_index *index); -+bool hlsl_index_chain_has_resource_access(struct hlsl_ir_index *index); - - struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *val, - struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc); -@@ -1315,6 +1322,9 @@ bool hlsl_type_is_resource(const struct hlsl_type *type); - unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset); - bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2); - -+void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx); -+void hlsl_prepend_global_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *block); -+ - const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type); - unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type); - -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 37a372893df..000e14b6de9 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -1915,7 +1915,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - } - } - -- if (lhs->type == HLSL_IR_INDEX && hlsl_index_is_resource_access(hlsl_ir_index(lhs))) -+ if (lhs->type == HLSL_IR_INDEX && hlsl_index_chain_has_resource_access(hlsl_ir_index(lhs))) - { - struct hlsl_ir_node *coords = hlsl_ir_index(lhs)->idx.node; - struct hlsl_deref resource_deref; -@@ -1923,6 +1923,12 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - struct hlsl_ir_node *store; - unsigned int dim_count; - -+ if (!hlsl_index_is_resource_access(hlsl_ir_index(lhs))) -+ { -+ hlsl_fixme(ctx, &lhs->loc, "Non-direct structured resource store."); -+ return NULL; -+ } -+ - if (!hlsl_init_deref_from_index_chain(ctx, &resource_deref, hlsl_ir_index(lhs)->val.node)) - return NULL; - -@@ -4229,6 +4235,7 @@ static unsigned int hlsl_offset_dim_count(enum hlsl_sampler_dim dim) - return 3; - case HLSL_SAMPLER_DIM_CUBE: - case HLSL_SAMPLER_DIM_CUBEARRAY: -+ case HLSL_SAMPLER_DIM_BUFFER: - /* Offset parameters not supported for these types. */ - return 0; - default: -@@ -4252,28 +4259,31 @@ static bool add_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, - const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { - const struct hlsl_type *object_type = object->data_type; -- const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -- const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_LOAD}; -+ unsigned int sampler_dim, offset_dim; - struct hlsl_ir_node *load; - bool multisampled; - -- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBE -- || object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBEARRAY) -+ if (object_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) - { -- return raise_invalid_method_object_type(ctx, object_type, name, loc); -+ hlsl_fixme(ctx, loc, "Method '%s' for structured buffers.", name); -+ return false; - } - -+ sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -+ offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); -+ - multisampled = object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS - || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY; - -- if (params->args_count < 1 + multisampled || params->args_count > 3 + multisampled) -+ if (params->args_count < 1 + multisampled || params->args_count > 2 + multisampled + !!offset_dim) - { - hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of arguments to method 'Load': expected between %u and %u, but got %u.", -- 1 + multisampled, 3 + multisampled, params->args_count); -+ 1 + multisampled, 2 + multisampled + !!offset_dim, params->args_count); - return false; - } -+ - if (multisampled) - { - if (!(load_params.sample_index = add_implicit_conversion(ctx, block, params->args[1], -@@ -4281,14 +4291,14 @@ static bool add_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, - return false; - } - -- assert(offset_dim); -- if (params->args_count > 1 + multisampled) -+ if (!!offset_dim && params->args_count > 1 + multisampled) - { - if (!(load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[1 + multisampled], - hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc))) - return false; - } -- if (params->args_count > 2 + multisampled) -+ -+ if (params->args_count > 1 + multisampled + !!offset_dim) - { - hlsl_fixme(ctx, loc, "Tiled resource status argument."); - } -@@ -4311,17 +4321,13 @@ static bool add_sample_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc - const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { - const struct hlsl_type *object_type = object->data_type; -- const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -- const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_SAMPLE}; -+ unsigned int sampler_dim, offset_dim; - const struct hlsl_type *sampler_type; - struct hlsl_ir_node *load; - -- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS -- || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) -- { -- return raise_invalid_method_object_type(ctx, object_type, name, loc); -- } -+ sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -+ offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - - if (params->args_count < 2 || params->args_count > 4 + !!offset_dim) - { -@@ -4375,17 +4381,13 @@ static bool add_sample_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block * - const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { - const struct hlsl_type *object_type = object->data_type; -- const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -- const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - struct hlsl_resource_load_params load_params = { 0 }; -+ unsigned int sampler_dim, offset_dim; - const struct hlsl_type *sampler_type; - struct hlsl_ir_node *load; - -- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS -- || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) -- { -- return raise_invalid_method_object_type(ctx, object_type, name, loc); -- } -+ sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -+ offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - - if (!strcmp(name, "SampleCmpLevelZero")) - load_params.type = HLSL_RESOURCE_SAMPLE_CMP_LZ; -@@ -4449,20 +4451,14 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc - const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { - const struct hlsl_type *object_type = object->data_type; -- const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -- const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - struct hlsl_resource_load_params load_params = {0}; -+ unsigned int sampler_dim, offset_dim; - const struct hlsl_type *sampler_type; - struct hlsl_ir_node *load; - unsigned int read_channel; - -- if (object_type->sampler_dim != HLSL_SAMPLER_DIM_2D -- && object_type->sampler_dim != HLSL_SAMPLER_DIM_2DARRAY -- && object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBE -- && object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBEARRAY) -- { -- return raise_invalid_method_object_type(ctx, object_type, name, loc); -- } -+ sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -+ offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - - if (!strcmp(name, "GatherGreen")) - { -@@ -4613,12 +4609,14 @@ static bool add_getdimensions_method_call(struct hlsl_ctx *ctx, struct hlsl_bloc - { HLSL_SAMPLER_DIM_CUBEARRAY, 5, { ARG_MIP_LEVEL, ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT, ARG_LEVEL_COUNT } }, - { HLSL_SAMPLER_DIM_2DMS, 3, { ARG_WIDTH, ARG_HEIGHT, ARG_SAMPLE_COUNT } }, - { HLSL_SAMPLER_DIM_2DMSARRAY, 4, { ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT, ARG_SAMPLE_COUNT } }, -+ { HLSL_SAMPLER_DIM_BUFFER, 1, { ARG_WIDTH} }, - }; - const struct overload *o = NULL; - -- if (object_type->sampler_dim > HLSL_SAMPLER_DIM_LAST_TEXTURE) -+ if (object_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) - { -- hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "GetDimensions() is not defined for this type."); -+ hlsl_fixme(ctx, loc, "Method '%s' for structured buffers.", name); -+ return false; - } - - uint_type = hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT); -@@ -4732,16 +4730,12 @@ static bool add_sample_lod_method_call(struct hlsl_ctx *ctx, struct hlsl_block * - { - const struct hlsl_type *object_type = object->data_type; - struct hlsl_resource_load_params load_params = { 0 }; -- const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -- const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); -+ unsigned int sampler_dim, offset_dim; - const struct hlsl_type *sampler_type; - struct hlsl_ir_node *load; - -- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS -- || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) -- { -- return raise_invalid_method_object_type(ctx, object_type, name, loc); -- } -+ sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -+ offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - - if (!strcmp(name, "SampleLevel")) - load_params.type = HLSL_RESOURCE_SAMPLE_LOD; -@@ -4802,16 +4796,12 @@ static bool add_sample_grad_method_call(struct hlsl_ctx *ctx, struct hlsl_block - { - const struct hlsl_type *object_type = object->data_type; - struct hlsl_resource_load_params load_params = { 0 }; -- const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -- const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); -+ unsigned int sampler_dim, offset_dim; - const struct hlsl_type *sampler_type; - struct hlsl_ir_node *load; - -- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS -- || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) -- { -- return raise_invalid_method_object_type(ctx, object_type, name, loc); -- } -+ sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); -+ offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); - - load_params.type = HLSL_RESOURCE_SAMPLE_GRAD; - -@@ -4873,25 +4863,27 @@ static const struct method_function - const char *name; - bool (*handler)(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *object, - const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc); -+ bool valid_dims[HLSL_SAMPLER_DIM_MAX + 1]; - } - object_methods[] = - { -- { "Gather", add_gather_method_call }, -- { "GatherAlpha", add_gather_method_call }, -- { "GatherBlue", add_gather_method_call }, -- { "GatherGreen", add_gather_method_call }, -- { "GatherRed", add_gather_method_call }, -+ /* g c 1d 2d 3d cube 1darr 2darr 2dms 2dmsarr cubearr buff sbuff*/ -+ { "Gather", add_gather_method_call, {0,0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0}}, -+ { "GatherAlpha", add_gather_method_call, {0,0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0}}, -+ { "GatherBlue", add_gather_method_call, {0,0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0}}, -+ { "GatherGreen", add_gather_method_call, {0,0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0}}, -+ { "GatherRed", add_gather_method_call, {0,0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0}}, - -- { "GetDimensions", add_getdimensions_method_call }, -+ { "GetDimensions", add_getdimensions_method_call, {0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, - -- { "Load", add_load_method_call }, -+ { "Load", add_load_method_call, {0,0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1}}, - -- { "Sample", add_sample_method_call }, -- { "SampleBias", add_sample_lod_method_call }, -- { "SampleCmp", add_sample_cmp_method_call }, -- { "SampleCmpLevelZero", add_sample_cmp_method_call }, -- { "SampleGrad", add_sample_grad_method_call }, -- { "SampleLevel", add_sample_lod_method_call }, -+ { "Sample", add_sample_method_call, {0,0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0}}, -+ { "SampleBias", add_sample_lod_method_call, {0,0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0}}, -+ { "SampleCmp", add_sample_cmp_method_call, {0,0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0}}, -+ { "SampleCmpLevelZero", add_sample_cmp_method_call, {0,0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0}}, -+ { "SampleGrad", add_sample_grad_method_call, {0,0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0}}, -+ { "SampleLevel", add_sample_lod_method_call, {0,0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0}}, - }; - - static int object_method_function_name_compare(const void *a, const void *b) -@@ -4919,8 +4911,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, stru - return false; - } - -- if ((method = bsearch(name, object_methods, ARRAY_SIZE(object_methods), -- sizeof(*method), object_method_function_name_compare))) -+ method = bsearch(name, object_methods, ARRAY_SIZE(object_methods), sizeof(*method), -+ object_method_function_name_compare); -+ -+ if (method && method->valid_dims[object_type->sampler_dim]) - { - return method->handler(ctx, block, object, name, params, loc); - } -@@ -6037,7 +6031,11 @@ parameter: - } - - texture_type: -- KW_TEXTURE1D -+ KW_BUFFER -+ { -+ $$ = HLSL_SAMPLER_DIM_BUFFER; -+ } -+ | KW_TEXTURE1D - { - $$ = HLSL_SAMPLER_DIM_1D; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 4121fadf333..7da427796e7 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -4335,7 +4335,7 @@ static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint3 - return NULL; - } - --static void calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, bool register_reservation) -+static void hlsl_calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, bool register_reservation) - { - unsigned int var_reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; - enum hlsl_type_class var_class = var->data_type->class; -@@ -4449,24 +4449,17 @@ static void validate_buffer_offsets(struct hlsl_ctx *ctx) - } - } - --static bool var_has_buffer_offset_register_reservation(struct hlsl_ctx *ctx, const struct hlsl_ir_var *var) -+void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx) - { -- return var->reg_reservation.reg_type == 'c' && var->buffer == ctx->globals_buffer; --} -- --static void allocate_buffers(struct hlsl_ctx *ctx) --{ -- struct hlsl_buffer *buffer; - struct hlsl_ir_var *var; -- uint32_t index = 0; - - LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) - { - if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) - continue; - -- if (var->is_param) -- var->buffer = ctx->params_buffer; -+ if (hlsl_var_has_buffer_offset_register_reservation(ctx, var)) -+ hlsl_calculate_buffer_offset(ctx, var, true); - } - - LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) -@@ -4474,19 +4467,27 @@ static void allocate_buffers(struct hlsl_ctx *ctx) - if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) - continue; - -- if (var_has_buffer_offset_register_reservation(ctx, var)) -- calculate_buffer_offset(ctx, var, true); -+ if (!hlsl_var_has_buffer_offset_register_reservation(ctx, var)) -+ hlsl_calculate_buffer_offset(ctx, var, false); - } -+} -+ -+static void allocate_buffers(struct hlsl_ctx *ctx) -+{ -+ struct hlsl_buffer *buffer; -+ struct hlsl_ir_var *var; -+ uint32_t index = 0; - - LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) - { - if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) - continue; - -- if (!var_has_buffer_offset_register_reservation(ctx, var)) -- calculate_buffer_offset(ctx, var, false); -+ if (var->is_param) -+ var->buffer = ctx->params_buffer; - } - -+ hlsl_calculate_buffer_offsets(ctx); - validate_buffer_offsets(ctx); - - LIST_FOR_EACH_ENTRY(buffer, &ctx->buffers, struct hlsl_buffer, entry) -@@ -4959,6 +4960,17 @@ static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *bod - } - } - -+void hlsl_prepend_global_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *body) -+{ -+ struct hlsl_ir_var *var; -+ -+ LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) -+ { -+ if (var->storage_modifiers & HLSL_STORAGE_UNIFORM) -+ prepend_uniform_copy(ctx, body, var); -+ } -+} -+ - int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, - enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out) - { -@@ -4987,11 +4999,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry - lower_ir(ctx, lower_matrix_swizzles, body); - lower_ir(ctx, lower_index_loads, body); - -- LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) -- { -- if (var->storage_modifiers & HLSL_STORAGE_UNIFORM) -- prepend_uniform_copy(ctx, body, var); -- } -+ hlsl_prepend_global_uniform_copy(ctx, body); - - for (i = 0; i < entry_func->parameters.count; ++i) - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index f70606e6f22..492e5ec027d 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -2810,6 +2810,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant - - {"position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, - {"sv_position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, -+ {"sv_primitiveid", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_PRIMITIVE_ID}, - {"sv_isfrontface", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_IS_FRONT_FACE}, - {"sv_rendertargetarrayindex", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_RENDER_TARGET_ARRAY_INDEX}, - {"sv_viewportarrayindex", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_VIEWPORT_ARRAY_INDEX}, -@@ -4764,6 +4765,13 @@ static void write_sm4_resinfo(const struct tpf_writer *tpf, const struct hlsl_ir - const struct hlsl_ir_node *dst = &load->node; - struct sm4_instruction instr; - -+ if (resource->data_type->sampler_dim == HLSL_SAMPLER_DIM_BUFFER -+ || resource->data_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) -+ { -+ hlsl_fixme(tpf->ctx, &load->node.loc, "resinfo for buffers."); -+ return; -+ } -+ - assert(dst->data_type->base_type == HLSL_TYPE_UINT || dst->data_type->base_type == HLSL_TYPE_FLOAT); - - memset(&instr, 0, sizeof(instr)); -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 1557fb3ea7f..b2f7b17eb73 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -366,9 +366,9 @@ size_t bytecode_align(struct vkd3d_bytecode_buffer *buffer) - return aligned_size; - } - --size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size) -+size_t bytecode_put_bytes_unaligned(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size) - { -- size_t offset = bytecode_align(buffer); -+ size_t offset = buffer->size; - - if (buffer->status) - return offset; -@@ -383,6 +383,12 @@ size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *byte - return offset; - } - -+size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size) -+{ -+ bytecode_align(buffer); -+ return bytecode_put_bytes_unaligned(buffer, bytes, size); -+} -+ - size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size) - { - size_t offset = bytecode_align(buffer); -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index acfd39b7643..910d34a7d13 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -1418,6 +1418,7 @@ struct vkd3d_bytecode_buffer - /* Align to the next 4-byte offset, and return that offset. */ - size_t bytecode_align(struct vkd3d_bytecode_buffer *buffer); - size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size); -+size_t bytecode_put_bytes_unaligned(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size); - size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size); - void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value); - void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length); --- -2.43.0 - diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-d65f331efc70454312f1e23653703e67b45.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-d65f331efc70454312f1e23653703e67b45.patch deleted file mode 100644 index ecc05b21..00000000 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-d65f331efc70454312f1e23653703e67b45.patch +++ /dev/null @@ -1,1485 +0,0 @@ -From 9b68e3865053a19a40c20a725f07115268c314da Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 24 Feb 2024 09:43:01 +1100 -Subject: [PATCH] Updated vkd3d to d65f331efc70454312f1e23653703e67b459d7cc. - ---- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 174 +++++++++- - libs/vkd3d/libs/vkd3d-shader/fx.c | 158 ++++++++- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 36 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 21 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 180 +++++++++- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 2 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 325 ++++++++++++++++++ - libs/vkd3d/libs/vkd3d-shader/tpf.c | 18 +- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 1 + - libs/vkd3d/libs/vkd3d/device.c | 1 + - 11 files changed, 861 insertions(+), 57 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 2ca3aa955e7..ac688e85e52 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -379,10 +379,15 @@ enum dx_intrinsic_opcode - DX_CREATE_HANDLE = 57, - DX_CBUFFER_LOAD_LEGACY = 59, - DX_SAMPLE = 60, -+ DX_SAMPLE_B = 61, -+ DX_SAMPLE_LOD = 62, - DX_SAMPLE_GRAD = 63, -+ DX_SAMPLE_C = 64, -+ DX_SAMPLE_C_LZ = 65, - DX_TEXTURE_LOAD = 66, - DX_TEXTURE_STORE = 67, - DX_BUFFER_LOAD = 68, -+ DX_BUFFER_STORE = 69, - DX_ATOMIC_BINOP = 78, - DX_ATOMIC_CMP_XCHG = 79, - DX_DERIV_COARSEX = 83, -@@ -393,6 +398,7 @@ enum dx_intrinsic_opcode - DX_LEGACY_F32TOF16 = 130, - DX_LEGACY_F16TOF32 = 131, - DX_RAW_BUFFER_LOAD = 139, -+ DX_RAW_BUFFER_STORE = 140, - }; - - enum dxil_cast_code -@@ -4137,6 +4143,76 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i - instruction_dst_param_init_ssa_vector(ins, component_count, sm6); - } - -+static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ unsigned int write_mask, component_count, alignment = 0, operand_count; -+ struct vkd3d_shader_src_param *src_params; -+ struct vkd3d_shader_dst_param *dst_param; -+ struct vkd3d_shader_instruction *ins; -+ struct vkd3d_shader_register data; -+ const struct sm6_value *resource; -+ bool raw; -+ -+ resource = operands[0]; -+ if (!sm6_value_validate_is_handle(resource, sm6)) -+ return; -+ raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; -+ -+ write_mask = sm6_value_get_constant_uint(operands[7]); -+ if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) -+ { -+ WARN("Invalid write mask %#x.\n", write_mask); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Write mask %#x for a raw/structured buffer store operation is invalid.", write_mask); -+ return; -+ } -+ else if (write_mask & (write_mask + 1)) -+ { -+ /* In this case, it is unclear which source operands will be defined unless we encounter it in a shader. */ -+ FIXME("Unhandled write mask %#x.\n", write_mask); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Write mask %#x for a raw/structured buffer store operation is unhandled.", write_mask); -+ } -+ component_count = vsir_write_mask_component_count(write_mask); -+ -+ if (op == DX_RAW_BUFFER_STORE) -+ { -+ if (!raw && resource->u.handle.d->kind != RESOURCE_KIND_STRUCTUREDBUFFER) -+ { -+ WARN("Resource is not a raw or structured buffer.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION, -+ "Resource for a raw buffer store is not a raw or structured buffer."); -+ } -+ -+ alignment = sm6_value_get_constant_uint(operands[8]); -+ if (alignment & (alignment - 1)) -+ { -+ FIXME("Invalid alignment %#x.\n", alignment); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Alignment %#x for a raw/structured buffer store operation is invalid.", alignment); -+ } -+ } -+ -+ if (!sm6_parser_emit_composite_construct(sm6, &operands[3], component_count, state, &data)) -+ return; -+ -+ ins = state->ins; -+ vsir_instruction_init(ins, &sm6->p.location, raw ? VKD3DSIH_STORE_RAW : VKD3DSIH_STORE_STRUCTURED); -+ operand_count = 2 + !raw; -+ -+ if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) -+ return; -+ src_params_init_from_operands(src_params, &operands[1], operand_count - 1); -+ data.data_type = VKD3D_DATA_UINT; -+ src_param_init_vector_from_reg(&src_params[operand_count - 1], &data); -+ -+ dst_param = instruction_dst_params_alloc(ins, 1, sm6); -+ dst_param_init_with_mask(dst_param, write_mask); -+ dst_param->reg = resource->u.handle.reg; -+ dst_param->reg.alignment = alignment; -+} -+ - static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, - const struct sm6_value **operands, struct function_emission_state *state) - { -@@ -4179,6 +4255,73 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri - instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); - } - -+static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_src_param *src_params; -+ struct vkd3d_shader_dst_param *dst_param; -+ unsigned int write_mask, component_count; -+ struct vkd3d_shader_instruction *ins; -+ struct vkd3d_shader_register texel; -+ const struct sm6_value *resource; -+ -+ resource = operands[0]; -+ if (!sm6_value_validate_is_handle(resource, sm6)) -+ return; -+ -+ if (resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER -+ || resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER) -+ { -+ return sm6_parser_emit_dx_raw_buffer_store(sm6, op, operands, state); -+ } -+ -+ if (resource->u.handle.d->kind != RESOURCE_KIND_TYPEDBUFFER) -+ { -+ WARN("Resource is not a typed buffer.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION, -+ "Resource for a typed buffer store is not a typed buffer."); -+ } -+ -+ write_mask = sm6_value_get_constant_uint(operands[7]); -+ if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) -+ { -+ WARN("Invalid write mask %#x.\n", write_mask); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Write mask %#x for a typed buffer store operation is invalid.", write_mask); -+ return; -+ } -+ else if (write_mask & (write_mask + 1)) -+ { -+ /* In this case, it is unclear which source operands will be defined unless we encounter it in a shader. */ -+ FIXME("Unhandled write mask %#x.\n", write_mask); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Write mask %#x for a typed buffer store operation is unhandled.", write_mask); -+ } -+ component_count = vsir_write_mask_component_count(write_mask); -+ -+ if (!sm6_parser_emit_composite_construct(sm6, &operands[3], component_count, state, &texel)) -+ return; -+ -+ ins = state->ins; -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_STORE_UAV_TYPED); -+ -+ if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) -+ return; -+ src_param_init_from_value(&src_params[0], operands[1]); -+ if (!sm6_value_is_undef(operands[2])) -+ { -+ /* Constant zero would have no effect, but is not worth checking for unless it shows up. */ -+ WARN("Ignoring structure offset.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring structure offset for a typed buffer store."); -+ } -+ src_param_init_vector_from_reg(&src_params[1], &texel); -+ -+ dst_param = instruction_dst_params_alloc(ins, 1, sm6); -+ dst_param_init_with_mask(dst_param, write_mask); -+ dst_param->reg = resource->u.handle.reg; -+} -+ - static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value) - { - return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value); -@@ -4195,11 +4338,11 @@ static void instruction_set_texel_offset(struct vkd3d_shader_instruction *ins, - static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, - const struct sm6_value **operands, struct function_emission_state *state) - { -+ unsigned int clamp_idx = 0, component_count = VKD3D_VEC4_SIZE; - struct vkd3d_shader_register coord, ddx, ddy; - const struct sm6_value *resource, *sampler; - struct vkd3d_shader_src_param *src_params; - struct vkd3d_shader_instruction *ins; -- unsigned int clamp_idx; - - resource = operands[0]; - sampler = operands[1]; -@@ -4228,6 +4371,25 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ - src_params = instruction_src_params_alloc(ins, 3, sm6); - clamp_idx = 9; - break; -+ case DX_SAMPLE_B: -+ clamp_idx = 10; -+ /* fall through */ -+ case DX_SAMPLE_LOD: -+ instruction_init_with_resource(ins, (op == DX_SAMPLE_B) ? VKD3DSIH_SAMPLE_B : VKD3DSIH_SAMPLE_LOD, -+ resource, sm6); -+ src_params = instruction_src_params_alloc(ins, 4, sm6); -+ src_param_init_from_value(&src_params[3], operands[9]); -+ break; -+ case DX_SAMPLE_C: -+ clamp_idx = 10; -+ /* fall through */ -+ case DX_SAMPLE_C_LZ: -+ instruction_init_with_resource(ins, (op == DX_SAMPLE_C_LZ) ? VKD3DSIH_SAMPLE_C_LZ : VKD3DSIH_SAMPLE_C, -+ resource, sm6); -+ src_params = instruction_src_params_alloc(ins, 4, sm6); -+ src_param_init_from_value(&src_params[3], operands[9]); -+ component_count = 1; -+ break; - case DX_SAMPLE_GRAD: - instruction_init_with_resource(ins, VKD3DSIH_SAMPLE_GRAD, resource, sm6); - src_params = instruction_src_params_alloc(ins, 5, sm6); -@@ -4242,7 +4404,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ - if (!src_params) - return; - -- if (!sm6_value_is_undef(operands[clamp_idx])) -+ if (clamp_idx && !sm6_value_is_undef(operands[clamp_idx])) - { - FIXME("Ignoring LOD clamp value.\n"); - vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -@@ -4254,7 +4416,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ - src_param_init_vector_from_reg(&src_params[2], &sampler->u.handle.reg); - instruction_set_texel_offset(ins, &operands[6], sm6); - -- instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); -+ instruction_dst_param_init_ssa_vector(ins, component_count, sm6); - } - - static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -4478,6 +4640,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - [DX_ATOMIC_CMP_XCHG ] = {"o", "HiiiRR", sm6_parser_emit_dx_atomic_binop}, - [DX_BFREV ] = {"m", "R", sm6_parser_emit_dx_unary}, - [DX_BUFFER_LOAD ] = {"o", "Hii", sm6_parser_emit_dx_buffer_load}, -+ [DX_BUFFER_STORE ] = {"v", "Hiiooooc", sm6_parser_emit_dx_buffer_store}, - [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, - [DX_COS ] = {"g", "R", sm6_parser_emit_dx_sincos}, - [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, -@@ -4507,13 +4670,18 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, - [DX_LOG ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_RAW_BUFFER_LOAD ] = {"o", "Hii8i", sm6_parser_emit_dx_raw_buffer_load}, -+ [DX_RAW_BUFFER_STORE ] = {"v", "Hiioooocc", sm6_parser_emit_dx_raw_buffer_store}, - [DX_ROUND_NE ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_ROUND_NI ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_ROUND_PI ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_ROUND_Z ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_RSQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_SAMPLE ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, -+ [DX_SAMPLE_B ] = {"o", "HHffffiiiff", sm6_parser_emit_dx_sample}, -+ [DX_SAMPLE_C ] = {"o", "HHffffiiiff", sm6_parser_emit_dx_sample}, -+ [DX_SAMPLE_C_LZ ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, - [DX_SAMPLE_GRAD ] = {"o", "HHffffiiifffffff", sm6_parser_emit_dx_sample}, -+ [DX_SAMPLE_LOD ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, - [DX_SIN ] = {"g", "R", sm6_parser_emit_dx_sincos}, - [DX_SPLIT_DOUBLE ] = {"S", "d", sm6_parser_emit_dx_split_double}, - [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 11dee4ba9d7..bc70d5220fd 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -83,6 +83,7 @@ struct fx_write_context - uint32_t group_count; - uint32_t buffer_count; - uint32_t numeric_variable_count; -+ uint32_t object_variable_count; - int status; - - const struct fx_write_context_ops *ops; -@@ -326,6 +327,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co - struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; - uint32_t name_offset, offset, size, stride, numeric_desc; - uint32_t elements_count = 0; -+ const char *name; - static const uint32_t variable_type[] = - { - [HLSL_CLASS_SCALAR] = 1, -@@ -334,6 +336,29 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co - [HLSL_CLASS_OBJECT] = 2, - [HLSL_CLASS_STRUCT] = 3, - }; -+ static const char * const texture_type_names[] = -+ { -+ [HLSL_SAMPLER_DIM_GENERIC] = "texture", -+ [HLSL_SAMPLER_DIM_1D] = "Texture1D", -+ [HLSL_SAMPLER_DIM_1DARRAY] = "Texture1DArray", -+ [HLSL_SAMPLER_DIM_2D] = "Texture2D", -+ [HLSL_SAMPLER_DIM_2DARRAY] = "Texture2DArray", -+ [HLSL_SAMPLER_DIM_2DMS] = "Texture2DMS", -+ [HLSL_SAMPLER_DIM_2DMSARRAY] = "Texture2DMSArray", -+ [HLSL_SAMPLER_DIM_3D] = "Texture3D", -+ [HLSL_SAMPLER_DIM_CUBE] = "TextureCube", -+ [HLSL_SAMPLER_DIM_CUBEARRAY] = "TextureCubeArray", -+ }; -+ static const char * const uav_type_names[] = -+ { -+ [HLSL_SAMPLER_DIM_1D] = "RWTexture1D", -+ [HLSL_SAMPLER_DIM_1DARRAY] = "RWTexture1DArray", -+ [HLSL_SAMPLER_DIM_2D] = "RWTexture2D", -+ [HLSL_SAMPLER_DIM_2DARRAY] = "RWTexture2DArray", -+ [HLSL_SAMPLER_DIM_3D] = "RWTexture3D", -+ [HLSL_SAMPLER_DIM_BUFFER] = "RWBuffer", -+ [HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = "RWStructuredBuffer", -+ }; - - /* Resolve arrays to element type and number of elements. */ - if (type->class == HLSL_CLASS_ARRAY) -@@ -342,7 +367,14 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co - type = hlsl_get_multiarray_element_type(type); - } - -- name_offset = write_string(type->name, fx); -+ if (type->base_type == HLSL_TYPE_TEXTURE) -+ name = texture_type_names[type->sampler_dim]; -+ else if (type->base_type == HLSL_TYPE_UAV) -+ name = uav_type_names[type->sampler_dim]; -+ else -+ name = type->name; -+ -+ name_offset = write_string(name, fx); - offset = put_u32_unaligned(buffer, name_offset); - - switch (type->class) -@@ -392,9 +424,52 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co - } - else if (type->class == HLSL_CLASS_OBJECT) - { -- FIXME("Object types are not supported.\n"); -- set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED); -- return 0; -+ static const uint32_t object_type[] = -+ { -+ [HLSL_TYPE_RENDERTARGETVIEW] = 19, -+ [HLSL_TYPE_DEPTHSTENCILVIEW] = 20, -+ }; -+ static const uint32_t texture_type[] = -+ { -+ [HLSL_SAMPLER_DIM_GENERIC] = 9, -+ [HLSL_SAMPLER_DIM_1D] = 10, -+ [HLSL_SAMPLER_DIM_1DARRAY] = 11, -+ [HLSL_SAMPLER_DIM_2D] = 12, -+ [HLSL_SAMPLER_DIM_2DARRAY] = 13, -+ [HLSL_SAMPLER_DIM_2DMS] = 14, -+ [HLSL_SAMPLER_DIM_2DMSARRAY] = 15, -+ [HLSL_SAMPLER_DIM_3D] = 16, -+ [HLSL_SAMPLER_DIM_CUBE] = 17, -+ [HLSL_SAMPLER_DIM_CUBEARRAY] = 23, -+ }; -+ static const uint32_t uav_type[] = -+ { -+ [HLSL_SAMPLER_DIM_1D] = 31, -+ [HLSL_SAMPLER_DIM_1DARRAY] = 32, -+ [HLSL_SAMPLER_DIM_2D] = 33, -+ [HLSL_SAMPLER_DIM_2DARRAY] = 34, -+ [HLSL_SAMPLER_DIM_3D] = 35, -+ [HLSL_SAMPLER_DIM_BUFFER] = 36, -+ [HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = 40, -+ }; -+ -+ switch (type->base_type) -+ { -+ case HLSL_TYPE_DEPTHSTENCILVIEW: -+ case HLSL_TYPE_RENDERTARGETVIEW: -+ put_u32_unaligned(buffer, object_type[type->base_type]); -+ break; -+ case HLSL_TYPE_TEXTURE: -+ put_u32_unaligned(buffer, texture_type[type->sampler_dim]); -+ break; -+ case HLSL_TYPE_UAV: -+ put_u32_unaligned(buffer, uav_type[type->sampler_dim]); -+ break; -+ default: -+ FIXME("Object type %u is not supported.\n", type->base_type); -+ set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED); -+ return 0; -+ } - } - else /* Numeric type */ - { -@@ -588,12 +663,12 @@ static const struct fx_write_context_ops fx_4_ops = - .write_pass = write_fx_4_pass, - }; - --static void write_fx_4_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) -+static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) - { - struct vkd3d_bytecode_buffer *buffer = &fx->structured; - uint32_t semantic_offset, flags = 0; - uint32_t name_offset, type_offset; -- enum fx_4_variable_flags -+ enum fx_4_numeric_variable_flags - { - HAS_EXPLICIT_BIND_POINT = 0x4, - }; -@@ -618,6 +693,29 @@ static void write_fx_4_variable(struct hlsl_ir_var *var, struct fx_write_context - /* FIXME: write annotations */ - } - -+static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t semantic_offset, bind_point = ~0u; -+ uint32_t name_offset, type_offset; -+ -+ if (var->reg_reservation.reg_type) -+ bind_point = var->reg_reservation.reg_index; -+ -+ type_offset = write_type(var->data_type, fx); -+ name_offset = write_string(var->name, fx); -+ semantic_offset = write_string(var->semantic.name, fx); -+ -+ put_u32(buffer, name_offset); -+ put_u32(buffer, type_offset); -+ -+ semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */ -+ put_u32(buffer, bind_point); /* Explicit bind point */ -+ -+ put_u32(buffer, 0); /* Annotations count */ -+ /* FIXME: write annotations */ -+} -+ - static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx) - { - enum fx_4_buffer_flags -@@ -656,7 +754,7 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx - if (var->buffer != b) - continue; - -- write_fx_4_variable(var, fx); -+ write_fx_4_numeric_variable(var, fx); - size += get_fx_4_type_size(var->data_type); - ++count; - } -@@ -687,6 +785,44 @@ static void write_buffers(struct fx_write_context *fx) - } - } - -+static bool is_object_variable(const struct hlsl_ir_var *var) -+{ -+ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); -+ -+ if (type->class != HLSL_CLASS_OBJECT) -+ return false; -+ -+ switch (type->base_type) -+ { -+ case HLSL_TYPE_SAMPLER: -+ case HLSL_TYPE_TEXTURE: -+ case HLSL_TYPE_UAV: -+ case HLSL_TYPE_PIXELSHADER: -+ case HLSL_TYPE_VERTEXSHADER: -+ case HLSL_TYPE_RENDERTARGETVIEW: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+static void write_objects(struct fx_write_context *fx) -+{ -+ struct hlsl_ir_var *var; -+ uint32_t count = 0; -+ -+ LIST_FOR_EACH_ENTRY(var, &fx->ctx->extern_vars, struct hlsl_ir_var, extern_entry) -+ { -+ if (!is_object_variable(var)) -+ continue; -+ -+ write_fx_4_object_variable(var, fx); -+ ++count; -+ } -+ -+ fx->object_variable_count += count; -+} -+ - static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - { - struct vkd3d_bytecode_buffer buffer = { 0 }; -@@ -698,7 +834,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ - - write_buffers(&fx); -- /* TODO: objects */ -+ write_objects(&fx); - /* TODO: shared buffers */ - /* TODO: shared objects */ - -@@ -707,7 +843,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - put_u32(&buffer, ctx->profile->minor_version == 0 ? 0xfeff1001 : 0xfeff1011); /* Version. */ - put_u32(&buffer, fx.buffer_count); /* Buffer count. */ - put_u32(&buffer, fx.numeric_variable_count); /* Numeric variable count. */ -- put_u32(&buffer, 0); /* Object variable count. */ -+ put_u32(&buffer, fx.object_variable_count); /* Object variable count. */ - put_u32(&buffer, 0); /* Pool buffer count. */ - put_u32(&buffer, 0); /* Pool variable count. */ - put_u32(&buffer, 0); /* Pool object count. */ -@@ -757,7 +893,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ - - write_buffers(&fx); -- /* TODO: objects */ -+ write_objects(&fx); - /* TODO: interface variables */ - - write_groups(&fx); -@@ -765,7 +901,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - put_u32(&buffer, 0xfeff2001); /* Version. */ - put_u32(&buffer, fx.buffer_count); /* Buffer count. */ - put_u32(&buffer, fx.numeric_variable_count); /* Numeric variable count. */ -- put_u32(&buffer, 0); /* Object variable count. */ -+ put_u32(&buffer, fx.object_variable_count); /* Object variable count. */ - put_u32(&buffer, 0); /* Pool buffer count. */ - put_u32(&buffer, 0); /* Pool variable count. */ - put_u32(&buffer, 0); /* Pool object count. */ -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index edd99238d59..0e75edd46f6 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -751,15 +751,15 @@ struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_ - type->dimx = 4; - type->dimy = 1; - type->sampler_dim = dim; -- type->e.resource_format = format; -+ type->e.resource.format = format; - type->sample_count = sample_count; - hlsl_type_calculate_reg_size(ctx, type); - list_add_tail(&ctx->types, &type->entry); - return type; - } - --struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, -- enum hlsl_sampler_dim dim, struct hlsl_type *format, uint32_t modifiers) -+struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, -+ struct hlsl_type *format, bool rasteriser_ordered) - { - struct hlsl_type *type; - -@@ -770,8 +770,8 @@ struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, - type->dimx = format->dimx; - type->dimy = 1; - type->sampler_dim = dim; -- type->modifiers = modifiers; -- type->e.resource_format = format; -+ type->e.resource.format = format; -+ type->e.resource.rasteriser_ordered = rasteriser_ordered; - hlsl_type_calculate_reg_size(ctx, type); - list_add_tail(&ctx->types, &type->entry); - return type; -@@ -887,8 +887,11 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 - { - if (t1->sampler_dim != t2->sampler_dim) - return false; -- if (t1->base_type == HLSL_TYPE_TEXTURE && t1->sampler_dim != HLSL_SAMPLER_DIM_GENERIC -- && !hlsl_types_are_equal(t1->e.resource_format, t2->e.resource_format)) -+ if ((t1->base_type == HLSL_TYPE_TEXTURE || t1->base_type == HLSL_TYPE_UAV) -+ && t1->sampler_dim != HLSL_SAMPLER_DIM_GENERIC -+ && !hlsl_types_are_equal(t1->e.resource.format, t2->e.resource.format)) -+ return false; -+ if (t1->base_type == HLSL_TYPE_UAV && t1->e.resource.rasteriser_ordered != t2->e.resource.rasteriser_ordered) - return false; - } - if ((t1->modifiers & HLSL_MODIFIER_ROW_MAJOR) -@@ -1009,7 +1012,10 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, - if (type->base_type == HLSL_TYPE_TECHNIQUE) - type->e.version = old->e.version; - if (old->base_type == HLSL_TYPE_TEXTURE || old->base_type == HLSL_TYPE_UAV) -- type->e.resource_format = old->e.resource_format; -+ { -+ type->e.resource.format = old->e.resource.format; -+ type->e.resource.rasteriser_ordered = old->e.resource.rasteriser_ordered; -+ } - break; - - default: -@@ -1573,7 +1579,7 @@ struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *v - return NULL; - - if (type->class == HLSL_CLASS_OBJECT) -- type = type->e.resource_format; -+ type = type->e.resource.format; - else if (type->class == HLSL_CLASS_MATRIX) - type = hlsl_get_vector_type(ctx, type->base_type, type->dimx); - else -@@ -2201,7 +2207,7 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru - return string; - } - -- assert(type->e.resource_format->base_type < ARRAY_SIZE(base_types)); -+ assert(type->e.resource.format->base_type < ARRAY_SIZE(base_types)); - if (type->sampler_dim == HLSL_SAMPLER_DIM_BUFFER) - { - vkd3d_string_buffer_printf(string, "Buffer"); -@@ -2211,7 +2217,7 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru - assert(type->sampler_dim < ARRAY_SIZE(dimensions)); - vkd3d_string_buffer_printf(string, "Texture%s", dimensions[type->sampler_dim]); - } -- if ((inner_string = hlsl_type_to_string(ctx, type->e.resource_format))) -+ if ((inner_string = hlsl_type_to_string(ctx, type->e.resource.format))) - { - vkd3d_string_buffer_printf(string, "<%s>", inner_string->buffer); - hlsl_release_string_buffer(ctx, inner_string); -@@ -2225,7 +2231,7 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru - vkd3d_string_buffer_printf(string, "RWStructuredBuffer"); - else - vkd3d_string_buffer_printf(string, "RWTexture%s", dimensions[type->sampler_dim]); -- if ((inner_string = hlsl_type_to_string(ctx, type->e.resource_format))) -+ if ((inner_string = hlsl_type_to_string(ctx, type->e.resource.format))) - { - vkd3d_string_buffer_printf(string, "<%s>", inner_string->buffer); - hlsl_release_string_buffer(ctx, inner_string); -@@ -3375,7 +3381,7 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) - - static const struct - { -- char name[13]; -+ char name[20]; - enum hlsl_type_class class; - enum hlsl_base_type base_type; - unsigned int dimx, dimy; -@@ -3391,11 +3397,13 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) - {"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1}, - {"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1}, - {"VERTEXSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_VERTEXSHADER, 1, 1}, -+ {"RenderTargetView",HLSL_CLASS_OBJECT, HLSL_TYPE_RENDERTARGETVIEW, 1, 1}, -+ {"DepthStencilView",HLSL_CLASS_OBJECT, HLSL_TYPE_DEPTHSTENCILVIEW, 1, 1}, - }; - - static const struct - { -- char *name; -+ const char *name; - unsigned int version; - } - technique_types[] = -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index 91500ed8b8b..df0a53b20de 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -96,6 +96,8 @@ enum hlsl_base_type - HLSL_TYPE_PIXELSHADER, - HLSL_TYPE_VERTEXSHADER, - HLSL_TYPE_PASS, -+ HLSL_TYPE_RENDERTARGETVIEW, -+ HLSL_TYPE_DEPTHSTENCILVIEW, - HLSL_TYPE_TECHNIQUE, - HLSL_TYPE_EFFECT_GROUP, - HLSL_TYPE_STRING, -@@ -194,9 +196,15 @@ struct hlsl_type - /* Array length, or HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT if it is not known yet at parse time. */ - unsigned int elements_count; - } array; -- /* Format of the data contained within the type if the base_type is HLSL_TYPE_TEXTURE or -- * HLSL_TYPE_UAV. */ -- struct hlsl_type *resource_format; -+ /* Additional information if the base_type is HLSL_TYPE_TEXTURE or -+ * HLSL_TYPE_UAV. */ -+ struct -+ { -+ /* Format of the data contained within the type. */ -+ struct hlsl_type *format; -+ /* The type is a rasteriser-ordered view. */ -+ bool rasteriser_ordered; -+ } resource; - /* Additional field to distinguish object types. Currently used only for technique types. */ - unsigned int version; - } e; -@@ -366,11 +374,10 @@ struct hlsl_attribute - #define HLSL_STORAGE_CENTROID 0x00004000 - #define HLSL_STORAGE_NOPERSPECTIVE 0x00008000 - #define HLSL_STORAGE_LINEAR 0x00010000 --#define HLSL_MODIFIER_RASTERIZER_ORDERED 0x00020000 - - #define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_MODIFIER_VOLATILE | \ - HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \ -- HLSL_MODIFIER_COLUMN_MAJOR | HLSL_MODIFIER_RASTERIZER_ORDERED) -+ HLSL_MODIFIER_COLUMN_MAJOR) - - #define HLSL_INTERPOLATION_MODIFIERS_MASK (HLSL_STORAGE_NOINTERPOLATION | HLSL_STORAGE_CENTROID | \ - HLSL_STORAGE_NOPERSPECTIVE | HLSL_STORAGE_LINEAR) -@@ -1278,8 +1285,8 @@ struct hlsl_ir_var *hlsl_new_synthetic_var_named(struct hlsl_ctx *ctx, const cha - struct hlsl_type *type, const struct vkd3d_shader_location *loc, bool dummy_scope); - struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format, - unsigned int sample_count); --struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, -- enum hlsl_sampler_dim dim, struct hlsl_type *format, uint32_t modifiers); -+struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, -+ struct hlsl_type *format, bool rasteriser_ordered); - struct hlsl_ir_node *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n, - const struct vkd3d_shader_location *loc); - struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 000e14b6de9..cd05fd008a6 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -1942,7 +1942,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - - dim_count = hlsl_sampler_dim_count(resource_type->sampler_dim); - -- if (writemask != ((1u << resource_type->e.resource_format->dimx) - 1)) -+ if (writemask != ((1u << resource_type->e.resource.format->dimx) - 1)) - hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, - "Resource store expressions must write to all components."); - -@@ -2666,6 +2666,55 @@ static bool intrinsic_abs(struct hlsl_ctx *ctx, - return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_ABS, params->args[0], loc); - } - -+static bool write_acos_or_asin(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc, bool asin_mode) -+{ -+ struct hlsl_ir_function_decl *func; -+ struct hlsl_type *type; -+ char *body; -+ -+ static const char template[] = -+ "%s %s(%s x)\n" -+ "{\n" -+ " %s abs_arg = abs(x);\n" -+ " %s poly_approx = (((-0.018729\n" -+ " * abs_arg + 0.074261)\n" -+ " * abs_arg - 0.212114)\n" -+ " * abs_arg + 1.570729);\n" -+ " %s correction = sqrt(1.0 - abs_arg);\n" -+ " %s zero_flip = (x < 0.0) * (-2.0 * correction * poly_approx + 3.141593);\n" -+ " %s result = poly_approx * correction + zero_flip;\n" -+ " return %s;\n" -+ "}"; -+ static const char fn_name_acos[] = "acos"; -+ static const char fn_name_asin[] = "asin"; -+ static const char return_stmt_acos[] = "result"; -+ static const char return_stmt_asin[] = "-result + 1.570796"; -+ -+ const char *fn_name = asin_mode ? fn_name_asin : fn_name_acos; -+ -+ type = params->args[0]->data_type; -+ type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->dimx, type->dimy); -+ -+ if (!(body = hlsl_sprintf_alloc(ctx, template, -+ type->name, fn_name, type->name, -+ type->name, type->name, type->name, type->name, type->name, -+ (asin_mode ? return_stmt_asin : return_stmt_acos)))) -+ return false; -+ func = hlsl_compile_internal_function(ctx, fn_name, body); -+ vkd3d_free(body); -+ if (!func) -+ return false; -+ -+ return add_user_call(ctx, func, params, loc); -+} -+ -+static bool intrinsic_acos(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ return write_acos_or_asin(ctx, params, loc, false); -+} -+ - static bool intrinsic_all(struct hlsl_ctx *ctx, - const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { -@@ -2743,6 +2792,105 @@ static bool intrinsic_any(struct hlsl_ctx *ctx, - return false; - } - -+static bool intrinsic_asin(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ return write_acos_or_asin(ctx, params, loc, true); -+} -+ -+static bool write_atan_or_atan2(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, -+ const struct vkd3d_shader_location *loc, bool atan2_mode) -+{ -+ struct hlsl_ir_function_decl *func; -+ struct hlsl_type *type; -+ struct vkd3d_string_buffer *buf; -+ int ret; -+ -+ static const char atan2_name[] = "atan2"; -+ static const char atan_name[] = "atan"; -+ -+ static const char atan2_header_template[] = -+ "%s atan2(%s y, %s x)\n" -+ "{\n" -+ " %s in_y, in_x;\n" -+ " in_y = y;\n" -+ " in_x = x;\n"; -+ static const char atan_header_template[] = -+ "%s atan(%s y)\n" -+ "{\n" -+ " %s in_y, in_x;\n" -+ " in_y = y;\n" -+ " in_x = 1.0;\n"; -+ -+ static const char body_template[] = -+ " %s recip, input, x2, poly_approx, flipped;" -+ " recip = 1.0 / max(abs(in_y), abs(in_x));\n" -+ " input = recip * min(abs(in_y), abs(in_x));\n" -+ " x2 = input * input;\n" -+ " poly_approx = ((((0.020835\n" -+ " * x2 - 0.085133)\n" -+ " * x2 + 0.180141)\n" -+ " * x2 - 0.330299)\n" -+ " * x2 + 0.999866)\n" -+ " * input;\n" -+ " flipped = poly_approx * -2.0 + 1.570796;\n" -+ " poly_approx += abs(in_x) < abs(in_y) ? flipped : 0.0;\n" -+ " poly_approx += in_x < 0.0 ? -3.1415927 : 0.0;\n" -+ " return (min(in_x, in_y) < 0.0 && max(in_x, in_y) >= 0.0)\n" -+ " ? -poly_approx\n" -+ " : poly_approx;\n" -+ "}"; -+ -+ if (!(type = elementwise_intrinsic_get_common_type(ctx, params, loc))) -+ return false; -+ type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->dimx, type->dimy); -+ -+ if (!(buf = hlsl_get_string_buffer(ctx))) -+ return false; -+ -+ if (atan2_mode) -+ ret = vkd3d_string_buffer_printf(buf, atan2_header_template, -+ type->name, type->name, type->name, type->name); -+ else -+ ret = vkd3d_string_buffer_printf(buf, atan_header_template, -+ type->name, type->name, type->name); -+ if (ret < 0) -+ { -+ vkd3d_string_buffer_cleanup(buf); -+ return false; -+ } -+ -+ ret = vkd3d_string_buffer_printf(buf, body_template, type->name); -+ if (ret < 0) -+ { -+ vkd3d_string_buffer_cleanup(buf); -+ return false; -+ } -+ -+ func = hlsl_compile_internal_function(ctx, -+ atan2_mode ? atan2_name : atan_name, buf->buffer); -+ vkd3d_string_buffer_cleanup(buf); -+ if (!func) -+ return false; -+ -+ return add_user_call(ctx, func, params, loc); -+} -+ -+static bool intrinsic_atan(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ return write_atan_or_atan2(ctx, params, loc, false); -+} -+ -+ -+static bool intrinsic_atan2(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ return write_atan_or_atan2(ctx, params, loc, true); -+} -+ -+ - /* Find the type corresponding to the given source type, with the same - * dimensions but a different base type. */ - static struct hlsl_type *convert_numeric_type(const struct hlsl_ctx *ctx, -@@ -3970,10 +4118,14 @@ intrinsic_functions[] = - /* Note: these entries should be kept in alphabetical order. */ - {"D3DCOLORtoUBYTE4", 1, true, intrinsic_d3dcolor_to_ubyte4}, - {"abs", 1, true, intrinsic_abs}, -+ {"acos", 1, true, intrinsic_acos}, - {"all", 1, true, intrinsic_all}, - {"any", 1, true, intrinsic_any}, - {"asfloat", 1, true, intrinsic_asfloat}, -+ {"asin", 1, true, intrinsic_asin}, - {"asuint", -1, true, intrinsic_asuint}, -+ {"atan", 1, true, intrinsic_atan}, -+ {"atan2", 2, true, intrinsic_atan2}, - {"ceil", 1, true, intrinsic_ceil}, - {"clamp", 3, true, intrinsic_clamp}, - {"clip", 1, true, intrinsic_clip}, -@@ -4308,7 +4460,7 @@ static bool add_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, - hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim + !multisampled), loc))) - return false; - -- load_params.format = object_type->e.resource_format; -+ load_params.format = object_type->e.resource.format; - load_params.resource = object; - - if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) -@@ -4366,7 +4518,7 @@ static bool add_sample_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc - if (params->args_count > 3 + !!offset_dim) - hlsl_fixme(ctx, loc, "Tiled resource status argument."); - -- load_params.format = object_type->e.resource_format; -+ load_params.format = object_type->e.resource.format; - load_params.resource = object; - load_params.sampler = params->args[0]; - -@@ -4436,7 +4588,7 @@ static bool add_sample_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block * - if (params->args_count > 4 + !!offset_dim) - hlsl_fixme(ctx, loc, "Tiled resource status argument."); - -- load_params.format = object_type->e.resource_format; -+ load_params.format = object_type->e.resource.format; - load_params.resource = object; - load_params.sampler = params->args[0]; - -@@ -4526,7 +4678,7 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc - return false; - } - -- if (read_channel >= object_type->e.resource_format->dimx) -+ if (read_channel >= object_type->e.resource.format->dimx) - { - hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Method %s() requires at least %u channels.", name, read_channel + 1); -@@ -4537,7 +4689,7 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) - return false; - -- load_params.format = hlsl_get_vector_type(ctx, object_type->e.resource_format->base_type, 4); -+ load_params.format = hlsl_get_vector_type(ctx, object_type->e.resource.format->base_type, 4); - load_params.resource = object; - load_params.sampler = params->args[0]; - -@@ -4781,7 +4933,7 @@ static bool add_sample_lod_method_call(struct hlsl_ctx *ctx, struct hlsl_block * - if (params->args_count > 3 + !!offset_dim) - hlsl_fixme(ctx, loc, "Tiled resource status argument."); - -- load_params.format = object_type->e.resource_format; -+ load_params.format = object_type->e.resource.format; - load_params.resource = object; - load_params.sampler = params->args[0]; - -@@ -4848,7 +5000,7 @@ static bool add_sample_grad_method_call(struct hlsl_ctx *ctx, struct hlsl_block - if (params->args_count > 4 + !!offset_dim) - hlsl_fixme(ctx, loc, "Tiled resource status argument."); - -- load_params.format = object_type->e.resource_format; -+ load_params.format = object_type->e.resource.format; - load_params.resource = object; - load_params.sampler = params->args[0]; - -@@ -6263,12 +6415,12 @@ type_no_void: - | uav_type '<' type '>' - { - validate_uav_type(ctx, $1, $3, &@3); -- $$ = hlsl_new_uav_type(ctx, $1, $3, 0); -+ $$ = hlsl_new_uav_type(ctx, $1, $3, false); - } - | rov_type '<' type '>' - { - validate_uav_type(ctx, $1, $3, &@3); -- $$ = hlsl_new_uav_type(ctx, $1, $3, HLSL_MODIFIER_RASTERIZER_ORDERED); -+ $$ = hlsl_new_uav_type(ctx, $1, $3, true); - } - | TYPE_IDENTIFIER - { -@@ -6294,6 +6446,14 @@ type_no_void: - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "\"%s\" redefined as a structure.", $2); - vkd3d_free($2); - } -+ | KW_RENDERTARGETVIEW -+ { -+ $$ = hlsl_get_type(ctx->cur_scope, "RenderTargetView", true, true); -+ } -+ | KW_DEPTHSTENCILVIEW -+ { -+ $$ = hlsl_get_type(ctx->cur_scope, "DepthStencilView", true, true); -+ } - - type: - type_no_void -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 7da427796e7..307f86f55b7 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -1107,7 +1107,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, - params.type = HLSL_RESOURCE_LOAD; - params.resource = val; - params.coords = coords; -- params.format = val->data_type->e.resource_format; -+ params.format = val->data_type->e.resource.format; - - if (!(resource_load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) - return false; -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 88634487482..f0bd85338c6 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -3009,6 +3009,319 @@ fail: - return VKD3D_ERROR_OUT_OF_MEMORY; - } - -+struct vsir_block_list -+{ -+ struct vsir_block **blocks; -+ size_t count, capacity; -+}; -+ -+static void vsir_block_list_init(struct vsir_block_list *list) -+{ -+ memset(list, 0, sizeof(*list)); -+} -+ -+static void vsir_block_list_cleanup(struct vsir_block_list *list) -+{ -+ vkd3d_free(list->blocks); -+} -+ -+static enum vkd3d_result vsir_block_list_add(struct vsir_block_list *list, struct vsir_block *block) -+{ -+ size_t i; -+ -+ for (i = 0; i < list->count; ++i) -+ if (block == list->blocks[i]) -+ return VKD3D_OK; -+ -+ if (!vkd3d_array_reserve((void **)&list->blocks, &list->capacity, list->count + 1, sizeof(*list->blocks))) -+ { -+ ERR("Cannot extend block list.\n"); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ -+ list->blocks[list->count++] = block; -+ -+ return VKD3D_OK; -+} -+ -+struct vsir_block -+{ -+ unsigned int label; -+ /* `begin' points to the instruction immediately following the -+ * LABEL that introduces the block. `end' points to the terminator -+ * instruction (either BRANCH or RET). They can coincide, meaning -+ * that the block is empty. */ -+ struct vkd3d_shader_instruction *begin, *end; -+ struct vsir_block_list predecessors, successors; -+ uint32_t *dominates; -+}; -+ -+static enum vkd3d_result vsir_block_init(struct vsir_block *block, unsigned int label, size_t block_count) -+{ -+ size_t byte_count; -+ -+ if (block_count > SIZE_MAX - (sizeof(*block->dominates) * CHAR_BIT - 1)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ block_count = align(block_count, sizeof(*block->dominates) * CHAR_BIT); -+ byte_count = block_count / CHAR_BIT; -+ -+ assert(label); -+ memset(block, 0, sizeof(*block)); -+ block->label = label; -+ vsir_block_list_init(&block->predecessors); -+ vsir_block_list_init(&block->successors); -+ -+ if (!(block->dominates = vkd3d_malloc(byte_count))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ memset(block->dominates, 0xff, byte_count); -+ -+ return VKD3D_OK; -+} -+ -+static void vsir_block_cleanup(struct vsir_block *block) -+{ -+ if (block->label == 0) -+ return; -+ vsir_block_list_cleanup(&block->predecessors); -+ vsir_block_list_cleanup(&block->successors); -+ vkd3d_free(block->dominates); -+} -+ -+struct vsir_cfg -+{ -+ struct vsir_program *program; -+ struct vsir_block *blocks; -+ struct vsir_block *entry; -+ size_t block_count; -+}; -+ -+static void vsir_cfg_cleanup(struct vsir_cfg *cfg) -+{ -+ size_t i; -+ -+ for (i = 0; i < cfg->block_count; ++i) -+ vsir_block_cleanup(&cfg->blocks[i]); -+ -+ vkd3d_free(cfg->blocks); -+} -+ -+static enum vkd3d_result vsir_cfg_add_edge(struct vsir_cfg *cfg, struct vsir_block *block, -+ struct vkd3d_shader_src_param *successor_param) -+{ -+ unsigned int target = label_from_src_param(successor_param); -+ struct vsir_block *successor = &cfg->blocks[target - 1]; -+ enum vkd3d_result ret; -+ -+ assert(successor->label != 0); -+ -+ if ((ret = vsir_block_list_add(&block->successors, successor)) < 0) -+ return ret; -+ -+ if ((ret = vsir_block_list_add(&successor->predecessors, block)) < 0) -+ return ret; -+ -+ return VKD3D_OK; -+} -+ -+static void vsir_cfg_dump_dot(struct vsir_cfg *cfg) -+{ -+ size_t i, j; -+ -+ TRACE("digraph cfg {\n"); -+ -+ for (i = 0; i < cfg->block_count; ++i) -+ { -+ struct vsir_block *block = &cfg->blocks[i]; -+ const char *shape; -+ -+ if (block->label == 0) -+ continue; -+ -+ switch (block->end->handler_idx) -+ { -+ case VKD3DSIH_RET: -+ shape = "trapezium"; -+ break; -+ -+ case VKD3DSIH_BRANCH: -+ shape = vsir_register_is_label(&block->end->src[0].reg) ? "ellipse" : "box"; -+ break; -+ -+ default: -+ vkd3d_unreachable(); -+ } -+ -+ TRACE(" n%u [label=\"%u\", shape=\"%s\"];\n", block->label, block->label, shape); -+ -+ for (j = 0; j < block->successors.count; ++j) -+ TRACE(" n%u -> n%u;\n", block->label, block->successors.blocks[j]->label); -+ } -+ -+ TRACE("}\n"); -+} -+ -+static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program *program) -+{ -+ struct vsir_block *current_block = NULL; -+ enum vkd3d_result ret; -+ size_t i; -+ -+ memset(cfg, 0, sizeof(*cfg)); -+ cfg->program = program; -+ cfg->block_count = program->block_count; -+ -+ if (!(cfg->blocks = vkd3d_calloc(cfg->block_count, sizeof(*cfg->blocks)))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ for (i = 0; i < program->instructions.count; ++i) -+ { -+ struct vkd3d_shader_instruction *instruction = &program->instructions.elements[i]; -+ -+ switch (instruction->handler_idx) -+ { -+ case VKD3DSIH_PHI: -+ case VKD3DSIH_SWITCH_MONOLITHIC: -+ vkd3d_unreachable(); -+ -+ case VKD3DSIH_LABEL: -+ { -+ unsigned int label = label_from_src_param(&instruction->src[0]); -+ -+ assert(!current_block); -+ assert(label > 0); -+ assert(label <= cfg->block_count); -+ current_block = &cfg->blocks[label - 1]; -+ assert(current_block->label == 0); -+ if ((ret = vsir_block_init(current_block, label, program->block_count)) < 0) -+ goto fail; -+ current_block->begin = &program->instructions.elements[i + 1]; -+ if (!cfg->entry) -+ cfg->entry = current_block; -+ break; -+ } -+ -+ case VKD3DSIH_BRANCH: -+ case VKD3DSIH_RET: -+ assert(current_block); -+ current_block->end = instruction; -+ current_block = NULL; -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ for (i = 0; i < cfg->block_count; ++i) -+ { -+ struct vsir_block *block = &cfg->blocks[i]; -+ -+ if (block->label == 0) -+ continue; -+ -+ switch (block->end->handler_idx) -+ { -+ case VKD3DSIH_RET: -+ break; -+ -+ case VKD3DSIH_BRANCH: -+ if (vsir_register_is_label(&block->end->src[0].reg)) -+ { -+ if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[0])) < 0) -+ goto fail; -+ } -+ else -+ { -+ if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[1])) < 0) -+ goto fail; -+ -+ if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[2])) < 0) -+ goto fail; -+ } -+ break; -+ -+ default: -+ vkd3d_unreachable(); -+ } -+ } -+ -+ if (TRACE_ON()) -+ vsir_cfg_dump_dot(cfg); -+ -+ return VKD3D_OK; -+ -+fail: -+ vsir_cfg_cleanup(cfg); -+ -+ return ret; -+} -+ -+/* Block A dominates block B if every path from the entry point to B -+ * must pass through A. Naively compute the set of blocks that are -+ * dominated by `reference' by running a graph visit starting from the -+ * entry point (which must be the initial value of `current') and -+ * avoiding `reference'. Running this for all the blocks takes -+ * quadratic time: if in the future something better is sought after, -+ * the standard tool seems to be the Lengauer-Tarjan algorithm. */ -+static void vsir_cfg_compute_dominators_recurse(struct vsir_block *current, struct vsir_block *reference) -+{ -+ size_t i; -+ -+ assert(current->label != 0); -+ -+ if (current == reference) -+ return; -+ -+ if (!bitmap_is_set(reference->dominates, current->label - 1)) -+ return; -+ -+ bitmap_clear(reference->dominates, current->label - 1); -+ -+ for (i = 0; i < current->successors.count; ++i) -+ vsir_cfg_compute_dominators_recurse(current->successors.blocks[i], reference); -+} -+ -+static void vsir_cfg_compute_dominators(struct vsir_cfg *cfg) -+{ -+ struct vkd3d_string_buffer buf; -+ size_t i, j; -+ -+ if (TRACE_ON()) -+ vkd3d_string_buffer_init(&buf); -+ -+ for (i = 0; i < cfg->block_count; ++i) -+ { -+ struct vsir_block *block = &cfg->blocks[i]; -+ -+ if (block->label == 0) -+ continue; -+ -+ vsir_cfg_compute_dominators_recurse(cfg->entry, block); -+ -+ if (TRACE_ON()) -+ { -+ vkd3d_string_buffer_printf(&buf, "Block %u dominates:", block->label); -+ for (j = 0; j < cfg->block_count; j++) -+ { -+ struct vsir_block *block2 = &cfg->blocks[j]; -+ -+ if (block2->label == 0) -+ continue; -+ -+ if (bitmap_is_set(block->dominates, j)) -+ vkd3d_string_buffer_printf(&buf, " %u", block2->label); -+ } -+ TRACE("%s\n", buf.buffer); -+ vkd3d_string_buffer_clear(&buf); -+ } -+ } -+ -+ if (TRACE_ON()) -+ vkd3d_string_buffer_cleanup(&buf); -+} -+ - enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, - const struct vkd3d_shader_compile_info *compile_info) - { -@@ -3022,14 +3335,26 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, - - if (parser->shader_desc.is_dxil) - { -+ struct vsir_cfg cfg; -+ - if ((result = lower_switch_to_if_ladder(&parser->program)) < 0) - return result; - - if ((result = materialize_ssas_to_temps(parser)) < 0) - return result; - -+ if ((result = vsir_cfg_init(&cfg, &parser->program)) < 0) -+ return result; -+ -+ vsir_cfg_compute_dominators(&cfg); -+ - if ((result = simple_structurizer_run(parser)) < 0) -+ { -+ vsir_cfg_cleanup(&cfg); - return result; -+ } -+ -+ vsir_cfg_cleanup(&cfg); - } - else - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 492e5ec027d..c6cf1c9519c 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -3156,7 +3156,7 @@ static D3D_RESOURCE_RETURN_TYPE sm4_resource_format(const struct hlsl_type *type - if (type->class == HLSL_CLASS_ARRAY) - return sm4_resource_format(type->e.array.type); - -- switch (type->e.resource_format->base_type) -+ switch (type->e.resource.format->base_type) - { - case HLSL_TYPE_DOUBLE: - return D3D_RETURN_TYPE_DOUBLE; -@@ -3446,7 +3446,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) - } - else - { -- unsigned int dimx = hlsl_type_get_component_type(ctx, resource->data_type, 0)->e.resource_format->dimx; -+ unsigned int dimx = hlsl_type_get_component_type(ctx, resource->data_type, 0)->e.resource.format->dimx; - - put_u32(&buffer, sm4_resource_format(resource->data_type)); - put_u32(&buffer, sm4_rdef_resource_dimension(resource->data_type)); -@@ -4253,12 +4253,15 @@ static void write_sm4_dcl_textures(const struct tpf_writer *tpf, const struct ex - { - case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: - instr.opcode = VKD3D_SM5_OP_DCL_UAV_STRUCTURED; -- instr.byte_stride = resource->data_type->e.resource_format->reg_size[HLSL_REGSET_NUMERIC] * 4; -+ instr.byte_stride = resource->data_type->e.resource.format->reg_size[HLSL_REGSET_NUMERIC] * 4; - break; - default: - instr.opcode = VKD3D_SM5_OP_DCL_UAV_TYPED; - break; - } -+ -+ if (resource->data_type->e.resource.rasteriser_ordered) -+ instr.opcode |= VKD3DSUF_RASTERISER_ORDERED_VIEW << VKD3D_SM5_UAV_FLAGS_SHIFT; - } - else - { -@@ -4272,9 +4275,6 @@ static void write_sm4_dcl_textures(const struct tpf_writer *tpf, const struct ex - instr.extra_bits |= component_type->sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; - } - -- if (resource->data_type->modifiers & HLSL_MODIFIER_RASTERIZER_ORDERED) -- instr.opcode |= VKD3DSUF_RASTERISER_ORDERED_VIEW << VKD3D_SM5_UAV_FLAGS_SHIFT; -- - write_sm4_instruction(tpf, &instr); - } - } -@@ -4477,7 +4477,7 @@ static void write_sm4_unary_op(const struct tpf_writer *tpf, enum vkd3d_sm4_opco - } - - static void write_sm4_unary_op_with_two_destinations(const struct tpf_writer *tpf, enum vkd3d_sm4_opcode opcode, -- const struct hlsl_ir_node *dst, unsigned dst_idx, const struct hlsl_ir_node *src) -+ const struct hlsl_ir_node *dst, unsigned int dst_idx, const struct hlsl_ir_node *src) - { - struct sm4_instruction instr; - -@@ -4486,7 +4486,6 @@ static void write_sm4_unary_op_with_two_destinations(const struct tpf_writer *tp - - assert(dst_idx < ARRAY_SIZE(instr.dsts)); - sm4_dst_from_node(&instr.dsts[dst_idx], dst); -- assert(1 - dst_idx >= 0); - instr.dsts[1 - dst_idx].reg.type = VKD3DSPR_NULL; - instr.dsts[1 - dst_idx].reg.dimension = VSIR_DIMENSION_NONE; - instr.dsts[1 - dst_idx].reg.idx_count = 0; -@@ -4536,7 +4535,7 @@ static void write_sm4_binary_op_dot(const struct tpf_writer *tpf, enum vkd3d_sm4 - } - - static void write_sm4_binary_op_with_two_destinations(const struct tpf_writer *tpf, -- enum vkd3d_sm4_opcode opcode, const struct hlsl_ir_node *dst, unsigned dst_idx, -+ enum vkd3d_sm4_opcode opcode, const struct hlsl_ir_node *dst, unsigned int dst_idx, - const struct hlsl_ir_node *src1, const struct hlsl_ir_node *src2) - { - struct sm4_instruction instr; -@@ -4546,7 +4545,6 @@ static void write_sm4_binary_op_with_two_destinations(const struct tpf_writer *t - - assert(dst_idx < ARRAY_SIZE(instr.dsts)); - sm4_dst_from_node(&instr.dsts[dst_idx], dst); -- assert(1 - dst_idx >= 0); - instr.dsts[1 - dst_idx].reg.type = VKD3DSPR_NULL; - instr.dsts[1 - dst_idx].reg.dimension = VSIR_DIMENSION_NONE; - instr.dsts[1 - dst_idx].reg.idx_count = 0; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index b2f7b17eb73..385c4368e31 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -71,7 +71,7 @@ void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer) - vkd3d_free(buffer->buffer); - } - --static void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer) -+void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer) - { - buffer->buffer[0] = '\0'; - buffer->content_size = 0; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 910d34a7d13..2d3b3254638 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -1399,6 +1399,7 @@ struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_c - void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer); - void vkd3d_string_buffer_cache_cleanup(struct vkd3d_string_buffer_cache *list); - void vkd3d_string_buffer_cache_init(struct vkd3d_string_buffer_cache *list); -+void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer); - int vkd3d_string_buffer_print_f32(struct vkd3d_string_buffer *buffer, float f); - int vkd3d_string_buffer_print_f64(struct vkd3d_string_buffer *buffer, double d); - int vkd3d_string_buffer_printf(struct vkd3d_string_buffer *buffer, const char *format, ...) VKD3D_PRINTF_FUNC(2, 3); -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 01818458e97..0f45b68fc38 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -1704,6 +1704,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, - { - WARN("Disabling robust buffer access for the update after bind feature.\n"); - features->robustBufferAccess = VK_FALSE; -+ physical_device_info->robustness2_features.robustBufferAccess2 = VK_FALSE; - } - - /* Select descriptor heap implementation. Forcing virtual heaps may be useful if --- -2.43.0 - diff --git a/patches/vkd3d-latest/0006-Updated-vkd3d-to-9177df883ecf1bc66b39e28d8f6bb616572.patch b/patches/vkd3d-latest/0006-Updated-vkd3d-to-9177df883ecf1bc66b39e28d8f6bb616572.patch deleted file mode 100644 index 038a45fd..00000000 --- a/patches/vkd3d-latest/0006-Updated-vkd3d-to-9177df883ecf1bc66b39e28d8f6bb616572.patch +++ /dev/null @@ -1,371 +0,0 @@ -From ee7b37e4b9c357e15f9f92fd7252e1a8c95a8e88 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 5 Mar 2024 13:33:16 +1100 -Subject: [PATCH] Updated vkd3d to 9177df883ecf1bc66b39e28d8f6bb616572a75fe. - ---- - libs/vkd3d/include/private/vkd3d_common.h | 1 + - libs/vkd3d/include/vkd3d.h | 2 +- - libs/vkd3d/include/vkd3d_shader.h | 6 ++ - libs/vkd3d/libs/vkd3d-shader/dxil.c | 116 ++++++++++++++++++++-- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 2 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 41 ++++++++ - libs/vkd3d/libs/vkd3d/device.c | 8 -- - libs/vkd3d/libs/vkd3d/resource.c | 4 +- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 8 ++ - 9 files changed, 166 insertions(+), 22 deletions(-) - -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index b5a8240d28e..9606e93e8cf 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -64,6 +64,7 @@ - #define TAG_RDEF VKD3D_MAKE_TAG('R', 'D', 'E', 'F') - #define TAG_RTS0 VKD3D_MAKE_TAG('R', 'T', 'S', '0') - #define TAG_SDBG VKD3D_MAKE_TAG('S', 'D', 'B', 'G') -+#define TAG_SFI0 VKD3D_MAKE_TAG('S', 'F', 'I', '0') - #define TAG_SHDR VKD3D_MAKE_TAG('S', 'H', 'D', 'R') - #define TAG_SHEX VKD3D_MAKE_TAG('S', 'H', 'E', 'X') - #define TAG_STAT VKD3D_MAKE_TAG('S', 'T', 'A', 'T') -diff --git a/libs/vkd3d/include/vkd3d.h b/libs/vkd3d/include/vkd3d.h -index df361f90177..8a8389f02a4 100644 ---- a/libs/vkd3d/include/vkd3d.h -+++ b/libs/vkd3d/include/vkd3d.h -@@ -182,7 +182,7 @@ struct vkd3d_image_resource_create_info - const void *next; - - VkImage vk_image; -- D3D12_RESOURCE_DESC1 desc; -+ D3D12_RESOURCE_DESC desc; - unsigned int flags; - D3D12_RESOURCE_STATES present_state; - }; -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index 2f4478a7983..6fa98f3d8fe 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -199,7 +199,13 @@ enum vkd3d_shader_compile_option_fragment_coordinate_origin - /** Advertises feature availability. \since 1.11 */ - enum vkd3d_shader_compile_option_feature_flags - { -+ /** The SPIR-V target environment supports 64-bit integer types. This -+ * corresponds to the "shaderInt64" feature in the Vulkan API, and the -+ * "GL_ARB_gpu_shader_int64" extension in the OpenGL API. */ - VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64 = 0x00000001, -+ /** The SPIR-V target environment supports 64-bit floating-point types. -+ * This corresponds to the "shaderFloat64" feature in the Vulkan API, and -+ * the "GL_ARB_gpu_shader_fp64" extension in the OpenGL API. */ - VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLOAT64 = 0x00000002, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS), -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index ac688e85e52..26a8a5c1cc3 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -388,6 +388,7 @@ enum dx_intrinsic_opcode - DX_TEXTURE_STORE = 67, - DX_BUFFER_LOAD = 68, - DX_BUFFER_STORE = 69, -+ DX_GET_DIMENSIONS = 72, - DX_ATOMIC_BINOP = 78, - DX_ATOMIC_CMP_XCHG = 79, - DX_DERIV_COARSEX = 83, -@@ -1937,6 +1938,16 @@ static const struct sm6_type *sm6_parser_get_type(struct sm6_parser *sm6, uint64 - return &sm6->types[type_id]; - } - -+static bool resource_kind_is_texture(enum dxil_resource_kind kind) -+{ -+ return kind >= RESOURCE_KIND_TEXTURE1D && kind <= RESOURCE_KIND_TEXTURECUBEARRAY; -+} -+ -+static bool resource_kind_is_multisampled(enum dxil_resource_kind kind) -+{ -+ return kind == RESOURCE_KIND_TEXTURE2DMS || kind == RESOURCE_KIND_TEXTURE2DMSARRAY; -+} -+ - static int global_symbol_compare(const void *a, const void *b) - { - return vkd3d_u32_compare(((const struct sm6_symbol *)a)->id, ((const struct sm6_symbol *)b)->id); -@@ -2346,6 +2357,23 @@ static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instructio - dst->u.reg = param->reg; - } - -+static bool instruction_dst_param_init_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) -+{ -+ struct sm6_value *dst = sm6_parser_get_current_value(sm6); -+ struct vkd3d_shader_dst_param *param; -+ -+ if (!(param = instruction_dst_params_alloc(ins, 1, sm6))) -+ return false; -+ -+ vsir_dst_param_init(param, VKD3DSPR_TEMP, vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(dst->type, 0)), 1); -+ param->write_mask = VKD3DSP_WRITEMASK_ALL; -+ param->reg.idx[0].offset = 0; -+ param->reg.dimension = VSIR_DIMENSION_VEC4; -+ dst->u.reg = param->reg; -+ -+ return true; -+} -+ - /* Recurse through the block tree while maintaining a current value count. The current - * count is the sum of the global count plus all declarations within the current function. - * Store into value_capacity the highest count seen. */ -@@ -4037,6 +4065,80 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int - ins->handler_idx = VKD3DSIH_NOP; - } - -+static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -+ const struct sm6_value **operands, struct function_emission_state *state) -+{ -+ struct vkd3d_shader_instruction *ins = state->ins; -+ struct vkd3d_shader_src_param *src_params; -+ unsigned int is_texture, component_count; -+ enum dxil_resource_kind resource_kind; -+ struct vkd3d_shader_dst_param *dst; -+ const struct sm6_value *resource; -+ -+ resource = operands[0]; -+ if (!sm6_value_validate_is_handle(resource, sm6)) -+ return; -+ is_texture = resource->u.handle.d->resource_type != VKD3D_SHADER_RESOURCE_BUFFER; -+ resource_kind = resource->u.handle.d->kind; -+ -+ instruction_init_with_resource(ins, is_texture ? VKD3DSIH_RESINFO : VKD3DSIH_BUFINFO, resource, sm6); -+ -+ if (!(src_params = instruction_src_params_alloc(ins, 1 + is_texture, sm6))) -+ return; -+ src_param_init_vector_from_reg(&src_params[is_texture], &resource->u.handle.reg); -+ -+ if (is_texture) -+ { -+ ins->flags = VKD3DSI_RESINFO_UINT; -+ src_param_init_from_value(&src_params[0], operands[1]); -+ component_count = VKD3D_VEC4_SIZE; -+ -+ if (resource_kind_is_multisampled(resource_kind)) -+ { -+ instruction_dst_param_init_temp_vector(ins++, sm6); -+ state->temp_idx = 1; -+ -+ /* DXIL does not have an instrinsic for sample info, and resinfo is expected to return -+ * the sample count in .w for MS textures. The result is always a struct of 4 x uint32. */ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SAMPLE_INFO); -+ ins->flags = VKD3DSI_SAMPLE_INFO_UINT; -+ -+ if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) -+ return; -+ src_param_init_vector_from_reg(&src_params[0], &resource->u.handle.reg); -+ src_params[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); -+ -+ if (!instruction_dst_param_init_temp_vector(ins, sm6)) -+ return; -+ dst = ins->dst; -+ dst->write_mask = VKD3DSP_WRITEMASK_3; -+ -+ /* Move the result to an SSA in case another instruction overwrites r0 before -+ * the components are extracted for use. */ -+ ++ins; -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); -+ if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) -+ return; -+ src_param_init_vector_from_reg(&src_params[0], &dst->reg); -+ -+ state->ins = ins; -+ state->code_block->instruction_count += 2; -+ } -+ } -+ else -+ { -+ if (!operands[1]->is_undefined) -+ { -+ WARN("Ignoring unexpected operand.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring an unexpected defined LOD value for buffer GetDimensions."); -+ } -+ component_count = 1 + (resource_kind == RESOURCE_KIND_STRUCTUREDBUFFER); -+ } -+ -+ instruction_dst_param_init_ssa_vector(ins, component_count, sm6); -+} -+ - static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode op) - { - switch (op) -@@ -4626,6 +4728,7 @@ struct sm6_dx_opcode_info - e -> half/float - g -> half/float/double - H -> handle -+ D -> Dimensions - S -> splitdouble - v -> void - o -> overloaded -@@ -4656,6 +4759,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - [DX_FMAX ] = {"g", "RR", sm6_parser_emit_dx_binary}, - [DX_FMIN ] = {"g", "RR", sm6_parser_emit_dx_binary}, - [DX_FRC ] = {"g", "R", sm6_parser_emit_dx_unary}, -+ [DX_GET_DIMENSIONS ] = {"D", "Hi", sm6_parser_emit_dx_get_dimensions}, - [DX_IBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, - [DX_HCOS ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_HSIN ] = {"g", "R", sm6_parser_emit_dx_unary}, -@@ -4733,6 +4837,8 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc - return sm6_type_is_floating_point(type); - case 'H': - return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; -+ case 'D': -+ return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Dimensions"); - case 'S': - return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.splitdouble"); - case 'v': -@@ -6778,16 +6884,6 @@ static bool sm6_parser_resources_load_register_range(struct sm6_parser *sm6, - return true; - } - --static bool resource_kind_is_texture(enum dxil_resource_kind kind) --{ -- return kind >= RESOURCE_KIND_TEXTURE1D && kind <= RESOURCE_KIND_TEXTURECUBEARRAY; --} -- --static bool resource_kind_is_multisampled(enum dxil_resource_kind kind) --{ -- return kind == RESOURCE_KIND_TEXTURE2DMS || kind == RESOURCE_KIND_TEXTURE2DMSARRAY; --} -- - static enum vkd3d_shader_resource_type shader_resource_type_from_dxil_resource_kind(enum dxil_resource_kind kind) - { - if (resource_kind_is_texture(kind)) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 0e75edd46f6..538f083df9c 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -3017,7 +3017,7 @@ static void free_ir_resource_load(struct hlsl_ir_resource_load *load) - - static void free_ir_resource_store(struct hlsl_ir_resource_store *store) - { -- hlsl_src_remove(&store->resource.rel_offset); -+ hlsl_cleanup_deref(&store->resource); - hlsl_src_remove(&store->coords); - hlsl_src_remove(&store->value); - vkd3d_free(store); -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index c6cf1c9519c..3be4e40ab0c 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -164,6 +164,21 @@ STATIC_ASSERT(SM4_MAX_SRC_COUNT <= SPIRV_MAX_SRC_COUNT); - /* The shift that corresponds to the D3D_SIF_TEXTURE_COMPONENTS mask. */ - #define VKD3D_SM4_SIF_TEXTURE_COMPONENTS_SHIFT 2 - -+#define VKD3D_SM4_REQUIRES_DOUBLES 0x00000001 -+#define VKD3D_SM4_REQUIRES_EARLY_DEPTH_STENCIL 0x00000002 -+#define VKD3D_SM4_REQUIRES_UAVS_AT_EVERY_STAGE 0x00000004 -+#define VKD3D_SM4_REQUIRES_64_UAVS 0x00000008 -+#define VKD3D_SM4_REQUIRES_MINIMUM_PRECISION 0x00000010 -+#define VKD3D_SM4_REQUIRES_11_1_DOUBLE_EXTENSIONS 0x00000020 -+#define VKD3D_SM4_REQUIRES_11_1_SHADER_EXTENSIONS 0x00000040 -+#define VKD3D_SM4_REQUIRES_LEVEL_9_COMPARISON_FILTERING 0x00000080 -+#define VKD3D_SM4_REQUIRES_TILED_RESOURCES 0x00000100 -+#define VKD3D_SM4_REQUIRES_STENCIL_REF 0x00000200 -+#define VKD3D_SM4_REQUIRES_INNER_COVERAGE 0x00000400 -+#define VKD3D_SM4_REQUIRES_TYPED_UAV_LOAD_ADDITIONAL_FORMATS 0x00000800 -+#define VKD3D_SM4_REQUIRES_ROVS 0x00001000 -+#define VKD3D_SM4_REQUIRES_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER 0x00002000 -+ - enum vkd3d_sm4_opcode - { - VKD3D_SM4_OP_ADD = 0x00, -@@ -5896,6 +5911,31 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, - sm4_free_extern_resources(extern_resources, extern_resources_count); - } - -+static void write_sm4_sfi0(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) -+{ -+ struct extern_resource *extern_resources; -+ unsigned int extern_resources_count; -+ uint64_t *flags; -+ -+ flags = vkd3d_calloc(1, sizeof(*flags)); -+ -+ extern_resources = sm4_get_extern_resources(ctx, &extern_resources_count); -+ for (unsigned int i = 0; i < extern_resources_count; ++i) -+ { -+ if (extern_resources[i].data_type->e.resource.rasteriser_ordered) -+ *flags |= VKD3D_SM4_REQUIRES_ROVS; -+ } -+ sm4_free_extern_resources(extern_resources, extern_resources_count); -+ -+ /* FIXME: We also emit code that should require UAVS_AT_EVERY_STAGE, -+ * STENCIL_REF, and TYPED_UAV_LOAD_ADDITIONAL_FORMATS. */ -+ -+ if (flags) -+ dxbc_writer_add_section(dxbc, TAG_SFI0, flags, sizeof(*flags)); -+ else -+ vkd3d_free(flags); -+} -+ - int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out) - { - struct dxbc_writer dxbc; -@@ -5908,6 +5948,7 @@ int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun - write_sm4_signature(ctx, &dxbc, true); - write_sm4_rdef(ctx, &dxbc); - write_sm4_shdr(ctx, entry_func, &dxbc); -+ write_sm4_sfi0(ctx, &dxbc); - - if (!(ret = ctx->result)) - ret = dxbc_writer_write(&dxbc, out); -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 0f45b68fc38..17c7ccb3e31 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -3733,14 +3733,6 @@ static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device7 * - 1, &src_descriptor_range_offset, &descriptor_count, descriptor_heap_type); - } - --static void d3d12_resource_desc1_from_desc(D3D12_RESOURCE_DESC1 *desc1, const D3D12_RESOURCE_DESC *desc) --{ -- memcpy(desc1, desc, sizeof(*desc)); -- desc1->SamplerFeedbackMipRegion.Width = 0; -- desc1->SamplerFeedbackMipRegion.Height = 0; -- desc1->SamplerFeedbackMipRegion.Depth = 0; --} -- - static void d3d12_resource_allocation_info1_from_vkd3d(D3D12_RESOURCE_ALLOCATION_INFO1 *result, - const struct vkd3d_resource_allocation_info *info) - { -diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c -index fc05fce14f3..89764d0901d 100644 ---- a/libs/vkd3d/libs/vkd3d/resource.c -+++ b/libs/vkd3d/libs/vkd3d/resource.c -@@ -2277,8 +2277,8 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, - object->ID3D12Resource2_iface.lpVtbl = &d3d12_resource_vtbl; - object->refcount = 1; - object->internal_refcount = 1; -- object->desc = create_info->desc; -- object->format = vkd3d_format_from_d3d12_resource_desc(d3d12_device, &create_info->desc, 0); -+ d3d12_resource_desc1_from_desc(&object->desc, &create_info->desc); -+ object->format = vkd3d_format_from_d3d12_resource_desc(d3d12_device, &object->desc, 0); - object->u.vk_image = create_info->vk_image; - object->flags = VKD3D_RESOURCE_EXTERNAL; - object->flags |= create_info->flags & VKD3D_RESOURCE_PUBLIC_FLAGS; -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index ed331ccbcc5..b092bb26ded 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -@@ -769,6 +769,14 @@ HRESULT d3d12_reserved_resource_create(struct d3d12_device *device, - const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource); - struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface); - -+static inline void d3d12_resource_desc1_from_desc(D3D12_RESOURCE_DESC1 *desc1, const D3D12_RESOURCE_DESC *desc) -+{ -+ memcpy(desc1, desc, sizeof(*desc)); -+ desc1->SamplerFeedbackMipRegion.Width = 0; -+ desc1->SamplerFeedbackMipRegion.Height = 0; -+ desc1->SamplerFeedbackMipRegion.Depth = 0; -+} -+ - HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_buffer, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, - VkDeviceMemory *vk_memory, uint32_t *vk_memory_type, VkDeviceSize *vk_memory_size); --- -2.43.0 -