.shaderStorageImageExtendedFormats = true,
.shaderStorageImageMultisample = false,
.shaderStorageImageReadWithoutFormat = false,
- .shaderStorageImageWriteWithoutFormat = false,
+ .shaderStorageImageWriteWithoutFormat = true,
.shaderUniformBufferArrayDynamicIndexing = true,
.shaderSampledImageArrayDynamicIndexing = true,
.shaderStorageBufferArrayDynamicIndexing = true,
/* NOTE: This one needs to go last since it may stomp isl_view.format */
if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
iview->storage_surface_state = alloc_surface_state(device);
+ iview->writeonly_storage_surface_state = alloc_surface_state(device);
+
+ struct isl_view view = iview->isl;
+ view.usage |= ISL_SURF_USAGE_STORAGE_BIT;
+
+ /* Write-only accesses always used a typed write instruction and should
+ * therefore use the real format.
+ */
+ isl_surf_fill_state(&device->isl_dev,
+ iview->writeonly_storage_surface_state.map,
+ .surf = &surface->isl,
+ .view = &view,
+ .aux_surf = &image->aux_surface.isl,
+ .aux_usage = surf_usage,
+ .mocs = device->default_mocs);
if (isl_has_matching_typed_storage_image_format(&device->info,
format.isl_format)) {
- struct isl_view view = iview->isl;
- view.usage |= ISL_SURF_USAGE_STORAGE_BIT;
+ /* Typed surface reads support a very limited subset of the shader
+ * image formats. Translate it into the closest format the hardware
+ * supports.
+ */
view.format = isl_lower_storage_image_format(&device->info,
format.isl_format);
+
isl_surf_fill_state(&device->isl_dev,
iview->storage_surface_state.map,
.surf = &surface->isl,
&iview->storage_image_param,
&surface->isl, &iview->isl);
- if (!device->info.has_llc)
+ if (!device->info.has_llc) {
anv_state_clflush(iview->storage_surface_state);
+ anv_state_clflush(iview->writeonly_storage_surface_state);
+ }
} else {
iview->storage_surface_state.alloc_size = 0;
+ iview->writeonly_storage_surface_state.alloc_size = 0;
}
*pView = anv_image_view_to_handle(iview);
iview->storage_surface_state);
}
+ if (iview->writeonly_storage_surface_state.alloc_size > 0) {
+ anv_state_pool_free(&device->surface_state_pool,
+ iview->writeonly_storage_surface_state);
+ }
+
vk_free2(&device->alloc, pAllocator, iview);
}
if (buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
view->storage_surface_state = alloc_surface_state(device);
+ view->writeonly_storage_surface_state = alloc_surface_state(device);
enum isl_format storage_format =
isl_has_matching_typed_storage_image_format(&device->info,
(storage_format == ISL_FORMAT_RAW ? 1 :
isl_format_get_layout(storage_format)->bpb / 8));
+ /* Write-only accesses should use the original format. */
+ anv_fill_buffer_surface_state(device, view->writeonly_storage_surface_state,
+ view->format,
+ view->offset, view->range,
+ isl_format_get_layout(view->format)->bpb / 8);
+
isl_buffer_fill_image_param(&device->isl_dev,
&view->storage_image_param,
view->format, view->range);
} else {
view->storage_surface_state = (struct anv_state){ 0 };
+ view->writeonly_storage_surface_state = (struct anv_state){ 0 };
}
*pView = anv_buffer_view_to_handle(view);
anv_state_pool_free(&device->surface_state_pool,
view->storage_surface_state);
+ if (view->writeonly_storage_surface_state.alloc_size > 0)
+ anv_state_pool_free(&device->surface_state_pool,
+ view->writeonly_storage_surface_state);
+
vk_free2(&device->alloc, pAllocator, view);
}
continue;
enum glsl_sampler_dim dim = glsl_get_sampler_dim(var->interface_type);
- if (dim != GLSL_SAMPLER_DIM_SUBPASS &&
- dim != GLSL_SAMPLER_DIM_SUBPASS_MS)
- continue;
const uint32_t set = var->data.descriptor_set;
const uint32_t binding = var->data.binding;
assert(pipe_binding[i].set == set);
assert(pipe_binding[i].binding == binding);
assert(pipe_binding[i].index == i);
- pipe_binding[i].input_attachment_index = var->data.index + i;
+
+ if (dim == GLSL_SAMPLER_DIM_SUBPASS ||
+ dim == GLSL_SAMPLER_DIM_SUBPASS_MS)
+ pipe_binding[i].input_attachment_index = var->data.index + i;
+
+ pipe_binding[i].write_only = var->data.image.write_only;
}
}
unsigned binding = var->data.binding;
unsigned image_index = state.set[set].image_offsets[binding];
- /* We have a very tight coupling between back-end compiler and
- * state setup which requires us to fill the image surface state
- * out differently if and only if the image is declared write-only.
- * Right now, our state setup code sets up all images as if they
- * are read-write. This means that the compiler needs to see
- * read-only as well.
- *
- * Whenever we implement shaderStorageImageWriteWithoutFormat, we
- * need to delete this.
- */
- var->data.image.write_only = false;
-
var->data.driver_location = shader->num_uniforms +
image_index * BRW_IMAGE_PARAM_SIZE * 4;
}
.float64 = device->instance->physicalDevice.info.gen >= 8,
.tessellation = true,
.draw_parameters = true,
+ .image_write_without_format = true,
};
nir_function *entry_point =
/* Input attachment index (relative to the subpass) */
uint8_t input_attachment_index;
+
+ /* For a storage image, whether it is write-only */
+ bool write_only;
};
struct anv_pipeline_layout {
/** RENDER_SURFACE_STATE when using image as a sampler surface. */
struct anv_state sampler_surface_state;
- /** RENDER_SURFACE_STATE when using image as a storage image. */
+ /**
+ * RENDER_SURFACE_STATE when using image as a storage image. Separate states
+ * for write-only and readable, using the real format for write-only and the
+ * lowered format for readable.
+ */
struct anv_state storage_surface_state;
+ struct anv_state writeonly_storage_surface_state;
struct brw_image_param storage_image_param;
};
struct anv_state surface_state;
struct anv_state storage_surface_state;
+ struct anv_state writeonly_storage_surface_state;
struct brw_image_param storage_image_param;
};
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
- surface_state = desc->image_view->storage_surface_state;
+ surface_state = (binding->write_only)
+ ? desc->image_view->writeonly_storage_surface_state
+ : desc->image_view->storage_surface_state;
assert(surface_state.alloc_size);
add_image_view_relocs(cmd_buffer, desc->image_view,
desc->image_view->image->aux_usage,
break;
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
- surface_state = desc->buffer_view->storage_surface_state;
+ surface_state = (binding->write_only)
+ ? desc->buffer_view->writeonly_storage_surface_state
+ : desc->buffer_view->storage_surface_state;
assert(surface_state.alloc_size);
add_surface_state_reloc(cmd_buffer, surface_state,
desc->buffer_view->bo,