#include "obj.h"
#include "cmd_priv.h"
-static XGL_RESULT cmd_writer_alloc_and_map(struct intel_cmd *cmd,
- enum intel_cmd_writer_type which,
- XGL_UINT size)
+/**
+ * Free all resources used by a writer. Note that the initial size is not
+ * reset.
+ */
+static void cmd_writer_reset(struct intel_cmd *cmd,
+ enum intel_cmd_writer_type which)
{
struct intel_cmd_writer *writer = &cmd->writers[which];
- struct intel_winsys *winsys = cmd->dev->winsys;
- const XGL_GPU_SIZE bo_size = sizeof(uint32_t) * size;
- struct intel_bo *bo;
- void *ptr;
- bo = intel_winsys_alloc_buffer(winsys,
- "batch buffer", bo_size, true);
- if (!bo)
- return XGL_ERROR_OUT_OF_GPU_MEMORY;
+ if (writer->ptr) {
+ intel_bo_unmap(writer->bo);
+ writer->ptr = NULL;
+ }
- ptr = intel_bo_map(bo, true);
- if (!bo) {
- intel_bo_unreference(bo);
- return XGL_ERROR_MEMORY_MAP_FAILED;
+ if (writer->bo) {
+ intel_bo_unreference(writer->bo);
+ writer->bo = NULL;
}
- writer->bo = bo;
- writer->ptr = ptr;
- writer->size = size;
writer->used = 0;
-
- return XGL_SUCCESS;
}
-static void cmd_writer_copy(struct intel_cmd *cmd,
- enum intel_cmd_writer_type which,
- const uint32_t *vals, XGL_UINT len)
+/**
+ * Discard everything written so far.
+ */
+static void cmd_writer_discard(struct intel_cmd *cmd,
+ enum intel_cmd_writer_type which)
{
struct intel_cmd_writer *writer = &cmd->writers[which];
- assert(writer->used + len <= writer->size);
- memcpy((uint32_t *) writer->ptr + writer->used,
- vals, sizeof(uint32_t) * len);
- writer->used += len;
+ intel_bo_truncate_relocs(writer->bo, 0);
+ writer->used = 0;
}
-static void cmd_writer_patch(struct intel_cmd *cmd,
- enum intel_cmd_writer_type which,
- XGL_UINT pos, uint32_t val)
+static struct intel_bo *alloc_writer_bo(struct intel_winsys *winsys,
+ enum intel_cmd_writer_type which,
+ XGL_UINT size)
{
- struct intel_cmd_writer *writer = &cmd->writers[which];
+ static const char *writer_names[INTEL_CMD_WRITER_COUNT] = {
+ [INTEL_CMD_WRITER_BATCH] = "batch",
+ [INTEL_CMD_WRITER_INSTRUCTION] = "instruction",
+ };
- assert(pos < writer->used);
- ((uint32_t *) writer->ptr)[pos] = val;
+ return intel_winsys_alloc_buffer(winsys, writer_names[which],
+ sizeof(uint32_t) * size, true);
}
-void cmd_writer_grow(struct intel_cmd *cmd,
- enum intel_cmd_writer_type which)
+/**
+ * Allocate and map the buffer for writing.
+ */
+static XGL_RESULT cmd_writer_alloc_and_map(struct intel_cmd *cmd,
+ enum intel_cmd_writer_type which)
{
struct intel_cmd_writer *writer = &cmd->writers[which];
- const XGL_UINT size = writer->size << 1;
- const XGL_UINT old_used = writer->used;
- struct intel_bo *old_bo = writer->bo;
- void *old_ptr = writer->ptr;
-
- if (size >= writer->size &&
- cmd_writer_alloc_and_map(cmd, which, size) == XGL_SUCCESS) {
- cmd_writer_copy(cmd, which, (const uint32_t *) old_ptr, old_used);
+ struct intel_bo *bo;
- intel_bo_unmap(old_bo);
- intel_bo_unreference(old_bo);
+ bo = alloc_writer_bo(cmd->dev->winsys, which, writer->size);
+ if (bo) {
+ if (writer->bo)
+ intel_bo_unreference(writer->bo);
+ writer->bo = bo;
+ } else if (writer->bo) {
+ /* reuse the old bo */
+ cmd_writer_discard(cmd, which);
} else {
- intel_dev_log(cmd->dev, XGL_DBG_MSG_ERROR,
- XGL_VALIDATION_LEVEL_0, XGL_NULL_HANDLE, 0, 0,
- "failed to grow command buffer of size %u", writer->size);
-
- /* wrap it and fail silently */
- writer->used = 0;
- cmd->result = XGL_ERROR_OUT_OF_GPU_MEMORY;
+ return XGL_ERROR_OUT_OF_GPU_MEMORY;
}
+
+ writer->used = 0;
+
+ writer->ptr = intel_bo_map(writer->bo, true);
+ if (!writer->ptr)
+ return XGL_ERROR_UNKNOWN;
+
+ return XGL_SUCCESS;
}
+/**
+ * Unmap the buffer for submission.
+ */
static void cmd_writer_unmap(struct intel_cmd *cmd,
enum intel_cmd_writer_type which)
{
writer->ptr = NULL;
}
-static void cmd_writer_free(struct intel_cmd *cmd,
- enum intel_cmd_writer_type which)
+/**
+ * Grow a mapped writer to at least \p new_size. Failures are handled
+ * silently.
+ */
+void cmd_writer_grow(struct intel_cmd *cmd,
+ enum intel_cmd_writer_type which,
+ XGL_UINT new_size)
{
struct intel_cmd_writer *writer = &cmd->writers[which];
+ struct intel_bo *new_bo;
+ void *new_ptr;
- intel_bo_unreference(writer->bo);
- writer->bo = NULL;
-}
+ if (new_size < writer->size << 1)
+ new_size = writer->size << 1;
+ /* STATE_BASE_ADDRESS requires page-aligned buffers */
+ new_size = u_align(new_size, 4096 / sizeof(uint32_t));
-static void cmd_writer_reset(struct intel_cmd *cmd,
- enum intel_cmd_writer_type which)
-{
- struct intel_cmd_writer *writer = &cmd->writers[which];
+ new_bo = alloc_writer_bo(cmd->dev->winsys, which, new_size);
+ if (!new_bo) {
+ cmd_writer_discard(cmd, which);
+ cmd->result = XGL_ERROR_OUT_OF_GPU_MEMORY;
+ return;
+ }
- /* do not reset writer->size as we want to know how big it has grown to */
- writer->used = 0;
+ /* map and copy the data over */
+ new_ptr = intel_bo_map(new_bo, true);
+ if (!new_ptr) {
+ intel_bo_unreference(new_bo);
+ cmd_writer_discard(cmd, which);
+ cmd->result = XGL_ERROR_UNKNOWN;
+ return;
+ }
+
+ memcpy(new_ptr, writer->ptr, sizeof(uint32_t) * writer->used);
- if (writer->ptr)
- cmd_writer_unmap(cmd, which);
- if (writer->bo)
- cmd_writer_free(cmd, which);
+ intel_bo_unmap(writer->bo);
+ intel_bo_unreference(writer->bo);
+
+ writer->size = new_size;
+ writer->bo = new_bo;
+ writer->ptr = new_ptr;
}
-static void cmd_unmap(struct intel_cmd *cmd)
+static void cmd_writer_patch(struct intel_cmd *cmd,
+ enum intel_cmd_writer_type which,
+ XGL_UINT pos, uint32_t val)
{
- XGL_UINT i;
+ struct intel_cmd_writer *writer = &cmd->writers[which];
- for (i = 0; i < INTEL_CMD_WRITER_COUNT; i++)
- cmd_writer_unmap(cmd, i);
+ assert(pos < writer->used);
+ ((uint32_t *) writer->ptr)[pos] = val;
}
static void cmd_reset(struct intel_cmd *cmd)
}
for (i = 0; i < INTEL_CMD_WRITER_COUNT; i++) {
- ret = cmd_writer_alloc_and_map(cmd, i, cmd->writers[i].size);
+ ret = cmd_writer_alloc_and_map(cmd, i);
if (ret != XGL_SUCCESS) {
cmd_reset(cmd);
return ret;
(uint32_t) presumed_offset);
}
- cmd_unmap(cmd);
+ for (i = 0; i < INTEL_CMD_WRITER_COUNT; i++)
+ cmd_writer_unmap(cmd, i);
if (cmd->result != XGL_SUCCESS)
return cmd->result;