meta_clear_end(&saved_state, cmd_buffer);
}
+
+static void
+do_buffer_fill(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_bo *dest, uint64_t dest_offset,
+ int width, int height, VkFormat fill_format, uint32_t data)
+{
+ VkDevice vk_device = anv_device_to_handle(cmd_buffer->device);
+
+ VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = fill_format,
+ .extent = {
+ .width = width,
+ .height = height,
+ .depth = 1,
+ },
+ .mipLevels = 1,
+ .arrayLayers = 1,
+ .samples = 1,
+ .tiling = VK_IMAGE_TILING_LINEAR,
+ .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ .flags = 0,
+ };
+
+ VkImage dest_image;
+ image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ anv_CreateImage(vk_device, &image_info,
+ &cmd_buffer->pool->alloc, &dest_image);
+
+ /* We could use a vk call to bind memory, but that would require
+ * creating a dummy memory object etc. so there's really no point.
+ */
+ anv_image_from_handle(dest_image)->bo = dest;
+ anv_image_from_handle(dest_image)->offset = dest_offset;
+
+ const VkClearValue clear_value = {
+ .color = {
+ .uint32 = { data, data, data, data }
+ }
+ };
+
+ const VkImageSubresourceRange range = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ };
+
+ anv_cmd_clear_image(cmd_buffer, anv_image_from_handle(dest_image),
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ &clear_value, 1, &range);
+}
+
+void anv_CmdFillBuffer(
+ VkCommandBuffer commandBuffer,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize fillSize,
+ uint32_t data)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
+ ANV_FROM_HANDLE(anv_buffer, dst_buffer, dstBuffer);
+ struct anv_meta_saved_state saved_state;
+
+ meta_clear_begin(&saved_state, cmd_buffer);
+
+ VkFormat format;
+ int bs;
+ if ((fillSize & 15) == 0 && (dstOffset & 15) == 0) {
+ format = VK_FORMAT_R32G32B32A32_UINT;
+ bs = 16;
+ } else if ((fillSize & 7) == 0 && (dstOffset & 15) == 0) {
+ format = VK_FORMAT_R32G32_UINT;
+ bs = 8;
+ } else {
+ assert((fillSize & 3) == 0 && (dstOffset & 3) == 0);
+ format = VK_FORMAT_R32_UINT;
+ bs = 4;
+ }
+
+ /* This is maximum possible width/height our HW can handle */
+ const uint64_t max_surface_dim = 1 << 14;
+
+ /* First, we make a bunch of max-sized copies */
+ const uint64_t max_fill_size = max_surface_dim * max_surface_dim * bs;
+ while (fillSize > max_fill_size) {
+ do_buffer_fill(cmd_buffer, dst_buffer->bo,
+ dst_buffer->offset + dstOffset,
+ max_surface_dim, max_surface_dim, format, data);
+ fillSize -= max_fill_size;
+ dstOffset += max_fill_size;
+ }
+
+ uint64_t height = fillSize / (max_surface_dim * bs);
+ assert(height < max_surface_dim);
+ if (height != 0) {
+ const uint64_t rect_fill_size = height * max_surface_dim * bs;
+ do_buffer_fill(cmd_buffer, dst_buffer->bo,
+ dst_buffer->offset + dstOffset,
+ max_surface_dim, height, format, data);
+ fillSize -= rect_fill_size;
+ dstOffset += rect_fill_size;
+ }
+
+ if (fillSize != 0) {
+ do_buffer_fill(cmd_buffer, dst_buffer->bo,
+ dst_buffer->offset + dstOffset,
+ fillSize / bs, 1, format, data);
+ }
+
+ meta_clear_end(&saved_state, cmd_buffer);
+}