[PATCH vkd3d 2/6] vkd3d-shader/hlsl: Write empty SM4 shaders.

Zebediah Figura zfigura at codeweavers.com
Tue Aug 17 12:38:57 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 Makefile.am                              |  1 +
 libs/vkd3d-shader/dxbc.c                 | 75 +++++++++++++++++++-----
 libs/vkd3d-shader/hlsl.h                 |  2 +
 libs/vkd3d-shader/hlsl_codegen.c         |  2 +-
 libs/vkd3d-shader/hlsl_sm4.c             | 31 ++++++++++
 libs/vkd3d-shader/vkd3d_shader_private.h | 35 +++++++++++
 tests/d3d12_test_utils.h                 |  2 +-
 tests/shader_runner_d3d12.c              |  2 +
 8 files changed, 132 insertions(+), 18 deletions(-)
 create mode 100644 libs/vkd3d-shader/hlsl_sm4.c

diff --git a/Makefile.am b/Makefile.am
index 9624485b..5cdccc52 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -173,6 +173,7 @@ libvkd3d_shader_la_SOURCES = \
 	libs/vkd3d-shader/hlsl.h \
 	libs/vkd3d-shader/hlsl_codegen.c \
 	libs/vkd3d-shader/hlsl_sm1.c \
+	libs/vkd3d-shader/hlsl_sm4.c \
 	libs/vkd3d-shader/preproc.h \
 	libs/vkd3d-shader/sm4.h \
 	libs/vkd3d-shader/spirv.c \
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index 5dfe9295..83f91960 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008-2009 Henri Verbeet for CodeWeavers
+ * Copyright 2010 Rico Schüller
  * Copyright 2017 Józef Kucia for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
@@ -20,6 +21,64 @@
 #include "vkd3d_shader_private.h"
 #include "sm4.h"
 
+void dxbc_writer_init(struct dxbc_writer *dxbc)
+{
+    memset(dxbc, 0, sizeof(*dxbc));
+}
+
+void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void *data, size_t size)
+{
+    struct dxbc_writer_section *section;
+
+    assert(dxbc->section_count < ARRAY_SIZE(dxbc->sections));
+
+    section = &dxbc->sections[dxbc->section_count++];
+    section->tag = tag;
+    section->data = data;
+    section->size = size;
+}
+
+int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
+{
+    size_t size_position, offsets_position, checksum_position, i;
+    struct vkd3d_bytecode_buffer buffer = {0};
+    uint32_t checksum[4];
+
+    put_u32(&buffer, TAG_DXBC);
+
+    checksum_position = bytecode_get_size(&buffer);
+    for (i = 0; i < 4; ++i)
+        put_u32(&buffer, 0);
+
+    put_u32(&buffer, 1); /* version */
+    size_position = put_u32(&buffer, 0);
+    put_u32(&buffer, dxbc->section_count);
+
+    offsets_position = bytecode_get_size(&buffer);
+    for (i = 0; i < dxbc->section_count; ++i)
+        put_u32(&buffer, 0);
+
+    for (i = 0; i < dxbc->section_count; ++i)
+    {
+        set_u32(&buffer, offsets_position + i * sizeof(uint32_t), bytecode_get_size(&buffer));
+        put_u32(&buffer, dxbc->sections[i].tag);
+        put_u32(&buffer, dxbc->sections[i].size);
+        bytecode_put_bytes(&buffer, dxbc->sections[i].data, dxbc->sections[i].size);
+    }
+    set_u32(&buffer, size_position, bytecode_get_size(&buffer));
+
+    vkd3d_compute_dxbc_checksum(buffer.data, buffer.size, checksum);
+    for (i = 0; i < 4; ++i)
+        set_u32(&buffer, checksum_position + i * sizeof(uint32_t), checksum[i]);
+
+    if (!buffer.status)
+    {
+        out->code = buffer.data;
+        out->size = buffer.size;
+    }
+    return buffer.status;
+}
+
 struct vkd3d_shader_src_param_entry
 {
     struct list entry;
@@ -1592,22 +1651,6 @@ bool shader_sm4_is_end(void *data, const DWORD **ptr)
     return *ptr == priv->end;
 }
 
