mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 04:48:08 +02:00
ilo: add a builder for building BOs for submission
Comparing to how we manage batch and instruction buffers, the new builder - does not flush - manages both types of buffers - manages STATE_BASE_ADDRESS - uploads kernels using unsynchronized mapping - has its own decoder for the buffers - provides more helpers
This commit is contained in:
parent
43bf14eaeb
commit
dab4a676f7
4 changed files with 1641 additions and 0 deletions
|
|
@ -15,6 +15,8 @@ C_SOURCES := \
|
|||
ilo_blitter_blt.c \
|
||||
ilo_blitter_pipe.c \
|
||||
ilo_blitter_rectlist.c \
|
||||
ilo_builder.c \
|
||||
ilo_builder_decode.c \
|
||||
ilo_common.h \
|
||||
ilo_context.c \
|
||||
ilo_context.h \
|
||||
|
|
|
|||
566
src/gallium/drivers/ilo/ilo_builder.c
Normal file
566
src/gallium/drivers/ilo/ilo_builder.c
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 2014 LunarG, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#include "genhw/genhw.h"
|
||||
#include "ilo_builder.h"
|
||||
|
||||
enum ilo_builder_writer_flags {
|
||||
/*
|
||||
* When this bit is set, ilo_builder_begin() will not realllocate. New
|
||||
* data will be appended instead.
|
||||
*/
|
||||
WRITER_FLAG_APPEND = 1 << 0,
|
||||
|
||||
/*
|
||||
* When this bit is set, the writer grows when full. When not, callers
|
||||
* must make sure the writer never needs to grow.
|
||||
*/
|
||||
WRITER_FLAG_GROW = 1 << 1,
|
||||
|
||||
/*
|
||||
* The writer will be mapped directly.
|
||||
*/
|
||||
WRITER_FLAG_MAP = 1 << 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the initial size and flags of a writer.
|
||||
*/
|
||||
static void
|
||||
ilo_builder_writer_init(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
switch (which) {
|
||||
case ILO_BUILDER_WRITER_BATCH:
|
||||
writer->size = sizeof(uint32_t) * 8192;
|
||||
break;
|
||||
case ILO_BUILDER_WRITER_INSTRUCTION:
|
||||
/*
|
||||
* The EUs pretch some instructions. But since the kernel invalidates
|
||||
* the instruction cache between batch buffers, we can set
|
||||
* WRITER_FLAG_APPEND without worrying the EUs would see invalid
|
||||
* instructions prefetched.
|
||||
*/
|
||||
writer->flags = WRITER_FLAG_APPEND | WRITER_FLAG_GROW;
|
||||
writer->size = 8192;
|
||||
break;
|
||||
default:
|
||||
assert(!"unknown builder writer");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (builder->dev->has_llc)
|
||||
writer->flags |= WRITER_FLAG_MAP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free all resources used by a writer. Note that the initial size is not
|
||||
* reset.
|
||||
*/
|
||||
static void
|
||||
ilo_builder_writer_reset(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
if (writer->ptr) {
|
||||
if (writer->flags & WRITER_FLAG_MAP)
|
||||
intel_bo_unmap(writer->bo);
|
||||
else
|
||||
FREE(writer->ptr);
|
||||
|
||||
writer->ptr = NULL;
|
||||
}
|
||||
|
||||
if (writer->bo) {
|
||||
intel_bo_unreference(writer->bo);
|
||||
writer->bo = NULL;
|
||||
}
|
||||
|
||||
writer->used = 0;
|
||||
writer->stolen = 0;
|
||||
|
||||
if (writer->items) {
|
||||
FREE(writer->items);
|
||||
writer->item_alloc = 0;
|
||||
writer->item_used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard everything written so far.
|
||||
*/
|
||||
void
|
||||
ilo_builder_writer_discard(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
intel_bo_truncate_relocs(writer->bo, 0);
|
||||
writer->used = 0;
|
||||
writer->stolen = 0;
|
||||
writer->item_used = 0;
|
||||
}
|
||||
|
||||
static struct intel_bo *
|
||||
alloc_writer_bo(struct intel_winsys *winsys,
|
||||
enum ilo_builder_writer_type which,
|
||||
unsigned size)
|
||||
{
|
||||
static const char *writer_names[ILO_BUILDER_WRITER_COUNT] = {
|
||||
[ILO_BUILDER_WRITER_BATCH] = "batch",
|
||||
[ILO_BUILDER_WRITER_INSTRUCTION] = "instruction",
|
||||
};
|
||||
|
||||
return intel_winsys_alloc_buffer(winsys, writer_names[which], size, true);
|
||||
}
|
||||
|
||||
static void *
|
||||
map_writer_bo(struct intel_bo *bo, unsigned flags)
|
||||
{
|
||||
assert(flags & WRITER_FLAG_MAP);
|
||||
|
||||
if (flags & WRITER_FLAG_APPEND)
|
||||
return intel_bo_map_gtt_async(bo);
|
||||
else
|
||||
return intel_bo_map(bo, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and map the buffer for writing.
|
||||
*/
|
||||
static bool
|
||||
ilo_builder_writer_alloc_and_map(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
/* allocate a new bo when not appending */
|
||||
if (!(writer->flags & WRITER_FLAG_APPEND) || !writer->bo) {
|
||||
struct intel_bo *bo;
|
||||
|
||||
bo = alloc_writer_bo(builder->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 */
|
||||
ilo_builder_writer_discard(builder, which);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
writer->used = 0;
|
||||
writer->stolen = 0;
|
||||
writer->item_used = 0;
|
||||
}
|
||||
|
||||
/* map the bo or allocate the staging system memory */
|
||||
if (writer->flags & WRITER_FLAG_MAP)
|
||||
writer->ptr = map_writer_bo(writer->bo, writer->flags);
|
||||
else if (!writer->ptr)
|
||||
writer->ptr = MALLOC(writer->size);
|
||||
|
||||
return (writer->ptr != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmap the buffer for submission.
|
||||
*/
|
||||
static bool
|
||||
ilo_builder_writer_unmap(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
unsigned offset;
|
||||
int err = 0;
|
||||
|
||||
if (writer->flags & WRITER_FLAG_MAP) {
|
||||
intel_bo_unmap(writer->bo);
|
||||
writer->ptr = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
offset = builder->begin_used[which];
|
||||
if (writer->used > offset) {
|
||||
err = intel_bo_pwrite(writer->bo, offset, writer->used - offset,
|
||||
(char *) writer->ptr + offset);
|
||||
}
|
||||
|
||||
if (writer->stolen && !err) {
|
||||
const unsigned offset = writer->size - writer->stolen;
|
||||
err = intel_bo_pwrite(writer->bo, offset, writer->stolen,
|
||||
(const char *) writer->ptr + offset);
|
||||
}
|
||||
|
||||
/* keep writer->ptr */
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow a mapped writer to at least \p new_size.
|
||||
*/
|
||||
bool
|
||||
ilo_builder_writer_grow(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
unsigned new_size, bool preserve)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
struct intel_bo *new_bo;
|
||||
void *new_ptr;
|
||||
|
||||
if (!(writer->flags & WRITER_FLAG_GROW))
|
||||
return false;
|
||||
|
||||
/* stolen data may already be referenced and cannot be moved */
|
||||
if (writer->stolen)
|
||||
return false;
|
||||
|
||||
if (new_size < writer->size << 1)
|
||||
new_size = writer->size << 1;
|
||||
/* STATE_BASE_ADDRESS requires page-aligned buffers */
|
||||
new_size = align(new_size, 4096);
|
||||
|
||||
new_bo = alloc_writer_bo(builder->winsys, which, new_size);
|
||||
if (!new_bo)
|
||||
return false;
|
||||
|
||||
/* map and copy the data over */
|
||||
if (writer->flags & WRITER_FLAG_MAP) {
|
||||
new_ptr = map_writer_bo(new_bo, writer->flags);
|
||||
|
||||
/*
|
||||
* When WRITER_FLAG_APPEND and WRITER_FLAG_GROW are both set, we may end
|
||||
* up copying between two GTT-mapped BOs. That is slow. The issue
|
||||
* could be solved by adding intel_bo_map_async(), or callers may choose
|
||||
* to manually grow the writer without preserving the data.
|
||||
*/
|
||||
if (new_ptr && preserve)
|
||||
memcpy(new_ptr, writer->ptr, writer->used);
|
||||
} else if (preserve) {
|
||||
new_ptr = REALLOC(writer->ptr, writer->size, new_size);
|
||||
} else {
|
||||
new_ptr = MALLOC(new_size);
|
||||
}
|
||||
|
||||
if (!new_ptr) {
|
||||
intel_bo_unreference(new_bo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (writer->flags & WRITER_FLAG_MAP)
|
||||
intel_bo_unmap(writer->bo);
|
||||
else if (!preserve)
|
||||
FREE(writer->ptr);
|
||||
|
||||
intel_bo_unreference(writer->bo);
|
||||
|
||||
writer->size = new_size;
|
||||
writer->bo = new_bo;
|
||||
writer->ptr = new_ptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record an item for later decoding.
|
||||
*/
|
||||
bool
|
||||
ilo_builder_writer_record(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
enum ilo_builder_item_type type,
|
||||
unsigned offset, unsigned size)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
struct ilo_builder_item *item;
|
||||
|
||||
if (writer->item_used == writer->item_alloc) {
|
||||
const unsigned new_alloc = (writer->item_alloc) ?
|
||||
writer->item_alloc << 1 : 256;
|
||||
struct ilo_builder_item *items;
|
||||
|
||||
items = REALLOC(writer->items,
|
||||
sizeof(writer->items[0]) * writer->item_alloc,
|
||||
sizeof(writer->items[0]) * new_alloc);
|
||||
if (!items)
|
||||
return false;
|
||||
|
||||
writer->items = items;
|
||||
writer->item_alloc = new_alloc;
|
||||
}
|
||||
|
||||
item = &writer->items[writer->item_used++];
|
||||
item->type = type;
|
||||
item->offset = offset;
|
||||
item->size = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the builder.
|
||||
*/
|
||||
void
|
||||
ilo_builder_init(struct ilo_builder *builder,
|
||||
const struct ilo_dev_info *dev,
|
||||
struct intel_winsys *winsys)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(builder, 0, sizeof(*builder));
|
||||
|
||||
builder->dev = dev;
|
||||
builder->winsys = winsys;
|
||||
|
||||
for (i = 0; i < ILO_BUILDER_WRITER_COUNT; i++)
|
||||
ilo_builder_writer_init(builder, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the builder and free all resources used. After resetting, the
|
||||
* builder behaves as if it is newly initialized, except for potentially
|
||||
* larger initial bo sizes.
|
||||
*/
|
||||
void
|
||||
ilo_builder_reset(struct ilo_builder *builder)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ILO_BUILDER_WRITER_COUNT; i++)
|
||||
ilo_builder_writer_reset(builder, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and map the BOs. It may re-allocate or reuse existing BOs if
|
||||
* there is any.
|
||||
*
|
||||
* Most builder functions can only be called after ilo_builder_begin() and
|
||||
* before ilo_builder_end().
|
||||
*/
|
||||
bool
|
||||
ilo_builder_begin(struct ilo_builder *builder)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ILO_BUILDER_WRITER_COUNT; i++) {
|
||||
if (!ilo_builder_writer_alloc_and_map(builder, i)) {
|
||||
ilo_builder_reset(builder);
|
||||
return false;
|
||||
}
|
||||
|
||||
builder->begin_used[i] = builder->writers[i].used;
|
||||
}
|
||||
|
||||
builder->unrecoverable_error = false;
|
||||
builder->sba_instruction_pos = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ilo_builder_batch_patch_sba(struct ilo_builder *builder)
|
||||
{
|
||||
const struct ilo_builder_writer *inst =
|
||||
&builder->writers[ILO_BUILDER_WRITER_INSTRUCTION];
|
||||
|
||||
if (!builder->sba_instruction_pos)
|
||||
return;
|
||||
|
||||
ilo_builder_batch_reloc(builder, builder->sba_instruction_pos,
|
||||
inst->bo, 1, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmap BOs and make sure the written data landed the BOs. The batch buffer
|
||||
* ready for submission is returned.
|
||||
*/
|
||||
struct intel_bo *
|
||||
ilo_builder_end(struct ilo_builder *builder, unsigned *used)
|
||||
{
|
||||
struct ilo_builder_writer *bat;
|
||||
int i;
|
||||
|
||||
ilo_builder_batch_patch_sba(builder);
|
||||
|
||||
assert(ilo_builder_validate(builder, 0, NULL));
|
||||
|
||||
for (i = 0; i < ILO_BUILDER_WRITER_COUNT; i++) {
|
||||
if (!ilo_builder_writer_unmap(builder, i))
|
||||
builder->unrecoverable_error = true;
|
||||
}
|
||||
|
||||
if (builder->unrecoverable_error)
|
||||
return NULL;
|
||||
|
||||
bat = &builder->writers[ILO_BUILDER_WRITER_BATCH];
|
||||
|
||||
*used = bat->used;
|
||||
|
||||
return bat->bo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the builder is in a valid state, after accounting for the
|
||||
* additional BOs specified. The additional BOs can be listed to avoid
|
||||
* snapshotting and restoring when they are known ahead of time.
|
||||
*
|
||||
* The number of additional BOs should not be more than a few. Like two, for
|
||||
* copying between two BOs.
|
||||
*
|
||||
* Callers must make sure the builder is in a valid state when
|
||||
* ilo_builder_end() is called.
|
||||
*/
|
||||
bool
|
||||
ilo_builder_validate(struct ilo_builder *builder,
|
||||
unsigned bo_count, struct intel_bo **bos)
|
||||
{
|
||||
const unsigned max_bo_count = 2;
|
||||
struct intel_bo *bos_to_submit[ILO_BUILDER_WRITER_COUNT + max_bo_count];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ILO_BUILDER_WRITER_COUNT; i++)
|
||||
bos_to_submit[i] = builder->writers[i].bo;
|
||||
|
||||
if (bo_count) {
|
||||
assert(bo_count <= max_bo_count);
|
||||
if (bo_count > max_bo_count)
|
||||
return false;
|
||||
|
||||
memcpy(&bos_to_submit[ILO_BUILDER_WRITER_COUNT],
|
||||
bos, sizeof(*bos) * bo_count);
|
||||
i += bo_count;
|
||||
}
|
||||
|
||||
return intel_winsys_can_submit_bo(builder->winsys, bos_to_submit, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a snapshot of the writer state.
|
||||
*/
|
||||
void
|
||||
ilo_builder_batch_snapshot(const struct ilo_builder *builder,
|
||||
struct ilo_builder_snapshot *snapshot)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
const struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
snapshot->reloc_count = intel_bo_get_reloc_count(writer->bo);
|
||||
snapshot->used = writer->used;
|
||||
snapshot->stolen = writer->stolen;
|
||||
snapshot->item_used = writer->item_used;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the writer state to when the snapshot was taken, except that it
|
||||
* does not (unnecessarily) shrink BOs or the item array.
|
||||
*/
|
||||
void
|
||||
ilo_builder_batch_restore(struct ilo_builder *builder,
|
||||
const struct ilo_builder_snapshot *snapshot)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
intel_bo_truncate_relocs(writer->bo, snapshot->reloc_count);
|
||||
writer->used = snapshot->used;
|
||||
writer->stolen = snapshot->stolen;
|
||||
writer->item_used = snapshot->item_used;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a STATE_BASE_ADDRESS to the batch buffer.
|
||||
*/
|
||||
void
|
||||
ilo_builder_batch_state_base_address(struct ilo_builder *builder,
|
||||
bool init_all)
|
||||
{
|
||||
const uint8_t cmd_len = 10;
|
||||
const struct ilo_builder_writer *bat =
|
||||
&builder->writers[ILO_BUILDER_WRITER_BATCH];
|
||||
unsigned pos;
|
||||
uint32_t *dw;
|
||||
|
||||
pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
|
||||
|
||||
dw[0] = GEN6_RENDER_CMD(COMMON, STATE_BASE_ADDRESS) | (cmd_len - 2);
|
||||
dw[1] = init_all;
|
||||
|
||||
ilo_builder_batch_reloc(builder, pos + 2, bat->bo, 1, 0);
|
||||
ilo_builder_batch_reloc(builder, pos + 3, bat->bo, 1, 0);
|
||||
|
||||
dw[4] = init_all;
|
||||
|
||||
/*
|
||||
* Since the instruction writer has WRITER_FLAG_APPEND set, it is tempting
|
||||
* not to set Instruction Base Address. The problem is that we do not know
|
||||
* if the bo has been or will be moved by the kernel. We need a relocation
|
||||
* entry because of that.
|
||||
*
|
||||
* And since we also set WRITER_FLAG_GROW, we have to wait until
|
||||
* ilo_builder_end(), when the final bo is known, to add the relocation
|
||||
* entry.
|
||||
*/
|
||||
ilo_builder_batch_patch_sba(builder);
|
||||
builder->sba_instruction_pos = pos + 5;
|
||||
|
||||
/* skip range checks */
|
||||
dw[6] = init_all;
|
||||
dw[7] = 0xfffff000 + init_all;
|
||||
dw[8] = 0xfffff000 + init_all;
|
||||
dw[9] = init_all;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a MI_BATCH_BUFFER_END to the batch buffer. Pad if necessary.
|
||||
*/
|
||||
void
|
||||
ilo_builder_batch_mi_batch_buffer_end(struct ilo_builder *builder)
|
||||
{
|
||||
const struct ilo_builder_writer *bat =
|
||||
&builder->writers[ILO_BUILDER_WRITER_BATCH];
|
||||
uint32_t *dw;
|
||||
|
||||
/*
|
||||
* From the Sandy Bridge PRM, volume 1 part 1, page 107:
|
||||
*
|
||||
* "The batch buffer must be QWord aligned and a multiple of QWords in
|
||||
* length."
|
||||
*/
|
||||
if (bat->used & 0x7) {
|
||||
ilo_builder_batch_pointer(builder, 1, &dw);
|
||||
dw[0] = GEN6_MI_CMD(MI_BATCH_BUFFER_END);
|
||||
} else {
|
||||
ilo_builder_batch_pointer(builder, 2, &dw);
|
||||
dw[0] = GEN6_MI_CMD(MI_BATCH_BUFFER_END);
|
||||
dw[1] = GEN6_MI_CMD(MI_NOOP);
|
||||
}
|
||||
}
|
||||
490
src/gallium/drivers/ilo/ilo_builder.h
Normal file
490
src/gallium/drivers/ilo/ilo_builder.h
Normal file
|
|
@ -0,0 +1,490 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 2014 LunarG, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#ifndef ILO_BUILDER_H
|
||||
#define ILO_BUILDER_H
|
||||
|
||||
#include "intel_winsys.h"
|
||||
#include "ilo_common.h"
|
||||
|
||||
enum ilo_builder_writer_type {
|
||||
ILO_BUILDER_WRITER_BATCH,
|
||||
ILO_BUILDER_WRITER_INSTRUCTION,
|
||||
|
||||
ILO_BUILDER_WRITER_COUNT,
|
||||
};
|
||||
|
||||
enum ilo_builder_item_type {
|
||||
/* for state buffer */
|
||||
ILO_BUILDER_ITEM_BLOB,
|
||||
ILO_BUILDER_ITEM_CLIP_VIEWPORT,
|
||||
ILO_BUILDER_ITEM_SF_VIEWPORT,
|
||||
ILO_BUILDER_ITEM_SCISSOR_RECT,
|
||||
ILO_BUILDER_ITEM_CC_VIEWPORT,
|
||||
ILO_BUILDER_ITEM_COLOR_CALC,
|
||||
ILO_BUILDER_ITEM_DEPTH_STENCIL,
|
||||
ILO_BUILDER_ITEM_BLEND,
|
||||
ILO_BUILDER_ITEM_SAMPLER,
|
||||
|
||||
/* for surface buffer */
|
||||
ILO_BUILDER_ITEM_SURFACE,
|
||||
ILO_BUILDER_ITEM_BINDING_TABLE,
|
||||
|
||||
/* for instruction buffer */
|
||||
ILO_BUILDER_ITEM_KERNEL,
|
||||
|
||||
ILO_BUILDER_ITEM_COUNT,
|
||||
};
|
||||
|
||||
struct ilo_builder_item {
|
||||
enum ilo_builder_item_type type;
|
||||
unsigned offset;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
struct ilo_builder_writer {
|
||||
/* internal flags */
|
||||
unsigned flags;
|
||||
|
||||
unsigned size;
|
||||
struct intel_bo *bo;
|
||||
void *ptr;
|
||||
|
||||
/* data written to the bottom */
|
||||
unsigned used;
|
||||
/* data written to the top */
|
||||
unsigned stolen;
|
||||
|
||||
/* for decoding */
|
||||
struct ilo_builder_item *items;
|
||||
unsigned item_alloc;
|
||||
unsigned item_used;
|
||||
};
|
||||
|
||||
/**
|
||||
* A snapshot of the writer state.
|
||||
*/
|
||||
struct ilo_builder_snapshot {
|
||||
unsigned reloc_count;
|
||||
|
||||
unsigned used;
|
||||
unsigned stolen;
|
||||
unsigned item_used;
|
||||
};
|
||||
|
||||
struct ilo_builder {
|
||||
const struct ilo_dev_info *dev;
|
||||
struct intel_winsys *winsys;
|
||||
|
||||
struct ilo_builder_writer writers[ILO_BUILDER_WRITER_COUNT];
|
||||
bool unrecoverable_error;
|
||||
|
||||
/* for writers that have their data appended */
|
||||
unsigned begin_used[ILO_BUILDER_WRITER_COUNT];
|
||||
|
||||
/* for STATE_BASE_ADDRESS */
|
||||
unsigned sba_instruction_pos;
|
||||
};
|
||||
|
||||
void
|
||||
ilo_builder_init(struct ilo_builder *builder,
|
||||
const struct ilo_dev_info *dev,
|
||||
struct intel_winsys *winsys);
|
||||
|
||||
void
|
||||
ilo_builder_reset(struct ilo_builder *builder);
|
||||
|
||||
void
|
||||
ilo_builder_decode(struct ilo_builder *builder);
|
||||
|
||||
bool
|
||||
ilo_builder_begin(struct ilo_builder *builder);
|
||||
|
||||
struct intel_bo *
|
||||
ilo_builder_end(struct ilo_builder *builder, unsigned *used);
|
||||
|
||||
bool
|
||||
ilo_builder_validate(struct ilo_builder *builder,
|
||||
unsigned bo_count, struct intel_bo **bos);
|
||||
|
||||
/**
|
||||
* Return true if the builder has a relocation entry for \p bo.
|
||||
*/
|
||||
static inline bool
|
||||
ilo_builder_has_reloc(const struct ilo_builder *builder,
|
||||
struct intel_bo *bo)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ILO_BUILDER_WRITER_COUNT; i++) {
|
||||
const struct ilo_builder_writer *writer = &builder->writers[i];
|
||||
if (intel_bo_has_reloc(writer->bo, bo))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ilo_builder_writer_discard(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which);
|
||||
|
||||
bool
|
||||
ilo_builder_writer_grow(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
unsigned new_size, bool preserve);
|
||||
|
||||
bool
|
||||
ilo_builder_writer_record(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
enum ilo_builder_item_type type,
|
||||
unsigned offset, unsigned size);
|
||||
|
||||
static inline void
|
||||
ilo_builder_writer_checked_record(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
enum ilo_builder_item_type item,
|
||||
unsigned offset, unsigned size)
|
||||
{
|
||||
if (unlikely(ilo_debug & ILO_DEBUG_3D)) {
|
||||
if (!ilo_builder_writer_record(builder, which, item, offset, size)) {
|
||||
builder->unrecoverable_error = true;
|
||||
builder->writers[which].item_used = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an offset to a region that is aligned to \p alignment and has at
|
||||
* least \p size bytes. The region is reserved from the bottom.
|
||||
*/
|
||||
static inline unsigned
|
||||
ilo_builder_writer_reserve_bottom(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
unsigned alignment, unsigned size)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
unsigned offset;
|
||||
|
||||
assert(alignment && util_is_power_of_two(alignment));
|
||||
offset = align(writer->used, alignment);
|
||||
|
||||
if (unlikely(offset + size > writer->size - writer->stolen)) {
|
||||
if (!ilo_builder_writer_grow(builder, which,
|
||||
offset + size + writer->stolen, true)) {
|
||||
builder->unrecoverable_error = true;
|
||||
ilo_builder_writer_discard(builder, which);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
assert(offset + size <= writer->size - writer->stolen);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to ilo_builder_writer_reserve_bottom(), but reserve from the top.
|
||||
*/
|
||||
static inline unsigned
|
||||
ilo_builder_writer_reserve_top(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
unsigned alignment, unsigned size)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
unsigned offset;
|
||||
|
||||
assert(alignment && util_is_power_of_two(alignment));
|
||||
offset = (writer->size - writer->stolen - size) & ~(alignment - 1);
|
||||
|
||||
if (unlikely(offset < writer->used ||
|
||||
size > writer->size - writer->stolen)) {
|
||||
if (!ilo_builder_writer_grow(builder, which,
|
||||
align(writer->used, alignment) + size + writer->stolen, true)) {
|
||||
builder->unrecoverable_error = true;
|
||||
ilo_builder_writer_discard(builder, which);
|
||||
}
|
||||
|
||||
offset = (writer->size - writer->stolen - size) & ~(alignment - 1);
|
||||
assert(offset + size <= writer->size - writer->stolen);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relocation entry to the writer.
|
||||
*/
|
||||
static inline void
|
||||
ilo_builder_writer_reloc(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
unsigned offset, struct intel_bo *bo,
|
||||
unsigned bo_offset, unsigned reloc_flags)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
uint64_t presumed_offset;
|
||||
int err;
|
||||
|
||||
assert(offset + sizeof(uint32_t) <= writer->used ||
|
||||
(offset >= writer->size - writer->stolen &&
|
||||
offset + sizeof(uint32_t) <= writer->size));
|
||||
|
||||
err = intel_bo_add_reloc(writer->bo, offset, bo, bo_offset,
|
||||
reloc_flags, &presumed_offset);
|
||||
if (unlikely(err))
|
||||
builder->unrecoverable_error = true;
|
||||
|
||||
/* 32-bit addressing */
|
||||
assert(presumed_offset == (uint64_t) ((uint32_t) presumed_offset));
|
||||
*((uint32_t *) ((char *) writer->ptr + offset)) = presumed_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve a region from the state buffer. Both the offset, in bytes, and the
|
||||
* pointer to the reserved region are returned.
|
||||
*
|
||||
* Note that \p alignment is in bytes and \p len is in DWords.
|
||||
*/
|
||||
static inline uint32_t
|
||||
ilo_builder_state_pointer(struct ilo_builder *builder,
|
||||
enum ilo_builder_item_type item,
|
||||
unsigned alignment, unsigned len,
|
||||
uint32_t **dw)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
const unsigned size = len << 2;
|
||||
const unsigned offset = ilo_builder_writer_reserve_top(builder,
|
||||
which, alignment, size);
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
/* all states are at least aligned to 32-bytes */
|
||||
assert(alignment % 32 == 0);
|
||||
|
||||
*dw = (uint32_t *) ((char *) writer->ptr + offset);
|
||||
|
||||
writer->stolen = writer->size - offset;
|
||||
|
||||
ilo_builder_writer_checked_record(builder, which, item, offset, size);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a dynamic state to the state buffer.
|
||||
*/
|
||||
static inline uint32_t
|
||||
ilo_builder_state_write(struct ilo_builder *builder,
|
||||
enum ilo_builder_item_type item,
|
||||
unsigned alignment, unsigned len,
|
||||
const uint32_t *dw)
|
||||
{
|
||||
uint32_t offset, *dst;
|
||||
|
||||
offset = ilo_builder_state_pointer(builder, item, alignment, len, &dst);
|
||||
memcpy(dst, dw, len << 2);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a surface state to the surface buffer. The offset, in bytes, of the
|
||||
* state is returned.
|
||||
*
|
||||
* Note that \p alignment is in bytes and \p len is in DWords.
|
||||
*/
|
||||
static inline uint32_t
|
||||
ilo_builder_surface_write(struct ilo_builder *builder,
|
||||
enum ilo_builder_item_type item,
|
||||
unsigned alignment, unsigned len,
|
||||
const uint32_t *dw)
|
||||
{
|
||||
assert(item == ILO_BUILDER_ITEM_SURFACE ||
|
||||
item == ILO_BUILDER_ITEM_BINDING_TABLE);
|
||||
|
||||
return ilo_builder_state_write(builder, item, alignment, len, dw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relocation entry for a DWord of a surface state.
|
||||
*/
|
||||
static inline void
|
||||
ilo_builder_surface_reloc(struct ilo_builder *builder,
|
||||
uint32_t offset, unsigned dw_index,
|
||||
struct intel_bo *bo, unsigned bo_offset,
|
||||
unsigned reloc_flags)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
|
||||
ilo_builder_writer_reloc(builder, which, offset + (dw_index << 2),
|
||||
bo, bo_offset, reloc_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a kernel to the instruction buffer. The offset, in bytes, of the
|
||||
* kernel is returned.
|
||||
*/
|
||||
static inline uint32_t
|
||||
ilo_builder_instruction_write(struct ilo_builder *builder,
|
||||
unsigned size, const void *kernel)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_INSTRUCTION;
|
||||
/*
|
||||
* From the Sandy Bridge PRM, volume 4 part 2, page 112:
|
||||
*
|
||||
* "Due to prefetch of the instruction stream, the EUs may attempt to
|
||||
* access up to 8 instructions (128 bytes) beyond the end of the
|
||||
* kernel program - possibly into the next memory page. Although
|
||||
* these instructions will not be executed, software must account for
|
||||
* the prefetch in order to avoid invalid page access faults."
|
||||
*/
|
||||
const unsigned reserved_size = size + 128;
|
||||
/* kernels are aligned to 64 bytes */
|
||||
const unsigned alignment = 64;
|
||||
const unsigned offset = ilo_builder_writer_reserve_bottom(builder,
|
||||
which, alignment, reserved_size);
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
memcpy((char *) writer->ptr + offset, kernel, size);
|
||||
|
||||
writer->used = offset + size;
|
||||
|
||||
ilo_builder_writer_checked_record(builder, which,
|
||||
ILO_BUILDER_ITEM_KERNEL, offset, size);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve a region from the batch buffer. Both the offset, in DWords, and
|
||||
* the pointer to the reserved region are returned.
|
||||
*
|
||||
* Note that \p len is in DWords.
|
||||
*/
|
||||
static inline unsigned
|
||||
ilo_builder_batch_pointer(struct ilo_builder *builder,
|
||||
unsigned len, uint32_t **dw)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
/*
|
||||
* We know the batch bo is always aligned. Using 1 here should allow the
|
||||
* compiler to optimize away aligning.
|
||||
*/
|
||||
const unsigned alignment = 1;
|
||||
const unsigned size = len << 2;
|
||||
const unsigned offset = ilo_builder_writer_reserve_bottom(builder,
|
||||
which, alignment, size);
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
assert(offset % 4 == 0);
|
||||
*dw = (uint32_t *) ((char *) writer->ptr + offset);
|
||||
|
||||
writer->used = offset + size;
|
||||
|
||||
return offset >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a command to the batch buffer.
|
||||
*/
|
||||
static inline unsigned
|
||||
ilo_builder_batch_write(struct ilo_builder *builder,
|
||||
unsigned len, const uint32_t *dw)
|
||||
{
|
||||
unsigned pos;
|
||||
uint32_t *dst;
|
||||
|
||||
pos = ilo_builder_batch_pointer(builder, len, &dst);
|
||||
memcpy(dst, dw, len << 2);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relocation entry for a DWord of a command.
|
||||
*/
|
||||
static inline void
|
||||
ilo_builder_batch_reloc(struct ilo_builder *builder, unsigned pos,
|
||||
struct intel_bo *bo, unsigned bo_offset,
|
||||
unsigned reloc_flags)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
|
||||
ilo_builder_writer_reloc(builder, which, pos << 2,
|
||||
bo, bo_offset, reloc_flags);
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
ilo_builder_batch_used(const struct ilo_builder *builder)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
const struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
return writer->used >> 2;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
ilo_builder_batch_space(const struct ilo_builder *builder)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
const struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
return (writer->size - writer->stolen - writer->used) >> 2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ilo_builder_batch_discard(struct ilo_builder *builder)
|
||||
{
|
||||
ilo_builder_writer_discard(builder, ILO_BUILDER_WRITER_BATCH);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ilo_builder_batch_print_stats(const struct ilo_builder *builder)
|
||||
{
|
||||
const enum ilo_builder_writer_type which = ILO_BUILDER_WRITER_BATCH;
|
||||
const struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
ilo_printf("%d+%d bytes (%d%% full)\n",
|
||||
writer->used, writer->stolen,
|
||||
(writer->used + writer->stolen) * 100 / writer->size);
|
||||
}
|
||||
|
||||
void
|
||||
ilo_builder_batch_snapshot(const struct ilo_builder *builder,
|
||||
struct ilo_builder_snapshot *snapshot);
|
||||
|
||||
void
|
||||
ilo_builder_batch_restore(struct ilo_builder *builder,
|
||||
const struct ilo_builder_snapshot *snapshot);
|
||||
|
||||
void
|
||||
ilo_builder_batch_state_base_address(struct ilo_builder *builder,
|
||||
bool init_all);
|
||||
|
||||
void
|
||||
ilo_builder_batch_mi_batch_buffer_end(struct ilo_builder *builder);
|
||||
|
||||
#endif /* ILO_BUILDER_H */
|
||||
583
src/gallium/drivers/ilo/ilo_builder_decode.c
Normal file
583
src/gallium/drivers/ilo/ilo_builder_decode.c
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 2014 LunarG, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Chia-I Wu <olv@lunarg.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "genhw/genhw.h"
|
||||
#include "shader/toy_compiler.h"
|
||||
#include "intel_winsys.h"
|
||||
#include "ilo_builder.h"
|
||||
|
||||
#define READ(dw, field) (((dw) & field ## __MASK) >> field ## __SHIFT)
|
||||
|
||||
static const uint32_t *
|
||||
writer_pointer(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
unsigned offset)
|
||||
{
|
||||
const struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
return (const uint32_t *) ((const char *) writer->ptr + offset);
|
||||
}
|
||||
|
||||
static uint32_t _util_printf_format(5, 6)
|
||||
writer_dw(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
unsigned offset, unsigned dw_index,
|
||||
const char *format, ...)
|
||||
{
|
||||
const uint32_t *dw = writer_pointer(builder, which, offset);
|
||||
va_list ap;
|
||||
char desc[16];
|
||||
int len;
|
||||
|
||||
ilo_printf("0x%08x: 0x%08x: ",
|
||||
offset + (dw_index << 2), dw[dw_index]);
|
||||
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(desc, sizeof(desc), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len >= sizeof(desc)) {
|
||||
len = sizeof(desc) - 1;
|
||||
desc[len] = '\0';
|
||||
}
|
||||
|
||||
if (desc[len - 1] == '\n') {
|
||||
desc[len - 1] = '\0';
|
||||
ilo_printf("%8s: \n", desc);
|
||||
} else {
|
||||
ilo_printf("%8s: ", desc);
|
||||
}
|
||||
|
||||
return dw[dw_index];
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_blob(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 4;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
const uint32_t *dw = writer_pointer(builder, which, offset);
|
||||
|
||||
writer_dw(builder, which, offset, 0, "BLOB%d", i);
|
||||
/* output a single line for all four DWords */
|
||||
ilo_printf("(% f, % f, % f, % f) (0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
|
||||
uif(dw[0]), uif(dw[1]), uif(dw[2]), uif(dw[3]),
|
||||
dw[0], dw[1], dw[2], dw[3]);
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_clip_viewport(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 4;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, offset, 0, "CLIP VP%d", i);
|
||||
ilo_printf("xmin = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 1, "CLIP VP%d", i);
|
||||
ilo_printf("xmax = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 2, "CLIP VP%d", i);
|
||||
ilo_printf("ymin = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 3, "CLIP VP%d", i);
|
||||
ilo_printf("ymax = %f\n", uif(dw));
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_sf_clip_viewport_gen7(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 16;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, offset, 0, "SF_CLIP VP%d", i);
|
||||
ilo_printf("m00 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 1, "SF_CLIP VP%d", i);
|
||||
ilo_printf("m11 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 2, "SF_CLIP VP%d", i);
|
||||
ilo_printf("m22 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 3, "SF_CLIP VP%d", i);
|
||||
ilo_printf("m30 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 4, "SF_CLIP VP%d", i);
|
||||
ilo_printf("m31 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 5, "SF_CLIP VP%d", i);
|
||||
ilo_printf("m32 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 8, "SF_CLIP VP%d", i);
|
||||
ilo_printf("guardband xmin = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 9, "SF_CLIP VP%d", i);
|
||||
ilo_printf("guardband xmax = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 10, "SF_CLIP VP%d", i);
|
||||
ilo_printf("guardband ymin = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 11, "SF_CLIP VP%d", i);
|
||||
ilo_printf("guardband ymax = %f\n", uif(dw));
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_sf_viewport_gen6(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 8;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, offset, 0, "SF VP%d", i);
|
||||
ilo_printf("m00 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 1, "SF VP%d", i);
|
||||
ilo_printf("m11 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 2, "SF VP%d", i);
|
||||
ilo_printf("m22 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 3, "SF VP%d", i);
|
||||
ilo_printf("m30 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 4, "SF VP%d", i);
|
||||
ilo_printf("m31 = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 5, "SF VP%d", i);
|
||||
ilo_printf("m32 = %f\n", uif(dw));
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_sf_viewport(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
if (builder->dev->gen >= ILO_GEN(7))
|
||||
writer_decode_sf_clip_viewport_gen7(builder, which, item);
|
||||
else
|
||||
writer_decode_sf_viewport_gen6(builder, which, item);
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_scissor_rect(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 2;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, offset, 0, "SCISSOR%d", i);
|
||||
ilo_printf("xmin %d, ymin %d\n",
|
||||
READ(dw, GEN6_SCISSOR_DW0_MIN_X),
|
||||
READ(dw, GEN6_SCISSOR_DW0_MIN_Y));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 1, "SCISSOR%d", i);
|
||||
ilo_printf("xmax %d, ymax %d\n",
|
||||
READ(dw, GEN6_SCISSOR_DW1_MAX_X),
|
||||
READ(dw, GEN6_SCISSOR_DW1_MAX_Y));
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_cc_viewport(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 2;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, offset, 0, "CC VP%d", i);
|
||||
ilo_printf("min_depth = %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, offset, 1, "CC VP%d", i);
|
||||
ilo_printf("max_depth = %f\n", uif(dw));
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_color_calc(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 0, "CC");
|
||||
ilo_printf("alpha test format %s, round disable %d, "
|
||||
"stencil ref %d, bf stencil ref %d\n",
|
||||
READ(dw, GEN6_CC_DW0_ALPHATEST) ? "FLOAT32" : "UNORM8",
|
||||
(bool) (dw & GEN6_CC_DW0_ROUND_DISABLE_DISABLE),
|
||||
READ(dw, GEN6_CC_DW0_STENCIL0_REF),
|
||||
READ(dw, GEN6_CC_DW0_STENCIL1_REF));
|
||||
|
||||
writer_dw(builder, which, item->offset, 1, "CC\n");
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 2, "CC");
|
||||
ilo_printf("constant red %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 3, "CC");
|
||||
ilo_printf("constant green %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 4, "CC");
|
||||
ilo_printf("constant blue %f\n", uif(dw));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 5, "CC");
|
||||
ilo_printf("constant alpha %f\n", uif(dw));
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_depth_stencil(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 0, "D_S");
|
||||
ilo_printf("stencil %sable, func %d, write %sable\n",
|
||||
(dw & GEN6_ZS_DW0_STENCIL_TEST_ENABLE) ? "en" : "dis",
|
||||
READ(dw, GEN6_ZS_DW0_STENCIL0_FUNC),
|
||||
(dw & GEN6_ZS_DW0_STENCIL_WRITE_ENABLE) ? "en" : "dis");
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 1, "D_S");
|
||||
ilo_printf("stencil test mask 0x%x, write mask 0x%x\n",
|
||||
READ(dw, GEN6_ZS_DW1_STENCIL0_VALUEMASK),
|
||||
READ(dw, GEN6_ZS_DW1_STENCIL0_WRITEMASK));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 2, "D_S");
|
||||
ilo_printf("depth test %sable, func %d, write %sable\n",
|
||||
(dw & GEN6_ZS_DW2_DEPTH_TEST_ENABLE) ? "en" : "dis",
|
||||
READ(dw, GEN6_ZS_DW2_DEPTH_FUNC),
|
||||
(dw & GEN6_ZS_DW2_DEPTH_WRITE_ENABLE) ? "en" : "dis");
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_blend(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 2;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
writer_dw(builder, which, offset, 0, "BLEND%d\n", i);
|
||||
writer_dw(builder, which, offset, 1, "BLEND%d\n", i);
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_sampler(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 4;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
writer_dw(builder, which, offset, 0, "WM SAMP%d", i);
|
||||
ilo_printf("filtering\n");
|
||||
|
||||
writer_dw(builder, which, offset, 1, "WM SAMP%d", i);
|
||||
ilo_printf("wrapping, lod\n");
|
||||
|
||||
writer_dw(builder, which, offset, 2, "WM SAMP%d", i);
|
||||
ilo_printf("default color pointer\n");
|
||||
|
||||
writer_dw(builder, which, offset, 3, "WM SAMP%d", i);
|
||||
ilo_printf("chroma key, aniso\n");
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_surface_gen7(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 0, "SURF");
|
||||
ilo_printf("type 0x%x, format 0x%x, tiling %d, %s array\n",
|
||||
READ(dw, GEN7_SURFACE_DW0_TYPE),
|
||||
READ(dw, GEN7_SURFACE_DW0_FORMAT),
|
||||
READ(dw, GEN7_SURFACE_DW0_TILING),
|
||||
(dw & GEN7_SURFACE_DW0_IS_ARRAY) ? "is" : "not");
|
||||
|
||||
writer_dw(builder, which, item->offset, 1, "SURF");
|
||||
ilo_printf("offset\n");
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 2, "SURF");
|
||||
ilo_printf("%dx%d size\n",
|
||||
READ(dw, GEN7_SURFACE_DW2_WIDTH),
|
||||
READ(dw, GEN7_SURFACE_DW2_HEIGHT));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 3, "SURF");
|
||||
ilo_printf("depth %d, pitch %d\n",
|
||||
READ(dw, GEN7_SURFACE_DW3_DEPTH),
|
||||
READ(dw, GEN7_SURFACE_DW3_PITCH));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 4, "SURF");
|
||||
ilo_printf("min array element %d, array extent %d\n",
|
||||
READ(dw, GEN7_SURFACE_DW4_MIN_ARRAY_ELEMENT),
|
||||
READ(dw, GEN7_SURFACE_DW4_RT_VIEW_EXTENT));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 5, "SURF");
|
||||
ilo_printf("mip base %d, mips %d, x,y offset: %d,%d\n",
|
||||
READ(dw, GEN7_SURFACE_DW5_MIN_LOD),
|
||||
READ(dw, GEN7_SURFACE_DW5_MIP_COUNT_LOD),
|
||||
READ(dw, GEN7_SURFACE_DW5_X_OFFSET),
|
||||
READ(dw, GEN7_SURFACE_DW5_Y_OFFSET));
|
||||
|
||||
writer_dw(builder, which, item->offset, 6, "SURF\n");
|
||||
writer_dw(builder, which, item->offset, 7, "SURF\n");
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_surface_gen6(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
uint32_t dw;
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 0, "SURF");
|
||||
ilo_printf("type 0x%x, format 0x%x\n",
|
||||
READ(dw, GEN6_SURFACE_DW0_TYPE),
|
||||
READ(dw, GEN6_SURFACE_DW0_FORMAT));
|
||||
|
||||
writer_dw(builder, which, item->offset, 1, "SURF");
|
||||
ilo_printf("offset\n");
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 2, "SURF");
|
||||
ilo_printf("%dx%d size, %d mips\n",
|
||||
READ(dw, GEN6_SURFACE_DW2_WIDTH),
|
||||
READ(dw, GEN6_SURFACE_DW2_HEIGHT),
|
||||
READ(dw, GEN6_SURFACE_DW2_MIP_COUNT_LOD));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 3, "SURF");
|
||||
ilo_printf("pitch %d, tiling %d\n",
|
||||
READ(dw, GEN6_SURFACE_DW3_PITCH),
|
||||
READ(dw, GEN6_SURFACE_DW3_TILING));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 4, "SURF");
|
||||
ilo_printf("mip base %d\n",
|
||||
READ(dw, GEN6_SURFACE_DW4_MIN_LOD));
|
||||
|
||||
dw = writer_dw(builder, which, item->offset, 5, "SURF");
|
||||
ilo_printf("x,y offset: %d,%d\n",
|
||||
READ(dw, GEN6_SURFACE_DW5_X_OFFSET),
|
||||
READ(dw, GEN6_SURFACE_DW5_Y_OFFSET));
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_surface(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
if (builder->dev->gen >= ILO_GEN(7))
|
||||
writer_decode_surface_gen7(builder, which, item);
|
||||
else
|
||||
writer_decode_surface_gen6(builder, which, item);
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_binding_table(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const unsigned state_size = sizeof(uint32_t) * 1;
|
||||
const unsigned count = item->size / state_size;
|
||||
unsigned offset = item->offset;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
writer_dw(builder, which, offset, 0, "BIND");
|
||||
ilo_printf("BINDING_TABLE_STATE[%d]\n", i);
|
||||
|
||||
offset += state_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
writer_decode_kernel(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item)
|
||||
{
|
||||
const void *kernel;
|
||||
|
||||
ilo_printf("0x%08x:\n", item->offset);
|
||||
kernel = (const void *) writer_pointer(builder, which, item->offset);
|
||||
toy_compiler_disassemble(builder->dev, kernel, item->size, true);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
void (*func)(const struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which,
|
||||
const struct ilo_builder_item *item);
|
||||
} writer_decode_table[ILO_BUILDER_ITEM_COUNT] = {
|
||||
[ILO_BUILDER_ITEM_BLOB] = { writer_decode_blob },
|
||||
[ILO_BUILDER_ITEM_CLIP_VIEWPORT] = { writer_decode_clip_viewport },
|
||||
[ILO_BUILDER_ITEM_SF_VIEWPORT] = { writer_decode_sf_viewport },
|
||||
[ILO_BUILDER_ITEM_SCISSOR_RECT] = { writer_decode_scissor_rect },
|
||||
[ILO_BUILDER_ITEM_CC_VIEWPORT] = { writer_decode_cc_viewport },
|
||||
[ILO_BUILDER_ITEM_COLOR_CALC] = { writer_decode_color_calc },
|
||||
[ILO_BUILDER_ITEM_DEPTH_STENCIL] = { writer_decode_depth_stencil },
|
||||
[ILO_BUILDER_ITEM_BLEND] = { writer_decode_blend },
|
||||
[ILO_BUILDER_ITEM_SAMPLER] = { writer_decode_sampler },
|
||||
[ILO_BUILDER_ITEM_SURFACE] = { writer_decode_surface },
|
||||
[ILO_BUILDER_ITEM_BINDING_TABLE] = { writer_decode_binding_table },
|
||||
[ILO_BUILDER_ITEM_KERNEL] = { writer_decode_kernel },
|
||||
};
|
||||
|
||||
static void
|
||||
ilo_builder_writer_decode_items(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
int i;
|
||||
|
||||
if (!writer->item_used)
|
||||
return;
|
||||
|
||||
writer->ptr = intel_bo_map(writer->bo, false);
|
||||
if (!writer->ptr)
|
||||
return;
|
||||
|
||||
for (i = 0; i < writer->item_used; i++) {
|
||||
const struct ilo_builder_item *item = &writer->items[i];
|
||||
|
||||
writer_decode_table[item->type].func(builder, which, item);
|
||||
}
|
||||
|
||||
intel_bo_unmap(writer->bo);
|
||||
}
|
||||
|
||||
static void
|
||||
ilo_builder_writer_decode(struct ilo_builder *builder,
|
||||
enum ilo_builder_writer_type which)
|
||||
{
|
||||
struct ilo_builder_writer *writer = &builder->writers[which];
|
||||
|
||||
assert(writer->bo && !writer->ptr);
|
||||
|
||||
switch (which) {
|
||||
case ILO_BUILDER_WRITER_BATCH:
|
||||
ilo_printf("decoding batch buffer: %d bytes\n", writer->used);
|
||||
if (writer->used)
|
||||
intel_winsys_decode_bo(builder->winsys, writer->bo, writer->used);
|
||||
|
||||
ilo_printf("decoding state buffer: %d states\n",
|
||||
writer->item_used);
|
||||
ilo_builder_writer_decode_items(builder, which);
|
||||
break;
|
||||
case ILO_BUILDER_WRITER_INSTRUCTION:
|
||||
if (true) {
|
||||
ilo_printf("skipping instruction buffer: %d kernels\n",
|
||||
writer->item_used);
|
||||
} else {
|
||||
ilo_printf("decoding instruction buffer: %d kernels\n",
|
||||
writer->item_used);
|
||||
|
||||
ilo_builder_writer_decode_items(builder, which);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the builder according to the recorded items. This can be called
|
||||
* only after a successful ilo_builder_end().
|
||||
*/
|
||||
void
|
||||
ilo_builder_decode(struct ilo_builder *builder)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(!builder->unrecoverable_error);
|
||||
|
||||
for (i = 0; i < ILO_BUILDER_WRITER_COUNT; i++)
|
||||
ilo_builder_writer_decode(builder, i);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue