summaryrefslogtreecommitdiff
path: root/src/microsoft/compiler/dxil_container.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microsoft/compiler/dxil_container.c')
-rw-r--r--src/microsoft/compiler/dxil_container.c122
1 files changed, 78 insertions, 44 deletions
diff --git a/src/microsoft/compiler/dxil_container.c b/src/microsoft/compiler/dxil_container.c
index e8373fb93ab..936bf9a792f 100644
--- a/src/microsoft/compiler/dxil_container.c
+++ b/src/microsoft/compiler/dxil_container.c
@@ -72,11 +72,12 @@ bool
dxil_container_add_features(struct dxil_container *c,
const struct dxil_features *features)
{
- union {
- struct dxil_features flags;
- uint64_t bits;
- } u = { .flags = *features };
- return add_part(c, DXIL_SFI0, &u.bits, sizeof(u.bits));
+ /* DXIL feature info is a bitfield packed into a uint64_t. */
+ static_assert(sizeof(struct dxil_features) <= sizeof(uint64_t),
+ "Expected dxil_features to fit into a uint64_t");
+ uint64_t bits = 0;
+ memcpy(&bits, features, sizeof(struct dxil_features));
+ return add_part(c, DXIL_SFI0, &bits, sizeof(uint64_t));
}
typedef struct {
@@ -89,12 +90,13 @@ typedef struct {
static uint32_t
get_semantic_name_offset(name_offset_cache_t *cache, const char *name,
- struct _mesa_string_buffer *buf, uint32_t buf_offset)
+ struct _mesa_string_buffer *buf, uint32_t buf_offset,
+ bool validator_7)
{
uint32_t offset = buf->length + buf_offset;
- // DXC doesn't de-duplicate arbitrary semantic names, only SVs.
- if (strncmp(name, "SV_", 3) == 0) {
+ /* DXC doesn't de-duplicate arbitrary semantic names until validator 1.7, only SVs. */
+ if (validator_7 || strncmp(name, "SV_", 3) == 0) {
/* consider replacing this with a binary search using rb_tree */
for (unsigned i = 0; i < cache->num_entries; ++i) {
if (!strcmp(name, cache->entries[i].name))
@@ -114,17 +116,23 @@ static uint32_t
collect_semantic_names(unsigned num_records,
struct dxil_signature_record *io_data,
struct _mesa_string_buffer *buf,
- uint32_t buf_offset)
+ uint32_t buf_offset,
+ bool validator_7)
{
name_offset_cache_t cache;
cache.num_entries = 0;
for (unsigned i = 0; i < num_records; ++i) {
struct dxil_signature_record *io = &io_data[i];
- uint32_t offset = get_semantic_name_offset(&cache, io->name, buf, buf_offset);
+ uint32_t offset = get_semantic_name_offset(&cache, io->name, buf, buf_offset, validator_7);
for (unsigned j = 0; j < io->num_elements; ++j)
io->elements[j].semantic_name_offset = offset;
}
+ if (validator_7 && buf->length % sizeof(uint32_t) != 0) {
+ unsigned padding_to_add = sizeof(uint32_t) - (buf->length % sizeof(uint32_t));
+ char padding[sizeof(uint32_t)] = { 0 };
+ _mesa_string_buffer_append_len(buf, padding, padding_to_add);
+ }
return buf_offset + buf->length;
}
@@ -132,7 +140,8 @@ bool
dxil_container_add_io_signature(struct dxil_container *c,
enum dxil_part_fourcc part,
unsigned num_records,
- struct dxil_signature_record *io_data)
+ struct dxil_signature_record *io_data,
+ bool validator_7)
{
struct {
uint32_t param_count;
@@ -156,7 +165,8 @@ dxil_container_add_io_signature(struct dxil_container *c,
_mesa_string_buffer_create(NULL, 1024);
uint32_t last_offset = collect_semantic_names(num_records, io_data,
- names, fixed_size);
+ names, fixed_size,
+ validator_7);
if (!add_part_header(c, part, last_offset) ||
@@ -190,12 +200,15 @@ dxil_container_add_state_validation(struct dxil_container *c,
const struct dxil_module *m,
struct dxil_validation_state *state)
{
- uint32_t psv1_size = sizeof(struct dxil_psv_runtime_info_1);
- uint32_t resource_bind_info_size = 4 * sizeof(uint32_t);
+ uint32_t psv_size = m->minor_validator >= 6 ?
+ sizeof(struct dxil_psv_runtime_info_2) :
+ sizeof(struct dxil_psv_runtime_info_1);
+ uint32_t resource_bind_info_size = m->minor_validator >= 6 ?
+ sizeof(struct dxil_resource_v1) : sizeof(struct dxil_resource_v0);
uint32_t dxil_pvs_sig_size = sizeof(struct dxil_psv_signature_element);
uint32_t resource_count = state->num_resources;
- uint32_t size = psv1_size + 2 * sizeof(uint32_t);
+ uint32_t size = psv_size + 2 * sizeof(uint32_t);
if (resource_count > 0) {
size += sizeof (uint32_t) +
resource_bind_info_size * resource_count;
@@ -203,43 +216,36 @@ dxil_container_add_state_validation(struct dxil_container *c,
uint32_t string_table_size = (m->sem_string_table->length + 3) & ~3u;
size += sizeof(uint32_t) + string_table_size;
- // Semantic index table size, currently always 0
size += sizeof(uint32_t) + m->sem_index_table.size * sizeof(uint32_t);
- if (m->num_sig_inputs || m->num_sig_outputs) {
+ if (m->num_sig_inputs || m->num_sig_outputs || m->num_sig_patch_consts) {
size += sizeof(uint32_t);
}
size += dxil_pvs_sig_size * m->num_sig_inputs;
size += dxil_pvs_sig_size * m->num_sig_outputs;
- // size += dxil_pvs_sig_size * m->num_sig_patch_const...;
-
- state->state.sig_input_vectors = (uint8_t)m->num_psv_inputs;
+ size += dxil_pvs_sig_size * m->num_sig_patch_consts;
- // TODO: check proper stream
- state->state.sig_output_vectors[0] = (uint8_t)m->num_psv_outputs;
+ state->state.psv1.sig_input_vectors = (uint8_t)m->num_psv_inputs;
- // TODO: Add viewID records size
+ for (unsigned i = 0; i < 4; ++i)
+ state->state.psv1.sig_output_vectors[i] = (uint8_t)m->num_psv_outputs[i];
- // TODO: Add sig input output dependency table size
- uint32_t dependency_table_size = 0;
- if (state->state.sig_input_vectors > 0) {
- for (unsigned i = 0; i < 4; ++i) {
- if (state->state.sig_output_vectors[i] > 0)
- dependency_table_size += sizeof(uint32_t) * ((state->state.sig_output_vectors[i] + 7) >> 3) *
- state->state.sig_input_vectors * 4;
- }
+ if (state->state.psv1.uses_view_id) {
+ for (unsigned i = 0; i < 4; ++i)
+ size += m->dependency_table_dwords_per_input[i] * sizeof(uint32_t);
}
- size += dependency_table_size;
- // TODO: Domain shader table goes here
+
+ for (unsigned i = 0; i < 4; ++i)
+ size += m->io_dependency_table_size[i] * sizeof(uint32_t);
if (!add_part_header(c, DXIL_PSV0, size))
return false;
- if (!blob_write_bytes(&c->parts, &psv1_size, sizeof(psv1_size)))
+ if (!blob_write_bytes(&c->parts, &psv_size, sizeof(psv_size)))
return false;
- if (!blob_write_bytes(&c->parts, &state->state, psv1_size))
+ if (!blob_write_bytes(&c->parts, &state->state, psv_size))
return false;
if (!blob_write_bytes(&c->parts, &resource_count, sizeof(resource_count)))
@@ -247,7 +253,7 @@ dxil_container_add_state_validation(struct dxil_container *c,
if (resource_count > 0) {
if (!blob_write_bytes(&c->parts, &resource_bind_info_size, sizeof(resource_bind_info_size)) ||
- !blob_write_bytes(&c->parts, state->resources, resource_bind_info_size * state->num_resources))
+ !blob_write_bytes(&c->parts, state->resources.v0, resource_bind_info_size * state->num_resources))
return false;
}
@@ -258,7 +264,6 @@ dxil_container_add_state_validation(struct dxil_container *c,
!blob_write_bytes(&c->parts, &fill, string_table_size - m->sem_string_table->length))
return false;
- // TODO: write the correct semantic index table. Currently it is empty
if (!blob_write_bytes(&c->parts, &m->sem_index_table.size, sizeof(uint32_t)))
return false;
@@ -268,7 +273,7 @@ dxil_container_add_state_validation(struct dxil_container *c,
return false;
}
- if (m->num_sig_inputs || m->num_sig_outputs) {
+ if (m->num_sig_inputs || m->num_sig_outputs || m->num_sig_patch_consts) {
if (!blob_write_bytes(&c->parts, &dxil_pvs_sig_size, sizeof(dxil_pvs_sig_size)))
return false;
@@ -277,16 +282,45 @@ dxil_container_add_state_validation(struct dxil_container *c,
if (!blob_write_bytes(&c->parts, &m->psv_outputs, dxil_pvs_sig_size * m->num_sig_outputs))
return false;
- }
- // TODO: Write PatchConst...
+ if (!blob_write_bytes(&c->parts, &m->psv_patch_consts, dxil_pvs_sig_size * m->num_sig_patch_consts))
+ return false;
+ }
- // TODO: Handle case when ViewID is used
+ /* This was a bug in the DXIL validation logic prior to 1.8. When replicating these I/O dependency
+ * tables from the metadata to the container, the pointer is advanced for each stream,
+ * and then copied for all streams... meaning that the first streams have zero data, since the
+ * pointer is advanced and then never written to. The last stream (that has data) then has the
+ * data from all streams written to it. However, if any stream before the last one has a larger
+ * size, this will cause corruption, since it's writing to the smaller space that was allocated
+ * for the last stream. We assume that never happens, and just zero all earlier streams. */
+ if (m->shader_kind == DXIL_GEOMETRY_SHADER && m->minor_validator < 8) {
+ bool zero_view_id_deps = false, zero_io_deps = false;
+ for (int i = 3; i >= 0; --i) {
+ if (state->state.psv1.uses_view_id && m->dependency_table_dwords_per_input[i]) {
+ if (zero_view_id_deps)
+ memset(m->viewid_dependency_table[i], 0, sizeof(uint32_t) * m->dependency_table_dwords_per_input[i]);
+ zero_view_id_deps = true;
+ }
+ if (m->io_dependency_table_size[i]) {
+ if (zero_io_deps)
+ memset(m->io_dependency_table[i], 0, sizeof(uint32_t) * m->io_dependency_table_size[i]);
+ zero_io_deps = true;
+ }
+ }
+ }
- // TODO: Handle sig input output dependency table
+ if (state->state.psv1.uses_view_id) {
+ for (unsigned i = 0; i < 4; ++i)
+ if (!blob_write_bytes(&c->parts, m->viewid_dependency_table[i],
+ sizeof(uint32_t) * m->dependency_table_dwords_per_input[i]))
+ return false;
+ }
- for (uint32_t i = 0; i < dependency_table_size; ++i)
- blob_write_uint8(&c->parts, 0);
+ for (unsigned i = 0; i < 4; ++i)
+ if (!blob_write_bytes(&c->parts, m->io_dependency_table[i],
+ sizeof(uint32_t) * m->io_dependency_table_size[i]))
+ return false;
return true;
}