+static void
+emit_ssbo_sizes(struct fd_context *ctx, const struct ir3_shader_variant *v,
+ struct fd_ringbuffer *ring, struct fd_shaderbuf_stateobj *sb)
+{
+ uint32_t offset = v->constbase.ssbo_sizes;
+ if (v->constlen > offset) {
+ uint32_t sizes[align(v->const_layout.ssbo_size.count, 4)];
+ unsigned mask = v->const_layout.ssbo_size.mask;
+
+ while (mask) {
+ unsigned index = u_bit_scan(&mask);
+ unsigned off = v->const_layout.ssbo_size.off[index];
+ sizes[off] = sb->sb[index].buffer_size;
+ }
+
+ ring_wfi(ctx->batch, ring);
+ ctx->emit_const(ring, v->type, offset * 4,
+ 0, ARRAY_SIZE(sizes), sizes, NULL);
+ }
+}
+
+static void
+emit_image_dims(struct fd_context *ctx, const struct ir3_shader_variant *v,
+ struct fd_ringbuffer *ring, struct fd_shaderimg_stateobj *si)
+{
+ uint32_t offset = v->constbase.image_dims;
+ if (v->constlen > offset) {
+ uint32_t dims[align(v->const_layout.image_dims.count, 4)];
+ unsigned mask = v->const_layout.image_dims.mask;
+
+ while (mask) {
+ struct pipe_image_view *img;
+ struct fd_resource *rsc;
+ unsigned index = u_bit_scan(&mask);
+ unsigned off = v->const_layout.image_dims.off[index];
+
+ img = &si->si[index];
+ rsc = fd_resource(img->resource);
+
+ dims[off + 0] = util_format_get_blocksize(img->format);
+ if (img->resource->target != PIPE_BUFFER) {
+ unsigned lvl = img->u.tex.level;
+ /* note for 2d/cube/etc images, even if re-interpreted
+ * as a different color format, the pixel size should
+ * be the same, so use original dimensions for y and z
+ * stride:
+ */
+ dims[off + 1] = rsc->slices[lvl].pitch * rsc->cpp;
+ /* see corresponding logic in fd_resource_offset(): */
+ if (rsc->layer_first) {
+ dims[off + 2] = rsc->layer_size;
+ } else {
+ dims[off + 2] = rsc->slices[lvl].size0;
+ }
+ } else {
+ /* For buffer-backed images, the log2 of the format's
+ * bytes-per-pixel is placed on the 2nd slot. This is useful
+ * when emitting image_size instructions, for which we need
+ * to divide by bpp for image buffers. Since the bpp
+ * can only be power-of-two, the division is implemented
+ * as a SHR, and for that it is handy to have the log2 of
+ * bpp as a constant. (log2 = first-set-bit - 1)
+ */
+ dims[off + 1] = ffs(dims[off + 0]) - 1;
+ }
+ }
+
+ ring_wfi(ctx->batch, ring);
+ ctx->emit_const(ring, v->type, offset * 4,
+ 0, ARRAY_SIZE(dims), dims, NULL);
+ }
+}
+