vkd3d-shader: Add support for OpenGL tessellation shaders.

In DXBC tessellator parameters are specified in hull shaders. In OpenGL,
even in SPIR-V, tessellator parameters must be specified in the
tessellation evaluation shader.

Signed-off-by: Józef Kucia <jkucia@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Józef Kucia 2019-02-14 12:22:33 +01:00 committed by Alexandre Julliard
parent 22330b5414
commit c333fddaf9
3 changed files with 60 additions and 25 deletions

View File

@ -33,6 +33,7 @@ enum vkd3d_shader_structure_type
VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_ARGUMENTS,
VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_DOMAIN_SHADER_COMPILE_ARGUMENTS,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
};
@ -195,6 +196,32 @@ struct vkd3d_shader_compile_arguments
unsigned int output_swizzle_count;
};
enum vkd3d_tessellator_output_primitive
{
VKD3D_TESSELLATOR_OUTPUT_POINT = 1,
VKD3D_TESSELLATOR_OUTPUT_LINE = 2,
VKD3D_TESSELLATOR_OUTPUT_TRIANGLE_CW = 3,
VKD3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4,
};
enum vkd3d_tessellator_partitioning
{
VKD3D_TESSELLATOR_PARTITIONING_INTEGER = 1,
VKD3D_TESSELLATOR_PARTITIONING_POW2 = 2,
VKD3D_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3,
VKD3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4,
};
/* Extends vkd3d_shader_compile_arguments. */
struct vkd3d_shader_domain_shader_compile_arguments
{
enum vkd3d_shader_structure_type type;
const void *next;
enum vkd3d_tessellator_output_primitive output_primitive;
enum vkd3d_tessellator_output_primitive partitioning;
};
int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_code *spirv, unsigned int compiler_options,
const struct vkd3d_shader_interface_info *shader_interface_info,

View File

@ -4856,6 +4856,9 @@ static void vkd3d_dxbc_compiler_emit_dcl_tessellator_domain(struct vkd3d_dxbc_co
enum vkd3d_tessellator_domain domain = instruction->declaration.tessellator_domain;
SpvExecutionMode mode;
if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && vkd3d_dxbc_compiler_is_opengl_target(compiler))
return;
switch (domain)
{
case VKD3D_TESSELLATOR_DOMAIN_LINE:
@ -4875,12 +4878,14 @@ static void vkd3d_dxbc_compiler_emit_dcl_tessellator_domain(struct vkd3d_dxbc_co
vkd3d_dxbc_compiler_emit_execution_mode(compiler, mode, NULL, 0);
}
static void vkd3d_dxbc_compiler_emit_dcl_tessellator_output_primitive(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
static void vkd3d_dxbc_compiler_emit_tessellator_output_primitive(struct vkd3d_dxbc_compiler *compiler,
enum vkd3d_tessellator_output_primitive primitive)
{
enum vkd3d_tessellator_output_primitive primitive = instruction->declaration.tessellator_output_primitive;
SpvExecutionMode mode;
if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && vkd3d_dxbc_compiler_is_opengl_target(compiler))
return;
switch (primitive)
{
case VKD3D_TESSELLATOR_OUTPUT_POINT:
@ -4902,12 +4907,14 @@ static void vkd3d_dxbc_compiler_emit_dcl_tessellator_output_primitive(struct vkd
vkd3d_dxbc_compiler_emit_execution_mode(compiler, mode, NULL, 0);
}
static void vkd3d_dxbc_compiler_emit_dcl_tessellator_partitioning(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
static void vkd3d_dxbc_compiler_emit_tessellator_partitioning(struct vkd3d_dxbc_compiler *compiler,
enum vkd3d_tessellator_partitioning partitioning)
{
enum vkd3d_tessellator_partitioning partitioning = instruction->declaration.tessellator_partitioning;
SpvExecutionMode mode;
if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && vkd3d_dxbc_compiler_is_opengl_target(compiler))
return;
switch (partitioning)
{
case VKD3D_TESSELLATOR_PARTITIONING_INTEGER:
@ -7426,10 +7433,12 @@ int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
vkd3d_dxbc_compiler_emit_dcl_tessellator_domain(compiler, instruction);
break;
case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE:
vkd3d_dxbc_compiler_emit_dcl_tessellator_output_primitive(compiler, instruction);
vkd3d_dxbc_compiler_emit_tessellator_output_primitive(compiler,
instruction->declaration.tessellator_output_primitive);
break;
case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING:
vkd3d_dxbc_compiler_emit_dcl_tessellator_partitioning(compiler, instruction);
vkd3d_dxbc_compiler_emit_tessellator_partitioning(compiler,
instruction->declaration.tessellator_partitioning);
break;
case VKD3DSIH_DCL_THREAD_GROUP:
vkd3d_dxbc_compiler_emit_dcl_thread_group(compiler, instruction);
@ -7775,6 +7784,8 @@ static void vkd3d_dxbc_compiler_emit_shader_epilogue_function(struct vkd3d_dxbc_
int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
struct vkd3d_shader_code *spirv)
{
const struct vkd3d_shader_compile_arguments *compile_args = compiler->compile_args;
const struct vkd3d_shader_domain_shader_compile_arguments *ds_args;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
vkd3d_spirv_build_op_function_end(builder);
@ -7782,6 +7793,20 @@ int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL)
vkd3d_dxbc_compiler_emit_hull_shader_main(compiler);
if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN)
{
if (compile_args && (ds_args = vkd3d_find_struct(compile_args->next, DOMAIN_SHADER_COMPILE_ARGUMENTS)))
{
vkd3d_dxbc_compiler_emit_tessellator_output_primitive(compiler, ds_args->output_primitive);
vkd3d_dxbc_compiler_emit_tessellator_partitioning(compiler, ds_args->partitioning);
}
else if (vkd3d_dxbc_compiler_is_opengl_target(compiler))
{
ERR("vkd3d_shader_domain_shader_compile_arguments are required for "
"OpenGL tessellation evaluation shader.\n");
}
}
if (compiler->epilogue_function_id)
vkd3d_dxbc_compiler_emit_shader_epilogue_function(compiler);

View File

@ -464,23 +464,6 @@ enum vkd3d_tessellator_domain
VKD3D_TESSELLATOR_DOMAIN_QUAD = 3,
};
enum vkd3d_tessellator_output_primitive
{
VKD3D_TESSELLATOR_OUTPUT_POINT = 1,
VKD3D_TESSELLATOR_OUTPUT_LINE = 2,
VKD3D_TESSELLATOR_OUTPUT_TRIANGLE_CW = 3,
VKD3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4,
};
enum vkd3d_tessellator_partitioning
{
VKD3D_TESSELLATOR_PARTITIONING_INTEGER = 1,
VKD3D_TESSELLATOR_PARTITIONING_POW2 = 2,
VKD3D_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3,
VKD3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4,
};
#define VKD3DSI_NONE 0x0
#define VKD3DSI_TEXLD_PROJECT 0x1
#define VKD3DSI_INDEXED_DYNAMIC 0x4