From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/fx.c | 148 +++++++++++++++++++++++++- tests/hlsl/technique-fx_5.shader_test | 12 +-- 2 files changed, 151 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index ca6bb7a83..97ea924c0 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -25,10 +25,47 @@ struct fx_write_context struct vkd3d_bytecode_buffer unstructured; struct vkd3d_bytecode_buffer structured;
+ unsigned int min_technique_version; + unsigned int max_technique_version; + uint32_t technique_count; + uint32_t group_count; int status; };
+static void fx_write_context_init(const struct hlsl_ctx *ctx, struct fx_write_context *fx) +{ + unsigned int version = ctx->profile->major_version; + + memset(fx, 0, sizeof(*fx)); + + if (version == 2) + { + fx->min_technique_version = 9; + fx->max_technique_version = 9; + } + else if (version == 4) + { + fx->min_technique_version = 10; + fx->max_technique_version = 10; + } + else if (version == 5) + { + fx->min_technique_version = 10; + fx->max_technique_version = 11; + } +} + +static bool technique_matches_version(const struct hlsl_ir_var *var, const struct fx_write_context *fx) +{ + const struct hlsl_type *type = var->data_type; + + if (type->base_type != HLSL_TYPE_TECHNIQUE) + return false; + + return type->e.version >= fx->min_technique_version && type->e.version <= fx->max_technique_version; +} + static uint32_t fx_put_raw_string(struct fx_write_context *fx, const char *string) { /* NULLs are emitted as empty strings using the same 4 bytes at the start of the section. */ @@ -94,13 +131,55 @@ static void write_techniques(struct hlsl_scope *scope, struct fx_write_context * set_status(fx, fx->structured.status); }
+static void write_group(struct hlsl_scope *scope, const char *name, struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->structured; + uint32_t name_offset = fx_put_raw_string(fx, name); + uint32_t count_offset, count; + + put_u32(buffer, name_offset); + count_offset = put_u32(buffer, 0); /* Technique count */ + put_u32(buffer, 0); /* Annotation count */ + + count = fx->technique_count; + write_techniques(scope, fx); + set_u32(buffer, count_offset, fx->technique_count - count); + + ++fx->group_count; +} + +static void write_groups(struct hlsl_scope *scope, struct fx_write_context *fx) +{ + bool needs_default_group = false; + struct hlsl_ir_var *var; + + LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) + { + if (technique_matches_version(var, fx)) + { + needs_default_group = true; + break; + } + } + + if (needs_default_group) + write_group(scope, NULL, fx); + LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) + { + const struct hlsl_type *type = var->data_type; + + if (type->base_type == HLSL_TYPE_EFFECT_GROUP) + write_group(var->scope, var->name, fx); + } +} + static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) { struct vkd3d_bytecode_buffer buffer = { 0 }; struct fx_write_context fx; uint32_t size_offset, size;
- memset(&fx, 0, sizeof(fx)); + fx_write_context_init(ctx, &fx);
put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
@@ -154,6 +233,70 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) return fx.status; }
+static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) +{ + struct vkd3d_bytecode_buffer buffer = { 0 }; + struct fx_write_context fx; + uint32_t size_offset, size; + + fx_write_context_init(ctx, &fx); + + put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ + + /* TODO: buffers */ + /* TODO: objects */ + /* TODO: interface variables */ + + write_groups(ctx->globals, &fx); + + put_u32(&buffer, 0xfeff2001); /* Version. */ + put_u32(&buffer, 0); /* Buffer count. */ + put_u32(&buffer, 0); /* Variable count. */ + put_u32(&buffer, 0); /* Object count. */ + put_u32(&buffer, 0); /* Pool buffer count. */ + put_u32(&buffer, 0); /* Pool variable count. */ + put_u32(&buffer, 0); /* Pool object count. */ + put_u32(&buffer, fx.technique_count); + size_offset = put_u32(&buffer, 0); /* Unstructured size. */ + put_u32(&buffer, 0); /* String count. */ + put_u32(&buffer, 0); /* Texture object count. */ + put_u32(&buffer, 0); /* Depth stencil state count. */ + put_u32(&buffer, 0); /* Blend state count. */ + put_u32(&buffer, 0); /* Rasterizer state count. */ + put_u32(&buffer, 0); /* Sampler state count. */ + put_u32(&buffer, 0); /* Rendertarget view count. */ + put_u32(&buffer, 0); /* Depth stencil view count. */ + put_u32(&buffer, 0); /* Shader count. */ + put_u32(&buffer, 0); /* Inline shader count. */ + put_u32(&buffer, fx.group_count); /* Group count. */ + put_u32(&buffer, 0); /* UAV count. */ + put_u32(&buffer, 0); /* Interface variables count. */ + put_u32(&buffer, 0); /* Interface variable element count. */ + put_u32(&buffer, 0); /* Class instance elements count. */ + + size = align(fx.unstructured.size, 4); + set_u32(&buffer, size_offset, size); + + bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); + bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); + + vkd3d_free(fx.unstructured.data); + vkd3d_free(fx.structured.data); + + set_status(&fx, buffer.status); + + if (!fx.status) + { + out->code = buffer.data; + out->size = buffer.size; + } + + if (fx.status < 0) + ctx->result = fx.status; + + return fx.status; +} + int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) { if (ctx->profile->major_version == 2) @@ -167,8 +310,7 @@ int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) } else if (ctx->profile->major_version == 5) { - hlsl_fixme(ctx, &ctx->location, "Writing fx_5_0 binaries is not implemented."); - return VKD3D_ERROR_NOT_IMPLEMENTED; + return hlsl_fx_5_write(ctx, out); } else { diff --git a/tests/hlsl/technique-fx_5.shader_test b/tests/hlsl/technique-fx_5.shader_test index 0ef88cd0e..c1e37ff17 100644 --- a/tests/hlsl/technique-fx_5.shader_test +++ b/tests/hlsl/technique-fx_5.shader_test @@ -37,7 +37,7 @@ float4 main() : sv_target return fxGroup; }
-[effect todo] +[effect] technique { } @@ -47,11 +47,11 @@ technique10 }
% Effects without techniques are allowed for fx_5_0 -[effect todo] +[effect] float4 f;
% fx_2_0 keyword is allowed with fx_5_0 profiles -[effect todo] +[effect] technique { } @@ -90,10 +90,10 @@ float4 technique10; [effect fail] float4 technique11;
-[effect todo] +[effect] float4 technIque10;
-[effect todo] +[effect] float4 technIque11;
% Regular shaders with technique blocks @@ -174,7 +174,7 @@ fxgroup group }
% Group provides scope for techniques -[effect todo] +[effect] fxgroup group1 { technique11 tech0 {}