-#define MAKE_TAG(ch0, ch1, ch2, ch3) \
-    ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \
-    ((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 ))
-#define TAG_DXBC MAKE_TAG('D', 'X', 'B', 'C')
-#define TAG_ISGN MAKE_TAG('I', 'S', 'G', 'N')
-#define TAG_ISG1 MAKE_TAG('I', 'S', 'G', '1')
-#define TAG_OSGN MAKE_TAG('O', 'S', 'G', 'N')
-#define TAG_OSG5 MAKE_TAG('O', 'S', 'G', '5')
-#define TAG_OSG1 MAKE_TAG('O', 'S', 'G', '1')
-#define TAG_PCSG MAKE_TAG('P', 'C', 'S', 'G')
-#define TAG_PSG1 MAKE_TAG('P', 'S', 'G', '1')
-#define TAG_SHDR MAKE_TAG('S', 'H', 'D', 'R')
-#define TAG_SHEX MAKE_TAG('S', 'H', 'E', 'X')
-#define TAG_AON9 MAKE_TAG('A', 'o', 'n', '9')
-#define TAG_RTS0 MAKE_TAG('R', 'T', 'S', '0')
-
 static bool require_space(size_t offset, size_t count, size_t size, size_t data_size)
 {
     return !count || (data_size - offset) / count >= size;
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index da309a6b..41c16b07 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -683,6 +683,8 @@ bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem
 bool hlsl_sm1_usage_from_semantic(const struct hlsl_semantic *semantic, D3DDECLUSAGE *usage, uint32_t *usage_idx);
 int hlsl_sm1_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
 
+int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
+
 int hlsl_lexer_compile(struct hlsl_ctx *ctx, const struct vkd3d_shader_code *hlsl);
 
 #endif
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index db340a78..b5f7832f 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -1272,5 +1272,5 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun
     if (ctx->profile->major_version < 4)
         return hlsl_sm1_write(ctx, entry_func, out);
     else
-        return VKD3D_ERROR_NOT_IMPLEMENTED;
+        return hlsl_sm4_write(ctx, entry_func, out);
 }
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
new file mode 100644
index 00000000..977b8395
--- /dev/null
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -0,0 +1,31 @@
+/*
+ * HLSL code generation for DXBC shader models 4-5
+ *
+ * Copyright 2019-2020 Zebediah Figura 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"
+#include <stdio.h>
+
+int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out)
+{
+    struct dxbc_writer dxbc;
+
+    dxbc_writer_init(&dxbc);
+
+    return dxbc_writer_write(&dxbc, out);
+}
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index 85503800..9320c517 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -1135,4 +1135,39 @@ static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
 #define VKD3D_DXBC_MAX_SOURCE_COUNT 6
 #define VKD3D_DXBC_HEADER_SIZE (8 * sizeof(uint32_t))
 
+#define MAKE_TAG(ch0, ch1, ch2, ch3) \
+    ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \
+    ((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 ))
+#define TAG_AON9 MAKE_TAG('A', 'o', 'n', '9')
+#define TAG_DXBC MAKE_TAG('D', 'X', 'B', 'C')
+#define TAG_ISG1 MAKE_TAG('I', 'S', 'G', '1')
+#define TAG_ISGN MAKE_TAG('I', 'S', 'G', 'N')
+#define TAG_OSG1 MAKE_TAG('O', 'S', 'G', '1')
+#define TAG_OSG5 MAKE_TAG('O', 'S', 'G', '5')
+#define TAG_OSGN MAKE_TAG('O', 'S', 'G', 'N')
+#define TAG_PCSG MAKE_TAG('P', 'C', 'S', 'G')
+#define TAG_PSG1 MAKE_TAG('P', 'S', 'G', '1')
+#define TAG_RTS0 MAKE_TAG('R', 'T', 'S', '0')
+#define TAG_SHDR MAKE_TAG('S', 'H', 'D', 'R')
+#define TAG_SHEX MAKE_TAG('S', 'H', 'E', 'X')
+
+struct dxbc_writer_section
+{
+    uint32_t tag;
+    const uint8_t *data;
+    size_t size;
+};
+
+#define DXBC_MAX_SECTION_COUNT 5
+
+struct dxbc_writer
+{
+    unsigned int section_count;
+    struct dxbc_writer_section sections[DXBC_MAX_SECTION_COUNT];
+};
+
+void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void *data, size_t size);
+void dxbc_writer_init(struct dxbc_writer *dxbc);
+int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *code);
+
 #endif  /* __VKD3D_SHADER_PRIVATE_H */
diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h
index 5fe6f1ef..0374d8d1 100644
--- a/tests/d3d12_test_utils.h
+++ b/tests/d3d12_test_utils.h
@@ -844,7 +844,7 @@ static ID3D12PipelineState *create_pipeline_state_(unsigned int line, ID3D12Devi
             &IID_ID3D12PipelineState, (void **)&pipeline_state);
     ok_(line)(SUCCEEDED(hr), "Failed to create graphics pipeline state, hr %#x.\n", hr);
 
-    return pipeline_state;
+    return SUCCEEDED(hr) ? pipeline_state : NULL;
 }
 
 struct test_context_desc
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index 353e42c7..3cc859ab 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -141,6 +141,8 @@ static void parse_test_directive(struct shader_context *context, const char *lin
 
         pso = create_pipeline_state(context->c.device, context->c.root_signature,
                 context->c.render_target_desc.Format, NULL, &ps, NULL);
+        if (!pso)
+            return;
 
         ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->c.root_signature);
         ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 0,
-- 
2.32.0




More information about the wine-devel mailing list