tests/shader_runner_gl: Implement tessellation support.

This commit is contained in:
Shaun Ren 2024-10-22 22:31:55 -04:00 committed by Henri Verbeet
parent 12ac1dd46b
commit 843fc980b5
Notes: Henri Verbeet 2024-11-21 19:34:41 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1217

View File

@ -76,6 +76,9 @@ struct gl_runner
uint32_t attribute_map; uint32_t attribute_map;
GLuint fbo_id; GLuint fbo_id;
enum vkd3d_shader_tessellator_output_primitive output_primitive;
enum vkd3d_shader_tessellator_partitioning partitioning;
struct vkd3d_shader_combined_resource_sampler *combined_samplers; struct vkd3d_shader_combined_resource_sampler *combined_samplers;
unsigned int combined_sampler_count; unsigned int combined_sampler_count;
enum shading_language language; enum shading_language language;
@ -114,10 +117,11 @@ static bool check_gl_extensions(struct gl_runner *runner)
"GL_ARB_clip_control", "GL_ARB_clip_control",
"GL_ARB_compute_shader", "GL_ARB_compute_shader",
"GL_ARB_copy_image", "GL_ARB_copy_image",
"GL_ARB_internalformat_query",
"GL_ARB_sampler_objects", "GL_ARB_sampler_objects",
"GL_ARB_shader_image_load_store", "GL_ARB_shader_image_load_store",
"GL_ARB_tessellation_shader",
"GL_ARB_texture_storage", "GL_ARB_texture_storage",
"GL_ARB_internalformat_query",
}; };
glGetIntegerv(GL_NUM_EXTENSIONS, &count); glGetIntegerv(GL_NUM_EXTENSIONS, &count);
@ -534,13 +538,16 @@ static void gl_runner_destroy_resource(struct shader_runner *r, struct resource
free(resource); free(resource);
} }
static bool compile_shader(struct gl_runner *runner, ID3DBlob *blob, struct vkd3d_shader_code *out) static bool compile_shader(struct gl_runner *runner, enum shader_type shader_type,
ID3DBlob *blob, struct vkd3d_shader_code *out)
{ {
struct vkd3d_shader_spirv_target_info spirv_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO}; struct vkd3d_shader_spirv_target_info spirv_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO};
struct vkd3d_shader_interface_info interface_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO}; struct vkd3d_shader_interface_info interface_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO};
struct vkd3d_shader_compile_info info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO}; struct vkd3d_shader_compile_info info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO};
struct vkd3d_shader_resource_binding bindings[MAX_RESOURCES + 1 /* CBV */]; struct vkd3d_shader_resource_binding bindings[MAX_RESOURCES + 1 /* CBV */];
struct vkd3d_shader_scan_combined_resource_sampler_info combined_sampler_info; struct vkd3d_shader_scan_combined_resource_sampler_info combined_sampler_info;
struct vkd3d_shader_scan_hull_shader_tessellation_info tessellation_info;
struct vkd3d_shader_spirv_domain_shader_target_info domain_info;
struct vkd3d_shader_combined_resource_sampler *sampler; struct vkd3d_shader_combined_resource_sampler *sampler;
struct vkd3d_shader_resource_binding *binding; struct vkd3d_shader_resource_binding *binding;
struct vkd3d_shader_parameter parameters[1]; struct vkd3d_shader_parameter parameters[1];
@ -566,7 +573,10 @@ static bool compile_shader(struct gl_runner *runner, ID3DBlob *blob, struct vkd3
info.log_level = VKD3D_SHADER_LOG_WARNING; info.log_level = VKD3D_SHADER_LOG_WARNING;
combined_sampler_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_COMBINED_RESOURCE_SAMPLER_INFO; combined_sampler_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_COMBINED_RESOURCE_SAMPLER_INFO;
combined_sampler_info.next = NULL; combined_sampler_info.next = &tessellation_info;
tessellation_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_HULL_SHADER_TESSELLATION_INFO;
tessellation_info.next = NULL;
ret = vkd3d_shader_scan(&info, &messages); ret = vkd3d_shader_scan(&info, &messages);
if (messages && vkd3d_test_state.debug_level) if (messages && vkd3d_test_state.debug_level)
@ -575,6 +585,12 @@ static bool compile_shader(struct gl_runner *runner, ID3DBlob *blob, struct vkd3
if (ret) if (ret)
return false; return false;
if (shader_type == SHADER_TYPE_HS)
{
runner->output_primitive = tessellation_info.output_primitive;
runner->partitioning = tessellation_info.partitioning;
}
count = runner->combined_sampler_count + combined_sampler_info.combined_sampler_count; count = runner->combined_sampler_count + combined_sampler_info.combined_sampler_count;
if (count && !(runner->combined_samplers = realloc(runner->combined_samplers, if (count && !(runner->combined_samplers = realloc(runner->combined_samplers,
count * sizeof(*runner->combined_samplers)))) count * sizeof(*runner->combined_samplers))))
@ -610,6 +626,16 @@ static bool compile_shader(struct gl_runner *runner, ID3DBlob *blob, struct vkd3
info.next = &interface_info; info.next = &interface_info;
} }
if (shader_type == SHADER_TYPE_DS)
{
interface_info.next = &domain_info;
domain_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_DOMAIN_SHADER_TARGET_INFO;
domain_info.next = NULL;
domain_info.output_primitive = runner->output_primitive;
domain_info.partitioning = runner->partitioning;
}
if (runner->r.uniform_count) if (runner->r.uniform_count)
{ {
binding = &bindings[interface_info.binding_count++]; binding = &bindings[interface_info.binding_count++];
@ -708,41 +734,85 @@ static void trace_info_log(GLuint id, bool program)
free(log); free(log);
} }
static GLuint compile_compute_shader_program(struct gl_runner *runner) static GLuint create_shader(struct gl_runner *runner, enum shader_type shader_type, ID3D10Blob *source)
{ {
struct vkd3d_shader_code cs_code; struct vkd3d_shader_code target;
GLuint program_id, cs_id; const GLchar *glsl_source;
const GLchar *source; GLenum gl_shader_type;
ID3D10Blob *cs_blob;
GLint status, size; GLint status, size;
bool ret; const char *name;
GLuint id;
reset_combined_samplers(runner); switch (shader_type)
if (!(cs_blob = compile_hlsl(&runner->r, SHADER_TYPE_CS))) {
return false; case SHADER_TYPE_VS:
ret = compile_shader(runner, cs_blob, &cs_code); gl_shader_type = GL_VERTEX_SHADER;
ID3D10Blob_Release(cs_blob); name = "vertex";
if (!ret) break;
return false;
cs_id = glCreateShader(GL_COMPUTE_SHADER); case SHADER_TYPE_PS:
gl_shader_type = GL_FRAGMENT_SHADER;
name = "fragment";
break;
case SHADER_TYPE_HS:
gl_shader_type = GL_TESS_CONTROL_SHADER;
name = "tessellation control";
break;
case SHADER_TYPE_DS:
gl_shader_type = GL_TESS_EVALUATION_SHADER;
name = "tessellation evaluation";
break;
case SHADER_TYPE_CS:
gl_shader_type = GL_COMPUTE_SHADER;
name = "compute";
break;
default:
fatal_error("Unhandled shader type %#x.\n", shader_type);
}
if (!compile_shader(runner, shader_type, source, &target))
return 0;
id = glCreateShader(gl_shader_type);
if (runner->language == SPIR_V) if (runner->language == SPIR_V)
{ {
glShaderBinary(1, &cs_id, GL_SHADER_BINARY_FORMAT_SPIR_V, cs_code.code, cs_code.size); glShaderBinary(1, &id, GL_SHADER_BINARY_FORMAT_SPIR_V, target.code, target.size);
p_glSpecializeShader(id, "main", 0, NULL, NULL);
} }
else else
{ {
source = cs_code.code; glsl_source = target.code;
size = cs_code.size; size = target.size;
glShaderSource(cs_id, 1, &source, &size); glShaderSource(id, 1, &glsl_source, &size);
glCompileShader(cs_id); glCompileShader(id);
} }
vkd3d_shader_free_shader_code(&cs_code); vkd3d_shader_free_shader_code(&target);
if (runner->language == SPIR_V)
p_glSpecializeShader(cs_id, "main", 0, NULL, NULL); glGetShaderiv(id, GL_COMPILE_STATUS, &status);
glGetShaderiv(cs_id, GL_COMPILE_STATUS, &status); ok(status, "Failed to compile %s shader.\n", name);
ok(status, "Failed to compile compute shader.\n"); trace_info_log(id, false);
trace_info_log(cs_id, false);
return id;
}
static GLuint compile_compute_shader_program(struct gl_runner *runner)
{
GLuint program_id, cs_id;
ID3D10Blob *cs_blob;
GLint status;
reset_combined_samplers(runner);
if (!(cs_blob = compile_hlsl(&runner->r, SHADER_TYPE_CS)))
return 0;
cs_id = create_shader(runner, SHADER_TYPE_CS, cs_blob);
ID3D10Blob_Release(cs_blob);
if (!cs_id)
return 0;
program_id = glCreateProgram(); program_id = glCreateProgram();
glAttachShader(program_id, cs_id); glAttachShader(program_id, cs_id);
@ -815,6 +885,9 @@ static GLenum get_topology_gl(D3D_PRIMITIVE_TOPOLOGY topology)
return GL_TRIANGLE_STRIP; return GL_TRIANGLE_STRIP;
default: default:
if (topology >= D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST
&& topology <= D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST)
return GL_PATCHES;
fatal_error("Unhandled topology %#x.\n", topology); fatal_error("Unhandled topology %#x.\n", topology);
} }
} }
@ -884,11 +957,9 @@ static GLenum get_compare_op_gl(D3D12_COMPARISON_FUNC op)
static GLuint compile_graphics_shader_program(struct gl_runner *runner, ID3D10Blob **vs_blob) static GLuint compile_graphics_shader_program(struct gl_runner *runner, ID3D10Blob **vs_blob)
{ {
ID3D10Blob *fs_blob, *hs_blob = NULL, *ds_blob = NULL, *gs_blob = NULL; ID3D10Blob *fs_blob, *hs_blob = NULL, *ds_blob = NULL, *gs_blob = NULL;
struct vkd3d_shader_code vs_code, fs_code; GLuint program_id, vs_id, fs_id, hs_id = 0, ds_id = 0;
GLuint program_id, vs_id, fs_id;
const GLchar *source;
GLint status, size;
bool succeeded; bool succeeded;
GLint status;
reset_combined_samplers(runner); reset_combined_samplers(runner);
@ -913,93 +984,68 @@ static GLuint compile_graphics_shader_program(struct gl_runner *runner, ID3D10Bl
} }
if (!succeeded) if (!succeeded)
{ goto fail;
if (*vs_blob)
ID3D10Blob_Release(*vs_blob); if (!(vs_id = create_shader(runner, SHADER_TYPE_VS, *vs_blob)))
if (fs_blob) goto fail;
if (!(fs_id = create_shader(runner, SHADER_TYPE_PS, fs_blob)))
goto fail;
ID3D10Blob_Release(fs_blob); ID3D10Blob_Release(fs_blob);
fs_blob = NULL;
if (hs_blob) if (hs_blob)
{
if (!(hs_id = create_shader(runner, SHADER_TYPE_HS, hs_blob)))
goto fail;
ID3D10Blob_Release(hs_blob); ID3D10Blob_Release(hs_blob);
hs_blob = NULL;
}
if (ds_blob) if (ds_blob)
{
if (!(ds_id = create_shader(runner, SHADER_TYPE_DS, ds_blob)))
goto fail;
ID3D10Blob_Release(ds_blob); ID3D10Blob_Release(ds_blob);
if (gs_blob) ds_blob = NULL;
ID3D10Blob_Release(gs_blob);
return false;
} }
if (!compile_shader(runner, *vs_blob, &vs_code)) /* TODO: compile and use the gs blobs too, but currently this
{
ID3D10Blob_Release(fs_blob);
ID3D10Blob_Release(*vs_blob);
return false;
}
if (!compile_shader(runner, fs_blob, &fs_code))
{
vkd3d_shader_free_shader_code(&vs_code);
ID3D10Blob_Release(fs_blob);
ID3D10Blob_Release(*vs_blob);
return false;
}
ID3D10Blob_Release(fs_blob);
/* TODO: compile and use the hs, ds and/or gs blobs too, but currently this
* point is not reached because compile_hlsl() fails on these. */ * point is not reached because compile_hlsl() fails on these. */
if (hs_blob)
ID3D10Blob_Release(hs_blob);
if (ds_blob)
ID3D10Blob_Release(ds_blob);
vs_id = glCreateShader(GL_VERTEX_SHADER);
if (runner->language == SPIR_V)
{
glShaderBinary(1, &vs_id, GL_SHADER_BINARY_FORMAT_SPIR_V, vs_code.code, vs_code.size);
}
else
{
source = vs_code.code;
size = vs_code.size;
glShaderSource(vs_id, 1, &source, &size);
glCompileShader(vs_id);
}
vkd3d_shader_free_shader_code(&vs_code);
if (runner->language == SPIR_V)
p_glSpecializeShader(vs_id, "main", 0, NULL, NULL);
glGetShaderiv(vs_id, GL_COMPILE_STATUS, &status);
ok(status, "Failed to compile vertex shader.\n");
trace_info_log(vs_id, false);
fs_id = glCreateShader(GL_FRAGMENT_SHADER);
if (runner->language == SPIR_V)
{
glShaderBinary(1, &fs_id, GL_SHADER_BINARY_FORMAT_SPIR_V, fs_code.code, fs_code.size);
}
else
{
source = fs_code.code;
size = fs_code.size;
glShaderSource(fs_id, 1, &source, &size);
glCompileShader(fs_id);
}
vkd3d_shader_free_shader_code(&fs_code);
if (runner->language == SPIR_V)
p_glSpecializeShader(fs_id, "main", 0, NULL, NULL);
glGetShaderiv(fs_id, GL_COMPILE_STATUS, &status);
ok(status, "Failed to compile fragment shader.\n");
trace_info_log(fs_id, false);
program_id = glCreateProgram(); program_id = glCreateProgram();
glAttachShader(program_id, vs_id); glAttachShader(program_id, vs_id);
glAttachShader(program_id, fs_id); glAttachShader(program_id, fs_id);
if (hs_id)
glAttachShader(program_id, hs_id);
if (ds_id)
glAttachShader(program_id, ds_id);
glLinkProgram(program_id); glLinkProgram(program_id);
glGetProgramiv(program_id, GL_LINK_STATUS, &status); glGetProgramiv(program_id, GL_LINK_STATUS, &status);
ok(status, "Failed to link program.\n"); ok(status, "Failed to link program.\n");
trace_info_log(program_id, true); trace_info_log(program_id, true);
if (ds_id)
glDeleteShader(ds_id);
if (hs_id)
glDeleteShader(hs_id);
glDeleteShader(fs_id); glDeleteShader(fs_id);
glDeleteShader(vs_id); glDeleteShader(vs_id);
return program_id; return program_id;
fail:
if (gs_blob)
ID3D10Blob_Release(gs_blob);
if (ds_blob)
ID3D10Blob_Release(ds_blob);
if (hs_blob)
ID3D10Blob_Release(hs_blob);
if (fs_blob)
ID3D10Blob_Release(fs_blob);
if (*vs_blob)
ID3D10Blob_Release(*vs_blob);
return 0;
} }
static void gl_runner_clear(struct shader_runner *r, struct resource *res, const struct vec4 *clear_value) static void gl_runner_clear(struct shader_runner *r, struct resource *res, const struct vec4 *clear_value)
@ -1236,6 +1282,9 @@ static bool gl_runner_draw(struct shader_runner *r,
glDisableVertexAttribArray(attribute_idx); glDisableVertexAttribArray(attribute_idx);
} }
if (runner->r.shader_source[SHADER_TYPE_HS])
glPatchParameteri(GL_PATCH_VERTICES, max(topology - D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + 1, 1));
glDrawArraysInstanced(get_topology_gl(topology), 0, vertex_count, instance_count); glDrawArraysInstanced(get_topology_gl(topology), 0, vertex_count, instance_count);
for (i = 0; i < runner->r.sampler_count; ++i) for (i = 0; i < runner->r.sampler_count; ++i)