mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-18 04:40:26 +01:00
v3dv/descriptor_set: combine texture and sampler indices
OpenGL doesn't have the concept of individual texture and sampler, so texture and sampler indexes have the same value. v3d compiler uses this assumption, so for example, the texture info at the v3d key include values that you need to use the texture format and the sampler to fill (like the return_size). One option would be to adapt the v3d compiler to handle both, but then we would need to adapt to the lowerings it uses, like nir_lower_tex, that also take the same assumption. We deal with this on the Vulkan driver, by reassigning the texture and sampler index to a combined one. We add a hash table to map the combined texture idx and sampler idx to this combined idx, and a simple array to the opposite map. On the driver we work with the separate indices to fill up the data, while the v3d compiler works with the combined one. As mentioned, this is needed to properly fill up the texture return size, so as we are here, we fix that. This gets tests like the following working: dEQP-VK.glsl.texture_gather.basic.2d.depth32f.base_level.level_2 Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
parent
9d8b1b01c3
commit
ee917d2b78
6 changed files with 141 additions and 25 deletions
|
|
@ -1951,35 +1951,55 @@ static bool
|
|||
cmd_buffer_populate_v3d_key(struct v3d_key *key,
|
||||
struct v3dv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
struct v3dv_descriptor_map *texture_map = &cmd_buffer->state.pipeline->texture_map;
|
||||
struct v3dv_descriptor_state *descriptor_state =
|
||||
&cmd_buffer->state.descriptor_state;
|
||||
if (cmd_buffer->state.pipeline->combined_index_map != NULL) {
|
||||
struct v3dv_descriptor_map *texture_map = &cmd_buffer->state.pipeline->texture_map;
|
||||
struct v3dv_descriptor_map *sampler_map = &cmd_buffer->state.pipeline->sampler_map;
|
||||
struct v3dv_descriptor_state *descriptor_state =
|
||||
&cmd_buffer->state.descriptor_state;
|
||||
|
||||
for (uint32_t i = 0; i < texture_map->num_desc; i++) {
|
||||
struct v3dv_image_view *image_view =
|
||||
v3dv_descriptor_map_get_image_view(descriptor_state,
|
||||
texture_map,
|
||||
hash_table_foreach(cmd_buffer->state.pipeline->combined_index_map, entry) {
|
||||
uint32_t combined_idx = (uint32_t)(uintptr_t) (entry->data);
|
||||
uint32_t combined_idx_key =
|
||||
cmd_buffer->state.pipeline->combined_index_to_key_map[combined_idx];
|
||||
uint32_t texture_idx;
|
||||
uint32_t sampler_idx;
|
||||
|
||||
v3dv_pipeline_combined_index_key_unpack(combined_idx_key,
|
||||
&texture_idx, &sampler_idx);
|
||||
|
||||
struct v3dv_image_view *image_view =
|
||||
v3dv_descriptor_map_get_image_view(descriptor_state,
|
||||
texture_map,
|
||||
cmd_buffer->state.pipeline->layout,
|
||||
texture_idx);
|
||||
|
||||
if (image_view == NULL)
|
||||
return false;
|
||||
|
||||
const struct v3dv_sampler *sampler =
|
||||
v3dv_descriptor_map_get_sampler(descriptor_state,
|
||||
sampler_map,
|
||||
cmd_buffer->state.pipeline->layout,
|
||||
i);
|
||||
sampler_idx);
|
||||
if (sampler == NULL)
|
||||
return false;
|
||||
|
||||
if (image_view == NULL)
|
||||
return false;
|
||||
key->tex[combined_idx].return_size =
|
||||
v3dv_get_tex_return_size(image_view->format,
|
||||
sampler ? sampler->compare_enable : false);
|
||||
|
||||
key->tex[i].return_size =
|
||||
v3dv_get_tex_return_size(image_view->format,
|
||||
0); /* FIXME: how to get the sampler compare mode? */
|
||||
|
||||
if (key->tex[i].return_size == 16) {
|
||||
key->tex[i].return_channels = 2;
|
||||
} else {
|
||||
key->tex[i].return_channels = 4;
|
||||
}
|
||||
if (key->tex[combined_idx].return_size == 16) {
|
||||
key->tex[combined_idx].return_channels = 2;
|
||||
} else {
|
||||
key->tex[combined_idx].return_channels = 4;
|
||||
}
|
||||
|
||||
/* Note: we don't need to do anything for the swizzle, as that is
|
||||
* handled with the swizzle info at the Texture State, and the
|
||||
* default values for key->tex[].swizzle were already filled up on
|
||||
* the pipeline populate.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -2036,6 +2036,7 @@ v3dv_CreateSampler(VkDevice _device,
|
|||
}
|
||||
}
|
||||
|
||||
sampler->compare_enable = pCreateInfo->compareEnable;
|
||||
pack_sampler_state(sampler, pCreateInfo);
|
||||
|
||||
*pSampler = v3dv_sampler_to_handle(sampler);
|
||||
|
|
|
|||
|
|
@ -310,9 +310,9 @@ v3dv_get_format_swizzle(VkFormat f)
|
|||
|
||||
uint8_t
|
||||
v3dv_get_tex_return_size(const struct v3dv_format *vf,
|
||||
enum pipe_tex_compare compare)
|
||||
bool compare_enable)
|
||||
{
|
||||
if (compare == PIPE_TEX_COMPARE_R_TO_TEXTURE)
|
||||
if (compare_enable)
|
||||
return 16;
|
||||
|
||||
return vf->return_size;
|
||||
|
|
|
|||
|
|
@ -131,6 +131,9 @@ v3dv_DestroyPipeline(VkDevice _device,
|
|||
pipeline->default_attribute_values = NULL;
|
||||
}
|
||||
|
||||
if (pipeline->combined_index_map)
|
||||
_mesa_hash_table_destroy(pipeline->combined_index_map, NULL);
|
||||
|
||||
vk_free2(&device->alloc, pAllocator, pipeline);
|
||||
}
|
||||
|
||||
|
|
@ -504,6 +507,41 @@ lower_vulkan_resource_index(nir_builder *b,
|
|||
nir_instr_remove(&instr->instr);
|
||||
}
|
||||
|
||||
static struct hash_table *
|
||||
pipeline_ensure_combined_index_map(struct v3dv_pipeline *pipeline)
|
||||
{
|
||||
if (pipeline->combined_index_map == NULL) {
|
||||
pipeline->combined_index_map =
|
||||
_mesa_hash_table_create(NULL, _mesa_hash_u32, _mesa_key_u32_equal);
|
||||
pipeline->next_combined_index = 0;
|
||||
}
|
||||
|
||||
assert(pipeline->combined_index_map);
|
||||
|
||||
return pipeline->combined_index_map;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_combined_index(struct v3dv_pipeline *pipeline,
|
||||
uint32_t texture_index,
|
||||
uint32_t sampler_index)
|
||||
{
|
||||
struct hash_table *ht = pipeline_ensure_combined_index_map(pipeline);
|
||||
uint32_t key = v3dv_pipeline_combined_index_key_create(texture_index, sampler_index);
|
||||
struct hash_entry *entry = _mesa_hash_table_search(ht, &key);
|
||||
|
||||
if (entry)
|
||||
return (uint32_t)(uintptr_t) (entry->data);
|
||||
|
||||
uint32_t new_index = pipeline->next_combined_index;
|
||||
|
||||
_mesa_hash_table_insert(ht, &key, (void *)(uintptr_t) (new_index));
|
||||
pipeline->combined_index_to_key_map[new_index] = key;
|
||||
pipeline->next_combined_index++;
|
||||
|
||||
return new_index;
|
||||
}
|
||||
|
||||
static void
|
||||
lower_tex_src_to_offset(nir_builder *b, nir_tex_instr *instr, unsigned src_idx,
|
||||
struct v3dv_pipeline *pipeline,
|
||||
|
|
@ -600,6 +638,12 @@ lower_sampler(nir_builder *b, nir_tex_instr *instr,
|
|||
if (texture_idx < 0 && sampler_idx < 0)
|
||||
return false;
|
||||
|
||||
int combined_index =
|
||||
get_combined_index(pipeline, instr->texture_index, instr->sampler_index);
|
||||
|
||||
instr->texture_index = combined_index;
|
||||
instr->sampler_index = combined_index;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1018,6 +1018,8 @@ struct v3dv_descriptor_map {
|
|||
};
|
||||
|
||||
struct v3dv_sampler {
|
||||
bool compare_enable;
|
||||
|
||||
/* FIXME: here we store the packet SAMPLER_STATE, that is referenced as part
|
||||
* of the tmu configuration, and the content is set per sampler. A possible
|
||||
* perf improvement, to avoid bo fragmentation, would be to save the state
|
||||
|
|
@ -1028,6 +1030,32 @@ struct v3dv_sampler {
|
|||
struct v3dv_bo *state;
|
||||
};
|
||||
|
||||
/*
|
||||
* Following two methods are using on the combined to/from texture/sampler
|
||||
* indices maps at v3dv_pipeline.
|
||||
*/
|
||||
static inline uint32_t
|
||||
v3dv_pipeline_combined_index_key_create(uint32_t texture_index,
|
||||
uint32_t sampler_index)
|
||||
{
|
||||
return texture_index << 24 | sampler_index;
|
||||
}
|
||||
|
||||
static inline void
|
||||
v3dv_pipeline_combined_index_key_unpack(uint32_t combined_index_key,
|
||||
uint32_t *texture_index,
|
||||
uint32_t *sampler_index)
|
||||
{
|
||||
uint32_t texture = combined_index_key >> 24;
|
||||
uint32_t sampler = combined_index_key & 0xffffff;
|
||||
|
||||
if (texture_index)
|
||||
*texture_index = texture;
|
||||
|
||||
if (sampler_index)
|
||||
*sampler_index = sampler;
|
||||
}
|
||||
|
||||
struct v3dv_pipeline {
|
||||
struct v3dv_device *device;
|
||||
|
||||
|
|
@ -1084,6 +1112,21 @@ struct v3dv_pipeline {
|
|||
struct v3dv_descriptor_map sampler_map;
|
||||
struct v3dv_descriptor_map texture_map;
|
||||
|
||||
/*
|
||||
* Vulkan has separate texture and sampler objects. Previous sampler and
|
||||
* texture map uses a sampler and texture index respectively, that can be
|
||||
* different. But OpenGL combine both (or in other words, they are the
|
||||
* same). The v3d compiler and all the nir lowerings that they use were
|
||||
* written under that assumption. In order to not update all those, we
|
||||
* combine the indexes, and we use the following maps to get one or the
|
||||
* other. In general the driver side uses the tex/sampler indexes to gather
|
||||
* resources, and the compiler side uses the combined index (so the v3d key
|
||||
* texture info will be indexed using the combined index).
|
||||
*/
|
||||
struct hash_table *combined_index_map;
|
||||
uint32_t combined_index_to_key_map[32];
|
||||
uint32_t next_combined_index;
|
||||
|
||||
/* FIXME: this bo is another candidate to data to be uploaded using a
|
||||
* resource manager, instead of a individual bo
|
||||
*/
|
||||
|
|
@ -1204,7 +1247,7 @@ void v3dv_loge_v(const char *format, va_list va);
|
|||
const struct v3dv_format *v3dv_get_format(VkFormat);
|
||||
const uint8_t *v3dv_get_format_swizzle(VkFormat f);
|
||||
void v3dv_get_internal_type_bpp_for_output_format(uint32_t format, uint32_t *type, uint32_t *bpp);
|
||||
uint8_t v3dv_get_tex_return_size(const struct v3dv_format *vf, enum pipe_tex_compare compare);
|
||||
uint8_t v3dv_get_tex_return_size(const struct v3dv_format *vf, bool compare_enable);
|
||||
|
||||
|
||||
uint32_t v3d_utile_width(int cpp);
|
||||
|
|
|
|||
|
|
@ -89,14 +89,18 @@ write_tmu_p0(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
uint32_t data)
|
||||
{
|
||||
int unit = v3d_unit_data_get_unit(data);
|
||||
|
||||
uint32_t texture_idx;
|
||||
struct v3dv_job *job = cmd_buffer->state.job;
|
||||
struct v3dv_descriptor_state *descriptor_state =
|
||||
&cmd_buffer->state.descriptor_state;
|
||||
|
||||
v3dv_pipeline_combined_index_key_unpack(pipeline->combined_index_to_key_map[unit],
|
||||
&texture_idx,
|
||||
NULL);
|
||||
|
||||
struct v3dv_image_view *image_view =
|
||||
v3dv_descriptor_map_get_image_view(descriptor_state, &pipeline->texture_map,
|
||||
pipeline->layout, unit);
|
||||
pipeline->layout, texture_idx);
|
||||
|
||||
assert(image_view);
|
||||
|
||||
|
|
@ -116,13 +120,17 @@ write_tmu_p1(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
uint32_t data)
|
||||
{
|
||||
uint32_t unit = v3d_unit_data_get_unit(data);
|
||||
uint32_t sampler_idx;
|
||||
struct v3dv_job *job = cmd_buffer->state.job;
|
||||
struct v3dv_descriptor_state *descriptor_state =
|
||||
&cmd_buffer->state.descriptor_state;
|
||||
|
||||
v3dv_pipeline_combined_index_key_unpack(pipeline->combined_index_to_key_map[unit],
|
||||
NULL, &sampler_idx);
|
||||
|
||||
const struct v3dv_sampler *sampler =
|
||||
v3dv_descriptor_map_get_sampler(descriptor_state, &pipeline->sampler_map,
|
||||
pipeline->layout, unit);
|
||||
pipeline->layout, sampler_idx);
|
||||
|
||||
assert(sampler);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue