Module: vkd3d
Branch: master
Commit: 3a1c32acd42be20d012bf85a8cdc6f22bd651dfb
URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/3a1c32acd42be20d012bf85a8cdc6…
Author: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Date: Fri Mar 1 11:46:51 2024 +0100
vkd3d-shader: Treat the HLSL case specially in vkd3d_shader_scan().
The other cases are similar and common code can be refactored.
Ideally the HLSL parser will eventually fit the same model, but that
will require more extensive work.
---
libs/vkd3d-shader/vkd3d_shader_main.c | 41 +++++++++++++++++++----------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index 85bdb463..81012216 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -1555,29 +1555,32 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
vkd3d_shader_dump_shader(compile_info);
- switch (compile_info->source_type)
+ if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL)
{
- case VKD3D_SHADER_SOURCE_DXBC_TPF:
- ret = scan_dxbc(compile_info, &message_context);
- break;
-
- case VKD3D_SHADER_SOURCE_HLSL:
- FIXME("HLSL support not implemented.\n");
- ret = VKD3D_ERROR_NOT_IMPLEMENTED;
- break;
+ FIXME("HLSL support not implemented.\n");
+ ret = VKD3D_ERROR_NOT_IMPLEMENTED;
+ }
+ else
+ {
+ switch (compile_info->source_type)
+ {
+ case VKD3D_SHADER_SOURCE_DXBC_TPF:
+ ret = scan_dxbc(compile_info, &message_context);
+ break;
- case VKD3D_SHADER_SOURCE_D3D_BYTECODE:
- ret = scan_d3dbc(compile_info, &message_context);
- break;
+ case VKD3D_SHADER_SOURCE_D3D_BYTECODE:
+ ret = scan_d3dbc(compile_info, &message_context);
+ break;
- case VKD3D_SHADER_SOURCE_DXBC_DXIL:
- ret = scan_dxil(compile_info, &message_context);
- break;
+ case VKD3D_SHADER_SOURCE_DXBC_DXIL:
+ ret = scan_dxil(compile_info, &message_context);
+ break;
- default:
- ERR("Unsupported source type %#x.\n", compile_info->source_type);
- ret = VKD3D_ERROR_INVALID_ARGUMENT;
- break;
+ default:
+ ERR("Unsupported source type %#x.\n", compile_info->source_type);
+ ret = VKD3D_ERROR_INVALID_ARGUMENT;
+ break;
+ }
}
vkd3d_shader_message_context_trace_messages(&message_context);
Module: vkd3d
Branch: master
Commit: b940d79aa8a0783a48bf28d566cce5c4e6259f08
URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/b940d79aa8a0783a48bf28d566cce…
Author: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Date: Fri Feb 2 23:35:21 2024 +0100
vkd3d-shader/ir: Keep loops contiguous in the topological sort.
---
libs/vkd3d-shader/ir.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 88 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c
index 894324c5..3c862f33 100644
--- a/libs/vkd3d-shader/ir.c
+++ b/libs/vkd3d-shader/ir.c
@@ -3121,6 +3121,11 @@ static void vsir_block_list_sort(struct vsir_block_list *list)
qsort(list->blocks, list->count, sizeof(*list->blocks), block_compare);
}
+static bool vsir_block_list_search(struct vsir_block_list *list, struct vsir_block *block)
+{
+ return !!bsearch(&block, list->blocks, list->count, sizeof(*list->blocks), block_compare);
+}
+
struct vsir_cfg
{
struct vkd3d_shader_message_context *message_context;
@@ -3487,16 +3492,37 @@ static enum vkd3d_result vsir_cfg_compute_loops(struct vsir_cfg *cfg)
struct vsir_cfg_node_sorter
{
struct vsir_cfg *cfg;
+ struct vsir_cfg_node_sorter_stack_item
+ {
+ struct vsir_block_list *loop;
+ unsigned int seen_count;
+ } *stack;
+ size_t stack_count, stack_capacity;
struct vsir_block_list available_blocks;
};
static enum vkd3d_result vsir_cfg_node_sorter_make_node_available(struct vsir_cfg_node_sorter *sorter, struct vsir_block *block)
{
+ struct vsir_block_list *loop = NULL;
+ struct vsir_cfg_node_sorter_stack_item *item;
enum vkd3d_result ret;
+ if (sorter->cfg->loops_by_header[block->label - 1] != SIZE_MAX)
+ loop = &sorter->cfg->loops[sorter->cfg->loops_by_header[block->label - 1]];
+
if ((ret = vsir_block_list_add_checked(&sorter->available_blocks, block)) < 0)
return ret;
+ if (!loop)
+ return VKD3D_OK;
+
+ if (!vkd3d_array_reserve((void **)&sorter->stack, &sorter->stack_capacity, sorter->stack_count + 1, sizeof(*sorter->stack)))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ item = &sorter->stack[sorter->stack_count++];
+ item->loop = loop;
+ item->seen_count = 0;
+
return VKD3D_OK;
}
@@ -3507,10 +3533,23 @@ static enum vkd3d_result vsir_cfg_node_sorter_make_node_available(struct vsir_cf
* available list of all the blocks whose incoming degree has reached
* zero. At each step we pick a block from the available list and
* strip it away from the graph, updating the incoming degrees and
- * available list. We prefer picking the most recently added block
- * (i.e., from the end of the available list) because it will keep
- * together related blocks in the order, which allow us to generate
- * fewer control flow primitives. */
+ * available list.
+ *
+ * In principle at each step we can pick whatever node we want from
+ * the available list, and will get a topological sort
+ * anyway. However, we use these two criteria to give to the computed
+ * order additional properties:
+ *
+ * 1. we keep track of which loops we're into, and pick blocks
+ * belonging to the current innermost loop, so that loops are kept
+ * contiguous in the order; this can always be done when the input
+ * CFG is reducible;
+ *
+ * 2. subject to the requirement above, we always pick the most
+ * recently added block to the available list, because this tends
+ * to keep related blocks and require fewer control flow
+ * primitives.
+ */
static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg)
{
struct vsir_cfg_node_sorter sorter = { .cfg = cfg };
@@ -3566,12 +3605,51 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg)
while (sorter.available_blocks.count != 0)
{
- struct vsir_block *block = sorter.available_blocks.blocks[sorter.available_blocks.count - 1];
+ struct vsir_cfg_node_sorter_stack_item *inner_stack_item = NULL;
+ struct vsir_block *block;
+ size_t new_seen_count;
+
+ if (sorter.stack_count != 0)
+ inner_stack_item = &sorter.stack[sorter.stack_count - 1];
+
+ for (i = sorter.available_blocks.count - 1; ; --i)
+ {
+ if (i == SIZE_MAX)
+ {
+ ERR("Couldn't find any viable next block, is the input CFG reducible?\n");
+ ret = VKD3D_ERROR_INVALID_SHADER;
+ goto fail;
+ }
+
+ block = sorter.available_blocks.blocks[i];
+
+ if (!inner_stack_item || vsir_block_list_search(inner_stack_item->loop, block))
+ break;
+ }
- vsir_block_list_remove_index(&sorter.available_blocks, sorter.available_blocks.count - 1);
+ vsir_block_list_remove_index(&sorter.available_blocks, i);
if ((ret = vsir_block_list_add_checked(&cfg->order, block)) < 0)
goto fail;
+ /* Close loops: since each loop is a strict subset of any
+ * outer loop, we just need to track how many blocks we've
+ * seen; when I close a loop I mark the same number of seen
+ * blocks for the next outer loop. */
+ new_seen_count = 1;
+ while (sorter.stack_count != 0)
+ {
+ inner_stack_item = &sorter.stack[sorter.stack_count - 1];
+
+ inner_stack_item->seen_count += new_seen_count;
+
+ assert(inner_stack_item->seen_count <= inner_stack_item->loop->count);
+ if (inner_stack_item->seen_count != inner_stack_item->loop->count)
+ break;
+
+ new_seen_count = inner_stack_item->loop->count;
+ --sorter.stack_count;
+ }
+
/* Remove (forward) edges and make new nodes available. */
for (i = 0; i < block->successors.count; ++i)
{
@@ -3601,7 +3679,10 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg)
goto fail;
}
+ assert(sorter.stack_count == 0);
+
vkd3d_free(in_degrees);
+ vkd3d_free(sorter.stack);
vsir_block_list_cleanup(&sorter.available_blocks);
if (TRACE_ON())
@@ -3619,6 +3700,7 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg)
fail:
vkd3d_free(in_degrees);
+ vkd3d_free(sorter.stack);
vsir_block_list_cleanup(&sorter.available_blocks);
return ret;