[PATCH vkd3d 4/8] vkd3d-shader/hlsl: Write SM4 constant buffer declarations.
Zebediah Figura
zfigura at codeweavers.com
Thu Aug 19 18:44:28 CDT 2021
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
libs/vkd3d-shader/hlsl_sm4.c | 116 +++++++++++++++++++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index 894c513f..029dc3de 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -549,10 +549,120 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
dxbc_writer_add_section(dxbc, TAG_RDEF, buffer.data, buffer.size);
}
+struct sm4_register
+{
+ enum vkd3d_sm4_register_type type;
+ uint32_t idx[2];
+ unsigned int idx_count;
+ enum vkd3d_sm4_dimension dim;
+};
+
+struct sm4_instruction
+{
+ enum vkd3d_sm4_opcode opcode;
+
+ struct
+ {
+ struct sm4_register reg;
+ unsigned int writemask;
+ } dst;
+
+ struct
+ {
+ struct sm4_register reg;
+ unsigned int swizzle;
+ } srcs[2];
+ unsigned int src_count;
+
+ unsigned int has_dst;
+};
+
+static unsigned int sm4_swizzle_type(enum vkd3d_sm4_register_type type)
+{
+ switch (type)
+ {
+ case VKD3D_SM4_RT_CONSTBUFFER:
+ return VKD3D_SM4_SWIZZLE_VEC4;
+
+ default:
+ FIXME("Unhandled register type %#x.\n", type);
+ return VKD3D_SM4_SWIZZLE_VEC4;
+ }
+}
+
+static uint32_t sm4_encode_register(const struct sm4_register *reg)
+{
+ return (reg->type << VKD3D_SM4_REGISTER_TYPE_SHIFT)
+ | (reg->idx_count << VKD3D_SM4_REGISTER_ORDER_SHIFT)
+ | (reg->dim << VKD3D_SM4_DIMENSION_SHIFT);
+}
+
+static uint32_t sm4_register_order(const struct sm4_register *reg)
+{
+ uint32_t order = 1;
+ if (reg->type == VKD3D_SM4_RT_IMMCONST)
+ order += reg->dim == VKD3D_SM4_DIMENSION_VEC4 ? 4 : 1;
+ order += reg->idx_count;
+ return order;
+}
+
+static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const struct sm4_instruction *instr)
+{
+ uint32_t token = instr->opcode;
+ unsigned int size = 1, i, j;
+
+ if (instr->has_dst)
+ size += sm4_register_order(&instr->dst.reg);
+ for (i = 0; i < instr->src_count; ++i)
+ size += sm4_register_order(&instr->srcs[i].reg);
+
+ token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT);
+ put_u32(buffer, token);
+
+ if (instr->has_dst)
+ {
+ token = sm4_encode_register(&instr->dst.reg);
+ if (instr->dst.reg.dim == VKD3D_SM4_DIMENSION_VEC4)
+ token |= instr->dst.writemask << VKD3D_SM4_WRITEMASK_SHIFT;
+ put_u32(buffer, token);
+
+ for (j = 0; j < instr->dst.reg.idx_count; ++j)
+ put_u32(buffer, instr->dst.reg.idx[j]);
+ }
+
+ for (i = 0; i < instr->src_count; ++i)
+ {
+ token = sm4_encode_register(&instr->srcs[i].reg);
+ token |= sm4_swizzle_type(instr->srcs[i].reg.type) << VKD3D_SM4_SWIZZLE_TYPE_SHIFT;
+ token |= instr->srcs[i].swizzle << VKD3D_SM4_SWIZZLE_SHIFT;
+ put_u32(buffer, token);
+
+ for (j = 0; j < instr->srcs[i].reg.idx_count; ++j)
+ put_u32(buffer, instr->srcs[i].reg.idx[j]);
+ }
+}
+
+static void write_sm4_dcl_constant_buffer(struct vkd3d_bytecode_buffer *buffer, const struct hlsl_buffer *cbuffer)
+{
+ const struct sm4_instruction instr =
+ {
+ .opcode = VKD3D_SM4_OP_DCL_CONSTANT_BUFFER,
+
+ .srcs[0].reg.dim = VKD3D_SM4_DIMENSION_VEC4,
+ .srcs[0].reg.type = VKD3D_SM4_RT_CONSTBUFFER,
+ .srcs[0].reg.idx = {cbuffer->reg.id, (cbuffer->used_size + 3) / 4},
+ .srcs[0].reg.idx_count = 2,
+ .srcs[0].swizzle = HLSL_SWIZZLE(X, Y, Z, W),
+ .src_count = 1,
+ };
+ write_sm4_instruction(buffer, &instr);
+}
+
static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
{
const struct hlsl_profile_info *profile = ctx->profile;
struct vkd3d_bytecode_buffer buffer = {0};
+ const struct hlsl_buffer *cbuffer;
static const uint16_t shader_types[VKD3D_SHADER_TYPE_COUNT] =
{
@@ -570,6 +680,12 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
put_u32(&buffer, vkd3d_make_u32((profile->major_version << 4) | profile->minor_version, shader_types[profile->type]));
put_u32(&buffer, 0); /* FIXME: instruction token count */
+ LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry)
+ {
+ if (cbuffer->reg.allocated)
+ write_sm4_dcl_constant_buffer(&buffer, cbuffer);
+ }
+
dxbc_writer_add_section(dxbc, TAG_SHDR, buffer.data, buffer.size);
}
--
2.32.0
More information about the wine-devel
mailing list