vkd3d-shader: Introduce an interface to specify sm1 shadow samplers.

This commit is contained in:
Elizabeth Figura
2025-10-03 15:01:09 -05:00
committed by Henri Verbeet
parent 539a5be370
commit 0bb8272f26
Notes: Henri Verbeet 2025-10-13 19:31:51 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1769
3 changed files with 84 additions and 11 deletions

View File

@@ -2350,6 +2350,26 @@ struct vkd3d_shader_d3dbc_source_info
* This field is ignored for shader models 2 and higher.
*/
enum vkd3d_shader_resource_type texture_dimensions[6];
/**
* A mask indicating which samplers should be shadow (i.e. comparison-mode)
* samplers. When legacy Direct3D shaders are used with the Direct3D 8 and 9
* APIs, this is implied by the format of the sampled resource; e.g. a
* D3DFMT_D24S8 texture implies shadow sampling, while a D3DFMT_A8R8G8B8
* or D3DFMT_INTZ texture does not.
* This information is necessary when converting to other formats
* (e.g. SPIR-V, GLSL) which specify this in the shader.
*
* For example, if bit 1 is set (so the value is 0x2), this indicates that
* the sampler at bind point 1 (and no others) should be a shadow sampler.
*
* Bits in this mask corresponding to textures not used by the shader will
* be ignored.
*
* If this structure is not specified, no samplers will be considered to
* be shadow samplers.
*/
uint32_t shadow_samplers;
};
/**

View File

@@ -946,17 +946,21 @@ static void d3dbc_add_combined_sampler_descriptor(struct vkd3d_shader_sm1_parser
unsigned int sampler_idx, enum vkd3d_shader_resource_type resource_type)
{
struct vkd3d_shader_register_range range = {.first = sampler_idx, .last = sampler_idx};
const struct vkd3d_shader_d3dbc_source_info *source_info = d3dbc->d3dbc_source_info;
struct vsir_program *program = d3dbc->program;
struct vkd3d_shader_descriptor_info1 *d;
if (!vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV,
sampler_idx, &range, resource_type, VSIR_DATA_F32))
vkd3d_shader_parser_error(&d3dbc->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY,
"Failed to create SRV descriptor for combined sampler %u.", sampler_idx);
if (!vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER,
sampler_idx, &range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED))
if (!(d = vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER,
sampler_idx, &range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED)))
vkd3d_shader_parser_error(&d3dbc->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY,
"Failed to create sampler descriptor for combined sampler %u.", sampler_idx);
else if (source_info && source_info->shadow_samplers & (1u << sampler_idx))
d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE;
}
/* Read a parameter token from the input stream, and possibly a relative

View File

@@ -1680,6 +1680,7 @@ static enum vkd3d_result vsir_program_lower_texcrd(struct vsir_program *program,
static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *program,
struct vkd3d_shader_instruction *ins, struct vkd3d_shader_message_context *message_context)
{
const struct vkd3d_shader_descriptor_info1 *sampler;
unsigned int idx = ins->src[0].reg.idx[0].offset;
struct vkd3d_shader_src_param *srcs;
@@ -1692,7 +1693,7 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr
return VKD3D_ERROR_NOT_IMPLEMENTED;
}
if (!(srcs = vsir_program_get_src_params(program, 3)))
if (!(srcs = vsir_program_get_src_params(program, 4)))
return VKD3D_ERROR_OUT_OF_MEMORY;
/* Note we run before I/O normalization. */
@@ -1700,9 +1701,26 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr
vsir_src_param_init_resource(&srcs[1], idx, idx);
vsir_src_param_init_sampler(&srcs[2], idx, idx);
ins->opcode = VSIR_OP_SAMPLE;
ins->src = srcs;
ins->src_count = 3;
sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx);
if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE)
{
enum vkd3d_shader_swizzle_component ref = vsir_swizzle_get_component(srcs[0].swizzle, 2);
ins->opcode = VSIR_OP_SAMPLE_C;
ins->src = srcs;
ins->src_count = 4;
srcs[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
srcs[3] = srcs[0];
srcs[3].swizzle = vkd3d_shader_create_swizzle(ref, ref, ref, ref);
}
else
{
ins->opcode = VSIR_OP_SAMPLE;
ins->src = srcs;
ins->src_count = 3;
}
return VKD3D_OK;
}
@@ -1762,6 +1780,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program,
static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program,
struct vkd3d_shader_instruction *tex, struct vkd3d_shader_message_context *message_context)
{
const struct vkd3d_shader_descriptor_info1 *sampler;
unsigned int idx = tex->src[1].reg.idx[0].offset;
struct vkd3d_shader_src_param *srcs;
@@ -1775,7 +1794,21 @@ static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program,
vsir_src_param_init_resource(&srcs[1], idx, idx);
vsir_src_param_init_sampler(&srcs[2], idx, idx);
if (!tex->flags)
sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx);
if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE)
{
enum vkd3d_shader_swizzle_component ref = vsir_swizzle_get_component(srcs[0].swizzle, 2);
tex->opcode = VSIR_OP_SAMPLE_C;
tex->src = srcs;
tex->src_count = 4;
srcs[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
srcs[3] = srcs[0];
srcs[3].swizzle = vkd3d_shader_create_swizzle(ref, ref, ref, ref);
}
else if (!tex->flags)
{
tex->opcode = VSIR_OP_SAMPLE;
tex->src = srcs;
@@ -1857,6 +1890,7 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program,
static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, struct vkd3d_shader_instruction *ins)
{
const struct vkd3d_shader_descriptor_info1 *sampler;
unsigned int idx = ins->dst[0].reg.idx[0].offset;
struct vkd3d_shader_src_param *srcs;
@@ -1866,7 +1900,7 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, st
/* We run before I/O normalization. */
VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6);
if (!(srcs = vsir_program_get_src_params(program, 3)))
if (!(srcs = vsir_program_get_src_params(program, 4)))
return VKD3D_ERROR_OUT_OF_MEMORY;
vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1);
@@ -1877,9 +1911,24 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, st
vsir_src_param_init_resource(&srcs[1], idx, idx);
vsir_src_param_init_sampler(&srcs[2], idx, idx);
ins->opcode = VSIR_OP_SAMPLE;
ins->src = srcs;
ins->src_count = 3;
sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx);
if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE)
{
ins->opcode = VSIR_OP_SAMPLE_C;
ins->src = srcs;
ins->src_count = 4;
srcs[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
srcs[3] = srcs[0];
srcs[3].swizzle = VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z);
}
else
{
ins->opcode = VSIR_OP_SAMPLE;
ins->src = srcs;
ins->src_count = 3;
}
return VKD3D_OK;
}