zink: implement ARB_texture_buffer_object
the pipe cap for this was enabled for some reason, but the actual functionality
was never implemented
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7132>
diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
index 47971cf..f8c1f34 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
+++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
@@ -446,6 +446,7 @@
return stage_offset + index;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
assert(index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
return stage_offset + PIPE_MAX_CONSTANT_BUFFERS + index;
@@ -500,7 +501,7 @@
spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
int binding = zink_binding(ctx->stage,
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ zink_sampler_type(glsl_without_array(var->type)),
var->data.binding + i);
spirv_builder_emit_binding(&ctx->builder, var_id, binding);
}
@@ -520,7 +521,7 @@
spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
int binding = zink_binding(ctx->stage,
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ zink_sampler_type(var->type),
var->data.binding);
spirv_builder_emit_binding(&ctx->builder, var_id, binding);
}
@@ -2166,6 +2167,8 @@
case MESA_SHADER_FRAGMENT:
case MESA_SHADER_COMPUTE:
spirv_builder_emit_cap(&ctx.builder, SpvCapabilityShader);
+ spirv_builder_emit_cap(&ctx.builder, SpvCapabilityImageBuffer);
+ spirv_builder_emit_cap(&ctx.builder, SpvCapabilitySampledBuffer);
break;
case MESA_SHADER_TESS_CTRL:
diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.h b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.h
index 04543c3..ec170a7 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.h
+++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.h
@@ -28,6 +28,7 @@
#include <stdint.h>
#include <vulkan/vulkan.h>
+#include "compiler/nir/nir.h"
#include "compiler/shader_enums.h"
#include "pipe/p_state.h"
@@ -51,6 +52,18 @@
uint32_t
zink_binding(gl_shader_stage stage, VkDescriptorType type, int index);
+static inline VkDescriptorType
+zink_sampler_type(const struct glsl_type *type)
+{
+ assert(glsl_type_is_sampler(type));
+ if (glsl_get_sampler_dim(type) < GLSL_SAMPLER_DIM_BUF || glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_MS)
+ return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_BUF)
+ return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ unreachable("unimplemented");
+ return 0;
+}
+
struct nir_shader;
bool
diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c
index ad2e6b0..77297d5 100644
--- a/src/gallium/drivers/zink/zink_compiler.c
+++ b/src/gallium/drivers/zink/zink_compiler.c
@@ -311,12 +311,13 @@
} else {
assert(var->data.mode == nir_var_uniform);
if (glsl_type_is_sampler(var->type)) {
+ VkDescriptorType vktype = zink_sampler_type(var->type);
int binding = zink_binding(nir->info.stage,
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ vktype,
var->data.binding);
ret->bindings[ret->num_bindings].index = var->data.binding;
ret->bindings[ret->num_bindings].binding = binding;
- ret->bindings[ret->num_bindings].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ ret->bindings[ret->num_bindings].type = vktype;
ret->num_bindings++;
} else if (glsl_type_is_array(var->type)) {
/* need to unroll possible arrays of arrays before checking type
@@ -325,15 +326,16 @@
const struct glsl_type *type = glsl_without_array(var->type);
if (!glsl_type_is_sampler(type))
continue;
+ VkDescriptorType vktype = zink_sampler_type(type);
unsigned size = glsl_get_aoa_size(var->type);
for (int i = 0; i < size; ++i) {
int binding = zink_binding(nir->info.stage,
- VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ vktype,
var->data.binding + i);
ret->bindings[ret->num_bindings].index = var->data.binding + i;
ret->bindings[ret->num_bindings].binding = binding;
- ret->bindings[ret->num_bindings].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ ret->bindings[ret->num_bindings].type = vktype;
ret->num_bindings++;
}
}
diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 514f705..1b0aaf5 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -252,6 +252,7 @@
struct zink_screen *screen = zink_screen(pctx->screen);
struct zink_resource *res = zink_resource(pres);
struct zink_sampler_view *sampler_view = CALLOC_STRUCT(zink_sampler_view);
+ VkResult err;
sampler_view->base = *state;
sampler_view->base.texture = NULL;
@@ -259,28 +260,38 @@
sampler_view->base.reference.count = 1;
sampler_view->base.context = pctx;
- VkImageViewCreateInfo ivci = {};
- ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- ivci.image = res->image;
- ivci.viewType = image_view_type(state->target);
- ivci.format = zink_get_format(screen, state->format);
- ivci.components.r = component_mapping(state->swizzle_r);
- ivci.components.g = component_mapping(state->swizzle_g);
- ivci.components.b = component_mapping(state->swizzle_b);
- ivci.components.a = component_mapping(state->swizzle_a);
+ if (state->target != PIPE_BUFFER) {
+ VkImageViewCreateInfo ivci = {};
+ ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ ivci.image = res->image;
+ ivci.viewType = image_view_type(state->target);
+ ivci.format = zink_get_format(screen, state->format);
+ ivci.components.r = component_mapping(state->swizzle_r);
+ ivci.components.g = component_mapping(state->swizzle_g);
+ ivci.components.b = component_mapping(state->swizzle_b);
+ ivci.components.a = component_mapping(state->swizzle_a);
- ivci.subresourceRange.aspectMask = sampler_aspect_from_format(state->format);
- ivci.subresourceRange.baseMipLevel = state->u.tex.first_level;
- ivci.subresourceRange.baseArrayLayer = state->u.tex.first_layer;
- ivci.subresourceRange.levelCount = state->u.tex.last_level - state->u.tex.first_level + 1;
- ivci.subresourceRange.layerCount = state->u.tex.last_layer - state->u.tex.first_layer + 1;
+ ivci.subresourceRange.aspectMask = sampler_aspect_from_format(state->format);
+ ivci.subresourceRange.baseMipLevel = state->u.tex.first_level;
+ ivci.subresourceRange.baseArrayLayer = state->u.tex.first_layer;
+ ivci.subresourceRange.levelCount = state->u.tex.last_level - state->u.tex.first_level + 1;
+ ivci.subresourceRange.layerCount = state->u.tex.last_layer - state->u.tex.first_layer + 1;
- VkResult err = vkCreateImageView(screen->dev, &ivci, NULL, &sampler_view->image_view);
+ err = vkCreateImageView(screen->dev, &ivci, NULL, &sampler_view->image_view);
+ } else {
+ VkBufferViewCreateInfo bvci = {};
+ bvci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
+ bvci.buffer = res->buffer;
+ bvci.format = zink_get_format(screen, state->format);
+ bvci.offset = state->u.buf.offset;
+ bvci.range = state->u.buf.size;
+
+ err = vkCreateBufferView(screen->dev, &bvci, NULL, &sampler_view->buffer_view);
+ }
if (err != VK_SUCCESS) {
FREE(sampler_view);
return NULL;
}
-
return &sampler_view->base;
}
@@ -289,7 +300,10 @@
struct pipe_sampler_view *pview)
{
struct zink_sampler_view *view = zink_sampler_view(pview);
- vkDestroyImageView(zink_screen(pctx->screen)->dev, view->image_view, NULL);
+ if (pview->texture->target == PIPE_BUFFER)
+ vkDestroyBufferView(zink_screen(pctx->screen)->dev, view->buffer_view, NULL);
+ else
+ vkDestroyImageView(zink_screen(pctx->screen)->dev, view->image_view, NULL);
pipe_resource_reference(&pview->texture, NULL);
FREE(view);
}
diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h
index e76e256..52c5459 100644
--- a/src/gallium/drivers/zink/zink_context.h
+++ b/src/gallium/drivers/zink/zink_context.h
@@ -48,7 +48,10 @@
struct zink_sampler_view {
struct pipe_sampler_view base;
- VkImageView image_view;
+ union {
+ VkImageView image_view;
+ VkBufferView buffer_view;
+ };
};
static inline struct zink_sampler_view *
diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c
index 6302436..ad5d6fa 100644
--- a/src/gallium/drivers/zink/zink_draw.c
+++ b/src/gallium/drivers/zink/zink_draw.c
@@ -320,18 +320,22 @@
struct zink_sampler_view *sampler_view = zink_sampler_view(psampler_view);
struct zink_resource *res = zink_resource(psampler_view->texture);
- VkImageLayout layout = res->layout;
- if (layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
- layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL &&
- layout != VK_IMAGE_LAYOUT_GENERAL) {
- transitions[num_transitions++] = res;
- layout = VK_IMAGE_LAYOUT_GENERAL;
+ if (res->base.target == PIPE_BUFFER)
+ wds[num_wds].pTexelBufferView = &sampler_view->buffer_view;
+ else {
+ VkImageLayout layout = res->layout;
+ if (layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
+ layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL &&
+ layout != VK_IMAGE_LAYOUT_GENERAL) {
+ transitions[num_transitions++] = res;
+ layout = VK_IMAGE_LAYOUT_GENERAL;
+ }
+ image_infos[num_image_info].imageLayout = layout;
+ image_infos[num_image_info].imageView = sampler_view->image_view;
+ image_infos[num_image_info].sampler = ctx->samplers[i][index];
+ wds[num_wds].pImageInfo = image_infos + num_image_info;
+ ++num_image_info;
}
- image_infos[num_image_info].imageLayout = layout;
- image_infos[num_image_info].imageView = sampler_view->image_view;
- image_infos[num_image_info].sampler = ctx->samplers[i][index];
- wds[num_wds].pImageInfo = image_infos + num_image_info;
- ++num_image_info;
}
wds[num_wds].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c
index eab65c6..06041e7 100644
--- a/src/gallium/drivers/zink/zink_resource.c
+++ b/src/gallium/drivers/zink/zink_resource.c
@@ -110,8 +110,12 @@
bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ if (templ->bind & PIPE_BIND_SAMPLER_VIEW)
+ bci.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+
if (templ->bind & PIPE_BIND_VERTEX_BUFFER)
- bci.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ bci.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
+ VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
if (templ->bind & PIPE_BIND_INDEX_BUFFER)
bci.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;