[PATCH vkd3d 5/6] vkd3d-shader: Write the SM1 constant table.

Zebediah Figura zfigura at codeweavers.com
Wed Apr 14 00:03:15 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 Makefile.am                      |   1 +
 include/vkd3d_d3d9types.h        |   6 +
 include/vkd3d_d3dx9shader.h      |  82 ++++++++++
 libs/vkd3d-shader/hlsl.h         |   7 +-
 libs/vkd3d-shader/hlsl.y         |   1 +
 libs/vkd3d-shader/hlsl_codegen.c | 251 ++++++++++++++++++++++++++++++-
 6 files changed, 346 insertions(+), 2 deletions(-)
 create mode 100644 include/vkd3d_d3dx9shader.h

diff --git a/Makefile.am b/Makefile.am
index 2ab2233a..2341ffe1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,6 +22,7 @@ vkd3d_public_headers = \
 	include/vkd3d_d3d9types.h \
 	include/vkd3d_d3dcommon.h \
 	include/vkd3d_d3dcompiler.h \
+	include/vkd3d_d3dx9shader.h \
 	include/vkd3d_dxgibase.h \
 	include/vkd3d_dxgiformat.h \
 	include/vkd3d_shader.h \
diff --git a/include/vkd3d_d3d9types.h b/include/vkd3d_d3d9types.h
index 11d2e2fc..22fb7880 100644
--- a/include/vkd3d_d3d9types.h
+++ b/include/vkd3d_d3d9types.h
@@ -21,6 +21,12 @@
 #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 D3DPS_VERSION(major, minor) (0xffff0000 | ((major) << 8) | (minor))
 #define D3DVS_VERSION(major, minor) (0xfffe0000 | ((major) << 8) | (minor))
 
diff --git a/include/vkd3d_d3dx9shader.h b/include/vkd3d_d3dx9shader.h
new file mode 100644
index 00000000..ba69efbd
--- /dev/null
+++ b/include/vkd3d_d3dx9shader.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2008 Luis Busquets
+ *
+ * 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_D3DX9SHADER_H
+#define __VKD3D_D3DX9SHADER_H
+#ifndef __D3DX9SHADER_H__
+
+#include <vkd3d_d3d9types.h>
+
+typedef enum _D3DXREGISTER_SET
+{
+    D3DXRS_BOOL,
+    D3DXRS_INT4,
+    D3DXRS_FLOAT4,
+    D3DXRS_SAMPLER,
+    D3DXRS_FORCE_DWORD = 0x7fffffff,
+} D3DXREGISTER_SET;
+
+typedef enum D3DXPARAMETER_CLASS
+{
+    D3DXPC_SCALAR,
+    D3DXPC_VECTOR,
+    D3DXPC_MATRIX_ROWS,
+    D3DXPC_MATRIX_COLUMNS,
+    D3DXPC_OBJECT,
+    D3DXPC_STRUCT,
+    D3DXPC_FORCE_DWORD = 0x7fffffff,
+} D3DXPARAMETER_CLASS;
+
+typedef enum D3DXPARAMETER_TYPE
+{
+    D3DXPT_VOID,
+    D3DXPT_BOOL,
+    D3DXPT_INT,
+    D3DXPT_FLOAT,
+    D3DXPT_STRING,
+    D3DXPT_TEXTURE,
+    D3DXPT_TEXTURE1D,
+    D3DXPT_TEXTURE2D,
+    D3DXPT_TEXTURE3D,
+    D3DXPT_TEXTURECUBE,
+    D3DXPT_SAMPLER,
+    D3DXPT_SAMPLER1D,
+    D3DXPT_SAMPLER2D,
+    D3DXPT_SAMPLER3D,
+    D3DXPT_SAMPLERCUBE,
+    D3DXPT_PIXELSHADER,
+    D3DXPT_VERTEXSHADER,
+    D3DXPT_PIXELFRAGMENT,
+    D3DXPT_VERTEXFRAGMENT,
+    D3DXPT_UNSUPPORTED,
+    D3DXPT_FORCE_DWORD = 0x7fffffff,
+} D3DXPARAMETER_TYPE;
+
+typedef struct _D3DXSHADER_CONSTANTTABLE
+{
+    DWORD Size;
+    DWORD Creator;
+    DWORD Version;
+    DWORD Constants;
+    DWORD ConstantInfo;
+    DWORD Flags;
+    DWORD Target;
+} D3DXSHADER_CONSTANTTABLE;
+
+#endif  /* __D3DX9SHADER_H__ */
+#endif  /* __VKD3D_D3DX9SHADER_H */
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index 3a0bf38d..3dc7a26b 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -115,7 +115,6 @@ struct hlsl_type
     unsigned int modifiers;
     unsigned int dimx;
     unsigned int dimy;
