mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader: Add support for combined samplers.
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:
committed by
Alexandre Julliard
parent
063f0f057a
commit
11de335abd
@@ -91,6 +91,18 @@ struct vkd3d_shader_resource_binding
|
|||||||
struct vkd3d_shader_descriptor_binding binding;
|
struct vkd3d_shader_descriptor_binding binding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define VKD3D_DUMMY_SAMPLER_INDEX ~0u
|
||||||
|
|
||||||
|
struct vkd3d_shader_combined_resource_sampler
|
||||||
|
{
|
||||||
|
unsigned int resource_index;
|
||||||
|
unsigned int sampler_index;
|
||||||
|
enum vkd3d_shader_visibility shader_visibility;
|
||||||
|
bool is_buffer;
|
||||||
|
|
||||||
|
struct vkd3d_shader_descriptor_binding binding;
|
||||||
|
};
|
||||||
|
|
||||||
struct vkd3d_shader_uav_counter_binding
|
struct vkd3d_shader_uav_counter_binding
|
||||||
{
|
{
|
||||||
unsigned int register_index; /* u# */
|
unsigned int register_index; /* u# */
|
||||||
@@ -116,6 +128,9 @@ struct vkd3d_shader_interface
|
|||||||
const struct vkd3d_shader_push_constant_buffer *push_constant_buffers;
|
const struct vkd3d_shader_push_constant_buffer *push_constant_buffers;
|
||||||
unsigned int push_constant_buffer_count;
|
unsigned int push_constant_buffer_count;
|
||||||
|
|
||||||
|
const struct vkd3d_shader_combined_resource_sampler *combined_samplers;
|
||||||
|
unsigned int combined_sampler_count;
|
||||||
|
|
||||||
/* A sampler used by OpImageFetches generated for SM4 ld instructions.
|
/* A sampler used by OpImageFetches generated for SM4 ld instructions.
|
||||||
*
|
*
|
||||||
* In Vulkan OpImageFetch must be used with a sampled image.
|
* In Vulkan OpImageFetch must be used with a sampled image.
|
||||||
|
@@ -1676,6 +1676,12 @@ struct vkd3d_symbol_resource
|
|||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct vkd3d_symbol_combined_sampler
|
||||||
|
{
|
||||||
|
unsigned int resource_idx;
|
||||||
|
unsigned int sampler_idx;
|
||||||
|
};
|
||||||
|
|
||||||
struct vkd3d_symbol_register_data
|
struct vkd3d_symbol_register_data
|
||||||
{
|
{
|
||||||
SpvStorageClass storage_class;
|
SpvStorageClass storage_class;
|
||||||
@@ -1703,12 +1709,14 @@ struct vkd3d_symbol
|
|||||||
{
|
{
|
||||||
VKD3D_SYMBOL_REGISTER,
|
VKD3D_SYMBOL_REGISTER,
|
||||||
VKD3D_SYMBOL_RESOURCE,
|
VKD3D_SYMBOL_RESOURCE,
|
||||||
|
VKD3D_SYMBOL_COMBINED_SAMPLER,
|
||||||
} type;
|
} type;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct vkd3d_symbol_register reg;
|
struct vkd3d_symbol_register reg;
|
||||||
struct vkd3d_symbol_resource resource;
|
struct vkd3d_symbol_resource resource;
|
||||||
|
struct vkd3d_symbol_combined_sampler combined_sampler;
|
||||||
} key;
|
} key;
|
||||||
|
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@@ -1757,6 +1765,15 @@ static void vkd3d_symbol_make_resource(struct vkd3d_symbol *symbol,
|
|||||||
symbol->key.resource.idx = reg->idx[0].offset;
|
symbol->key.resource.idx = reg->idx[0].offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vkd3d_symbol_make_combined_sampler(struct vkd3d_symbol *symbol,
|
||||||
|
unsigned int resource_index, unsigned int sampler_index)
|
||||||
|
{
|
||||||
|
symbol->type = VKD3D_SYMBOL_COMBINED_SAMPLER;
|
||||||
|
memset(&symbol->key, 0, sizeof(symbol->key));
|
||||||
|
symbol->key.combined_sampler.resource_idx = resource_index;
|
||||||
|
symbol->key.combined_sampler.sampler_idx = sampler_index;
|
||||||
|
}
|
||||||
|
|
||||||
static struct vkd3d_symbol *vkd3d_symbol_dup(const struct vkd3d_symbol *symbol)
|
static struct vkd3d_symbol *vkd3d_symbol_dup(const struct vkd3d_symbol *symbol)
|
||||||
{
|
{
|
||||||
struct vkd3d_symbol *s;
|
struct vkd3d_symbol *s;
|
||||||
@@ -2009,6 +2026,31 @@ static struct vkd3d_push_constant_buffer_binding *vkd3d_dxbc_compiler_find_push_
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool vkd3d_dxbc_compiler_have_combined_sampler(const struct vkd3d_dxbc_compiler *compiler,
|
||||||
|
const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler)
|
||||||
|
{
|
||||||
|
const struct vkd3d_shader_interface *shader_interface = &compiler->shader_interface;
|
||||||
|
const struct vkd3d_shader_combined_resource_sampler *combined_sampler;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!shader_interface->combined_sampler_count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (resource && resource->type == VKD3DSPR_UAV)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (i = 0; i < shader_interface->combined_sampler_count; ++i)
|
||||||
|
{
|
||||||
|
combined_sampler = &shader_interface->combined_samplers[i];
|
||||||
|
|
||||||
|
if (!(resource || combined_sampler->resource_index == resource->idx[0].offset)
|
||||||
|
&& (!sampler || combined_sampler->sampler_index == sampler->idx[0].offset))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding(
|
static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding(
|
||||||
struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg,
|
struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg,
|
||||||
enum vkd3d_shader_resource_type resource_type, bool is_uav_counter)
|
enum vkd3d_shader_resource_type resource_type, bool is_uav_counter)
|
||||||
@@ -3753,6 +3795,9 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com
|
|||||||
uint32_t type_id, ptr_type_id, var_id;
|
uint32_t type_id, ptr_type_id, var_id;
|
||||||
struct vkd3d_symbol reg_symbol;
|
struct vkd3d_symbol reg_symbol;
|
||||||
|
|
||||||
|
if (vkd3d_dxbc_compiler_have_combined_sampler(compiler, NULL, reg))
|
||||||
|
return;
|
||||||
|
|
||||||
type_id = vkd3d_spirv_get_op_type_sampler(builder);
|
type_id = vkd3d_spirv_get_op_type_sampler(builder);
|
||||||
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
|
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
|
||||||
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
|
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
|
||||||
@@ -3852,6 +3897,64 @@ static uint32_t vkd3d_dxbc_compiler_get_image_type_id(struct vkd3d_dxbc_compiler
|
|||||||
reg->type == VKD3DSPR_UAV ? 2 : 1, format);
|
reg->type == VKD3DSPR_UAV ? 2 : 1, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vkd3d_dxbc_compiler_emit_combined_sampler_declarations(struct vkd3d_dxbc_compiler *compiler,
|
||||||
|
const struct vkd3d_shader_register *resource, enum vkd3d_shader_resource_type resource_type,
|
||||||
|
enum vkd3d_component_type sampled_type, unsigned int structure_stride, bool raw,
|
||||||
|
const struct vkd3d_spirv_resource_type *resource_type_info)
|
||||||
|
{
|
||||||
|
const struct vkd3d_shader_interface *shader_interface = &compiler->shader_interface;
|
||||||
|
const struct vkd3d_shader_scan_info *scan_info = compiler->scan_info;
|
||||||
|
const SpvStorageClass storage_class = SpvStorageClassUniformConstant;
|
||||||
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||||||
|
const struct vkd3d_shader_combined_resource_sampler *current;
|
||||||
|
const unsigned int resource_index = resource->idx[0].offset;
|
||||||
|
uint32_t image_type_id, type_id, ptr_type_id, var_id;
|
||||||
|
bool is_buffer_resource, depth;
|
||||||
|
struct vkd3d_symbol symbol;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
is_buffer_resource = resource_type == VKD3D_SHADER_RESOURCE_BUFFER;
|
||||||
|
|
||||||
|
for (i = 0; i < shader_interface->combined_sampler_count; ++i)
|
||||||
|
{
|
||||||
|
current = &shader_interface->combined_samplers[i];
|
||||||
|
|
||||||
|
if (current->resource_index != resource_index || current->is_buffer != is_buffer_resource)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!vkd3d_dxbc_compiler_check_shader_visibility(compiler, current->shader_visibility))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
depth = current->sampler_index != VKD3D_DUMMY_SAMPLER_INDEX
|
||||||
|
&& scan_info->sampler_comparison_mode_mask & (1u << current->sampler_index);
|
||||||
|
|
||||||
|
image_type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler,
|
||||||
|
resource, resource_type_info, sampled_type, structure_stride || raw, depth);
|
||||||
|
type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image_type_id);
|
||||||
|
|
||||||
|
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
|
||||||
|
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
|
||||||
|
ptr_type_id, storage_class, 0);
|
||||||
|
|
||||||
|
vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, ¤t->binding);
|
||||||
|
|
||||||
|
if (current->sampler_index == VKD3D_DUMMY_SAMPLER_INDEX)
|
||||||
|
vkd3d_spirv_build_op_name(builder, var_id, "t%u_dummy_sampler", resource_index);
|
||||||
|
else
|
||||||
|
vkd3d_spirv_build_op_name(builder, var_id, "t%u_s%u", resource_index, current->sampler_index);
|
||||||
|
|
||||||
|
vkd3d_symbol_make_combined_sampler(&symbol, resource_index, current->sampler_index);
|
||||||
|
symbol.id = var_id;
|
||||||
|
symbol.info.resource.sampled_type = sampled_type;
|
||||||
|
symbol.info.resource.type_id = image_type_id;
|
||||||
|
symbol.info.resource.resource_type_info = resource_type_info;
|
||||||
|
symbol.info.resource.structure_stride = structure_stride;
|
||||||
|
symbol.info.resource.raw = raw;
|
||||||
|
symbol.info.resource.uav_counter_id = 0;
|
||||||
|
vkd3d_dxbc_compiler_put_symbol(compiler, &symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_compiler *compiler,
|
static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_compiler *compiler,
|
||||||
const struct vkd3d_shader_register *reg, enum vkd3d_shader_resource_type resource_type,
|
const struct vkd3d_shader_register *reg, enum vkd3d_shader_resource_type resource_type,
|
||||||
enum vkd3d_data_type resource_data_type, unsigned int structure_stride, bool raw)
|
enum vkd3d_data_type resource_data_type, unsigned int structure_stride, bool raw)
|
||||||
@@ -3875,6 +3978,13 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
|
|||||||
|
|
||||||
sampled_type = vkd3d_component_type_from_data_type(resource_data_type);
|
sampled_type = vkd3d_component_type_from_data_type(resource_data_type);
|
||||||
|
|
||||||
|
if (vkd3d_dxbc_compiler_have_combined_sampler(compiler, reg, NULL))
|
||||||
|
{
|
||||||
|
vkd3d_dxbc_compiler_emit_combined_sampler_declarations(compiler,
|
||||||
|
reg, resource_type, sampled_type, structure_stride, raw, resource_type_info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler,
|
type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler,
|
||||||
reg, resource_type_info, sampled_type, structure_stride || raw, 0);
|
reg, resource_type_info, sampled_type, structure_stride || raw, 0);
|
||||||
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
|
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
|
||||||
@@ -5350,27 +5460,65 @@ static const struct vkd3d_symbol *vkd3d_dxbc_compiler_find_resource(struct vkd3d
|
|||||||
return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
|
return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct vkd3d_symbol *vkd3d_dxbc_compiler_find_combined_sampler(struct vkd3d_dxbc_compiler *compiler,
|
||||||
|
const struct vkd3d_shader_register *resource_reg, const struct vkd3d_shader_register *sampler_reg)
|
||||||
|
{
|
||||||
|
const struct vkd3d_shader_interface *shader_interface = &compiler->shader_interface;
|
||||||
|
unsigned int resource_index, sampler_index;
|
||||||
|
struct vkd3d_symbol key;
|
||||||
|
struct rb_entry *entry;
|
||||||
|
|
||||||
|
if (!shader_interface->combined_sampler_count)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
resource_index = resource_reg->idx[0].offset;
|
||||||
|
sampler_index = sampler_reg ? sampler_reg->idx[0].offset : VKD3D_DUMMY_SAMPLER_INDEX;
|
||||||
|
|
||||||
|
vkd3d_symbol_make_combined_sampler(&key, resource_index, sampler_index);
|
||||||
|
if ((entry = rb_get(&compiler->symbol_table, &key)))
|
||||||
|
return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compiler,
|
static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compiler,
|
||||||
struct vkd3d_shader_image *image, const struct vkd3d_shader_register *resource_reg,
|
struct vkd3d_shader_image *image, const struct vkd3d_shader_register *resource_reg,
|
||||||
const struct vkd3d_shader_register *sampler_reg, unsigned int flags)
|
const struct vkd3d_shader_register *sampler_reg, unsigned int flags)
|
||||||
{
|
{
|
||||||
|
const struct vkd3d_symbol *symbol = NULL, *combined_sampler = NULL;
|
||||||
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||||||
uint32_t sampler_var_id, sampler_id, sampled_image_type_id;
|
uint32_t sampler_var_id, sampler_id, sampled_image_type_id;
|
||||||
const struct vkd3d_symbol *resource_symbol;
|
|
||||||
bool load, depth_comparison;
|
bool load, depth_comparison;
|
||||||
|
|
||||||
load = !(flags & VKD3D_IMAGE_FLAG_NO_LOAD);
|
load = !(flags & VKD3D_IMAGE_FLAG_NO_LOAD);
|
||||||
depth_comparison = flags & VKD3D_IMAGE_FLAG_DEPTH;
|
depth_comparison = flags & VKD3D_IMAGE_FLAG_DEPTH;
|
||||||
|
|
||||||
resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, resource_reg);
|
if (flags & VKD3D_IMAGE_FLAG_SAMPLED)
|
||||||
|
{
|
||||||
|
assert(load);
|
||||||
|
combined_sampler = vkd3d_dxbc_compiler_find_combined_sampler(compiler,
|
||||||
|
resource_reg, sampler_reg);
|
||||||
|
symbol = combined_sampler;
|
||||||
|
}
|
||||||
|
if (!symbol)
|
||||||
|
symbol = vkd3d_dxbc_compiler_find_resource(compiler, resource_reg);
|
||||||
|
|
||||||
image->sampled_type = resource_symbol->info.resource.sampled_type;
|
image->id = symbol->id;
|
||||||
image->image_type_id = resource_symbol->info.resource.type_id;
|
image->sampled_type = symbol->info.resource.sampled_type;
|
||||||
image->resource_type_info = resource_symbol->info.resource.resource_type_info;
|
image->image_type_id = symbol->info.resource.type_id;
|
||||||
image->structure_stride = resource_symbol->info.resource.structure_stride;
|
image->resource_type_info = symbol->info.resource.resource_type_info;
|
||||||
image->raw = resource_symbol->info.resource.raw;
|
image->structure_stride = symbol->info.resource.structure_stride;
|
||||||
|
image->raw = symbol->info.resource.raw;
|
||||||
|
|
||||||
|
if (combined_sampler)
|
||||||
|
{
|
||||||
|
sampled_image_type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image->image_type_id);
|
||||||
|
image->sampled_image_id = vkd3d_spirv_build_op_load(builder,
|
||||||
|
sampled_image_type_id, image->id, SpvMemoryAccessMaskNone);
|
||||||
|
image->image_id = vkd3d_spirv_build_op_image(builder,
|
||||||
|
image->image_type_id, image->sampled_image_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
image->id = resource_symbol->id;
|
|
||||||
image->image_id = load ? vkd3d_spirv_build_op_load(builder,
|
image->image_id = load ? vkd3d_spirv_build_op_load(builder,
|
||||||
image->image_type_id, image->id, SpvMemoryAccessMaskNone) : 0;
|
image->image_type_id, image->id, SpvMemoryAccessMaskNone) : 0;
|
||||||
|
|
||||||
|
@@ -1434,6 +1434,8 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
|
|||||||
shader_interface.binding_count = root_signature->descriptor_count;
|
shader_interface.binding_count = root_signature->descriptor_count;
|
||||||
shader_interface.push_constant_buffers = root_signature->root_constants;
|
shader_interface.push_constant_buffers = root_signature->root_constants;
|
||||||
shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
|
shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
|
||||||
|
shader_interface.combined_samplers = NULL;
|
||||||
|
shader_interface.combined_sampler_count = 0;
|
||||||
shader_interface.dummy_sampler = root_signature->dummy_sampler;
|
shader_interface.dummy_sampler = root_signature->dummy_sampler;
|
||||||
shader_interface.uav_counters = state->uav_counters;
|
shader_interface.uav_counters = state->uav_counters;
|
||||||
shader_interface.uav_counter_count = vkd3d_popcount(state->uav_counter_mask);
|
shader_interface.uav_counter_count = vkd3d_popcount(state->uav_counter_mask);
|
||||||
@@ -2002,6 +2004,8 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
|
|||||||
shader_interface.binding_count = root_signature->descriptor_count;
|
shader_interface.binding_count = root_signature->descriptor_count;
|
||||||
shader_interface.push_constant_buffers = root_signature->root_constants;
|
shader_interface.push_constant_buffers = root_signature->root_constants;
|
||||||
shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
|
shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
|
||||||
|
shader_interface.combined_samplers = NULL;
|
||||||
|
shader_interface.combined_sampler_count = 0;
|
||||||
shader_interface.dummy_sampler = root_signature->dummy_sampler;
|
shader_interface.dummy_sampler = root_signature->dummy_sampler;
|
||||||
shader_interface.uav_counters = NULL;
|
shader_interface.uav_counters = NULL;
|
||||||
shader_interface.uav_counter_count = 0;
|
shader_interface.uav_counter_count = 0;
|
||||||
|
Reference in New Issue
Block a user