vkd3d-shader/glsl: Implement support for VKD3DSPR_INPUT registers.

This commit is contained in:
Henri Verbeet 2023-11-22 14:33:18 +01:00
parent deda49e501
commit c462c62108
Notes: Henri Verbeet 2024-09-17 18:15:55 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1078

View File

@ -38,7 +38,14 @@ struct vkd3d_glsl_generator
struct vkd3d_shader_location location;
struct vkd3d_shader_message_context *message_context;
unsigned int indent;
const char *prefix;
bool failed;
struct shader_limits
{
unsigned int input_count;
} limits;
bool interstage_input;
};
static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error(
@ -53,6 +60,27 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error(
generator->failed = true;
}
static const char *shader_glsl_get_prefix(enum vkd3d_shader_type type)
{
switch (type)
{
case VKD3D_SHADER_TYPE_VERTEX:
return "vs";
case VKD3D_SHADER_TYPE_HULL:
return "hs";
case VKD3D_SHADER_TYPE_DOMAIN:
return "ds";
case VKD3D_SHADER_TYPE_GEOMETRY:
return "gs";
case VKD3D_SHADER_TYPE_PIXEL:
return "ps";
case VKD3D_SHADER_TYPE_COMPUTE:
return "cs";
default:
return NULL;
}
}
static void shader_glsl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int indent)
{
vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, "");
@ -67,6 +95,24 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer,
vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset);
break;
case VKD3DSPR_INPUT:
if (reg->idx_count != 1)
{
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled input register index count %u.", reg->idx_count);
vkd3d_string_buffer_printf(buffer, "<unhandled register %#x>", reg->type);
break;
}
if (reg->idx[0].rel_addr)
{
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled input register indirect addressing.");
vkd3d_string_buffer_printf(buffer, "<unhandled register %#x>", reg->type);
break;
}
vkd3d_string_buffer_printf(buffer, "%s_in[%u]", gen->prefix, reg->idx[0].offset);
break;
default:
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled register type %#x.", reg->type);
@ -198,6 +244,50 @@ static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d
glsl_dst_cleanup(&dst, &gen->string_buffers);
}
static void shader_glsl_shader_prologue(struct vkd3d_glsl_generator *gen)
{
const struct shader_signature *signature = &gen->program->input_signature;
struct vkd3d_string_buffer *buffer = gen->buffer;
const struct signature_element *e;
unsigned int i;
for (i = 0; i < signature->element_count; ++i)
{
e = &signature->elements[i];
if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED)
continue;
shader_glsl_print_indent(buffer, gen->indent);
vkd3d_string_buffer_printf(buffer, "%s_in[%u]", gen->prefix, e->register_index);
shader_glsl_print_write_mask(buffer, e->mask);
if (e->sysval_semantic == VKD3D_SHADER_SV_NONE)
{
if (gen->interstage_input)
{
vkd3d_string_buffer_printf(buffer, " = shader_in.reg_%u", e->target_location);
if (e->target_location >= gen->limits.input_count)
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Input element %u specifies target location %u, "
"but only %u inputs are supported.",
i, e->target_location, gen->limits.input_count);
}
else
{
vkd3d_string_buffer_printf(buffer, " = shader_in_%u", i);
}
}
else
{
vkd3d_string_buffer_printf(buffer, " = <unhandled sysval %#x>", e->sysval_semantic);
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic);
}
shader_glsl_print_write_mask(buffer, e->mask);
vkd3d_string_buffer_printf(buffer, ";\n");
}
}
static void shader_glsl_ret(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins)
{
const struct vkd3d_shader_version *version = &gen->program->shader_version;
@ -237,13 +327,78 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen,
}
}
static void shader_glsl_generate_input_declarations(struct vkd3d_glsl_generator *gen)
{
const struct shader_signature *signature = &gen->program->input_signature;
struct vkd3d_string_buffer *buffer = gen->buffer;
const struct signature_element *e;
unsigned int i;
if (!gen->interstage_input)
{
for (i = 0; i < signature->element_count; ++i)
{
e = &signature->elements[i];
if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED)
continue;
if (e->sysval_semantic)
{
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled system value %#x.", e->sysval_semantic);
continue;
}
if (e->component_type != VKD3D_SHADER_COMPONENT_FLOAT)
{
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled component type %#x.", e->component_type);
continue;
}
if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE)
{
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled minimum precision %#x.", e->min_precision);
continue;
}
if (e->interpolation_mode != VKD3DSIM_NONE)
{
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled interpolation mode %#x.", e->interpolation_mode);
continue;
}
vkd3d_string_buffer_printf(buffer,
"layout(location = %u) in vec4 shader_in_%u;\n", e->target_location, i);
}
}
else if (gen->limits.input_count)
{
vkd3d_string_buffer_printf(buffer, "in shader_in_out\n{\n");
for (i = 0; i < gen->limits.input_count; ++i)
{
vkd3d_string_buffer_printf(buffer, " vec4 reg_%u;\n", i);
}
vkd3d_string_buffer_printf(buffer, "} shader_in;\n");
}
vkd3d_string_buffer_printf(buffer, "\n");
}
static void shader_glsl_generate_declarations(struct vkd3d_glsl_generator *gen)
{
const struct vsir_program *program = gen->program;
struct vkd3d_string_buffer *buffer = gen->buffer;
shader_glsl_generate_input_declarations(gen);
if (gen->limits.input_count)
vkd3d_string_buffer_printf(buffer, "vec4 %s_in[%u];\n", gen->prefix, gen->limits.input_count);
if (program->temp_count)
vkd3d_string_buffer_printf(buffer, "vec4 r[%u];\n\n", program->temp_count);
vkd3d_string_buffer_printf(buffer, "vec4 r[%u];\n", program->temp_count);
vkd3d_string_buffer_printf(buffer, "\n");
}
static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struct vkd3d_shader_code *out)
@ -264,6 +419,7 @@ static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struc
vkd3d_string_buffer_printf(buffer, "void main()\n{\n");
++gen->indent;
shader_glsl_shader_prologue(gen);
for (i = 0; i < instructions->count; ++i)
{
vkd3d_glsl_handle_instruction(gen, &instructions->elements[i]);
@ -294,14 +450,48 @@ static void vkd3d_glsl_generator_cleanup(struct vkd3d_glsl_generator *gen)
vkd3d_string_buffer_cache_cleanup(&gen->string_buffers);
}
static void shader_glsl_init_limits(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_version *version)
{
struct shader_limits *limits = &gen->limits;
if (version->major < 4 || version->major >= 6)
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled shader version %u.%u.", version->major, version->minor);
switch (version->type)
{
case VKD3D_SHADER_TYPE_VERTEX:
limits->input_count = 32;
break;
case VKD3D_SHADER_TYPE_PIXEL:
limits->input_count = 32;
break;
default:
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled shader type %#x.", version->type);
limits->input_count = 0;
break;
}
}
static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen,
struct vsir_program *program, struct vkd3d_shader_message_context *message_context)
{
enum vkd3d_shader_type type = program->shader_version.type;
memset(gen, 0, sizeof(*gen));
gen->program = program;
vkd3d_string_buffer_cache_init(&gen->string_buffers);
gen->buffer = vkd3d_string_buffer_get(&gen->string_buffers);
gen->message_context = message_context;
if (!(gen->prefix = shader_glsl_get_prefix(type)))
{
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled shader type %#x.", type);
gen->prefix = "unknown";
}
shader_glsl_init_limits(gen, &program->shader_version);
gen->interstage_input = type != VKD3D_SHADER_TYPE_VERTEX;
}
int glsl_compile(struct vsir_program *program, uint64_t config_flags,