summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/intel/vulkan/anv_descriptor_set.c43
-rw-r--r--src/intel/vulkan/anv_device.c6
-rw-r--r--src/intel/vulkan/anv_nir_apply_pipeline_layout.c91
-rw-r--r--src/intel/vulkan/anv_private.h9
4 files changed, 122 insertions, 27 deletions
diff --git a/src/intel/vulkan/anv_descriptor_set.c b/src/intel/vulkan/anv_descriptor_set.c
index 004d3f2f77f..90a02997a8d 100644
--- a/src/intel/vulkan/anv_descriptor_set.c
+++ b/src/intel/vulkan/anv_descriptor_set.c
@@ -125,22 +125,60 @@ anv_descriptor_type_size(const struct anv_physical_device *pdevice,
return anv_descriptor_data_size(anv_descriptor_data_for_type(pdevice, type));
}
+static bool
+anv_descriptor_data_supports_bindless(const struct anv_physical_device *pdevice,
+ enum anv_descriptor_data data,
+ bool sampler)
+{
+ return false;
+}
+
+bool
+anv_descriptor_supports_bindless(const struct anv_physical_device *pdevice,
+ const struct anv_descriptor_set_binding_layout *binding,
+ bool sampler)
+{
+ return anv_descriptor_data_supports_bindless(pdevice, binding->data,
+ sampler);
+}
+
+bool
+anv_descriptor_requires_bindless(const struct anv_physical_device *pdevice,
+ const struct anv_descriptor_set_binding_layout *binding,
+ bool sampler)
+{
+ if (pdevice->always_use_bindless)
+ return anv_descriptor_supports_bindless(pdevice, binding, sampler);
+
+ return false;
+}
+
void anv_GetDescriptorSetLayoutSupport(
- VkDevice device,
+ VkDevice _device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
VkDescriptorSetLayoutSupport* pSupport)
{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ const struct anv_physical_device *pdevice =
+ &device->instance->physicalDevice;
+
uint32_t surface_count[MESA_SHADER_STAGES] = { 0, };
for (uint32_t b = 0; b < pCreateInfo->bindingCount; b++) {
const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[b];
+ enum anv_descriptor_data desc_data =
+ anv_descriptor_data_for_type(pdevice, binding->descriptorType);
+
switch (binding->descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
/* There is no real limit on samplers */
break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ if (anv_descriptor_data_supports_bindless(pdevice, desc_data, false))
+ break;
+
if (binding->pImmutableSamplers) {
for (uint32_t i = 0; i < binding->descriptorCount; i++) {
ANV_FROM_HANDLE(anv_sampler, sampler,
@@ -155,6 +193,9 @@ void anv_GetDescriptorSetLayoutSupport(
break;
default:
+ if (anv_descriptor_data_supports_bindless(pdevice, desc_data, false))
+ break;
+
anv_foreach_stage(s, binding->stageFlags)
surface_count[s] += binding->descriptorCount;
break;
diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index 71de8865986..2f1260dae2f 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -276,6 +276,8 @@ anv_physical_device_init_uuids(struct anv_physical_device *device)
_mesa_sha1_update(&sha1_ctx, build_id_data(note), build_id_len);
_mesa_sha1_update(&sha1_ctx, &device->chipset_id,
sizeof(device->chipset_id));
+ _mesa_sha1_update(&sha1_ctx, &device->always_use_bindless,
+ sizeof(device->always_use_bindless));
_mesa_sha1_final(&sha1_ctx, sha1);
memcpy(device->pipeline_cache_uuid, sha1, VK_UUID_SIZE);
@@ -451,6 +453,10 @@ anv_physical_device_init(struct anv_physical_device *device,
device->has_context_isolation =
anv_gem_get_param(fd, I915_PARAM_HAS_CONTEXT_ISOLATION);
+ device->always_use_bindless =
+ env_var_as_boolean("ANV_ALWAYS_BINDLESS", false);
+
+
/* Starting with Gen10, the timestamp frequency of the command streamer may
* vary from one part to another. We can query the value from the kernel.
*/
diff --git a/src/intel/vulkan/anv_nir_apply_pipeline_layout.c b/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
index 74f70806586..ea02ed1be78 100644
--- a/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
+++ b/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
@@ -26,6 +26,12 @@
#include "nir/nir_builder.h"
#include "compiler/brw_nir.h"
+/* Sampler tables don't actually have a maximum size but we pick one just so
+ * that we don't end up emitting too much state on-the-fly.
+ */
+#define MAX_SAMPLER_TABLE_SIZE 128
+#define BINDLESS_OFFSET 255
+
struct apply_pipeline_layout_state {
const struct anv_physical_device *pdevice;
@@ -600,11 +606,21 @@ anv_nir_apply_pipeline_layout(const struct anv_physical_device *pdevice,
&layout->set[set].layout->binding[b];
/* Do a fixed-point calculation to generate a score based on the
- * number of uses and the binding array size.
+ * number of uses and the binding array size. We shift by 7 instead
+ * of 8 because we're going to use the top bit below to make
+ * everything which does not support bindless super higher priority
+ * than things which do.
*/
uint16_t score = ((uint16_t)state.set[set].use_count[b] << 7) /
binding->array_size;
+ /* If the descriptor type doesn't support bindless then put it at the
+ * beginning so we guarantee it gets a slot.
+ */
+ if (!anv_descriptor_supports_bindless(pdevice, binding, true) ||
+ !anv_descriptor_supports_bindless(pdevice, binding, false))
+ score |= 1 << 15;
+
infos[used_binding_count++] = (struct binding_info) {
.set = set,
.binding = b,
@@ -624,37 +640,57 @@ anv_nir_apply_pipeline_layout(const struct anv_physical_device *pdevice,
struct anv_descriptor_set_binding_layout *binding =
&layout->set[set].layout->binding[b];
+ const uint32_t array_size = binding->array_size;
+
if (binding->data & ANV_DESCRIPTOR_SURFACE_STATE) {
- state.set[set].surface_offsets[b] = map->surface_count;
- struct anv_sampler **samplers = binding->immutable_samplers;
- for (unsigned i = 0; i < binding->array_size; i++) {
- uint8_t planes = samplers ? samplers[i]->n_planes : 1;
- for (uint8_t p = 0; p < planes; p++) {
- map->surface_to_descriptor[map->surface_count++] =
- (struct anv_pipeline_binding) {
- .set = set,
- .binding = b,
- .index = i,
- .plane = p,
- };
+ if (map->surface_count + array_size > MAX_BINDING_TABLE_SIZE ||
+ anv_descriptor_requires_bindless(pdevice, binding, false)) {
+ /* If this descriptor doesn't fit in the binding table or if it
+ * requires bindless for some reason, flag it as bindless.
+ */
+ assert(anv_descriptor_supports_bindless(pdevice, binding, false));
+ state.set[set].surface_offsets[b] = BINDLESS_OFFSET;
+ } else {
+ state.set[set].surface_offsets[b] = map->surface_count;
+ struct anv_sampler **samplers = binding->immutable_samplers;
+ for (unsigned i = 0; i < binding->array_size; i++) {
+ uint8_t planes = samplers ? samplers[i]->n_planes : 1;
+ for (uint8_t p = 0; p < planes; p++) {
+ map->surface_to_descriptor[map->surface_count++] =
+ (struct anv_pipeline_binding) {
+ .set = set,
+ .binding = b,
+ .index = i,
+ .plane = p,
+ };
+ }
}
}
+ assert(map->surface_count <= MAX_BINDING_TABLE_SIZE);
}
- assert(map->surface_count <= MAX_BINDING_TABLE_SIZE);
if (binding->data & ANV_DESCRIPTOR_SAMPLER_STATE) {
- state.set[set].sampler_offsets[b] = map->sampler_count;
- struct anv_sampler **samplers = binding->immutable_samplers;
- for (unsigned i = 0; i < binding->array_size; i++) {
- uint8_t planes = samplers ? samplers[i]->n_planes : 1;
- for (uint8_t p = 0; p < planes; p++) {
- map->sampler_to_descriptor[map->sampler_count++] =
- (struct anv_pipeline_binding) {
- .set = set,
- .binding = b,
- .index = i,
- .plane = p,
- };
+ if (map->sampler_count + array_size > MAX_SAMPLER_TABLE_SIZE ||
+ anv_descriptor_requires_bindless(pdevice, binding, true)) {
+ /* If this descriptor doesn't fit in the binding table or if it
+ * requires bindless for some reason, flag it as bindless.
+ */
+ assert(anv_descriptor_supports_bindless(pdevice, binding, true));
+ state.set[set].sampler_offsets[b] = BINDLESS_OFFSET;
+ } else {
+ state.set[set].sampler_offsets[b] = map->sampler_count;
+ struct anv_sampler **samplers = binding->immutable_samplers;
+ for (unsigned i = 0; i < binding->array_size; i++) {
+ uint8_t planes = samplers ? samplers[i]->n_planes : 1;
+ for (uint8_t p = 0; p < planes; p++) {
+ map->sampler_to_descriptor[map->sampler_count++] =
+ (struct anv_pipeline_binding) {
+ .set = set,
+ .binding = b,
+ .index = i,
+ .plane = p,
+ };
+ }
}
}
}
@@ -676,6 +712,9 @@ anv_nir_apply_pipeline_layout(const struct anv_physical_device *pdevice,
if (state.set[set].use_count[binding] == 0)
continue;
+ if (state.set[set].surface_offsets[binding] >= MAX_BINDING_TABLE_SIZE)
+ continue;
+
struct anv_pipeline_binding *pipe_binding =
&map->surface_to_descriptor[state.set[set].surface_offsets[binding]];
for (unsigned i = 0; i < array_size; i++) {
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 5ae71b4e8c4..4f22a405d0d 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -949,6 +949,7 @@ struct anv_physical_device {
bool has_context_priority;
bool use_softpin;
bool has_context_isolation;
+ bool always_use_bindless;
struct anv_device_extension_table supported_extensions;
@@ -1565,6 +1566,14 @@ unsigned anv_descriptor_size(const struct anv_descriptor_set_binding_layout *lay
unsigned anv_descriptor_type_size(const struct anv_physical_device *pdevice,
VkDescriptorType type);
+bool anv_descriptor_supports_bindless(const struct anv_physical_device *pdevice,
+ const struct anv_descriptor_set_binding_layout *binding,
+ bool sampler);
+
+bool anv_descriptor_requires_bindless(const struct anv_physical_device *pdevice,
+ const struct anv_descriptor_set_binding_layout *binding,
+ bool sampler);
+
struct anv_descriptor_set_layout {
/* Descriptor set layouts can be destroyed at almost any time */
uint32_t ref_cnt;