From 2f43965c2c7489b162f3ad61fae7b1771c6da18f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Thu, 11 Oct 2018 15:33:34 +0200 Subject: [PATCH] vkd3d-shader: Add OpenGL SPIR-V target environment. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More changes are needed for full support. Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- include/private/vkd3d_shader.h | 10 +++++ libs/vkd3d-shader/spirv.c | 63 +++++++++++++++++++-------- libs/vkd3d-shader/vkd3d_shader_main.c | 21 +++++++++ libs/vkd3d/state.c | 1 + 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/include/private/vkd3d_shader.h b/include/private/vkd3d_shader.h index 61789d63..121fa755 100644 --- a/include/private/vkd3d_shader.h +++ b/include/private/vkd3d_shader.h @@ -125,8 +125,18 @@ struct vkd3d_shader_interface unsigned int uav_counter_count; }; +enum vkd3d_shader_target +{ + VKD3D_SHADER_TARGET_NONE, + VKD3D_SHADER_TARGET_SPIRV_OPENGL_4_5, + VKD3D_SHADER_TARGET_SPIRV_VULKAN_1_0, /* default target */ + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET), +}; + struct vkd3d_shader_compile_arguments { + enum vkd3d_shader_target target; unsigned int *output_swizzles; unsigned int output_swizzle_count; }; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 7d4a3b30..644c0a71 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -36,7 +36,21 @@ #ifdef HAVE_SPIRV_TOOLS # include "spirv-tools/libspirv.h" -static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv) +static spv_target_env spv_target_env_from_vkd3d(enum vkd3d_shader_target target) +{ + switch (target) + { + case VKD3D_SHADER_TARGET_SPIRV_OPENGL_4_5: + return SPV_ENV_OPENGL_4_5; + case VKD3D_SHADER_TARGET_SPIRV_VULKAN_1_0: + return SPV_ENV_VULKAN_1_0; + default: + ERR("Invalid shader target %#x.\n", target); + return SPV_ENV_VULKAN_1_0; + } +} + +static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_shader_target target) { const static uint32_t options = SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT; @@ -45,7 +59,7 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv) spv_context context; spv_result_t ret; - context = spvContextCreate(SPV_ENV_VULKAN_1_0); + context = spvContextCreate(spv_target_env_from_vkd3d(target)); if (!(ret = spvBinaryToText(context, spirv->code, spirv->size / sizeof(uint32_t), options, &text, &diagnostic))) @@ -68,13 +82,13 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv) spvContextDestroy(context); } -static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv) +static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, enum vkd3d_shader_target target) { spv_diagnostic diagnostic = NULL; spv_context context; spv_result_t ret; - context = spvContextCreate(SPV_ENV_VULKAN_1_0); + context = spvContextCreate(spv_target_env_from_vkd3d(target)); if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t), &diagnostic))) @@ -89,8 +103,8 @@ static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv) #else -static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv) {} -static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv) {} +static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_shader_target target) {} +static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, enum vkd3d_shader_target target) {} #endif /* HAVE_SPIRV_TOOLS */ @@ -1968,6 +1982,12 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader return compiler; } +static enum vkd3d_shader_target vkd3d_dxbc_compiler_get_target(struct vkd3d_dxbc_compiler *compiler) +{ + const struct vkd3d_shader_compile_arguments *args = compiler->compile_args; + return args ? args->target : VKD3D_SHADER_TARGET_SPIRV_VULKAN_1_0; +} + static bool vkd3d_dxbc_compiler_check_shader_visibility(struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_visibility visibility) { @@ -2983,9 +3003,13 @@ static const struct { enum vkd3d_shader_input_sysval_semantic sysval; struct vkd3d_spirv_builtin builtin; + enum vkd3d_shader_target target; } vkd3d_system_value_builtins[] = { + {VKD3D_SIV_VERTEX_ID, {VKD3D_TYPE_INT, 1, SpvBuiltInVertexId}, VKD3D_SHADER_TARGET_SPIRV_OPENGL_4_5}, + {VKD3D_SIV_INSTANCE_ID, {VKD3D_TYPE_INT, 1, SpvBuiltInInstanceId}, VKD3D_SHADER_TARGET_SPIRV_OPENGL_4_5}, + {VKD3D_SIV_POSITION, {VKD3D_TYPE_FLOAT, 4, SpvBuiltInPosition}}, {VKD3D_SIV_VERTEX_ID, {VKD3D_TYPE_INT, 1, SpvBuiltInVertexIndex}}, {VKD3D_SIV_INSTANCE_ID, {VKD3D_TYPE_INT, 1, SpvBuiltInInstanceIndex, sv_instance_id_fixup}}, @@ -3020,16 +3044,20 @@ vkd3d_register_builtins[] = }; static const struct vkd3d_spirv_builtin *get_spirv_builtin_for_sysval( - enum vkd3d_shader_input_sysval_semantic sysval) + struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_input_sysval_semantic sysval) { + enum vkd3d_shader_target target; unsigned int i; if (!sysval) return NULL; + target = vkd3d_dxbc_compiler_get_target(compiler); for (i = 0; i < ARRAY_SIZE(vkd3d_system_value_builtins); ++i) { - if (vkd3d_system_value_builtins[i].sysval == sysval) + if (vkd3d_system_value_builtins[i].sysval == sysval + && (!vkd3d_system_value_builtins[i].target + || vkd3d_system_value_builtins[i].target == target)) return &vkd3d_system_value_builtins[i].builtin; } @@ -3052,12 +3080,12 @@ static const struct vkd3d_spirv_builtin *get_spirv_builtin_for_register( return NULL; } -static const struct vkd3d_spirv_builtin *vkd3d_get_spirv_builtin(enum vkd3d_shader_register_type reg_type, - enum vkd3d_shader_input_sysval_semantic sysval) +static const struct vkd3d_spirv_builtin *vkd3d_get_spirv_builtin(struct vkd3d_dxbc_compiler *compiler, + enum vkd3d_shader_register_type reg_type, enum vkd3d_shader_input_sysval_semantic sysval) { const struct vkd3d_spirv_builtin *builtin; - if ((builtin = get_spirv_builtin_for_sysval(sysval))) + if ((builtin = get_spirv_builtin_for_sysval(compiler, sysval))) return builtin; if ((builtin = get_spirv_builtin_for_register(reg_type))) return builtin; @@ -3124,7 +3152,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi reg_idx = reg->idx[0].offset; } - builtin = get_spirv_builtin_for_sysval(sysval); + builtin = get_spirv_builtin_for_sysval(compiler, sysval); component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask); component_count = vkd3d_write_mask_component_count(dst->write_mask); @@ -3321,7 +3349,7 @@ static void vkd3d_dxbc_compiler_emit_shader_signature_outputs(struct vkd3d_dxbc_ if (clip_distance_mask) { count = vkd3d_popcount(clip_distance_mask); - builtin = get_spirv_builtin_for_sysval(VKD3D_SIV_CLIP_DISTANCE); + builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SIV_CLIP_DISTANCE); clip_distance_id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream, SpvStorageClassOutput, builtin->component_type, builtin->component_count, count); vkd3d_spirv_add_iface_variable(builder, clip_distance_id); @@ -3331,7 +3359,7 @@ static void vkd3d_dxbc_compiler_emit_shader_signature_outputs(struct vkd3d_dxbc_ if (cull_distance_mask) { count = vkd3d_popcount(cull_distance_mask); - builtin = get_spirv_builtin_for_sysval(VKD3D_SIV_CULL_DISTANCE); + builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SIV_CULL_DISTANCE); cull_distance_id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream, SpvStorageClassOutput, builtin->component_type, builtin->component_count, count); vkd3d_spirv_add_iface_variable(builder, cull_distance_id); @@ -3383,7 +3411,7 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler return; } - builtin = vkd3d_get_spirv_builtin(dst->reg.type, sysval); + builtin = vkd3d_get_spirv_builtin(compiler, dst->reg.type, sysval); component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask); component_count = vkd3d_write_mask_component_count(dst->write_mask); @@ -6631,8 +6659,9 @@ int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler, if (TRACE_ON()) { - vkd3d_spirv_dump(spirv); - vkd3d_spirv_validate(spirv); + enum vkd3d_shader_target target = vkd3d_dxbc_compiler_get_target(compiler); + vkd3d_spirv_dump(spirv, target); + vkd3d_spirv_validate(spirv, target); } return VKD3D_OK; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index f6bb9645..5b269bd6 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -56,6 +56,24 @@ static void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser) free_shader_desc(&parser->shader_desc); } +static int vkd3d_shader_validate_compile_args(const struct vkd3d_shader_compile_arguments *compile_args) +{ + if (!compile_args) + return VKD3D_OK; + + switch (compile_args->target) + { + case VKD3D_SHADER_TARGET_SPIRV_OPENGL_4_5: + case VKD3D_SHADER_TARGET_SPIRV_VULKAN_1_0: + break; + default: + WARN("Invalid shader target %#x.\n", compile_args->target); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + + return VKD3D_OK; +} + int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_code *spirv, uint32_t compiler_options, const struct vkd3d_shader_interface *shader_interface, @@ -70,6 +88,9 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x, shader_interface %p, compile_args %p.\n", dxbc->code, dxbc->size, spirv, compiler_options, shader_interface, compile_args); + if ((ret = vkd3d_shader_validate_compile_args(compile_args)) < 0) + return ret; + if ((ret = vkd3d_shader_scan_dxbc(dxbc, &scan_info)) < 0) return ret; diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 1d18c31a..82721f27 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1994,6 +1994,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s } graphics->attachment_count = graphics->rt_idx + rt_count; + ps_compile_args.target = VKD3D_SHADER_TARGET_SPIRV_VULKAN_1_0; ps_compile_args.output_swizzles = ps_output_swizzle; ps_compile_args.output_swizzle_count = rt_count;