-    unsigned int reg_size;
     union
     {
         struct list *elements;
@@ -125,6 +124,9 @@ struct hlsl_type
             unsigned int elements_count;
         } array;
     } e;
+
+    unsigned int reg_size;
+    unsigned int bytecode_offset;
 };
 
 struct hlsl_struct_field
@@ -134,7 +136,9 @@ struct hlsl_struct_field
     struct hlsl_type *type;
     const char *name;
     const char *semantic;
+
     unsigned int reg_offset;
+    unsigned int name_offset;
 };
 
 struct hlsl_reg
@@ -221,6 +225,7 @@ struct hlsl_ir_var
     uint32_t is_input_varying : 1;
     uint32_t is_output_varying : 1;
     uint32_t is_uniform : 1;
+    uint32_t is_param : 1;
 };
 
 struct hlsl_ir_function
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 6216b100..8cd80533 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -765,6 +765,7 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct list *list,
 
     if (!(var = hlsl_new_var(param->name, param->type, loc, param->semantic, param->reg_reservation)))
         return false;
+    var->is_param = 1;
 
     if (param->type->type != HLSL_CLASS_OBJECT)
     {
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index e168f3d1..d04dc649 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -20,7 +20,7 @@
 
 #include "hlsl.h"
 #include <stdio.h>
-#include "vkd3d_d3d9types.h"
+#include "vkd3d_d3dx9shader.h"
 
 /* Split uniforms into two variables representing the constant and temp
  * registers, and copy the former to the latter, so that writes to uniforms
@@ -44,6 +44,7 @@ static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct list *instrs, stru
     list_add_tail(&ctx->extern_vars, &uniform->extern_entry);
     temp->is_uniform = 0;
     uniform->is_uniform = 1;
+    uniform->is_param = temp->is_param;
 
     if (!(name = vkd3d_string_buffer_get(&ctx->string_buffers)))
     {
@@ -92,6 +93,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct
     }
     vkd3d_string_buffer_release(&ctx->string_buffers, name);
     varying->is_input_varying = 1;
+    varying->is_param = var->is_param;
     list_add_before(&var->scope_entry, &varying->scope_entry);
     list_add_tail(&ctx->extern_vars, &varying->extern_entry);
 
@@ -170,6 +172,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct
     }
     vkd3d_string_buffer_release(&ctx->string_buffers, name);
     varying->is_output_varying = 1;
+    varying->is_param = var->is_param;
     list_add_before(&var->scope_entry, &varying->scope_entry);
     list_add_tail(&ctx->extern_vars, &varying->extern_entry);
 
@@ -896,6 +899,33 @@ static void put_dword(struct bytecode_buffer *buffer, DWORD value)
     buffer->data[buffer->count++] = value;
 }
 
+static void set_dword(struct bytecode_buffer *buffer, unsigned int index, uint32_t value)
+{
+    if (buffer->status)
+        return;
+
+    assert(index < buffer->count);
+    buffer->data[index] = value;
+}
+
+static void put_string(struct bytecode_buffer *buffer, const char *str)
+{
+    unsigned int len = (strlen(str) + 1 + 3) / sizeof(DWORD);
+
+    if (buffer->status)
+        return;
+
+    if (!vkd3d_array_reserve((void **)&buffer->data, &buffer->size, buffer->count + len, sizeof(*buffer->data)))
+    {
+        buffer->status = E_OUTOFMEMORY;
+        return;
+    }
+
+    buffer->data[buffer->count + len - 1] = 0xabababab;
+    strcpy((char *)(buffer->data + buffer->count), str);
+    buffer->count += len;
+}
+
 static DWORD sm1_version(enum vkd3d_shader_type type, unsigned int major, unsigned int minor)
 {
     if (type == VKD3D_SHADER_TYPE_VERTEX)
@@ -904,6 +934,223 @@ static DWORD sm1_version(enum vkd3d_shader_type type, unsigned int major, unsign
         return D3DPS_VERSION(major, minor);
 }
 
+static D3DXPARAMETER_CLASS sm1_class(const struct hlsl_type *type)
+{
+    switch (type->type)
+    {
+        case HLSL_CLASS_ARRAY:
+            return sm1_class(type->e.array.type);
+        case HLSL_CLASS_MATRIX:
+            assert(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
+            if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR)
+                return D3DXPC_MATRIX_COLUMNS;
+            else
+                return D3DXPC_MATRIX_ROWS;
+        case HLSL_CLASS_OBJECT:
+            return D3DXPC_OBJECT;
+        case HLSL_CLASS_SCALAR:
+            return D3DXPC_SCALAR;
+        case HLSL_CLASS_STRUCT:
+            return D3DXPC_STRUCT;
+        case HLSL_CLASS_VECTOR:
+            return D3DXPC_VECTOR;
+        default:
+            ERR("Invalid class %#x.\n", type->type);
+            assert(0);
+            return 0;
+    }
+}
+
+static D3DXPARAMETER_TYPE sm1_base_type(const struct hlsl_type *type)
+{
+    switch (type->base_type)
+    {
+        case HLSL_TYPE_BOOL:
+            return D3DXPT_BOOL;
+        case HLSL_TYPE_FLOAT:
+        case HLSL_TYPE_HALF:
+            return D3DXPT_FLOAT;
+        case HLSL_TYPE_INT:
+        case HLSL_TYPE_UINT:
+            return D3DXPT_INT;
+        case HLSL_TYPE_PIXELSHADER:
+            return D3DXPT_PIXELSHADER;
+        case HLSL_TYPE_SAMPLER:
+            switch (type->sampler_dim)
+            {
+                case HLSL_SAMPLER_DIM_1D:
+                    return D3DXPT_SAMPLER1D;
+                case HLSL_SAMPLER_DIM_2D:
+                    return D3DXPT_SAMPLER2D;
+                case HLSL_SAMPLER_DIM_3D:
+                    return D3DXPT_SAMPLER3D;
+                case HLSL_SAMPLER_DIM_CUBE:
+                    return D3DXPT_SAMPLERCUBE;
+                case HLSL_SAMPLER_DIM_GENERIC:
+                    return D3DXPT_SAMPLER;
+                default:
+                    ERR("Invalid dimension %#x.\n", type->sampler_dim);
+            }
+            break;
+        case HLSL_TYPE_STRING:
+            return D3DXPT_STRING;
+        case HLSL_TYPE_TEXTURE:
+            switch (type->sampler_dim)
+            {
+                case HLSL_SAMPLER_DIM_1D:
+                    return D3DXPT_TEXTURE1D;
+                case HLSL_SAMPLER_DIM_2D:
+                    return D3DXPT_TEXTURE2D;
+                case HLSL_SAMPLER_DIM_3D:
+                    return D3DXPT_TEXTURE3D;
+                case HLSL_SAMPLER_DIM_CUBE:
+                    return D3DXPT_TEXTURECUBE;
+                case HLSL_SAMPLER_DIM_GENERIC:
+                    return D3DXPT_TEXTURE;
+                default:
+                    ERR("Invalid dimension %#x.\n", type->sampler_dim);
+            }
+            break;
+        case HLSL_TYPE_VERTEXSHADER:
+            return D3DXPT_VERTEXSHADER;
+        case HLSL_TYPE_VOID:
+            return D3DXPT_VOID;
+        default:
+            assert(0);
+    }
+    assert(0);
+    return 0;
+}
+
+static const struct hlsl_type *get_array_type(const struct hlsl_type *type)
+{
+    if (type->type == HLSL_CLASS_ARRAY)
+        return get_array_type(type->e.array.type);
+    return type;
+}
+
+static unsigned int get_array_size(const struct hlsl_type *type)
+{
+    if (type->type == HLSL_CLASS_ARRAY)
+        return get_array_size(type->e.array.type) * type->e.array.elements_count;
+    return 1;
+}
+
+static void write_sm1_type(struct bytecode_buffer *buffer, struct hlsl_type *type, unsigned int ctab_start)
+{
+    const struct hlsl_type *array_type = get_array_type(type);
+    unsigned int fields_offset = 0, field_count = 0;
+    unsigned int array_size = get_array_size(type);
+    struct hlsl_struct_field *field;
+
+    if (type->bytecode_offset)
+        return;
+
+    if (array_type->type == HLSL_CLASS_STRUCT)
+    {
+        LIST_FOR_EACH_ENTRY(field, array_type->e.elements, struct hlsl_struct_field, entry)
+        {
+            field->name_offset = buffer->count;
+            put_string(buffer, field->name);
+            write_sm1_type(buffer, field->type, ctab_start);
+        }
+
+        fields_offset = (buffer->count - ctab_start) * sizeof(DWORD);
+
+        LIST_FOR_EACH_ENTRY(field, array_type->e.elements, struct hlsl_struct_field, entry)
+        {
+            put_dword(buffer, (field->name_offset - ctab_start) * sizeof(DWORD));
+            put_dword(buffer, (field->type->bytecode_offset - ctab_start) * sizeof(DWORD));
+            ++field_count;
+        }
+    }
+
+    type->bytecode_offset = buffer->count;
+    put_dword(buffer, sm1_class(type) | (sm1_base_type(type) << 16));
+    put_dword(buffer, type->dimy | (type->dimx << 16));
+    put_dword(buffer, array_size | (field_count << 16));
+    put_dword(buffer, fields_offset);
+}
+
+static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer,
+        struct hlsl_ir_function_decl *entry_func)
+{
+    unsigned int ctab_start, vars_start;
+    unsigned int uniform_count = 0;
+    struct hlsl_ir_var *var;
+
+    LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
+    {
+        if (!var->semantic && var->reg.allocated)
+        {
+            ++uniform_count;
+
+            if (var->is_param && var->is_uniform)
+            {
+                char *name;
+
+                if (!(name = vkd3d_malloc(strlen(var->name) + 2)))
+                {
+                    buffer->status = VKD3D_ERROR_OUT_OF_MEMORY;
+                    return;
+                }
+                name[0] = '$';
+                strcpy(name + 1, var->name);
+                vkd3d_free((char *)var->name);
+                var->name = name;
+            }
+        }
+    }
+
+    put_dword(buffer, 0); /* COMMENT tag + size */
+    put_dword(buffer, MAKEFOURCC('C','T','A','B'));
+
+    ctab_start = buffer->count;
+
+    put_dword(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); /* size of this header */
+    put_dword(buffer, 0); /* creator */
+    put_dword(buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version));
+    put_dword(buffer, uniform_count);
+    put_dword(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); /* offset of constants */
+    put_dword(buffer, 0); /* FIXME: flags */
+    put_dword(buffer, 0); /* FIXME: target string */
+
+    vars_start = buffer->count;
+
+    LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
+    {
+        if (!var->semantic && var->reg.allocated)
+        {
+            put_dword(buffer, 0); /* name */
+            put_dword(buffer, D3DXRS_FLOAT4 | (var->reg.id << 16));
+            put_dword(buffer, var->data_type->reg_size);
+            put_dword(buffer, 0); /* type */
+            put_dword(buffer, 0); /* FIXME: default value */
+        }
+    }
+
+    uniform_count = 0;
+
+    LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
+    {
+        if (!var->semantic && var->reg.allocated)
+        {
+            set_dword(buffer, vars_start + (uniform_count * 5), (buffer->count - ctab_start) * sizeof(DWORD));
+            put_string(buffer, var->name);
+
+            write_sm1_type(buffer, var->data_type, ctab_start);
+            set_dword(buffer, vars_start + (uniform_count * 5) + 3,
+                    (var->data_type->bytecode_offset - ctab_start) * sizeof(DWORD));
+            ++uniform_count;
+        }
+    }
+
+    set_dword(buffer, ctab_start + 1, (buffer->count - ctab_start) * sizeof(DWORD));
+    put_string(buffer, "vkd3d HLSL shader compiler");
+
+    set_dword(buffer, ctab_start - 2, D3DSIO_COMMENT | ((buffer->count - (ctab_start - 1)) << 16));
+}
+
 static int write_sm1_shader(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
         struct vkd3d_shader_code *out)
 {
@@ -912,6 +1159,8 @@ static int write_sm1_shader(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *
 
     put_dword(&buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version));
 
+    write_sm1_uniforms(ctx, &buffer, entry_func);
+
     put_dword(&buffer, D3DSIO_END);
 
     if (!(ret = buffer.status))
-- 
2.31.1




More information about the wine-devel mailing list