[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