diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 94f79c7c..1d6cbbf8 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -173,6 +173,21 @@ enum vkd3d_shader_compile_option_backward_compatibility VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY), }; +/** + * Determines the origin of fragment coordinates. + * + * \since 1.10 + */ +enum vkd3d_shader_compile_option_fragment_coordinate_origin +{ + /** Fragment coordinates originate from the upper-left. This is the + * default; it's also the only value supported by Vulkan environments. */ + VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN_UPPER_LEFT = 0x00000000, + /** Fragment coordinates originate from the lower-left. This matches the + * traditional behaviour of OpenGL environments. */ + VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN_LOWER_LEFT = 0x00000001, +}; + enum vkd3d_shader_compile_option_name { /** @@ -220,6 +235,16 @@ enum vkd3d_shader_compile_option_name * \since 1.10 */ VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY = 0x00000008, + /** + * This option specifies the origin of fragment coordinates for SPIR-V + * targets. + * + * \a value is a member of enum + * vkd3d_shader_compile_option_fragment_coordinate_origin. + * + * \since 1.10 + */ + VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN = 0x00000009, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), }; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 61d75757..c681b9f8 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2288,6 +2288,7 @@ struct spirv_compiler bool strip_debug; bool ssbo_uavs; bool uav_read_without_format; + SpvExecutionMode fragment_coordinate_origin; struct rb_tree symbol_table; uint32_t temp_id; @@ -2453,6 +2454,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve compiler->formatting = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT | VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER; compiler->write_tess_geom_point_size = true; + compiler->fragment_coordinate_origin = SpvExecutionModeOriginUpperLeft; for (i = 0; i < compile_info->option_count; ++i) { @@ -2493,6 +2495,15 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve compiler->write_tess_geom_point_size = option->value; break; + case VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN: + if (option->value == VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN_UPPER_LEFT) + compiler->fragment_coordinate_origin = SpvExecutionModeOriginUpperLeft; + else if (option->value == VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN_LOWER_LEFT) + compiler->fragment_coordinate_origin = SpvExecutionModeOriginLowerLeft; + else + WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name); + break; + default: WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value); break; @@ -5358,7 +5369,7 @@ static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *comp break; case VKD3D_SHADER_TYPE_PIXEL: vkd3d_spirv_set_execution_model(builder, SpvExecutionModelFragment); - spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeOriginUpperLeft, NULL, 0); + spirv_compiler_emit_execution_mode(compiler, compiler->fragment_coordinate_origin, NULL, 0); break; case VKD3D_SHADER_TYPE_COMPUTE: vkd3d_spirv_set_execution_model(builder, SpvExecutionModelGLCompute);