microsoft/compiler: add dxil-util code

This is support-code to emit the DirectX Intermediate Language, which is
a dialect of LLVM 3.7 bitcode. Because modern versions of LLVM doesn't
support emitting bitcode for older versions, and we can't rely on an old
LLVM version because we need the OpenCL support from Clang later on, we
instead implement our own LLVM bitcode encoder as part of this work.

See the official DXIL documentation for more details on DXIL:
https://github.com/Microsoft/DirectXShaderCompiler/blob/master/docs/DXIL.rst

The reason this comes as a separate library, is because we're also using
this code as the basis for an OpenCL C compiler, which will follow as a
separate merge-request later.

This is the combination of more than 230 commits from our development
branch, including the work from several authors.

Co-authored-by: Bill Kristiansen <billkris@microsoft.com>
Co-authored-by: Boris Brezillon <boris.brezillon@collabora.com>
Co-authored-by: Daniel Stone <daniels@collabora.com>
Co-authored-by: Gert Wollny <gert.wollny@collabora.com>
Co-authored-by: Jesse Natalie <jenatali@microsoft.com>
Co-authored-by: Louis-Francis Ratté-Boulianne <lfrb@collabora.com>
Acked-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7477>
This commit is contained in:
Erik Faye-Lund 2019-09-04 11:51:29 +02:00 committed by Marge Bot
parent 10dfd3cfb4
commit dd5fe2f3de
19 changed files with 7528 additions and 0 deletions

View File

@ -0,0 +1,104 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#include "dxil_buffer.h"
#include <assert.h>
void
dxil_buffer_init(struct dxil_buffer *b, unsigned abbrev_width)
{
blob_init(&b->blob);
b->buf = 0;
b->buf_bits = 0;
b->abbrev_width = abbrev_width;
}
void
dxil_buffer_finish(struct dxil_buffer *b)
{
blob_finish(&b->blob);
}
static bool
flush_dword(struct dxil_buffer *b)
{
assert(b->buf_bits >= 32 && b->buf_bits < 64);
uint32_t lower_bits = b->buf & UINT32_MAX;
if (!blob_write_bytes(&b->blob, &lower_bits, sizeof(lower_bits)))
return false;
b->buf >>= 32;
b->buf_bits -= 32;
return true;
}
bool
dxil_buffer_emit_bits(struct dxil_buffer *b, uint32_t data, unsigned width)
{
assert(b->buf_bits < 32);
assert(width > 0 && width <= 32);
assert((data & ~((UINT64_C(1) << width) - 1)) == 0);
b->buf |= ((uint64_t)data) << b->buf_bits;
b->buf_bits += width;
if (b->buf_bits >= 32)
return flush_dword(b);
return true;
}
bool
dxil_buffer_emit_vbr_bits(struct dxil_buffer *b, uint64_t data,
unsigned width)
{
assert(width > 1 && width <= 32);
uint32_t tag = UINT32_C(1) << (width - 1);
uint32_t max = tag - 1;
while (data > max) {
uint32_t value = (data & max) | tag;
data >>= width - 1;
if (!dxil_buffer_emit_bits(b, value, width))
return false;
}
return dxil_buffer_emit_bits(b, data, width);
}
bool
dxil_buffer_align(struct dxil_buffer *b)
{
assert(b->buf_bits < 32);
if (b->buf_bits) {
b->buf_bits = 32;
return flush_dword(b);
}
return true;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#ifndef DXIL_BUFFER_H
#define DXIL_BUFFER_H
#include "util/blob.h"
struct dxil_buffer {
struct blob blob;
uint64_t buf;
unsigned buf_bits;
unsigned abbrev_width;
};
void
dxil_buffer_init(struct dxil_buffer *b, unsigned abbrev_width);
void
dxil_buffer_finish(struct dxil_buffer *b);
bool
dxil_buffer_emit_bits(struct dxil_buffer *b, uint32_t data, unsigned width);
bool
dxil_buffer_emit_vbr_bits(struct dxil_buffer *b, uint64_t data,
unsigned width);
bool
dxil_buffer_align(struct dxil_buffer *b);
static bool
dxil_buffer_emit_abbrev_id(struct dxil_buffer *b, uint32_t id)
{
return dxil_buffer_emit_bits(b, id, b->abbrev_width);
}
#endif

View File

@ -0,0 +1,129 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#include "dxil_buffer.h"
#include <assert.h>
#include <stdio.h>
static void
init()
{
struct dxil_buffer buf;
dxil_buffer_init(&buf, 2);
assert(!buf.buf);
assert(!buf.buf_bits);
}
static void
assert_blob_data(const struct dxil_buffer *m, const uint8_t *data,
size_t len)
{
if (m->blob.size != len) {
fprintf(stderr, "blob-size mismatch, expected %zd, got %zd",
len, m->blob.size);
abort();
}
for (size_t i = 0; i < len; ++i) {
if (m->blob.data[i] != data[i]) {
fprintf(stderr, "blob-data mismatch at index %zd, "
"expected 0x%02x, got 0x%02x", i,
data[i], m->blob.data[i]);
abort();
}
}
}
#define ASSERT_BLOB_DATA(m, data) \
assert_blob_data(m, data, sizeof(data))
static void
align()
{
struct dxil_buffer buf;
dxil_buffer_init(&buf, 2);
assert_blob_data(&buf, NULL, 0);
dxil_buffer_init(&buf, 2);
dxil_buffer_emit_bits(&buf, 0xbeef, 16);
dxil_buffer_align(&buf);
assert(!buf.buf);
assert(!buf.buf_bits);
uint8_t expected0[] = { 0xef, 0xbe, 0x00, 0x00 };
ASSERT_BLOB_DATA(&buf, expected0);
dxil_buffer_align(&buf);
ASSERT_BLOB_DATA(&buf, expected0);
}
static void
emit_bits()
{
struct dxil_buffer buf;
dxil_buffer_init(&buf, 2);
dxil_buffer_emit_bits(&buf, 0xbeef, 16);
dxil_buffer_align(&buf);
assert(!buf.buf);
assert(!buf.buf_bits);
uint8_t expected0[] = { 0xef, 0xbe, 0x00, 0x00 };
ASSERT_BLOB_DATA(&buf, expected0);
dxil_buffer_init(&buf, 2);
dxil_buffer_emit_bits(&buf, 0xdead, 16);
dxil_buffer_emit_bits(&buf, 0xbeef, 16);
assert(!buf.buf);
assert(!buf.buf_bits);
uint8_t expected1[] = { 0xad, 0xde, 0xef, 0xbe };
ASSERT_BLOB_DATA(&buf, expected1);
dxil_buffer_init(&buf, 2);
dxil_buffer_emit_bits(&buf, 0x1111111, 28);
dxil_buffer_emit_bits(&buf, 0x22222222, 32);
dxil_buffer_align(&buf);
uint8_t expected2[] = { 0x11, 0x11, 0x11, 0x21, 0x22, 0x22, 0x22, 0x02 };
ASSERT_BLOB_DATA(&buf, expected2);
}
static void
emit_vbr_bits()
{
struct dxil_buffer buf;
dxil_buffer_init(&buf, 2);
dxil_buffer_emit_vbr_bits(&buf, 0x1a, 8);
dxil_buffer_emit_vbr_bits(&buf, 0x1a, 6);
dxil_buffer_emit_vbr_bits(&buf, 0x00, 2);
dxil_buffer_emit_vbr_bits(&buf, 0x0a, 4);
dxil_buffer_emit_vbr_bits(&buf, 0x04, 2);
dxil_buffer_emit_vbr_bits(&buf, 0x00, 2);
uint8_t expected[] = { 0x1a, 0x1a, 0x1a, 0x1a };
ASSERT_BLOB_DATA(&buf, expected);
}
int
main()
{
init();
align();
emit_bits();
emit_vbr_bits();
return 0;
}

View File

@ -0,0 +1,353 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#include "dxil_container.h"
#include "dxil_module.h"
#include "util/u_debug.h"
#include <assert.h>
const uint32_t DXIL_DXBC = DXIL_FOURCC('D', 'X', 'B', 'C');
void
dxil_container_init(struct dxil_container *c)
{
blob_init(&c->parts);
c->num_parts = 0;
}
void
dxil_container_finish(struct dxil_container *c)
{
blob_finish(&c->parts);
}
static bool
add_part_header(struct dxil_container *c,
enum dxil_part_fourcc fourcc,
uint32_t part_size)
{
assert(c->parts.size < UINT_MAX);
unsigned offset = (unsigned)c->parts.size;
if (!blob_write_bytes(&c->parts, &fourcc, sizeof(fourcc)) ||
!blob_write_bytes(&c->parts, &part_size, sizeof(part_size)))
return false;
assert(c->num_parts < DXIL_MAX_PARTS);
c->part_offsets[c->num_parts++] = offset;
return true;
}
static bool
add_part(struct dxil_container *c,
enum dxil_part_fourcc fourcc,
const void *part_data, uint32_t part_size)
{
return add_part_header(c, fourcc, part_size) &&
blob_write_bytes(&c->parts, part_data, part_size);
}
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));
}
typedef struct {
struct {
const char *name;
uint32_t offset;
} entries[DXIL_SHADER_MAX_IO_ROWS];
uint32_t num_entries;
} name_offset_cache_t;
static uint32_t
get_semantic_name_offset(name_offset_cache_t *cache, const char *name,
struct _mesa_string_buffer *buf, uint32_t buf_offset)
{
/* 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))
return cache->entries[i].offset;
}
uint32_t offset = buf->length + buf_offset;
cache->entries[cache->num_entries].name = name;
cache->entries[cache->num_entries].offset = offset;
++cache->num_entries;
_mesa_string_buffer_append_len(buf, name, strlen(name) + 1);
return offset;
}
static uint32_t
collect_semantic_names(unsigned num_records,
struct dxil_signature_record *io_data,
struct _mesa_string_buffer *buf,
uint32_t buf_offset)
{
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);
for (unsigned j = 0; j < io->num_elements; ++j)
io->elements[j].semantic_name_offset = offset;
}
return buf_offset + buf->length;
}
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 {
uint32_t param_count;
uint32_t param_offset;
} header;
header.param_count = 0;
uint32_t fixed_size = sizeof(header);
header.param_offset = fixed_size;
bool retval = true;
for (unsigned i = 0; i < num_records; ++i) {
/* TODO:
* - Here we need to check whether the value is actually part of the
* signature */
fixed_size += sizeof(struct dxil_signature_element) * io_data[i].num_elements;
header.param_count += io_data[i].num_elements;
}
struct _mesa_string_buffer *names =
_mesa_string_buffer_create(NULL, 1024);
uint32_t last_offset = collect_semantic_names(num_records, io_data,
names, fixed_size);
if (!add_part_header(c, part, last_offset) ||
!blob_write_bytes(&c->parts, &header, sizeof(header))) {
retval = false;
goto cleanup;
}
/* write all parts */
for (unsigned i = 0; i < num_records; ++i)
for (unsigned j = 0; j < io_data[i].num_elements; ++j) {
if (!blob_write_bytes(&c->parts, &io_data[i].elements[j],
sizeof(io_data[i].elements[j]))) {
retval = false;
goto cleanup;
}
}
/* write all names */
if (!blob_write_bytes(&c->parts, names->buf, names->length))
retval = false;
cleanup:
_mesa_string_buffer_destroy(names);
return retval;
}
bool
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 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);
if (resource_count > 0) {
size += sizeof (uint32_t) +
resource_bind_info_size * resource_count;
}
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) {
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;
// TODO: check proper stream
state->state.sig_output_vectors[0] = (uint8_t)m->num_psv_outputs;
// TODO: Add viewID records size
// 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;
}
}
size += dependency_table_size;
// TODO: Domain shader table goes here
if (!add_part_header(c, DXIL_PSV0, size))
return false;
if (!blob_write_bytes(&c->parts, &psv1_size, sizeof(psv1_size)))
return false;
if (!blob_write_bytes(&c->parts, &state->state, psv1_size))
return false;
if (!blob_write_bytes(&c->parts, &resource_count, sizeof(resource_count)))
return false;
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))
return false;
}
uint32_t fill = 0;
if (!blob_write_bytes(&c->parts, &string_table_size, sizeof(string_table_size)) ||
!blob_write_bytes(&c->parts, m->sem_string_table->buf, m->sem_string_table->length) ||
!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;
if (m->sem_index_table.size > 0) {
if (!blob_write_bytes(&c->parts, m->sem_index_table.data,
m->sem_index_table.size * sizeof(uint32_t)))
return false;
}
if (m->num_sig_inputs || m->num_sig_outputs) {
if (!blob_write_bytes(&c->parts, &dxil_pvs_sig_size, sizeof(dxil_pvs_sig_size)))
return false;
if (!blob_write_bytes(&c->parts, &m->psv_inputs, dxil_pvs_sig_size * m->num_sig_inputs))
return false;
if (!blob_write_bytes(&c->parts, &m->psv_outputs, dxil_pvs_sig_size * m->num_sig_outputs))
return false;
}
// TODO: Write PatchConst...
// TODO: Handle case when ViewID is used
// TODO: Handle sig input output dependency table
for (uint32_t i = 0; i < dependency_table_size; ++i)
blob_write_uint8(&c->parts, 0);
return true;
}
bool
dxil_container_add_module(struct dxil_container *c,
const struct dxil_module *m)
{
assert(m->buf.buf_bits == 0); // make sure the module is fully flushed
uint32_t version = (m->shader_kind << 16) |
(m->major_version << 4) |
m->minor_version;
uint32_t size = 6 * sizeof(uint32_t) + m->buf.blob.size;
assert(size % sizeof(uint32_t) == 0);
uint32_t uint32_size = size / sizeof(uint32_t);
uint32_t magic = 0x4C495844;
uint32_t dxil_version = 1 << 8; // I have no idea...
uint32_t bitcode_offset = 16;
uint32_t bitcode_size = m->buf.blob.size;
return add_part_header(c, DXIL_DXIL, size) &&
blob_write_bytes(&c->parts, &version, sizeof(version)) &&
blob_write_bytes(&c->parts, &uint32_size, sizeof(uint32_size)) &&
blob_write_bytes(&c->parts, &magic, sizeof(magic)) &&
blob_write_bytes(&c->parts, &dxil_version, sizeof(dxil_version)) &&
blob_write_bytes(&c->parts, &bitcode_offset, sizeof(bitcode_offset)) &&
blob_write_bytes(&c->parts, &bitcode_size, sizeof(bitcode_size)) &&
blob_write_bytes(&c->parts, m->buf.blob.data, m->buf.blob.size);
}
bool
dxil_container_write(struct dxil_container *c, struct blob *blob)
{
assert(blob->size == 0);
if (!blob_write_bytes(blob, &DXIL_DXBC, sizeof(DXIL_DXBC)))
return false;
const uint8_t unsigned_digest[16] = { 0 }; // null-digest means unsigned
if (!blob_write_bytes(blob, unsigned_digest, sizeof(unsigned_digest)))
return false;
uint16_t major_version = 1;
uint16_t minor_version = 0;
if (!blob_write_bytes(blob, &major_version, sizeof(major_version)) ||
!blob_write_bytes(blob, &minor_version, sizeof(minor_version)))
return false;
size_t header_size = 32 + 4 * c->num_parts;
size_t size = header_size + c->parts.size;
assert(size <= UINT32_MAX);
uint32_t container_size = (uint32_t)size;
if (!blob_write_bytes(blob, &container_size, sizeof(container_size)))
return false;
uint32_t part_offsets[DXIL_MAX_PARTS];
for (int i = 0; i < c->num_parts; ++i) {
size_t offset = header_size + c->part_offsets[i];
assert(offset <= UINT32_MAX);
part_offsets[i] = (uint32_t)offset;
}
if (!blob_write_bytes(blob, &c->num_parts, sizeof(c->num_parts)) ||
!blob_write_bytes(blob, part_offsets, sizeof(uint32_t) * c->num_parts) ||
!blob_write_bytes(blob, c->parts.data, c->parts.size))
return false;
return true;
}

View File

@ -0,0 +1,123 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#ifndef DXIL_CONTAINER_H
#define DXIL_CONTAINER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "util/blob.h"
#include "dxil_signature.h"
#define DXIL_MAX_PARTS 8
struct dxil_container {
struct blob parts;
unsigned part_offsets[DXIL_MAX_PARTS];
unsigned num_parts;
};
enum dxil_resource_type {
DXIL_RES_INVALID = 0,
DXIL_RES_SAMPLER = 1,
DXIL_RES_CBV = 2,
DXIL_RES_SRV_TYPED = 3,
DXIL_RES_SRV_RAW = 4,
DXIL_RES_SRC_STRUCTURED = 5,
DXIL_RES_UAV_TYPED = 6,
DXIL_RES_UAV_RAW = 7,
DXIL_RES_UAV_STRUCTURED,
DXIL_RES_UAV_STRUCTURED_WITH_COUNTER,
DXIL_RES_NUM_ENTRIES /* should always be last */
};
#define DXIL_FOURCC(ch0, ch1, ch2, ch3) ( \
(uint32_t)(ch0) | (uint32_t)(ch1) << 8 | \
(uint32_t)(ch2) << 16 | (uint32_t)(ch3) << 24)
enum dxil_part_fourcc {
DXIL_RDEF = DXIL_FOURCC('R', 'D', 'E', 'F'),
DXIL_ISG1 = DXIL_FOURCC('I', 'S', 'G', '1'),
DXIL_OSG1 = DXIL_FOURCC('O', 'S', 'G', '1'),
DXIL_PSG1 = DXIL_FOURCC('P', 'S', 'G', '1'),
DXIL_STAT = DXIL_FOURCC('S', 'T', 'A', 'T'),
DXIL_ILDB = DXIL_FOURCC('I', 'L', 'D', 'B'),
DXIL_ILDN = DXIL_FOURCC('I', 'L', 'D', 'N'),
DXIL_SFI0 = DXIL_FOURCC('S', 'F', 'I', '0'),
DXIL_PRIV = DXIL_FOURCC('P', 'R', 'I', 'V'),
DXIL_RTS0 = DXIL_FOURCC('R', 'T', 'S', '0'),
DXIL_DXIL = DXIL_FOURCC('D', 'X', 'I', 'L'),
DXIL_PSV0 = DXIL_FOURCC('P', 'S', 'V', '0'),
DXIL_RDAT = DXIL_FOURCC('R', 'D', 'A', 'T'),
DXIL_HASH = DXIL_FOURCC('H', 'A', 'S', 'H'),
};
struct dxil_resource {
uint32_t resource_type;
uint32_t space;
uint32_t lower_bound;
uint32_t upper_bound;
};
struct dxil_validation_state {
struct dxil_psv_runtime_info_1 state;
const struct dxil_resource *resources;
uint32_t num_resources;
};
void
dxil_container_init(struct dxil_container *c);
void
dxil_container_finish(struct dxil_container *c);
bool
dxil_container_add_features(struct dxil_container *c,
const struct dxil_features *features);
bool
dxil_container_add_io_signature(struct dxil_container *c,
enum dxil_part_fourcc part,
unsigned num_records,
struct dxil_signature_record *io);
bool
dxil_container_add_state_validation(struct dxil_container *c,
const struct dxil_module *m,
struct dxil_validation_state *state);
bool
dxil_container_add_module(struct dxil_container *c,
const struct dxil_module *m);
bool
dxil_container_write(struct dxil_container *c, struct blob *blob);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,778 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#include "dxil_dump.h"
#include "dxil_internal.h"
#define DIXL_DUMP_DECL
#include "dxil_dump_decls.h"
#include "dxil_module.h"
#include "util/string_buffer.h"
#include "util/list.h"
#include <stdio.h>
struct dxil_dumper {
struct _mesa_string_buffer *buf;
int current_indent;
};
struct dxil_dumper *dxil_dump_create(void)
{
struct dxil_dumper *d = calloc(1, sizeof(struct dxil_dumper));
d->buf = _mesa_string_buffer_create(NULL, 1024);
d->current_indent = 0;
return d;
}
void dxil_dump_free(struct dxil_dumper *d)
{
_mesa_string_buffer_destroy(d->buf);
d->buf = 0;
free(d);
}
void dxil_dump_buf_to_file(struct dxil_dumper *d, FILE *f)
{
assert(f);
assert(d);
assert(d->buf);
fprintf(f, "%s", d->buf->buf);
}
static
void dxil_dump_indention_inc(struct dxil_dumper *d)
{
++d->current_indent;
}
static
void dxil_dump_indention_dec(struct dxil_dumper *d)
{
--d->current_indent;
assert(d->current_indent >= 0);
}
static
void dxil_dump_indent(struct dxil_dumper *d)
{
for (int i = 0; i < 2 * d->current_indent; ++i)
_mesa_string_buffer_append_char(d->buf, ' ');
}
void
dxil_dump_module(struct dxil_dumper *d, struct dxil_module *m)
{
assert(m);
assert(d);
_mesa_string_buffer_printf(d->buf, "DXIL MODULE:\n");
dump_metadata(d, m);
dump_shader_info(d, &m->info);
dump_types(d, &m->type_list);
dump_gvars(d, &m->gvar_list);
dump_funcs(d, &m->func_list);
dump_attr_set_list(d, &m->attr_set_list);
dump_constants(d, &m->const_list);
dump_instrs(d, &m->instr_list);
dump_mdnodes(d, &m->mdnode_list);
dump_named_nodes(d, &m->md_named_node_list);
dump_io_signatures(d->buf, m);
dump_psv(d->buf, m);
_mesa_string_buffer_printf(d->buf, "END DXIL MODULE\n");
}
static void
dump_metadata(struct dxil_dumper *d, struct dxil_module *m)
{
_mesa_string_buffer_printf(d->buf, "Shader: %s\n",
dump_shader_string(m->shader_kind));
_mesa_string_buffer_printf(d->buf, "Version: %d.%d\n",
m->major_version, m->minor_version);
dump_features(d->buf, &m->feats);
}
static void
dump_shader_info(struct dxil_dumper *d, struct dxil_shader_info *info)
{
_mesa_string_buffer_append(d->buf, "Shader Info:\n");
if (info->has_out_position)
_mesa_string_buffer_append(d->buf, " has_out_position\n");
}
static const char *
dump_shader_string(enum dxil_shader_kind kind)
{
#define SHADER_STR(X) case DXIL_ ## X ## _SHADER: return #X
switch (kind) {
SHADER_STR(VERTEX);
SHADER_STR(PIXEL);
SHADER_STR(GEOMETRY);
SHADER_STR(COMPUTE);
default:
return "UNSUPPORTED";
}
#undef SHADER_STR
}
static void
dump_features(struct _mesa_string_buffer *buf, struct dxil_features *feat)
{
_mesa_string_buffer_printf(buf, "Features:\n");
#define PRINT_FEAT(F) if (feat->F) _mesa_string_buffer_printf(buf, " %s\n", #F)
PRINT_FEAT(doubles);
PRINT_FEAT(cs_4x_raw_sb);
PRINT_FEAT(uavs_at_every_stage);
PRINT_FEAT(use_64uavs);
PRINT_FEAT(min_precision);
PRINT_FEAT(dx11_1_double_extensions);
PRINT_FEAT(dx11_1_shader_extensions);
PRINT_FEAT(dx9_comparison_filtering);
PRINT_FEAT(tiled_resources);
PRINT_FEAT(stencil_ref);
PRINT_FEAT(inner_coverage);
PRINT_FEAT(typed_uav_load_additional_formats);
PRINT_FEAT(rovs);
PRINT_FEAT(array_layer_from_vs_or_ds);
PRINT_FEAT(wave_ops);
PRINT_FEAT(int64_ops);
PRINT_FEAT(view_id);
PRINT_FEAT(barycentrics);
PRINT_FEAT(native_low_precision);
PRINT_FEAT(shading_rate);
PRINT_FEAT(raytracing_tier_1_1);
PRINT_FEAT(sampler_feedback);
#undef PRINT_FEAT
}
static void
dump_types(struct dxil_dumper *d, struct list_head *list)
{
if (!list_length(list))
return;
_mesa_string_buffer_append(d->buf, "Types:\n");
dxil_dump_indention_inc(d);
list_for_each_entry(struct dxil_type, type, list, head) {
dxil_dump_indent(d);
dump_type(d, type);
_mesa_string_buffer_append(d->buf, "\n");
}
dxil_dump_indention_dec(d);
}
static void dump_type_name(struct dxil_dumper *d, const struct dxil_type *type)
{
if (!type) {
_mesa_string_buffer_append(d->buf, "(type error)");
return;
}
switch (type->type) {
case TYPE_VOID:
_mesa_string_buffer_append(d->buf, "void");
break;
case TYPE_INTEGER:
_mesa_string_buffer_printf(d->buf, "int%d", type->int_bits);
break;
case TYPE_FLOAT:
_mesa_string_buffer_printf(d->buf, "float%d", type->float_bits);
break;
case TYPE_POINTER:
dump_type_name(d, type->ptr_target_type);
_mesa_string_buffer_append(d->buf, "*");
break;
case TYPE_STRUCT:
_mesa_string_buffer_printf(d->buf, "struct %s", type->struct_def.name);
break;
case TYPE_ARRAY:
dump_type_name(d, type->array_or_vector_def.elem_type);
_mesa_string_buffer_printf(d->buf, "[%d]", type->array_or_vector_def.num_elems);
break;
case TYPE_FUNCTION:
_mesa_string_buffer_append(d->buf, "(");
dump_type_name(d, type->function_def.ret_type);
_mesa_string_buffer_append(d->buf, ")(");
for (size_t i = 0; i < type->function_def.args.num_types; ++i) {
if (i > 0)
_mesa_string_buffer_append(d->buf, ", ");
dump_type_name(d, type->function_def.args.types[i]);
}
_mesa_string_buffer_append(d->buf, ")");
break;
case TYPE_VECTOR:
_mesa_string_buffer_append(d->buf, "vector<");
dump_type_name(d, type->array_or_vector_def.elem_type);
_mesa_string_buffer_printf(d->buf, ", %d>", type->array_or_vector_def.num_elems);
break;
default:
_mesa_string_buffer_printf(d->buf, "unknown type %d", type->type);
}
}
static void
dump_type(struct dxil_dumper *d, const struct dxil_type *type)
{
switch (type->type) {
case TYPE_STRUCT:
_mesa_string_buffer_printf(d->buf, "struct %s {\n", type->struct_def.name);
dxil_dump_indention_inc(d);
for (size_t i = 0; i < type->struct_def.elem.num_types; ++i) {
dxil_dump_indent(d);
dump_type(d, type->struct_def.elem.types[i]);
_mesa_string_buffer_append(d->buf, "\n");
}
dxil_dump_indention_dec(d);
dxil_dump_indent(d);
_mesa_string_buffer_append(d->buf, "}\n");
break;
default:
dump_type_name(d, type);
break;
}
}
static void
dump_gvars(struct dxil_dumper *d, struct list_head *list)
{
if (!list_length(list))
return;
_mesa_string_buffer_append(d->buf, "Global variables:\n");
dxil_dump_indention_inc(d);
list_for_each_entry(struct dxil_gvar, gvar, list, head) {
dxil_dump_indent(d);
_mesa_string_buffer_printf(d->buf, "address_space(%d) ", gvar->as);
if (gvar->constant)
_mesa_string_buffer_append(d->buf, "const ");
if (gvar->align)
_mesa_string_buffer_append(d->buf, "align ");
if (gvar->initializer)
_mesa_string_buffer_printf(d->buf, "init_id:%d\n", gvar->initializer->id);
dump_type_name(d, gvar->type);
_mesa_string_buffer_printf(d->buf, " val_id:%d\n", gvar->value.id);
}
dxil_dump_indention_dec(d);
}
static void
dump_funcs(struct dxil_dumper *d, struct list_head *list)
{
if (!list_length(list))
return;
_mesa_string_buffer_append(d->buf, "Functions:\n");
dxil_dump_indention_inc(d);
list_for_each_entry(struct dxil_func, func, list, head) {
dxil_dump_indent(d);
if (func->decl)
_mesa_string_buffer_append(d->buf, "declare ");
_mesa_string_buffer_append(d->buf, func->name);
_mesa_string_buffer_append_char(d->buf, ' ');
dump_type_name(d, func->type);
if (func->attr_set)
_mesa_string_buffer_printf(d->buf, " #%d", func->attr_set);
_mesa_string_buffer_append_char(d->buf, '\n');
}
dxil_dump_indention_dec(d);
}
static void
dump_attr_set_list(struct dxil_dumper *d, struct list_head *list)
{
if (!list_length(list))
return;
_mesa_string_buffer_append(d->buf, "Attribute set:\n");
dxil_dump_indention_inc(d);
int attr_id = 1;
list_for_each_entry(struct attrib_set, attr, list, head) {
_mesa_string_buffer_printf(d->buf, " #%d: {", attr_id++);
for (unsigned i = 0; i < attr->num_attrs; ++i) {
if (i > 0)
_mesa_string_buffer_append_char(d->buf, ' ');
assert(attr->attrs[i].type == DXIL_ATTR_ENUM);
const char *value = "";
switch (attr->attrs[i].kind) {
case DXIL_ATTR_KIND_NONE: value = "none"; break;
case DXIL_ATTR_KIND_NO_UNWIND: value = "nounwind"; break;
case DXIL_ATTR_KIND_READ_NONE: value = "readnone"; break;
case DXIL_ATTR_KIND_READ_ONLY: value = "readonly"; break;
}
_mesa_string_buffer_append(d->buf, value);
}
_mesa_string_buffer_append(d->buf, "}\n");
}
dxil_dump_indention_dec(d);
}
static void
dump_constants(struct dxil_dumper *d, struct list_head *list)
{
if (!list_length(list))
return;
_mesa_string_buffer_append(d->buf, "Constants:\n");
dxil_dump_indention_inc(d);
list_for_each_entry(struct dxil_const, cnst, list, head) {
_mesa_string_buffer_append_char(d->buf, ' ');
dump_value(d, &cnst->value);
_mesa_string_buffer_append(d->buf, " = ");
dump_type_name(d, cnst->value.type);
if (!cnst->undef) {
switch (cnst->value.type->type) {
case TYPE_FLOAT:
_mesa_string_buffer_printf(d->buf, " %10.5f\n", cnst->float_value);
break;
case TYPE_INTEGER:
_mesa_string_buffer_printf(d->buf, " %d\n", cnst->int_value);
break;
case TYPE_ARRAY:
_mesa_string_buffer_append(d->buf, "{");
for (unsigned i = 0;
i < cnst->value.type->array_or_vector_def.num_elems; i++) {
_mesa_string_buffer_printf(d->buf, " %%%d",
cnst->array_values[i]->id);
dump_type_name(d, cnst->value.type);
if (i != cnst->value.type->array_or_vector_def.num_elems - 1)
_mesa_string_buffer_append(d->buf, ",");
_mesa_string_buffer_append(d->buf, " ");
}
_mesa_string_buffer_append(d->buf, "}\n");
break;
default:
unreachable("Unsupported const type");
}
} else
_mesa_string_buffer_append(d->buf, " undef\n");
}
dxil_dump_indention_dec(d);
}
static void
dump_instrs(struct dxil_dumper *d, struct list_head *list)
{
_mesa_string_buffer_append(d->buf, "Shader body:\n");
dxil_dump_indention_inc(d);
list_for_each_entry(struct dxil_instr, instr, list, head) {
dxil_dump_indent(d);
if (instr->has_value) {
dump_value(d, &instr->value);
_mesa_string_buffer_append(d->buf, " = ");
} else {
_mesa_string_buffer_append_char(d->buf, ' ');
}
switch (instr->type) {
case INSTR_BINOP: dump_instr_binop(d, &instr->binop); break;
case INSTR_CMP: dump_instr_cmp(d, &instr->cmp);break;
case INSTR_SELECT:dump_instr_select(d, &instr->select); break;
case INSTR_CAST: dump_instr_cast(d, &instr->cast); break;
case INSTR_CALL: dump_instr_call(d, &instr->call); break;
case INSTR_RET: dump_instr_ret(d, &instr->ret); break;
case INSTR_EXTRACTVAL: dump_instr_extractval(d, &instr->extractval); break;
case INSTR_BR: dump_instr_branch(d, &instr->br); break;
case INSTR_PHI: dump_instr_phi(d, &instr->phi); break;
case INSTR_ALLOCA: dump_instr_alloca(d, &instr->alloca); break;
case INSTR_GEP: dump_instr_gep(d, &instr->gep); break;
case INSTR_LOAD: dump_instr_load(d, &instr->load); break;
case INSTR_STORE: dump_instr_store(d, &instr->store); break;
case INSTR_ATOMICRMW: dump_instr_atomicrmw(d, &instr->atomicrmw); break;
default:
_mesa_string_buffer_printf(d->buf, "unknown instruction type %d", instr->type);
}
_mesa_string_buffer_append(d->buf, "\n");
}
dxil_dump_indention_dec(d);
}
static void
dump_instr_binop(struct dxil_dumper *d, struct dxil_instr_binop *binop)
{
const char *str = binop->opcode < DXIL_BINOP_INSTR_COUNT ?
binop_strings[binop->opcode] : "INVALID";
_mesa_string_buffer_printf(d->buf, "%s ", str);
dump_instr_print_operands(d, 2, binop->operands);
}
static void
dump_instr_cmp(struct dxil_dumper *d, struct dxil_instr_cmp *cmp)
{
const char *str = cmp->pred < DXIL_CMP_INSTR_COUNT ?
pred_strings[cmp->pred] : "INVALID";
_mesa_string_buffer_printf(d->buf, "%s ", str);
dump_instr_print_operands(d, 2, cmp->operands);
}
static void
dump_instr_select(struct dxil_dumper *d, struct dxil_instr_select *select)
{
_mesa_string_buffer_append(d->buf, "sel ");
dump_instr_print_operands(d, 3, select->operands);
}
static void
dump_instr_cast(struct dxil_dumper *d, struct dxil_instr_cast *cast)
{
const char *str = cast->opcode < DXIL_CAST_INSTR_COUNT ?
cast_opcode_strings[cast->opcode] : "INVALID";
_mesa_string_buffer_printf(d->buf, "%s.", str);
dump_type_name(d, cast->type);
_mesa_string_buffer_append_char(d->buf, ' ');
dump_value(d, cast->value);
}
static void
dump_instr_call(struct dxil_dumper *d, struct dxil_instr_call *call)
{
assert(call->num_args == call->func->type->function_def.args.num_types);
struct dxil_type **func_arg_types = call->func->type->function_def.args.types;
_mesa_string_buffer_printf(d->buf, "%s(", call->func->name);
for (unsigned i = 0; i < call->num_args; ++i) {
if (i > 0)
_mesa_string_buffer_append(d->buf, ", ");
dump_type_name(d, func_arg_types[i]);
_mesa_string_buffer_append_char(d->buf, ' ');
dump_value(d, call->args[i]);
}
_mesa_string_buffer_append_char(d->buf, ')');
}
static void
dump_instr_ret(struct dxil_dumper *d, struct dxil_instr_ret *ret)
{
_mesa_string_buffer_append(d->buf, "ret ");
if (ret->value)
dump_value(d, ret->value);
}
static void
dump_instr_extractval(struct dxil_dumper *d, struct dxil_instr_extractval *extr)
{
_mesa_string_buffer_append(d->buf, "extractvalue ");
dump_type_name(d, extr->type);
dump_value(d, extr->src);
_mesa_string_buffer_printf(d->buf, ", %d", extr->idx);
}
static void
dump_instr_branch(struct dxil_dumper *d, struct dxil_instr_br *br)
{
_mesa_string_buffer_append(d->buf, "branch ");
if (br->cond)
dump_value(d, br->cond);
else
_mesa_string_buffer_append(d->buf, " (uncond)");
_mesa_string_buffer_printf(d->buf, " %d %d", br->succ[0], br->succ[1]);
}
static void
dump_instr_phi(struct dxil_dumper *d, struct dxil_instr_phi *phi)
{
_mesa_string_buffer_append(d->buf, "phi ");
dump_type_name(d, phi->type);
struct dxil_phi_src *src = phi->incoming;
for (unsigned i = 0; i < phi->num_incoming; ++i, ++src) {
if (i > 0)
_mesa_string_buffer_append(d->buf, ", ");
dump_value(d, src->value);
_mesa_string_buffer_printf(d->buf, "(%d)", src->block);
}
}
static void
dump_instr_alloca(struct dxil_dumper *d, struct dxil_instr_alloca *alloca)
{
_mesa_string_buffer_append(d->buf, "alloca ");
dump_type_name(d, alloca->alloc_type);
_mesa_string_buffer_append(d->buf, ", ");
dump_type_name(d, alloca->size_type);
_mesa_string_buffer_append(d->buf, ", ");
dump_value(d, alloca->size);
unsigned align_mask = (1 << 6 ) - 1;
unsigned align = alloca->align & align_mask;
_mesa_string_buffer_printf(d->buf, ", %d", 1 << (align - 1));
}
static void
dump_instr_gep(struct dxil_dumper *d, struct dxil_instr_gep *gep)
{
_mesa_string_buffer_append(d->buf, "getelementptr ");
if (gep->inbounds)
_mesa_string_buffer_append(d->buf, "inbounds ");
dump_type_name(d, gep->source_elem_type);
_mesa_string_buffer_append(d->buf, ", ");
for (unsigned i = 0; i < gep->num_operands; ++i) {
if (i > 0)
_mesa_string_buffer_append(d->buf, ", ");
dump_value(d, gep->operands[i]);
}
}
static void
dump_instr_load(struct dxil_dumper *d, struct dxil_instr_load *load)
{
_mesa_string_buffer_append(d->buf, "load ");
if (load->is_volatile)
_mesa_string_buffer_append(d->buf, " volatile");
dump_type_name(d, load->type);
_mesa_string_buffer_append(d->buf, ", ");
dump_value(d, load->ptr);
_mesa_string_buffer_printf(d->buf, ", %d", load->align);
}
static void
dump_instr_store(struct dxil_dumper *d, struct dxil_instr_store *store)
{
_mesa_string_buffer_append(d->buf, "store ");
if (store->is_volatile)
_mesa_string_buffer_append(d->buf, " volatile");
dump_value(d, store->value);
_mesa_string_buffer_append(d->buf, ", ");
dump_value(d, store->ptr);
_mesa_string_buffer_printf(d->buf, ", %d", store->align);
}
static const char *rmworder_str[] = {
[DXIL_ATOMIC_ORDERING_NOTATOMIC] = "not-atomic",
[DXIL_ATOMIC_ORDERING_UNORDERED] = "unordered",
[DXIL_ATOMIC_ORDERING_MONOTONIC] = "monotonic",
[DXIL_ATOMIC_ORDERING_ACQUIRE] = "acquire",
[DXIL_ATOMIC_ORDERING_RELEASE] = "release",
[DXIL_ATOMIC_ORDERING_ACQREL] = "acqrel",
[DXIL_ATOMIC_ORDERING_SEQCST] = "seqcst",
};
static const char *rmwsync_str[] = {
[DXIL_SYNC_SCOPE_SINGLETHREAD] = "single-thread",
[DXIL_SYNC_SCOPE_CROSSTHREAD] = "cross-thread",
};
static const char *rmwop_str[] = {
[DXIL_RMWOP_XCHG] = "xchg",
[DXIL_RMWOP_ADD] = "add",
[DXIL_RMWOP_SUB] = "sub",
[DXIL_RMWOP_AND] = "and",
[DXIL_RMWOP_NAND] = "nand",
[DXIL_RMWOP_OR] = "or",
[DXIL_RMWOP_XOR] = "xor",
[DXIL_RMWOP_MAX] = "max",
[DXIL_RMWOP_MIN] = "min",
[DXIL_RMWOP_UMAX] = "umax",
[DXIL_RMWOP_UMIN] = "umin",
};
static void
dump_instr_atomicrmw(struct dxil_dumper *d, struct dxil_instr_atomicrmw *rmw)
{
_mesa_string_buffer_printf(d->buf, "atomicrmw.%s ", rmwop_str[rmw->op]);
if (rmw->is_volatile)
_mesa_string_buffer_append(d->buf, " volatile");
dump_value(d, rmw->value);
_mesa_string_buffer_append(d->buf, ", ");
dump_value(d, rmw->ptr);
_mesa_string_buffer_printf(d->buf, ", ordering(%s)", rmworder_str[rmw->ordering]);
_mesa_string_buffer_printf(d->buf, ", sync_scope(%s)", rmwsync_str[rmw->syncscope]);
}
static void
dump_instr_print_operands(struct dxil_dumper *d, int num,
const struct dxil_value *val[])
{
for (int i = 0; i < num; ++i) {
if (i > 0)
_mesa_string_buffer_append(d->buf, ", ");
dump_value(d, val[i]);
}
}
static void
dump_value(struct dxil_dumper *d, const struct dxil_value *val)
{
if (val->id < 10)
_mesa_string_buffer_append(d->buf, " ");
if (val->id < 100)
_mesa_string_buffer_append(d->buf, " ");
_mesa_string_buffer_printf(d->buf, "%%%d", val->id);
dump_type_name(d, val->type);
}
static void
dump_mdnodes(struct dxil_dumper *d, struct list_head *list)
{
if (!list_length(list))
return;
_mesa_string_buffer_append(d->buf, "MD-Nodes:\n");
dxil_dump_indention_inc(d);
list_for_each_entry(struct dxil_mdnode, node, list, head) {
dump_mdnode(d, node);
}
dxil_dump_indention_dec(d);
}
static void
dump_mdnode(struct dxil_dumper *d, struct dxil_mdnode *node)
{
dxil_dump_indent(d);
switch (node->type) {
case MD_STRING:
_mesa_string_buffer_printf(d->buf, "S:%s\n", node->string);
break;
case MD_VALUE:
_mesa_string_buffer_append(d->buf, "V:");
dump_type_name(d, node->value.type);
_mesa_string_buffer_append_char(d->buf, ' ');
dump_value(d, node->value.value);
_mesa_string_buffer_append_char(d->buf, '\n');
break;
case MD_NODE:
_mesa_string_buffer_append(d->buf, " \\\n");
dxil_dump_indention_inc(d);
for (size_t i = 0; i < node->node.num_subnodes; ++i) {
if (node->node.subnodes[i])
dump_mdnode(d, node->node.subnodes[i]);
else {
dxil_dump_indent(d);
_mesa_string_buffer_append(d->buf, "(nullptr)\n");
}
}
dxil_dump_indention_dec(d);
break;
}
}
static void
dump_named_nodes(struct dxil_dumper *d, struct list_head *list)
{
if (!list_length(list))
return;
_mesa_string_buffer_append(d->buf, "Named Nodes:\n");
dxil_dump_indention_inc(d);
list_for_each_entry(struct dxil_named_node, node, list, head) {
dxil_dump_indent(d);
_mesa_string_buffer_printf(d->buf, "%s:\n", node->name);
dxil_dump_indention_inc(d);
for (size_t i = 0; i < node->num_subnodes; ++i) {
if (node->subnodes[i])
dump_mdnode(d, node->subnodes[i]);
else {
dxil_dump_indent(d);
_mesa_string_buffer_append(d->buf, "(nullptr)\n");
}
}
dxil_dump_indention_dec(d);
}
dxil_dump_indention_dec(d);
}
static void
mask_to_string(uint32_t mask, char str[5])
{
const char *mc = "xyzw";
for (int i = 0; i < 4 && mask; ++i) {
str[i] = (mask & (1 << i)) ? mc[i] : '_';
}
str[4] = 0;
}
static void dump_io_signatures(struct _mesa_string_buffer *buf, struct dxil_module *m)
{
_mesa_string_buffer_append(buf, "\nInput signature:\n");
dump_io_signature(buf, m->num_sig_inputs, m->inputs);
_mesa_string_buffer_append(buf, "\nOutput signature:\n");
dump_io_signature(buf, m->num_sig_outputs, m->outputs);
}
static void dump_io_signature(struct _mesa_string_buffer *buf, unsigned num,
struct dxil_signature_record *io)
{
_mesa_string_buffer_append(buf, " SEMANTIC-NAME Index Mask Reg SysValue Format\n");
_mesa_string_buffer_append(buf, "----------------------------------------------\n");
for (unsigned i = 0; i < num; ++i, ++io) {
for (unsigned j = 0; j < io->num_elements; ++j) {
char mask[5] = "";
mask_to_string(io->elements[j].mask, mask);
_mesa_string_buffer_printf(buf, "%-15s %3d %4s %3d %-8s %-7s\n",
io->name, io->elements[j].semantic_index,
mask, io->elements[j].reg, io->sysvalue,
component_type_as_string(io->elements[j].comp_type));
}
}
}
static const char *component_type_as_string(uint32_t type)
{
return (type < DXIL_PROG_SIG_COMP_TYPE_COUNT) ?
dxil_type_strings[type] : "invalid";
}
static void dump_psv(struct _mesa_string_buffer *buf,
struct dxil_module *m)
{
_mesa_string_buffer_append(buf, "\nPipeline State Validation\nInputs:\n");
dump_psv_io(buf, m, m->num_sig_inputs, m->psv_inputs);
_mesa_string_buffer_append(buf, "\nOutputs:\n");
dump_psv_io(buf, m, m->num_sig_outputs, m->psv_outputs);
}
static void dump_psv_io(struct _mesa_string_buffer *buf, struct dxil_module *m,
unsigned num, struct dxil_psv_signature_element *io)
{
_mesa_string_buffer_append(buf, " SEMANTIC-NAME Rows Cols Kind Comp-Type Interp dynmask+stream Indices\n");
_mesa_string_buffer_append(buf, "----------------------------------------------\n");
for (unsigned i = 0; i < num; ++i, ++io) {
_mesa_string_buffer_printf(buf, "%-14s %d+%d %d+%d %4d %-7s %-4d %-9d [",
m->sem_string_table->buf + io->semantic_name_offset,
(int)io->start_row, (int)io->rows,
(int)((io->cols_and_start & 0xf) >> 4),
(int)(io->cols_and_start & 0xf),
(int)io->semantic_kind,
component_type_as_string(io->component_type),
(int)io->interpolation_mode,
(int)io->dynamic_mask_and_stream);
for (int k = 0; k < io->rows; ++k) {
if (k > 0)
_mesa_string_buffer_append(buf, ", ");
_mesa_string_buffer_printf(buf,"%d ", m->sem_index_table.data[io->start_row + k]);
}
_mesa_string_buffer_append(buf, "]\n");
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#ifndef DXIL_DUMP_H
#define DXIL_DUMP_H
#include <stdio.h>
struct dxil_module;
struct _mesa_string_buffer;
#ifdef __cplusplus
extern "C" {
#endif
struct dxil_dumper;
struct dxil_dumper *dxil_dump_create(void);
void dxil_dump_free(struct dxil_dumper *d);
void dxil_dump_buf_to_file(struct dxil_dumper *d, FILE *f);
void
dxil_dump_module(struct dxil_dumper *d, struct dxil_module *m);
#ifdef __cplusplus
}
#endif
#endif // DXIL_DUMP_H

View File

@ -0,0 +1,179 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#ifndef DIXL_DUMP_DECL
#error This header can only be included from dxil_dump.c
#endif
#include "dxil_module.h"
static void
dump_metadata(struct dxil_dumper *buf, struct dxil_module *m);
static void
dump_shader_info(struct dxil_dumper *buf, struct dxil_shader_info *info);
static const char *
dump_shader_string(enum dxil_shader_kind kind);
static void
dump_features(struct _mesa_string_buffer *buf, struct dxil_features *feat);
static void
dump_types(struct dxil_dumper *buf, struct list_head *list);
static void
dump_gvars(struct dxil_dumper *buf, struct list_head *list);
static void
dump_constants(struct dxil_dumper *buf, struct list_head *list);
static void
dump_funcs(struct dxil_dumper *buf, struct list_head *list);
static void
dump_attr_set_list(struct dxil_dumper *buf, struct list_head *list);
static void
dump_instrs(struct dxil_dumper *buf, struct list_head *list);
static void
dump_mdnodes(struct dxil_dumper *buf, struct list_head *list);
static void
dump_mdnode(struct dxil_dumper *d, struct dxil_mdnode *node);
static void
dump_named_nodes(struct dxil_dumper *d, struct list_head *list);
static void
dump_type(struct dxil_dumper *buf, const struct dxil_type *type);
static void
dump_instr_binop(struct dxil_dumper *d, struct dxil_instr_binop *binop);
static void
dump_instr_cmp(struct dxil_dumper *d, struct dxil_instr_cmp *cmp);
static void
dump_instr_select(struct dxil_dumper *d, struct dxil_instr_select *select);
static void
dump_instr_cast(struct dxil_dumper *d, struct dxil_instr_cast *cast);
static void
dump_instr_call(struct dxil_dumper *d, struct dxil_instr_call *call);
static void
dump_instr_ret(struct dxil_dumper *d, struct dxil_instr_ret *ret);
static void
dump_instr_extractval(struct dxil_dumper *d, struct dxil_instr_extractval *ret);
static void
dump_instr_branch(struct dxil_dumper *d, struct dxil_instr_br *br);
static void
dump_instr_phi(struct dxil_dumper *d, struct dxil_instr_phi *phi);
static void
dump_instr_alloca(struct dxil_dumper *d, struct dxil_instr_alloca *alloca);
static void
dump_instr_gep(struct dxil_dumper *d, struct dxil_instr_gep *gep);
static void
dump_instr_load(struct dxil_dumper *d, struct dxil_instr_load *store);
static void
dump_instr_store(struct dxil_dumper *d, struct dxil_instr_store *store);
static void
dump_instr_atomicrmw(struct dxil_dumper *d, struct dxil_instr_atomicrmw *rmw);
static void
dump_instr_print_operands(struct dxil_dumper *d, int num,
const struct dxil_value *val[]);
static void dump_io_signatures(struct _mesa_string_buffer *buf,
struct dxil_module *m);
static void
dump_io_signature(struct _mesa_string_buffer *buf, unsigned num,
struct dxil_signature_record *io);
static const char *component_type_as_string(uint32_t type);
static void dump_psv(struct _mesa_string_buffer *buf,
struct dxil_module *m);
static void dump_psv_io(struct _mesa_string_buffer *buf, struct dxil_module *m,
unsigned num, struct dxil_psv_signature_element *io);
static void
dump_value(struct dxil_dumper *d, const struct dxil_value *val);
static const char *binop_strings[DXIL_BINOP_INSTR_COUNT] = {
[DXIL_BINOP_ADD] = "add",
[DXIL_BINOP_SUB] = "sub",
[DXIL_BINOP_MUL] = "mul",
[DXIL_BINOP_UDIV] = "udiv",
[DXIL_BINOP_SDIV] = "sdiv",
[DXIL_BINOP_UREM] = "urem",
[DXIL_BINOP_SREM] = "srem",
[DXIL_BINOP_SHL] = "shl",
[DXIL_BINOP_LSHR] = "lshr",
[DXIL_BINOP_ASHR] = "ashr",
[DXIL_BINOP_AND] = "and",
[DXIL_BINOP_OR] = "or",
[DXIL_BINOP_XOR]= "xor"
};
static const char *pred_strings[DXIL_CMP_INSTR_COUNT] = {
[DXIL_FCMP_FALSE] = "FALSE",
[DXIL_FCMP_OEQ] = "ord-fEQ",
[DXIL_FCMP_OGT] = "ord-fGT",
[DXIL_FCMP_OGE] = "ord-fGE",
[DXIL_FCMP_OLT] = "ord-fLT",
[DXIL_FCMP_OLE] = "ord-fLE",
[DXIL_FCMP_ONE] = "ord-fNE",
[DXIL_FCMP_ORD] = "ord-fRD",
[DXIL_FCMP_UNO] = "unord-fNO",
[DXIL_FCMP_UEQ] = "unord-fEQ",
[DXIL_FCMP_UGT] = "unord-fGT",
[DXIL_FCMP_UGE] = "unord-fGE",
[DXIL_FCMP_ULT] = "unord-fLT",
[DXIL_FCMP_ULE] = "unord-fLE",
[DXIL_FCMP_UNE] = "unord-fNE",
[DXIL_FCMP_TRUE] = "TRUE",
[DXIL_ICMP_EQ] = "iEQ",
[DXIL_ICMP_NE] = "iNE",
[DXIL_ICMP_UGT] = "uiGT",
[DXIL_ICMP_UGE] = "uiGE",
[DXIL_ICMP_ULT] = "uiLT",
[DXIL_ICMP_ULE] = "uiLE",
[DXIL_ICMP_SGT] = "iGT",
[DXIL_ICMP_SGE] = "iGE",
[DXIL_ICMP_SLT] = "iLT",
[DXIL_ICMP_SLE] = "iLE"
};
static const char *cast_opcode_strings[DXIL_CAST_INSTR_COUNT] = {
[DXIL_CAST_TRUNC] = "trunc",
[DXIL_CAST_ZEXT] = "zext",
[DXIL_CAST_SEXT] = "sext",
[DXIL_CAST_FPTOUI] = "ftoui",
[DXIL_CAST_FPTOSI] = "ftoi",
[DXIL_CAST_UITOFP] = "uitof",
[DXIL_CAST_SITOFP] = "itof",
[DXIL_CAST_FPTRUNC] = "ftrunc",
[DXIL_CAST_FPEXT] = "fext",
[DXIL_CAST_PTRTOINT] = "ptrtoint",
[DXIL_CAST_INTTOPTR] = "inttoptr",
[DXIL_CAST_BITCAST] = "bitcast",
[DXIL_CAST_ADDRSPACECAST] = "addrspacecast",
};
static const char *dxil_type_strings[DXIL_PROG_SIG_COMP_TYPE_COUNT] = {
[DXIL_PROG_SIG_COMP_TYPE_UNKNOWN] = "unknown",
[DXIL_PROG_SIG_COMP_TYPE_UINT32] = "uint32",
[DXIL_PROG_SIG_COMP_TYPE_SINT32] = "int32",
[DXIL_PROG_SIG_COMP_TYPE_FLOAT32] = "float32",
[DXIL_PROG_SIG_COMP_TYPE_UINT16] = "uint16",
[DXIL_PROG_SIG_COMP_TYPE_SINT16] = "int16",
[DXIL_PROG_SIG_COMP_TYPE_FLOAT16] = "float16",
[DXIL_PROG_SIG_COMP_TYPE_UINT64] = "uint64",
[DXIL_PROG_SIG_COMP_TYPE_SINT64] = "int64",
[DXIL_PROG_SIG_COMP_TYPE_FLOAT64] = "float64"
};

View File

@ -0,0 +1,163 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#include "dxil_enums.h"
#include "nir.h"
#include "nir_types.h"
#include "util/u_debug.h"
enum dxil_prog_sig_comp_type dxil_get_prog_sig_comp_type(const struct glsl_type *type)
{
type = glsl_without_array(type);
switch (glsl_get_base_type(type)) {
case GLSL_TYPE_UINT: return DXIL_PROG_SIG_COMP_TYPE_UINT32;
case GLSL_TYPE_INT: return DXIL_PROG_SIG_COMP_TYPE_SINT32;
case GLSL_TYPE_FLOAT: return DXIL_PROG_SIG_COMP_TYPE_FLOAT32;
case GLSL_TYPE_FLOAT16: return DXIL_PROG_SIG_COMP_TYPE_FLOAT16;
case GLSL_TYPE_DOUBLE: return DXIL_PROG_SIG_COMP_TYPE_FLOAT64;
case GLSL_TYPE_UINT16: return DXIL_PROG_SIG_COMP_TYPE_UINT16;
case GLSL_TYPE_INT16: return DXIL_PROG_SIG_COMP_TYPE_SINT16;
case GLSL_TYPE_UINT64: return DXIL_PROG_SIG_COMP_TYPE_UINT64;
case GLSL_TYPE_INT64: return DXIL_PROG_SIG_COMP_TYPE_SINT64;
case GLSL_TYPE_BOOL: return DXIL_PROG_SIG_COMP_TYPE_UINT32;
default:
debug_printf("unexpected type: %s\n", glsl_get_type_name(type));
return DXIL_PROG_SIG_COMP_TYPE_UNKNOWN;
}
}
enum dxil_component_type dxil_get_comp_type(const struct glsl_type *type)
{
type = glsl_without_array(type);
enum glsl_base_type base_type = glsl_get_base_type(type);
if (glsl_type_is_sampler(type) || glsl_type_is_image(type))
base_type = glsl_get_sampler_result_type(type);
switch (base_type) {
case GLSL_TYPE_UINT: return DXIL_COMP_TYPE_U32;
case GLSL_TYPE_INT: return DXIL_COMP_TYPE_I32;
case GLSL_TYPE_FLOAT: return DXIL_COMP_TYPE_F32;
case GLSL_TYPE_FLOAT16: return DXIL_COMP_TYPE_F16;
case GLSL_TYPE_DOUBLE: return DXIL_COMP_TYPE_F64;
case GLSL_TYPE_UINT16: return DXIL_COMP_TYPE_U16;
case GLSL_TYPE_INT16: return DXIL_COMP_TYPE_I16;
case GLSL_TYPE_UINT64: return DXIL_COMP_TYPE_U64;
case GLSL_TYPE_INT64: return DXIL_COMP_TYPE_I64;
case GLSL_TYPE_BOOL: return DXIL_COMP_TYPE_I1;
default:
debug_printf("type: %s\n", glsl_get_type_name(type));
unreachable("unexpected glsl type");
}
}
enum dxil_resource_kind dxil_get_resource_kind(const struct glsl_type *type)
{
type = glsl_without_array(type);
/* This looks weird, we strip the arrays but then we still test whether it's
* an array, key is the first refers to sampler[] and the second to samplerArray */
bool is_array = glsl_sampler_type_is_array(type);
if (glsl_type_is_sampler(type) || glsl_type_is_image(type)) {
switch (glsl_get_sampler_dim(type)) {
case GLSL_SAMPLER_DIM_1D:
return is_array ? DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY
: DXIL_RESOURCE_KIND_TEXTURE1D;
case GLSL_SAMPLER_DIM_2D:
return is_array ? DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY
: DXIL_RESOURCE_KIND_TEXTURE2D;
case GLSL_SAMPLER_DIM_3D:
return DXIL_RESOURCE_KIND_TEXTURE3D;
case GLSL_SAMPLER_DIM_CUBE:
return is_array ? DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY
: DXIL_RESOURCE_KIND_TEXTURECUBE;
case GLSL_SAMPLER_DIM_RECT:
return DXIL_RESOURCE_KIND_TEXTURE2D;
case GLSL_SAMPLER_DIM_BUF:
return DXIL_RESOURCE_KIND_TYPED_BUFFER;
case GLSL_SAMPLER_DIM_MS:
return is_array ? DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY
: DXIL_RESOURCE_KIND_TEXTURE2DMS;
default:
debug_printf("type: %s\n", glsl_get_type_name(type));
unreachable("unexpected sampler type");
}
}
debug_printf("type: %s\n", glsl_get_type_name(type));
unreachable("unexpected glsl type");
}
enum dxil_input_primitive dxil_get_input_primitive(unsigned primitive)
{
switch (primitive) {
case GL_POINTS:
return DXIL_INPUT_PRIMITIVE_POINT;
case GL_LINES:
return DXIL_INPUT_PRIMITIVE_LINE;
case GL_LINES_ADJACENCY:
return DXIL_INPUT_PRIMITIVE_LINES_ADJENCY;
case GL_TRIANGLES:
return DXIL_INPUT_PRIMITIVE_TRIANGLE;
case GL_TRIANGLES_ADJACENCY:
return DXIL_INPUT_PRIMITIVE_TRIANGLES_ADJENCY;
default:
unreachable("unhandled primitive topology");
}
}
enum dxil_primitive_topology dxil_get_primitive_topology(unsigned topology)
{
switch (topology) {
case GL_POINTS:
return DXIL_PRIMITIVE_TOPOLOGY_POINT_LIST;
case GL_LINES:
return DXIL_PRIMITIVE_TOPOLOGY_LINE_LIST;
case GL_LINE_STRIP:
return DXIL_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case GL_TRIANGLE_STRIP:
return DXIL_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
default:
unreachable("unhandled primitive topology");
}
}
static const char *overload_str[DXIL_NUM_OVERLOADS] = {
[DXIL_NONE] = "",
[DXIL_I16] = "i16",
[DXIL_I32] = "i32",
[DXIL_I64] = "i64",
[DXIL_F32] = "f32",
[DXIL_F64] = "f64",
};
const char *dxil_overload_suffix( enum overload_type overload)
{
assert(overload < DXIL_NUM_OVERLOADS);
return overload_str[overload];
}

View File

@ -0,0 +1,340 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#ifndef DIXL_ENUMS_H
#define DIXL_ENUMS_H
enum dxil_signature_kind {
DXIL_SIG_INVALID = 0,
DXIL_SIG_INPUT,
DXIL_SIG_OUTPUT,
DXIL_SIG_PATCH_CONST_OR_PRIM
};
/* These enums are taken from
* DirectXShaderCompiler/lib/dxc/DXIL/DxilConstants.h
*/
enum dxil_semantic_kind {
DXIL_SEM_ARBITRARY,
DXIL_SEM_VERTEX_ID,
DXIL_SEM_INSTANCE_ID,
DXIL_SEM_POSITION,
DXIL_SEM_RENDERTARGET_ARRAY_INDEX,
DXIL_SEM_VIEWPORT_ARRAY_INDEX,
DXIL_SEM_CLIP_DISTANCE,
DXIL_SEM_CULL_DISTANCE,
DXIL_SEM_OUTPUT_CONTROL_POINT_ID,
DXIL_SEM_DOMAIN_LOCATION,
DXIL_SEM_PRIMITIVE_ID,
DXIL_SEM_GS_INSTANCE_ID,
DXIL_SEM_SAMPLE_INDEX,
DXIL_SEM_IS_FRONT_FACE,
DXIL_SEM_COVERAGE,
DXIL_SEM_INNER_COVERAGE,
DXIL_SEM_TARGET,
DXIL_SEM_DEPTH,
DXIL_SEM_DEPTH_LE,
DXIL_SEM_DEPTH_GE,
DXIL_SEM_STENCIL_REF,
DXIL_SEM_DISPATCH_THREAD_ID,
DXIL_SEM_GROUP_ID,
DXIL_SEM_GROUP_INDEX,
DXIL_SEM_GROUP_THREAD_ID,
DXIL_SEM_TESS_FACTOR,
DXIL_SEM_INSIDE_TESS_FACTOR,
DXIL_SEM_VIEW_ID,
DXIL_SEM_BARYCENTRICS,
DXIL_SEM_SHADING_RATE,
DXIL_SEM_CULL_PRIMITIVE,
DXIL_SEM_INVALID
};
enum dxil_prog_sig_semantic {
DXIL_PROG_SEM_UNDEFINED = 0,
DXIL_PROG_SEM_POSITION = 1,
DXIL_PROG_SEM_CLIP_DISTANCE = 2,
DXIL_PROG_SEM_CULL_DISTANCE = 3,
DXIL_PROG_SEM_RENDERTARGET_ARRAY_INDEX = 4,
DXIL_PROG_SEM_VIEWPORT_ARRAY_INDEX = 5,
DXIL_PROG_SEM_VERTEX_ID = 6,
DXIL_PROG_SEM_PRIMITIVE_ID = 7,
DXIL_PROG_SEM_INSTANCE_ID = 8,
DXIL_PROG_SEM_IS_FRONTFACE = 9,
DXIL_PROG_SEM_SAMPLE_INDEX = 10,
DXIL_PROG_SEM_FINAL_QUAD_EDGE_TESSFACTOR = 11,
DXIL_PROG_SEM_FINAL_QUAD_INSIDE_EDGE_TESSFACTOR = 12,
DXIL_PROG_SEM_FINAL_TRI_EDGE_TESSFACTOR = 13,
DXIL_PROG_SEM_FINAL_TRI_INSIDE_EDGE_TESSFACTOR = 14,
DXIL_PROG_SEM_FINAL_LINE_DETAIL_TESSFACTOR = 15,
DXIL_PROG_SEM_FINAL_LINE_DENSITY_TESSFACTOR = 16,
DXIL_PROG_SEM_BARYCENTRICS = 23,
DXIL_PROG_SEM_SHADING_RATE = 24,
DXIL_PROG_SEM_CULL_PRIMITIVE = 25,
DXIL_PROG_SEM_TARGET = 64,
DXIL_PROG_SEM_DEPTH = 65,
DXIL_PROG_SEM_COVERAGE = 66,
DXIL_PROG_SEM_DEPTH_GE = 67,
DXIL_PROG_SEM_DEPTH_LE = 68,
DXIL_PROG_SEM_STENCIL_REF = 69,
DXIL_PROG_SEM_INNER_COVERAGE = 70
};
enum dxil_prog_sig_comp_type {
DXIL_PROG_SIG_COMP_TYPE_UNKNOWN = 0,
DXIL_PROG_SIG_COMP_TYPE_UINT32 = 1,
DXIL_PROG_SIG_COMP_TYPE_SINT32 = 2,
DXIL_PROG_SIG_COMP_TYPE_FLOAT32 = 3,
DXIL_PROG_SIG_COMP_TYPE_UINT16 = 4,
DXIL_PROG_SIG_COMP_TYPE_SINT16 = 5,
DXIL_PROG_SIG_COMP_TYPE_FLOAT16 = 6,
DXIL_PROG_SIG_COMP_TYPE_UINT64 = 7,
DXIL_PROG_SIG_COMP_TYPE_SINT64 = 8,
DXIL_PROG_SIG_COMP_TYPE_FLOAT64 = 9,
DXIL_PROG_SIG_COMP_TYPE_COUNT
};
enum dxil_sig_point_kind {
DXIL_SIG_POINT_VSIN, // Ordinary Vertex Shader input from Input Assembler
DXIL_SIG_POINT_VSOUT, // Ordinary Vertex Shader output that may feed Rasterizer
DXIL_SIG_POINT_PCIN, // Patch Constant function non-patch inputs
DXIL_SIG_POINT_HSIN, // Hull Shader function non-patch inputs
DXIL_SIG_POINT_HSCPIN, // Hull Shader patch inputs - Control Points
DXIL_SIG_POINT_HSCPOut, // Hull Shader function output - Control Point
DXIL_SIG_POINT_PCOUT, // Patch Constant function output - Patch Constant data passed to Domain Shader
DXIL_SIG_POINT_DSIN, // Domain Shader regular input - Patch Constant data plus system values
DXIL_SIG_POINT_DSCPIN, // Domain Shader patch input - Control Points
DXIL_SIG_POINT_DSOUT, // Domain Shader output - vertex data that may feed Rasterizer
DXIL_SIG_POINT_GSVIN, // Geometry Shader vertex input - qualified with primitive type
DXIL_SIG_POINT_GSIN, // Geometry Shader non-vertex inputs (system values)
DXIL_SIG_POINT_GSOUT, // Geometry Shader output - vertex data that may feed Rasterizer
DXIL_SIG_POINT_PSIN, // Pixel Shader input
DXIL_SIG_POINT_PSOUT, // Pixel Shader output
DXIL_SIG_POINT_CSIN, // Compute Shader input
DXIL_SIG_POINT_MSIN, // Mesh Shader input
DXIL_SIG_POINT_MSOUT, // Mesh Shader vertices output
DXIL_SIG_POINT_MSPOUT, // Mesh Shader primitives output
DXIL_SIG_POINT_ASIN, // Amplification Shader input
DXIL_SIG_POINT_INVALID
};
enum dxil_min_precision {
DXIL_MIN_PREC_DEFAULT = 0,
DXIL_MIN_PREC_FLOAT16 = 1,
DXIL_MIN_PREC_FLOAT2_8 = 2,
DXIL_MIN_PREC_RESERVED = 3,
DXIL_MIN_PREC_SINT16 = 4,
DXIL_MIN_PREC_UINT16 = 5,
DXIL_MIN_PREC_ANY16 = 0xf0,
DXIL_MIN_PREC_ANY10 = 0xf1
};
enum dxil_semantic_interpret_kind {
DXIL_SEM_INTERP_NA, // Not Available
DXIL_SEM_INTERP_SV, // Normal System Value
DXIL_SEM_INTERP_SGV, // System Generated Value (sorted last)
DXIL_SEM_INTERP_ARB, // Treated as Arbitrary
DXIL_SEM_INTERP_NOT_IN_SIG, // Not included in signature (intrinsic access)
DXIL_SEM_INTERP_NOT_PACKED, // Included in signature, but does not contribute to packing
DXIL_SEM_INTERP_TARGET, // Special handling for SV_Target
DXIL_SEM_INTERP_TESSFACTOR, // Special handling for tessellation factors
DXIL_SEM_INTERP_SHADOW, // Shadow element must be added to a signature for compatibility
DXIL_SEM_INTERP_CLIPCULL, // Special packing rules for SV_ClipDistance or SV_CullDistance
DXIL_SEM_INTERP_INVALID
};
enum dxil_component_type {
DXIL_COMP_TYPE_INVALID = 0,
DXIL_COMP_TYPE_I1 = 1,
DXIL_COMP_TYPE_I16 = 2,
DXIL_COMP_TYPE_U16 = 3,
DXIL_COMP_TYPE_I32 = 4,
DXIL_COMP_TYPE_U32 = 5,
DXIL_COMP_TYPE_I64 = 6,
DXIL_COMP_TYPE_U64 = 7,
DXIL_COMP_TYPE_F16 = 8,
DXIL_COMP_TYPE_F32 = 9,
DXIL_COMP_TYPE_F64 = 10,
DXIL_COMP_TYPE_SNORMF16 = 11,
DXIL_COMP_TYPE_UNORMF16 = 12,
DXIL_COMP_TYPE_SNORMF32 = 13,
DXIL_COMP_TYPE_UNORMF32 = 14,
DXIL_COMP_TYPE_SNORMF64 = 15,
DXIL_COMP_TYPE_UNORMF64 = 16
};
enum dxil_interpolation_mode {
DXIL_INTERP_UNDEFINED = 0,
DXIL_INTERP_CONSTANT = 1,
DXIL_INTERP_LINEAR = 2,
DXIL_INTERP_LINEAR_CENTROID = 3,
DXIL_INTERP_LINEAR_NOPERSPECTIVE = 4,
DXIL_INTERP_LINEAR_NOPERSPECTIVE_CENTROID = 5,
DXIL_INTERP_LINEAR_SAMPLE = 6,
DXIL_INTERP_LINEAR_NOPERSPECTIVE_SAMPLE = 7,
DXIL_INTERP_INVALID = 8
};
enum overload_type {
DXIL_NONE,
DXIL_I16,
DXIL_I32,
DXIL_I64,
DXIL_F16,
DXIL_F32,
DXIL_F64,
DXIL_NUM_OVERLOADS
};
enum dxil_resource_class {
DXIL_RESOURCE_CLASS_SRV = 0,
DXIL_RESOURCE_CLASS_UAV = 1,
DXIL_RESOURCE_CLASS_CBV = 2,
DXIL_RESOURCE_CLASS_SAMPLER = 3
};
enum dxil_resource_kind {
DXIL_RESOURCE_KIND_INVALID = 0,
DXIL_RESOURCE_KIND_TEXTURE1D = 1,
DXIL_RESOURCE_KIND_TEXTURE2D = 2,
DXIL_RESOURCE_KIND_TEXTURE2DMS = 3,
DXIL_RESOURCE_KIND_TEXTURE3D = 4,
DXIL_RESOURCE_KIND_TEXTURECUBE = 5,
DXIL_RESOURCE_KIND_TEXTURE1D_ARRAY = 6,
DXIL_RESOURCE_KIND_TEXTURE2D_ARRAY = 7,
DXIL_RESOURCE_KIND_TEXTURE2DMS_ARRAY = 8,
DXIL_RESOURCE_KIND_TEXTURECUBE_ARRAY = 9,
DXIL_RESOURCE_KIND_TYPED_BUFFER = 10,
DXIL_RESOURCE_KIND_RAW_BUFFER = 11,
DXIL_RESOURCE_KIND_STRUCTURED_BUFFER = 12,
DXIL_RESOURCE_KIND_CBUFFER = 13,
DXIL_RESOURCE_KIND_SAMPLER = 14,
DXIL_RESOURCE_KIND_TBUFFER = 15,
};
enum dxil_sampler_kind {
DXIL_SAMPLER_KIND_DEFAULT = 0,
DXIL_SAMPLER_KIND_COMPARISON = 1,
DXIL_SAMPLER_KIND_MONO = 2,
DXIL_SAMPLER_KIND_INVALID = 3,
};
enum dxil_attr_kind {
DXIL_ATTR_KIND_NONE = 0,
DXIL_ATTR_KIND_NO_DUPLICATE = 12,
DXIL_ATTR_KIND_NO_UNWIND = 18,
DXIL_ATTR_KIND_READ_NONE = 20,
DXIL_ATTR_KIND_READ_ONLY = 21,
};
enum dxil_input_primitive {
DXIL_INPUT_PRIMITIVE_UNDEFINED = 0,
DXIL_INPUT_PRIMITIVE_POINT = 1,
DXIL_INPUT_PRIMITIVE_LINE = 2,
DXIL_INPUT_PRIMITIVE_TRIANGLE = 3,
DXIL_INPUT_PRIMITIVE_LINES_ADJENCY = 6,
DXIL_INPUT_PRIMITIVE_TRIANGLES_ADJENCY = 7,
};
enum dxil_primitive_topology {
DXIL_PRIMITIVE_TOPOLOGY_UNDEFINED = 0,
DXIL_PRIMITIVE_TOPOLOGY_POINT_LIST = 1,
DXIL_PRIMITIVE_TOPOLOGY_LINE_LIST = 2,
DXIL_PRIMITIVE_TOPOLOGY_LINE_STRIP = 3,
DXIL_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 4,
DXIL_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 5,
};
enum dxil_shader_tag {
DXIL_SHADER_TAG_FLAGS = 0,
DXIL_SHADER_TAG_GS_STATE = 1,
DXIL_SHADER_TAG_DS_STATE = 2,
DXIL_SHADER_TAG_HS_STATE = 3,
DXIL_SHADER_TAG_NUM_THREADS = 4,
};
enum dxil_barrier_mode {
DXIL_BARRIER_MODE_SYNC_THREAD_GROUP = 1,
DXIL_BARRIER_MODE_UAV_FENCE_GLOBAL = 2,
DXIL_BARRIER_MODE_UAV_FENCE_THREAD_GROUP = 4,
DXIL_BARRIER_MODE_GROUPSHARED_MEM_FENCE = 8,
};
enum dxil_address_space {
DXIL_AS_DEFAULT = 0,
DXIL_AS_DEVMEM = 1,
DXIL_AS_CBUF = 2,
DXIL_AS_GROUPSHARED = 3,
};
enum dxil_rmw_op {
DXIL_RMWOP_XCHG = 0,
DXIL_RMWOP_ADD = 1,
DXIL_RMWOP_SUB = 2,
DXIL_RMWOP_AND = 3,
DXIL_RMWOP_NAND = 4,
DXIL_RMWOP_OR = 5,
DXIL_RMWOP_XOR = 6,
DXIL_RMWOP_MAX = 7,
DXIL_RMWOP_MIN = 8,
DXIL_RMWOP_UMAX = 9,
DXIL_RMWOP_UMIN = 10,
};
enum dxil_atomic_ordering {
DXIL_ATOMIC_ORDERING_NOTATOMIC = 0,
DXIL_ATOMIC_ORDERING_UNORDERED = 1,
DXIL_ATOMIC_ORDERING_MONOTONIC = 2,
DXIL_ATOMIC_ORDERING_ACQUIRE = 3,
DXIL_ATOMIC_ORDERING_RELEASE = 4,
DXIL_ATOMIC_ORDERING_ACQREL = 5,
DXIL_ATOMIC_ORDERING_SEQCST = 6,
};
enum dxil_sync_scope {
DXIL_SYNC_SCOPE_SINGLETHREAD = 0,
DXIL_SYNC_SCOPE_CROSSTHREAD = 1,
};
#ifdef __cplusplus
extern "C" {
#endif
enum dxil_component_type dxil_get_comp_type(const struct glsl_type *type);
enum dxil_prog_sig_comp_type dxil_get_prog_sig_comp_type(const struct glsl_type *type);
enum dxil_resource_kind dxil_get_resource_kind(const struct glsl_type *type);
enum dxil_primitive_topology dxil_get_primitive_topology(unsigned topology);
enum dxil_input_primitive dxil_get_input_primitive(unsigned primitive);
const char *dxil_overload_suffix( enum overload_type overload);
#ifdef __cplusplus
}
#endif
#endif // DXIL_ENUMS_H

View File

@ -0,0 +1,236 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#include "dxil_function.h"
#include "dxil_module.h"
#define MAX_FUNC_PARAMS 17
struct predefined_func_descr {
const char *base_name;
const char *retval_descr;
const char *param_descr;
enum dxil_attr_kind attr;
};
static struct predefined_func_descr predefined_funcs[] = {
{"dx.op.atomicBinOp", "O", "i@iiiii", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.cbufferLoad", "O", "i@ii", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.cbufferLoadLegacy", "B", "i@i", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.createHandle", "@", "iciib", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.storeOutput", "v", "iiicO", DXIL_ATTR_KIND_NO_UNWIND},
{"dx.op.loadInput", "O", "iiici", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.tertiary", "O", "iOOO", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.threadId", "i", "ii", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.threadIdInGroup", "i", "ii", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.groupId", "i", "ii", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.unary", "O", "iO", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.unaryBits", "i", "iO", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.isSpecialFloat", "b", "iO", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.binary", "O", "iOO", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.bufferStore", "v", "i@iiiiiic", DXIL_ATTR_KIND_NONE},
{"dx.op.bufferLoad", "R", "i@ii", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.attributeAtVertex", "O", "iiicc", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.sample", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.sampleBias", "R", "i@@ffffiiiff", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.sampleLevel", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.sampleGrad", "R", "i@@ffffiiifffffff", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.sampleCmp", "R", "i@@ffffiiiff", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.sampleCmpLevelZero", "R", "i@@ffffiiif", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.textureLoad", "R", "i@iiiiiii", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.discard", "v", "ib", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.emitStream", "v", "ic", DXIL_ATTR_KIND_NONE},
{"dx.op.cutStream", "v", "ic", DXIL_ATTR_KIND_NONE},
{"dx.op.getDimensions", "D", "i@i", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.calculateLOD", "f", "i@@fffb", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.barrier", "v", "ii", DXIL_ATTR_KIND_NO_DUPLICATE},
{"dx.op.atomicCompareExchange", "O", "i@iiiii", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.textureStore", "v", "i@iiiOOOOc", DXIL_ATTR_KIND_NONE},
{"dx.op.primitiveID", "i", "i", DXIL_ATTR_KIND_READ_NONE},
{"dx.op.legacyF16ToF32", "f", "ii", DXIL_ATTR_KIND_READ_ONLY},
{"dx.op.legacyF32ToF16", "i", "if", DXIL_ATTR_KIND_READ_ONLY},
};
struct func_descr {
const char *name;
enum overload_type overload;
};
struct func_rb_node {
struct rb_node node;
const struct dxil_func *func;
struct func_descr descr;
};
static inline
const struct func_rb_node *
func_rb_node(const struct rb_node *n)
{
return (const struct func_rb_node *)n;
}
static int
func_compare_to_name_and_overload(const struct rb_node *node, const void *data)
{
const struct func_descr *descr = (const struct func_descr *)data;
const struct func_rb_node *f = func_rb_node(node);
if (f->descr.overload < descr->overload)
return -1;
if (f->descr.overload > descr->overload)
return 1;
return strcmp(f->descr.name, descr->name);
}
static const struct dxil_func *
allocate_function_from_predefined(struct dxil_module *mod,
const char *name,
enum overload_type overload)
{
for (unsigned i = 0; i < ARRAYSIZE(predefined_funcs); ++i) {
if (!strcmp(predefined_funcs[i].base_name, name)) {
return dxil_alloc_func(mod, name, overload,
predefined_funcs[i].retval_descr,
predefined_funcs[i].param_descr,
predefined_funcs[i].attr);
}
}
return false;
}
const struct dxil_func *
dxil_get_function(struct dxil_module *mod,
const char *name, enum overload_type overload)
{
struct func_descr descr = { name, overload };
const struct rb_node *node = rb_tree_search(mod->functions, &descr,
func_compare_to_name_and_overload);
if (node)
return func_rb_node(node)->func;
return allocate_function_from_predefined(mod, name, overload);
}
static int func_compare_name(const struct rb_node *lhs, const struct rb_node *rhs)
{
const struct func_rb_node *node = func_rb_node(rhs);
return func_compare_to_name_and_overload(lhs, &node->descr);
}
static void
dxil_add_function(struct rb_tree *functions, const struct dxil_func *func,
const char *name, enum overload_type overload)
{
struct func_rb_node *f = rzalloc(functions, struct func_rb_node);
f->func = func;
f->descr.name = name;
f->descr.overload = overload;
rb_tree_insert(functions, &f->node, func_compare_name);
}
static const struct dxil_type *
get_type_from_string(struct dxil_module *mod, const char *param_descr,
enum overload_type overload, int *idx)
{
assert(param_descr);
char type_id = param_descr[(*idx)++];
assert(*idx <= (int)strlen(param_descr));
switch (type_id) {
case DXIL_FUNC_PARAM_INT64: return dxil_module_get_int_type(mod, 64);
case DXIL_FUNC_PARAM_INT32: return dxil_module_get_int_type(mod, 32);
case DXIL_FUNC_PARAM_INT16: return dxil_module_get_int_type(mod, 16);
case DXIL_FUNC_PARAM_INT8: return dxil_module_get_int_type(mod, 8);
case DXIL_FUNC_PARAM_BOOL: return dxil_module_get_int_type(mod, 1);
case DXIL_FUNC_PARAM_FLOAT64: return dxil_module_get_float_type(mod, 64);
case DXIL_FUNC_PARAM_FLOAT32: return dxil_module_get_float_type(mod, 32);
case DXIL_FUNC_PARAM_FLOAT16: return dxil_module_get_float_type(mod, 16);
case DXIL_FUNC_PARAM_HANDLE: return dxil_module_get_handle_type(mod);
case DXIL_FUNC_PARAM_VOID: return dxil_module_get_void_type(mod);
case DXIL_FUNC_PARAM_FROM_OVERLOAD: return dxil_get_overload_type(mod, overload);
case DXIL_FUNC_PARAM_RESRET: return dxil_module_get_resret_type(mod, overload);
case DXIL_FUNC_PARAM_DIM: return dxil_module_get_dimret_type(mod);
case DXIL_FUNC_PARAM_CBUF_RET: return dxil_module_get_cbuf_ret_type(mod, overload);
case DXIL_FUNC_PARAM_POINTER: {
const struct dxil_type *target = get_type_from_string(mod, param_descr, overload, idx);
return dxil_module_get_pointer_type(mod, target);
}
default:
assert(0 && "unknown type identifier");
}
return NULL;
}
const struct dxil_func *
dxil_alloc_func_with_rettype(struct dxil_module *mod, const char *name,
enum overload_type overload,
const struct dxil_type *retval_type,
const char *param_descr,
enum dxil_attr_kind attr)
{
assert(param_descr);
const struct dxil_type *arg_types[MAX_FUNC_PARAMS];
int index = 0;
unsigned num_params = 0;
while (param_descr[num_params]) {
const struct dxil_type *t = get_type_from_string(mod, param_descr, overload, &index);
if (!t)
return false;
assert(num_params < MAX_FUNC_PARAMS);
arg_types[num_params++] = t;
}
const struct dxil_type *func_type =
dxil_module_add_function_type(mod, retval_type,
arg_types, num_params);
if (!func_type) {
fprintf(stderr, "%s: Func type allocation failed\n", __func__);
return false;
}
char full_name[100];
snprintf(full_name, sizeof (full_name), "%s%s%s", name,
overload == DXIL_NONE ? "" : ".", dxil_overload_suffix(overload));
const struct dxil_func *func = dxil_add_function_decl(mod, full_name, func_type, attr);
if (func)
dxil_add_function(mod->functions, func, name, overload);
return func;
}
const struct dxil_func *
dxil_alloc_func(struct dxil_module *mod, const char *name, enum overload_type overload,
const char *retval_type_descr,
const char *param_descr, enum dxil_attr_kind attr)
{
int index = 0;
const struct dxil_type *retval_type = get_type_from_string(mod, retval_type_descr, overload, &index);
assert(retval_type_descr[index] == 0);
return dxil_alloc_func_with_rettype(mod, name, overload, retval_type,
param_descr, attr);
}

View File

@ -0,0 +1,92 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#ifndef DXIL_FUNCTION_H
#define DXIL_FUNCTION_H
#define DXIL_FUNC_PARAM_INT64 'l'
#define DXIL_FUNC_PARAM_INT32 'i'
#define DXIL_FUNC_PARAM_INT16 'h'
#define DXIL_FUNC_PARAM_INT8 'c'
#define DXIL_FUNC_PARAM_BOOL 'b'
#define DXIL_FUNC_PARAM_FLOAT64 'g'
#define DXIL_FUNC_PARAM_FLOAT32 'f'
#define DXIL_FUNC_PARAM_FLOAT16 'e'
#define DXIL_FUNC_PARAM_HANDLE '@'
#define DXIL_FUNC_PARAM_POINTER '*'
#define DXIL_FUNC_PARAM_VOID 'v'
#define DXIL_FUNC_PARAM_FROM_OVERLOAD 'O'
#define DXIL_FUNC_PARAM_RESRET 'R'
#define DXIL_FUNC_PARAM_CBUF_RET 'B'
#define DXIL_FUNC_PARAM_DIM 'D'
#include "dxil_module.h"
#include "util/rb_tree.h"
const char *dxil_overload_suffix( enum overload_type overload);
const struct dxil_type *
dxil_get_overload_type(struct dxil_module *mod, enum overload_type overload);
/* These functions implement a generic method for declaring functions
* The input parameters types are given as a string using the characters
* given above as identifyer for the types. Only scalars and pointers to
* scalars are implemented at this point.
*
* Examples:
*
* Call: dxil_alloc_func(mod, "storeData.f32", "v", "icf");
* Result function: void storeData.f32(int32, int8, float32)
*
* Call: dxil_alloc_func(mod, "storeData.f32", "e", "*icf");
* Result function: float16 storeData.f32(int32 *, int8, float32)
*
* Call: dxil_alloc_func(mod, "storeData.f32", "*h", "b*f");
* Result function: float16 storeData.f32(bool *, float32 *)
*
*/
const struct dxil_func *
dxil_alloc_func(struct dxil_module *mod, const char *name, enum overload_type overload,
const char *retval_type_descr, const char *param_descr, enum dxil_attr_kind attr);
/* For specifically constructed return types one can also create the return type
* seperately and pass it as paramaer
*/
const struct dxil_func *
dxil_alloc_func_with_rettype(struct dxil_module *mod, const char *name, enum overload_type overload,
const struct dxil_type *retval_type, const char *param_descr,
enum dxil_attr_kind attr);
/* This call should be the usual entry point to allocate a new function type.
* 'name' must either be in the list of predefined functions, or a function
* with 'name' and 'overload' must already be allocated by using one of the above
* function calls. The allocated functions are searched for by using an rb_tree, so
* the search complexity should be O(log(n)).
*/
const struct dxil_func *
dxil_get_function(struct dxil_module *mod, const char *name,
enum overload_type overload);
#endif // DXIL_FUNCTION_H

View File

@ -0,0 +1,300 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#ifndef DXIL_INTERNAL_H
#define DXIL_INTERNAL_H
#include "dxil_module.h"
#include "util/list.h"
#include <stdint.h>
// Malloc.h defines a macro for alloca. Let's at least make sure that all includers
// of this header have the same definition of alloca.
#include <malloc.h>
struct dxil_type_list {
struct dxil_type **types;
size_t num_types;
};
struct dxil_type {
enum type_type {
TYPE_VOID,
TYPE_INTEGER,
TYPE_FLOAT,
TYPE_POINTER,
TYPE_STRUCT,
TYPE_ARRAY,
TYPE_VECTOR,
TYPE_FUNCTION
} type;
union {
unsigned int_bits;
unsigned float_bits;
const struct dxil_type *ptr_target_type;
struct {
const char *name;
struct dxil_type_list elem;
} struct_def;
struct {
const struct dxil_type *ret_type;
struct dxil_type_list args;
} function_def;
struct {
const struct dxil_type *elem_type;
size_t num_elems;
} array_or_vector_def;
};
struct list_head head;
unsigned id;
};
struct dxil_value {
int id;
const struct dxil_type *type;
};
struct dxil_gvar {
const char *name;
const struct dxil_type *type;
bool constant;
enum dxil_address_space as;
int align;
const struct dxil_value *initializer;
struct dxil_value value;
struct list_head head;
};
struct dxil_func {
char *name;
const struct dxil_type *type;
bool decl;
unsigned attr_set;
struct dxil_value value;
struct list_head head;
};
struct dxil_attrib {
enum {
DXIL_ATTR_ENUM
} type;
union {
enum dxil_attr_kind kind;
};
};
struct attrib_set {
struct dxil_attrib attrs[2];
unsigned num_attrs;
struct list_head head;
};
struct dxil_instr_binop {
enum dxil_bin_opcode opcode;
const struct dxil_value *operands[2];
enum dxil_opt_flags flags;
};
struct dxil_instr_cmp {
enum dxil_cmp_pred pred;
const struct dxil_value *operands[2];
};
struct dxil_instr_select {
const struct dxil_value *operands[3];
};
struct dxil_instr_cast {
enum dxil_cast_opcode opcode;
const struct dxil_type *type;
const struct dxil_value *value;
};
struct dxil_instr_call {
const struct dxil_func *func;
struct dxil_value **args;
size_t num_args;
};
struct dxil_instr_ret {
struct dxil_value *value;
};
struct dxil_instr_extractval {
const struct dxil_value *src;
const struct dxil_type *type;
unsigned int idx;
};
struct dxil_instr_br {
const struct dxil_value *cond;
unsigned succ[2];
};
struct dxil_instr_phi {
const struct dxil_type *type;
struct dxil_phi_src {
const struct dxil_value *value;
unsigned block;
} incoming[127];
size_t num_incoming;
};
struct dxil_instr_alloca {
const struct dxil_type *alloc_type;
const struct dxil_type *size_type;
const struct dxil_value *size;
unsigned align;
};
struct dxil_instr_gep {
bool inbounds;
const struct dxil_type *source_elem_type;
struct dxil_value **operands;
size_t num_operands;
};
struct dxil_instr_load {
const struct dxil_value *ptr;
const struct dxil_type *type;
unsigned align;
bool is_volatile;
};
struct dxil_instr_store {
const struct dxil_value *value, *ptr;
unsigned align;
bool is_volatile;
};
struct dxil_instr_atomicrmw {
const struct dxil_value *value, *ptr;
enum dxil_rmw_op op;
bool is_volatile;
enum dxil_atomic_ordering ordering;
enum dxil_sync_scope syncscope;
};
struct dxil_instr_cmpxchg {
const struct dxil_value *cmpval, *newval, *ptr;
bool is_volatile;
enum dxil_atomic_ordering ordering;
enum dxil_sync_scope syncscope;
};
struct dxil_instr {
enum instr_type {
INSTR_BINOP,
INSTR_CMP,
INSTR_SELECT,
INSTR_CAST,
INSTR_BR,
INSTR_PHI,
INSTR_CALL,
INSTR_RET,
INSTR_EXTRACTVAL,
INSTR_ALLOCA,
INSTR_GEP,
INSTR_LOAD,
INSTR_STORE,
INSTR_ATOMICRMW,
INSTR_CMPXCHG,
} type;
union {
struct dxil_instr_binop binop;
struct dxil_instr_cmp cmp;
struct dxil_instr_select select;
struct dxil_instr_cast cast;
struct dxil_instr_call call;
struct dxil_instr_ret ret;
struct dxil_instr_extractval extractval;
struct dxil_instr_phi phi;
struct dxil_instr_br br;
struct dxil_instr_alloca alloca;
struct dxil_instr_gep gep;
struct dxil_instr_load load;
struct dxil_instr_store store;
struct dxil_instr_atomicrmw atomicrmw;
struct dxil_instr_cmpxchg cmpxchg;
};
bool has_value;
struct dxil_value value;
struct list_head head;
};
struct dxil_const {
struct dxil_value value;
bool undef;
union {
intmax_t int_value;
double float_value;
const struct dxil_value **array_values;
};
struct list_head head;
};
struct dxil_mdnode {
enum mdnode_type {
MD_STRING,
MD_VALUE,
MD_NODE
} type;
union {
char *string;
struct {
const struct dxil_type *type;
const struct dxil_value *value;
} value;
struct {
struct dxil_mdnode **subnodes;
size_t num_subnodes;
} node;
};
struct list_head head;
unsigned id;
};
struct dxil_named_node {
char *name;
struct dxil_mdnode **subnodes;
size_t num_subnodes;
struct list_head head;
};
#endif // DXIL_INTERNAL_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,469 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
/*
* See the DirectX Shader Compiler for documentation for DXIL details:
* https://github.com/Microsoft/DirectXShaderCompiler/blob/master/docs/DXIL.rst
*/
#ifndef DXIL_MODULE_H
#define DXIL_MODULE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "dxil_buffer.h"
#include "dxil_signature.h"
#include "util/list.h"
#define DXIL_SHADER_MAX_IO_ROWS 80
enum dxil_shader_kind {
DXIL_PIXEL_SHADER = 0,
DXIL_VERTEX_SHADER = 1,
DXIL_GEOMETRY_SHADER = 2,
DXIL_HULL_SHADER = 3,
DXIL_DOMAIN_SHADER = 4,
DXIL_COMPUTE_SHADER = 5,
};
extern int debug_dxil;
enum dxil_debug_flags {
DXIL_DEBUG_VERBOSE = 1 << 0,
DXIL_DEBUG_DUMP_BLOB = 1 << 1,
DXIL_DEBUG_TRACE = 1 << 2,
DXIL_DEBUG_DUMP_MODULE = 1 << 3,
};
enum dxil_bin_opcode {
DXIL_BINOP_ADD = 0,
DXIL_BINOP_SUB = 1,
DXIL_BINOP_MUL = 2,
DXIL_BINOP_UDIV = 3,
DXIL_BINOP_SDIV = 4,
DXIL_BINOP_UREM = 5,
DXIL_BINOP_SREM = 6,
DXIL_BINOP_SHL = 7,
DXIL_BINOP_LSHR = 8,
DXIL_BINOP_ASHR = 9,
DXIL_BINOP_AND = 10,
DXIL_BINOP_OR = 11,
DXIL_BINOP_XOR = 12,
DXIL_BINOP_INSTR_COUNT
};
enum dxil_cast_opcode {
DXIL_CAST_TRUNC = 0,
DXIL_CAST_ZEXT = 1,
DXIL_CAST_SEXT = 2,
DXIL_CAST_FPTOUI = 3,
DXIL_CAST_FPTOSI = 4,
DXIL_CAST_UITOFP = 5,
DXIL_CAST_SITOFP = 6,
DXIL_CAST_FPTRUNC = 7,
DXIL_CAST_FPEXT = 8,
DXIL_CAST_PTRTOINT = 9,
DXIL_CAST_INTTOPTR = 10,
DXIL_CAST_BITCAST = 11,
DXIL_CAST_ADDRSPACECAST = 12,
DXIL_CAST_INSTR_COUNT
};
enum dxil_cmp_pred {
DXIL_FCMP_FALSE = 0,
DXIL_FCMP_OEQ = 1,
DXIL_FCMP_OGT = 2,
DXIL_FCMP_OGE = 3,
DXIL_FCMP_OLT = 4,
DXIL_FCMP_OLE = 5,
DXIL_FCMP_ONE = 6,
DXIL_FCMP_ORD = 7,
DXIL_FCMP_UNO = 8,
DXIL_FCMP_UEQ = 9,
DXIL_FCMP_UGT = 10,
DXIL_FCMP_UGE = 11,
DXIL_FCMP_ULT = 12,
DXIL_FCMP_ULE = 13,
DXIL_FCMP_UNE = 14,
DXIL_FCMP_TRUE = 15,
DXIL_ICMP_EQ = 32,
DXIL_ICMP_NE = 33,
DXIL_ICMP_UGT = 34,
DXIL_ICMP_UGE = 35,
DXIL_ICMP_ULT = 36,
DXIL_ICMP_ULE = 37,
DXIL_ICMP_SGT = 38,
DXIL_ICMP_SGE = 39,
DXIL_ICMP_SLT = 40,
DXIL_ICMP_SLE = 41,
DXIL_CMP_INSTR_COUNT
};
enum dxil_opt_flags {
DXIL_UNSAFE_ALGEBRA = (1 << 0),
DXIL_NO_NANS = (1 << 1),
DXIL_NO_INFS = (1 << 2),
DXIL_NO_SIGNED_ZEROS = (1 << 3),
DXIL_ALLOW_RECIPROCAL = (1 << 4)
};
struct dxil_features {
unsigned doubles : 1,
cs_4x_raw_sb : 1,
uavs_at_every_stage : 1,
use_64uavs : 1,
min_precision : 1,
dx11_1_double_extensions : 1,
dx11_1_shader_extensions : 1,
dx9_comparison_filtering : 1,
tiled_resources : 1,
stencil_ref : 1,
inner_coverage : 1,
typed_uav_load_additional_formats : 1,
rovs : 1,
array_layer_from_vs_or_ds : 1,
wave_ops : 1,
int64_ops : 1,
view_id : 1,
barycentrics : 1,
native_low_precision : 1,
shading_rate : 1,
raytracing_tier_1_1 : 1,
sampler_feedback : 1;
};
struct dxil_shader_info {
unsigned has_out_position:1;
unsigned has_out_depth:1;
};
struct dxil_module {
void *ralloc_ctx;
enum dxil_shader_kind shader_kind;
unsigned major_version, minor_version;
struct dxil_features feats;
unsigned raw_and_structured_buffers : 1;
struct dxil_shader_info info;
struct dxil_buffer buf;
unsigned num_sig_inputs;
unsigned num_sig_outputs;
unsigned num_psv_inputs;
unsigned num_psv_outputs;
struct dxil_signature_record inputs[DXIL_SHADER_MAX_IO_ROWS];
struct dxil_signature_record outputs[DXIL_SHADER_MAX_IO_ROWS];
struct dxil_psv_signature_element psv_inputs[DXIL_SHADER_MAX_IO_ROWS];
struct dxil_psv_signature_element psv_outputs[DXIL_SHADER_MAX_IO_ROWS];
struct _mesa_string_buffer *sem_string_table;
struct dxil_psv_sem_index_table sem_index_table;
struct {
unsigned abbrev_width;
intptr_t offset;
} blocks[16];
size_t num_blocks;
struct list_head type_list;
struct list_head gvar_list;
struct list_head func_list;
struct list_head attr_set_list;
struct list_head instr_list;
struct list_head const_list;
struct list_head mdnode_list;
struct list_head md_named_node_list;
const struct dxil_type *void_type;
const struct dxil_type *int1_type, *int8_type, *int16_type,
*int32_type, *int64_type;
const struct dxil_type *float16_type, *float32_type, *float64_type;
struct rb_tree *functions;
int *basic_block_ids; /* maps from "user" ids to LLVM ids */
size_t num_basic_block_ids;
unsigned curr_block;
};
struct dxil_instr;
struct dxil_value;
void
dxil_module_init(struct dxil_module *m, void *ralloc_ctx);
void
dxil_module_release(struct dxil_module *m);
const struct dxil_value *
dxil_add_global_var(struct dxil_module *m, const char *name,
const struct dxil_type *type,
enum dxil_address_space as, int align,
const struct dxil_value *value);
const struct dxil_value *
dxil_add_global_ptr_var(struct dxil_module *m, const char *name,
const struct dxil_type *type,
enum dxil_address_space as, int align,
const struct dxil_value *value);
const struct dxil_func *
dxil_add_function_def(struct dxil_module *m, const char *name,
const struct dxil_type *type);
const struct dxil_func *
dxil_add_function_decl(struct dxil_module *m, const char *name,
const struct dxil_type *type,
enum dxil_attr_kind attr);
const struct dxil_type *
dxil_module_get_void_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_int_type(struct dxil_module *m, unsigned bit_size);
const struct dxil_type *
dxil_module_get_float_type(struct dxil_module *m, unsigned bit_size);
const struct dxil_type *
dxil_module_get_pointer_type(struct dxil_module *m,
const struct dxil_type *target);
const struct dxil_type *
dxil_get_overload_type(struct dxil_module *mod, enum overload_type overload);
const struct dxil_type *
dxil_module_get_handle_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_cbuf_ret_type(struct dxil_module *mod, enum overload_type overload);
const struct dxil_type *
dxil_module_get_res_type(struct dxil_module *m, enum dxil_resource_kind kind,
enum dxil_component_type comp_type, bool readwrite);
const struct dxil_type *
dxil_module_get_resret_type(struct dxil_module *m, enum overload_type overload);
const struct dxil_type *
dxil_module_get_dimret_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_struct_type(struct dxil_module *m,
const char *name,
const struct dxil_type **elem_types,
size_t num_elem_types);
const struct dxil_type *
dxil_module_get_array_type(struct dxil_module *m,
const struct dxil_type *elem_type,
size_t num_elems);
const struct dxil_type *
dxil_module_get_vector_type(struct dxil_module *m,
const struct dxil_type *elem_type,
size_t num_elems);
const struct dxil_type *
dxil_module_add_function_type(struct dxil_module *m,
const struct dxil_type *ret_type,
const struct dxil_type **arg_types,
size_t num_arg_types);
nir_alu_type
dxil_type_to_nir_type(const struct dxil_type *type);
bool
dxil_value_type_equal_to(const struct dxil_value *value,
const struct dxil_type *lhs);
bool
dxil_value_type_bitsize_equal_to(const struct dxil_value *value, unsigned bitsize);
const struct dxil_type *
dxil_value_get_type(const struct dxil_value *value);
const struct dxil_value *
dxil_module_get_int1_const(struct dxil_module *m, bool value);
const struct dxil_value *
dxil_module_get_int8_const(struct dxil_module *m, int8_t value);
const struct dxil_value *
dxil_module_get_int16_const(struct dxil_module *m, int16_t value);
const struct dxil_value *
dxil_module_get_int32_const(struct dxil_module *m, int32_t value);
const struct dxil_value *
dxil_module_get_int64_const(struct dxil_module *m, int64_t value);
const struct dxil_value *
dxil_module_get_int_const(struct dxil_module *m, intmax_t value,
unsigned bit_size);
const struct dxil_value *
dxil_module_get_float_const(struct dxil_module *m, float value);
const struct dxil_value *
dxil_module_get_double_const(struct dxil_module *m, double value);
const struct dxil_value *
dxil_module_get_array_const(struct dxil_module *m, const struct dxil_type *type,
const struct dxil_value **values);
const struct dxil_value *
dxil_module_get_undef(struct dxil_module *m, const struct dxil_type *type);
const struct dxil_mdnode *
dxil_get_metadata_string(struct dxil_module *m, const char *str);
const struct dxil_mdnode *
dxil_get_metadata_value(struct dxil_module *m, const struct dxil_type *type,
const struct dxil_value *value);
const struct dxil_mdnode *
dxil_get_metadata_func(struct dxil_module *m, const struct dxil_func *func);
const struct dxil_mdnode *
dxil_get_metadata_int1(struct dxil_module *m, bool value);
const struct dxil_mdnode *
dxil_get_metadata_int8(struct dxil_module *m, int8_t value);
const struct dxil_mdnode *
dxil_get_metadata_int32(struct dxil_module *m, int32_t value);
const struct dxil_mdnode *
dxil_get_metadata_int64(struct dxil_module *m, int64_t value);
const struct dxil_mdnode *
dxil_get_metadata_node(struct dxil_module *m,
const struct dxil_mdnode *subnodes[],
size_t num_subnodes);
bool
dxil_add_metadata_named_node(struct dxil_module *m, const char *name,
const struct dxil_mdnode *subnodes[],
size_t num_subnodes);
const struct dxil_value *
dxil_emit_binop(struct dxil_module *m, enum dxil_bin_opcode opcode,
const struct dxil_value *op0, const struct dxil_value *op1,
enum dxil_opt_flags flags);
const struct dxil_value *
dxil_emit_cmp(struct dxil_module *m, enum dxil_cmp_pred pred,
const struct dxil_value *op0, const struct dxil_value *op1);
const struct dxil_value *
dxil_emit_select(struct dxil_module *m,
const struct dxil_value *op0,
const struct dxil_value *op1,
const struct dxil_value *op2);
const struct dxil_value *
dxil_emit_extractval(struct dxil_module *m, const struct dxil_value *src,
const unsigned int index);
const struct dxil_value *
dxil_emit_cast(struct dxil_module *m, enum dxil_cast_opcode opcode,
const struct dxil_type *type,
const struct dxil_value *value);
bool
dxil_emit_branch(struct dxil_module *m, const struct dxil_value *cond,
unsigned true_block, unsigned false_block);
const struct dxil_value *
dxil_instr_get_return_value(struct dxil_instr *instr);
struct dxil_instr *
dxil_emit_phi(struct dxil_module *m, const struct dxil_type *type);
void
dxil_phi_set_incoming(struct dxil_instr *instr,
const struct dxil_value *incoming_values[],
const unsigned incoming_blocks[],
size_t num_incoming);
const struct dxil_value *
dxil_emit_call(struct dxil_module *m,
const struct dxil_func *func,
const struct dxil_value **args, size_t num_args);
bool
dxil_emit_call_void(struct dxil_module *m,
const struct dxil_func *func,
const struct dxil_value **args, size_t num_args);
bool
dxil_emit_ret_void(struct dxil_module *m);
const struct dxil_value *
dxil_emit_alloca(struct dxil_module *m, const struct dxil_type *alloc_type,
const struct dxil_type *size_type,
const struct dxil_value *size,
unsigned int align);
const struct dxil_value *
dxil_emit_gep_inbounds(struct dxil_module *m,
const struct dxil_value **operands,
size_t num_operands);
const struct dxil_value *
dxil_emit_load(struct dxil_module *m, const struct dxil_value *ptr,
unsigned align,
bool is_volatile);
bool
dxil_emit_store(struct dxil_module *m, const struct dxil_value *value,
const struct dxil_value *ptr, unsigned align,
bool is_volatile);
const struct dxil_value *
dxil_emit_cmpxchg(struct dxil_module *m, const struct dxil_value *cmpval,
const struct dxil_value *newval,
const struct dxil_value *ptr, bool is_volatile,
enum dxil_atomic_ordering ordering,
enum dxil_sync_scope syncscope);
const struct dxil_value *
dxil_emit_atomicrmw(struct dxil_module *m, const struct dxil_value *value,
const struct dxil_value *ptr, enum dxil_rmw_op op,
bool is_volatile, enum dxil_atomic_ordering ordering,
enum dxil_sync_scope syncscope);
bool
dxil_emit_module(struct dxil_module *m);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,589 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#include "dxil_enums.h"
#include "dxil_module.h"
#include "dxil_signature.h"
#include "nir_to_dxil.h"
#include "glsl_types.h"
#include "util/u_debug.h"
#include <string.h>
struct semantic_info {
enum dxil_semantic_kind kind;
char name[64];
int index;
enum dxil_prog_sig_comp_type comp_type;
uint8_t sig_comp_type;
int32_t start_row;
int32_t rows;
uint8_t start_col;
uint8_t cols;
uint8_t interpolation;
const char *sysvalue_name;
};
static bool
is_depth_output(enum dxil_semantic_kind kind)
{
return kind == DXIL_SEM_DEPTH ||
kind == DXIL_SEM_STENCIL_REF;
}
static uint8_t
get_interpolation(nir_variable *var)
{
if (unlikely(var->data.centroid)) {
switch (var->data.interpolation) {
case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR_CENTROID;
case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE_CENTROID;
case INTERP_MODE_SMOOTH: DXIL_INTERP_LINEAR_CENTROID;
}
} else {
switch (var->data.interpolation) {
case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR;
case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE;
case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR;
}
}
return DXIL_INTERP_LINEAR;
}
static const char *
in_sysvalue_name(nir_variable *var)
{
switch (var->data.location) {
case VARYING_SLOT_POS:
return "POS";
case VARYING_SLOT_FACE:
return "FACE";
default:
return "NONE";
}
}
/*
* The signatures are written into the stream in two pieces:
* DxilProgramSignatureElement is a fixes size structure that gets dumped
* to the stream in order of the registers and each contains an offset
* to the semantic name string. Then these strings are dumped into the stream.
*/
static unsigned
get_additional_semantic_info(nir_variable *var, struct semantic_info *info,
unsigned next_row, bool is_gs_shader)
{
const struct glsl_type *type = var->type;
info->comp_type =
dxil_get_prog_sig_comp_type(var->type);
bool is_depth = is_depth_output(info->kind);
info->sig_comp_type = dxil_get_comp_type(var->type);
info->rows = 1;
if (info->kind == DXIL_SEM_TARGET) {
info->start_row = info->index;
} else if (is_depth || (info->kind == DXIL_SEM_PRIMITIVE_ID && is_gs_shader)) {
info->start_row = -1;
} else {
info->start_row = next_row;
if (glsl_type_is_array(type) && is_gs_shader)
type = glsl_without_array(type);
if (glsl_type_is_array(type)) {
info->rows = glsl_get_aoa_size(type);
type = glsl_get_array_element(type);
assert(info->rows);
}
next_row += info->rows;
}
info->start_col = (uint8_t)var->data.location_frac;
if (glsl_type_is_array(type))
type = glsl_get_array_element(type);
info->cols = (uint8_t)glsl_get_components(type);
return next_row;
}
typedef void (*semantic_info_proc)(nir_variable *var, struct semantic_info *info);
static void
get_semantic_vs_in_name(nir_variable *var, struct semantic_info *info)
{
const char *name = dxil_vs_attr_index_to_name(var->data.driver_location);
assert(strlen(name) < 63);
strcpy(info->name, name);
info->kind = DXIL_SEM_ARBITRARY;
}
static void
get_semantic_sv_name(nir_variable *var, struct semantic_info *info)
{
switch (var->data.location) {
case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE:
info->kind = DXIL_SEM_VERTEX_ID;
break;
case SYSTEM_VALUE_FRONT_FACE:
info->kind = DXIL_SEM_IS_FRONT_FACE;
break;
case SYSTEM_VALUE_INSTANCE_ID:
info->kind = DXIL_SEM_INSTANCE_ID;
break;
case SYSTEM_VALUE_PRIMITIVE_ID:
info->kind = DXIL_SEM_PRIMITIVE_ID;
break;
default:
unreachable("unsupported system value");
}
strncpy(info->name, var->name, 64);
}
static void
get_semantic_ps_outname(nir_variable *var, struct semantic_info *info)
{
info->kind = DXIL_SEM_INVALID;
switch (var->data.location) {
case FRAG_RESULT_COLOR:
snprintf(info->name, 64, "%s", "SV_Target");
info->index = var->data.index;
info->kind = DXIL_SEM_TARGET;
break;
case FRAG_RESULT_DATA0:
case FRAG_RESULT_DATA1:
case FRAG_RESULT_DATA2:
case FRAG_RESULT_DATA3:
case FRAG_RESULT_DATA4:
case FRAG_RESULT_DATA5:
case FRAG_RESULT_DATA6:
case FRAG_RESULT_DATA7:
snprintf(info->name, 64, "%s", "SV_Target");
info->index = var->data.location - FRAG_RESULT_DATA0;
if (var->data.location == FRAG_RESULT_DATA0 &&
var->data.index > 0)
info->index = var->data.index;
info->kind = DXIL_SEM_TARGET;
break;
case FRAG_RESULT_DEPTH:
snprintf(info->name, 64, "%s", "SV_Depth");
info->kind = DXIL_SEM_DEPTH;
break;
case FRAG_RESULT_STENCIL:
snprintf(info->name, 64, "%s", "SV_StencilRef");
info->kind = DXIL_SEM_STENCIL_REF; //??
break;
case FRAG_RESULT_SAMPLE_MASK:
snprintf(info->name, 64, "%s", "SV_Coverage");
info->kind = DXIL_SEM_COVERAGE; //??
break;
default:
snprintf(info->name, 64, "%s", "UNDEFINED");
break;
}
}
static void
get_semantic_name(nir_variable *var, struct semantic_info *info,
const struct glsl_type *type)
{
info->kind = DXIL_SEM_INVALID;
info->interpolation = get_interpolation(var);
switch (var->data.location) {
case VARYING_SLOT_POS:
assert(glsl_get_components(type) == 4);
snprintf(info->name, 64, "%s", "SV_Position");
info->kind = DXIL_SEM_POSITION;
break;
case VARYING_SLOT_FACE:
assert(glsl_get_components(var->type) == 1);
snprintf(info->name, 64, "%s", "SV_IsFrontFace");
info->kind = DXIL_SEM_IS_FRONT_FACE;
break;
case VARYING_SLOT_PRIMITIVE_ID:
assert(glsl_get_components(var->type) == 1);
snprintf(info->name, 64, "%s", "SV_PrimitiveID");
info->kind = DXIL_SEM_PRIMITIVE_ID;
break;
case VARYING_SLOT_CLIP_DIST1:
info->index = 1;
/* fallthrough */
case VARYING_SLOT_CLIP_DIST0:
assert(var->data.location == VARYING_SLOT_CLIP_DIST1 || info->index == 0);
snprintf(info->name, 64, "%s", "SV_ClipDistance");
info->kind = DXIL_SEM_CLIP_DISTANCE;
break;
default: {
int index = var->data.location - VARYING_SLOT_POS;
const char idx1 = 'A' + (char)(index >> 4);
const char idx2 = 'A' + (char)(index & 0xf);
snprintf(info->name, 64, "VARYING%c%c", idx1, idx2);
info->kind = DXIL_SEM_ARBITRARY;
}
}
}
static void
get_semantic_in_name(nir_variable *var, struct semantic_info *info)
{
get_semantic_name(var, info, var->type);
info->sysvalue_name = in_sysvalue_name(var);
}
static void
get_semantic_gs_in_name(nir_variable *var, struct semantic_info *info)
{
/* geometry shader input varyings come as arrays, but we want to use
* the element type */
const struct glsl_type *type =
glsl_type_is_array(var->type) ? glsl_without_array(var->type) : var->type;
get_semantic_name(var, info, type);
info->sysvalue_name = in_sysvalue_name(var);
}
static enum dxil_prog_sig_semantic
prog_semantic_from_kind(enum dxil_semantic_kind kind)
{
switch (kind) {
case DXIL_SEM_ARBITRARY: return DXIL_PROG_SEM_UNDEFINED;
case DXIL_SEM_VERTEX_ID: return DXIL_PROG_SEM_VERTEX_ID;
case DXIL_SEM_INSTANCE_ID: return DXIL_PROG_SEM_INSTANCE_ID;
case DXIL_SEM_POSITION: return DXIL_PROG_SEM_POSITION;
case DXIL_SEM_COVERAGE: return DXIL_PROG_SEM_COVERAGE;
case DXIL_SEM_INNER_COVERAGE: return DXIL_PROG_SEM_INNER_COVERAGE;
case DXIL_SEM_PRIMITIVE_ID: return DXIL_PROG_SEM_PRIMITIVE_ID;
case DXIL_SEM_SAMPLE_INDEX: return DXIL_PROG_SEM_SAMPLE_INDEX;
case DXIL_SEM_IS_FRONT_FACE: return DXIL_PROG_SEM_IS_FRONTFACE;
case DXIL_SEM_RENDERTARGET_ARRAY_INDEX: return DXIL_PROG_SEM_RENDERTARGET_ARRAY_INDEX;
case DXIL_SEM_VIEWPORT_ARRAY_INDEX: return DXIL_PROG_SEM_VIEWPORT_ARRAY_INDEX;
case DXIL_SEM_CLIP_DISTANCE: return DXIL_PROG_SEM_CLIP_DISTANCE;
case DXIL_SEM_CULL_DISTANCE: return DXIL_PROG_SEM_CULL_DISTANCE;
case DXIL_SEM_BARYCENTRICS: return DXIL_PROG_SEM_BARYCENTRICS;
case DXIL_SEM_SHADING_RATE: return DXIL_PROG_SEM_SHADING_RATE;
case DXIL_SEM_CULL_PRIMITIVE: return DXIL_PROG_SEM_CULL_PRIMITIVE;
case DXIL_SEM_TARGET: return DXIL_PROG_SEM_TARGET;
case DXIL_SEM_DEPTH: return DXIL_PROG_SEM_DEPTH;
case DXIL_SEM_DEPTH_LE: return DXIL_PROG_SEM_DEPTH_LE;
case DXIL_SEM_DEPTH_GE: return DXIL_PROG_SEM_DEPTH_GE;
case DXIL_SEM_STENCIL_REF: return DXIL_PROG_SEM_STENCIL_REF;
default:
return DXIL_PROG_SEM_UNDEFINED;
}
}
static
uint32_t
copy_semantic_name_to_string(struct _mesa_string_buffer *string_out, const char *name)
{
/* copy the semantic name */
uint32_t retval = string_out->length;
size_t name_len = strlen(name) + 1;
_mesa_string_buffer_append_len(string_out, name, name_len);
return retval;
}
static
uint32_t
append_semantic_index_to_table(struct dxil_psv_sem_index_table *table, uint32_t index,
uint32_t num_rows)
{
if (num_rows == 1) {
for (unsigned i = 0; i < table->size; ++i) {
if (table->data[i] == index)
return i;
}
}
uint32_t retval = table->size;
assert(table->size + num_rows <= 80);
for (unsigned i = 0; i < num_rows; ++i)
table->data[table->size++] = index + i;
return retval;
}
static const struct dxil_mdnode *
fill_SV_param_nodes(struct dxil_module *mod, unsigned record_id,
struct semantic_info *semantic) {
const struct dxil_mdnode *SV_params_nodes[11];
/* For this to always work we should use vectorize_io, but for FS out and VS in
* this is not implemented globally */
const struct dxil_mdnode *flattened_semantics[256];
for (unsigned i = 0; i < semantic->rows; ++i)
flattened_semantics[i] = dxil_get_metadata_int32(mod, semantic->index + i);
SV_params_nodes[0] = dxil_get_metadata_int32(mod, (int)record_id); // Unique element ID
SV_params_nodes[1] = dxil_get_metadata_string(mod, semantic->name); // Element name
SV_params_nodes[2] = dxil_get_metadata_int8(mod, semantic->sig_comp_type); // Element type
SV_params_nodes[3] = dxil_get_metadata_int8(mod, (int8_t)semantic->kind); // Effective system value
SV_params_nodes[4] = dxil_get_metadata_node(mod, flattened_semantics,
semantic->rows); // Semantic index vector
SV_params_nodes[5] = dxil_get_metadata_int8(mod, semantic->interpolation); // Interpolation mode
SV_params_nodes[6] = dxil_get_metadata_int32(mod, semantic->rows); // Number of rows
SV_params_nodes[7] = dxil_get_metadata_int8(mod, semantic->cols); // Number of columns
SV_params_nodes[8] = dxil_get_metadata_int32(mod, semantic->start_row); // Element packing start row
SV_params_nodes[9] = dxil_get_metadata_int8(mod, semantic->start_col); // Element packing start column
SV_params_nodes[10] = 0; // optional Metadata
return dxil_get_metadata_node(mod, SV_params_nodes, ARRAY_SIZE(SV_params_nodes));
}
static void
fill_signature_element(struct dxil_signature_element *elm,
struct semantic_info *semantic,
unsigned row)
{
memset(elm, 0, sizeof(struct dxil_signature_element));
// elm->stream = 0;
// elm->semantic_name_offset = 0; // Offset needs to be filled out when writing
elm->semantic_index = semantic->index + row;
elm->system_value = (uint32_t) prog_semantic_from_kind(semantic->kind);
elm->comp_type = (uint32_t) semantic->comp_type;
elm->reg = semantic->start_row + row;
assert(semantic->cols + semantic->start_col <= 4);
elm->mask = (uint8_t) (((1 << semantic->cols) - 1) << semantic->start_col);
// elm->never_writes_mask = 0;
elm->min_precision = DXIL_MIN_PREC_DEFAULT;
}
static bool
fill_psv_signature_element(struct dxil_psv_signature_element *psv_elm,
struct semantic_info *semantic, struct dxil_module *mod)
{
memset(psv_elm, 0, sizeof(struct dxil_psv_signature_element));
psv_elm->rows = semantic->rows;
if (semantic->start_row >= 0) {
assert(semantic->start_row < 256);
psv_elm->start_row = semantic->start_row;
psv_elm->cols_and_start = (1u << 6) | (semantic->start_col << 4) | semantic->cols;
} else {
/* The validation expects that the the start row is not egative
* and apparently the extra bit in the cols_and_start indicates that the
* row is meant literally, so don't set it in this case.
* (Source of information: Comparing with the validation structures
* created by dxcompiler)
*/
psv_elm->start_row = 0;
psv_elm->cols_and_start = (semantic->start_col << 4) | semantic->cols;
}
psv_elm->semantic_kind = (uint8_t)semantic->kind;
psv_elm->component_type = semantic->comp_type; //`??
psv_elm->interpolation_mode = semantic->interpolation;
/* to be filled later
psv_elm->dynamic_mask_and_stream = 0;
*/
if (semantic->kind == DXIL_SEM_ARBITRARY && strlen(semantic->name)) {
psv_elm->semantic_name_offset =
copy_semantic_name_to_string(mod->sem_string_table, semantic->name);
/* TODO: clean up memory */
if (psv_elm->semantic_name_offset == (uint32_t)-1)
return false;
}
psv_elm->semantic_indexes_offset =
append_semantic_index_to_table(&mod->sem_index_table, semantic->index, semantic->rows);
return true;
}
static bool
fill_io_signature(struct dxil_module *mod, int id,
struct semantic_info *semantic,
const struct dxil_mdnode **io,
struct dxil_signature_element *elm,
struct dxil_psv_signature_element *psv_elm)
{
*io = fill_SV_param_nodes(mod, id, semantic);
for (unsigned i = 0; i < semantic->rows; ++i)
fill_signature_element(&elm[i], semantic, i);
return fill_psv_signature_element(psv_elm, semantic, mod);
}
static unsigned
get_input_signature_group(struct dxil_module *mod, const struct dxil_mdnode **inputs,
unsigned num_inputs,
nir_shader *s, nir_variable_mode modes,
semantic_info_proc get_semantics, unsigned *row_iter,
bool is_gs_shader)
{
nir_foreach_variable_with_modes(var, s, modes) {
struct semantic_info semantic = {0};
get_semantics(var, &semantic);
mod->inputs[num_inputs].sysvalue = semantic.sysvalue_name;
*row_iter = get_additional_semantic_info(var, &semantic, *row_iter, is_gs_shader);
mod->inputs[num_inputs].name = ralloc_strdup(mod->ralloc_ctx,
semantic.name);
mod->inputs[num_inputs].num_elements = semantic.rows;
struct dxil_signature_element *elm = mod->inputs[num_inputs].elements;
struct dxil_psv_signature_element *psv_elm = &mod->psv_inputs[num_inputs];
if (!fill_io_signature(mod, num_inputs, &semantic,
&inputs[num_inputs], elm, psv_elm))
return 0;
++num_inputs;
assert(num_inputs < VARYING_SLOT_MAX);
}
return num_inputs;
}
static const struct dxil_mdnode *
get_input_signature(struct dxil_module *mod, nir_shader *s)
{
if (s->info.stage == MESA_SHADER_KERNEL)
return NULL;
const struct dxil_mdnode *inputs[VARYING_SLOT_MAX];
unsigned next_row = 0;
bool is_gs_shader = s->info.stage == MESA_SHADER_GEOMETRY;
mod->num_sig_inputs = get_input_signature_group(mod, inputs, 0,
s, nir_var_shader_in,
s->info.stage == MESA_SHADER_VERTEX ?
get_semantic_vs_in_name :
(s->info.stage == MESA_SHADER_GEOMETRY ?
get_semantic_gs_in_name : get_semantic_in_name),
&next_row, is_gs_shader);
mod->num_sig_inputs = get_input_signature_group(mod, inputs, mod->num_sig_inputs,
s, nir_var_system_value,
get_semantic_sv_name,
&next_row, is_gs_shader);
if (!mod->num_sig_inputs && !mod->num_sig_inputs)
return NULL;
mod->num_psv_inputs = next_row;
const struct dxil_mdnode *retval = mod->num_sig_inputs ?
dxil_get_metadata_node(mod, inputs, mod->num_sig_inputs) : NULL;
return retval;
}
static const char *out_sysvalue_name(nir_variable *var)
{
switch (var->data.location) {
case VARYING_SLOT_FACE:
return "FACE";
case VARYING_SLOT_POS:
return "POS";
case VARYING_SLOT_CLIP_DIST0:
case VARYING_SLOT_CLIP_DIST1:
return "CLIPDST";
case VARYING_SLOT_PRIMITIVE_ID:
return "PRIMID";
default:
return "NO";
}
}
static const struct dxil_mdnode *
get_output_signature(struct dxil_module *mod, nir_shader *s)
{
const struct dxil_mdnode *outputs[VARYING_SLOT_MAX];
unsigned num_outputs = 0;
unsigned next_row = 0;
nir_foreach_variable_with_modes(var, s, nir_var_shader_out) {
struct semantic_info semantic = {0};
if (s->info.stage == MESA_SHADER_FRAGMENT) {
get_semantic_ps_outname(var, &semantic);
mod->outputs[num_outputs].sysvalue = "TARGET";
} else {
get_semantic_name(var, &semantic, var->type);
mod->outputs[num_outputs].sysvalue = out_sysvalue_name(var);
}
next_row = get_additional_semantic_info(var, &semantic, next_row, false);
mod->info.has_out_position |= semantic.kind== DXIL_SEM_POSITION;
mod->info.has_out_depth |= semantic.kind == DXIL_SEM_DEPTH;
mod->outputs[num_outputs].name = ralloc_strdup(mod->ralloc_ctx,
semantic.name);
mod->outputs[num_outputs].num_elements = semantic.rows;
struct dxil_signature_element *elm = mod->outputs[num_outputs].elements;
struct dxil_psv_signature_element *psv_elm = &mod->psv_outputs[num_outputs];
if (!fill_io_signature(mod, num_outputs, &semantic,
&outputs[num_outputs], elm, psv_elm))
return NULL;
/* This is fishy, logic suggests that the LHS should be 0xf, but from the
* validation it needs to be 0xff */
elm->never_writes_mask = 0xff & ~elm->mask;
++num_outputs;
if (!is_depth_output(semantic.kind))
++mod->num_psv_outputs;
assert(num_outputs < ARRAY_SIZE(outputs));
}
if (!num_outputs)
return NULL;
const struct dxil_mdnode *retval = dxil_get_metadata_node(mod, outputs, num_outputs);
mod->num_sig_outputs = num_outputs;
return retval;
}
const struct dxil_mdnode *
get_signatures(struct dxil_module *mod, nir_shader *s)
{
/* DXC does the same: Add an empty string before everything else */
mod->sem_string_table = _mesa_string_buffer_create(mod->ralloc_ctx, 1024);
copy_semantic_name_to_string(mod->sem_string_table, "");
const struct dxil_mdnode *input_signature = get_input_signature(mod, s);
const struct dxil_mdnode *output_signature = get_output_signature(mod, s);
const struct dxil_mdnode *SV_nodes[3] = {
input_signature,
output_signature,
NULL
};
if (output_signature || input_signature)
return dxil_get_metadata_node(mod, SV_nodes, ARRAY_SIZE(SV_nodes));
else
return NULL;
}

View File

@ -0,0 +1,161 @@
/*
* Copyright © Microsoft Corporation
*
* 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 (including the next
* paragraph) 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.
*/
#ifndef DXIL_SIGNATURE_H
#define DXIL_SIGNATURE_H
#include "dxil_enums.h"
#include "nir.h"
#include "util/string_buffer.h"
/* struct taken from DXILContainer
* Enums values were replaced by uint32_t since the must occupy 32 bit
*/
struct dxil_signature_element {
uint32_t stream; // Stream index (parameters must appear in non-decreasing stream order)
uint32_t semantic_name_offset; // Offset to char * stream from start of DxilProgramSignature.
uint32_t semantic_index; // Semantic Index
uint32_t system_value; // Semantic type. Similar to DxilSemantic::Kind, but a serialized rather than processing rep.
uint32_t comp_type; // Type of bits.
uint32_t reg; // Register Index (row index)
uint8_t mask; // Mask (column allocation)
union { // Unconditional cases useful for validation of shader linkage.
uint8_t never_writes_mask; // For an output signature, the shader the signature belongs to never
// writes the masked components of the output register.
uint8_t always_reads_mask; // For an input signature, the shader the signature belongs to always
// reads the masked components of the input register.
};
uint16_t pad;
uint32_t min_precision; // Minimum precision of input/output data
};
struct dxil_signature_record {
struct dxil_signature_element elements[32];
unsigned num_elements;
const char *sysvalue;
char *name;
};
struct dxil_psv_sem_index_table {
uint32_t data[80];
uint32_t size;
};
struct dxil_psv_signature_element {
uint32_t semantic_name_offset; // Offset into StringTable
uint32_t semantic_indexes_offset; // Offset into PSVSemanticIndexTable, count == Rows
uint8_t rows; // Number of rows this element occupies
uint8_t start_row; // Starting row of packing location if allocated
uint8_t cols_and_start; // 0:4 = Cols, 4:6 = StartCol, 6:7 == Allocated
uint8_t semantic_kind; // PSVSemanticKind
uint8_t component_type; // DxilProgramSigCompType
uint8_t interpolation_mode; // DXIL::InterpolationMode or D3D10_SB_INTERPOLATION_MODE
uint8_t dynamic_mask_and_stream; // 0:4 = DynamicIndexMask, 4:6 = OutputStream (0-3)
uint8_t reserved;
};
struct dxil_vs_info {
char output_position_present;
};
struct dxil_gs_info {
uint32_t input_primitive;
uint32_t output_toplology;
uint32_t output_stream_mask;
char output_position_present;
};
struct dxil_ps_info {
char depth_output;
char sample_frequency;
};
/* Maximum sized defining the union size (MSInfo)*/
struct dxil_max_sized_info {
uint32_t dummy1[3];
uint16_t dummy2[2];
};
struct dxil_psv_runtime_info_0 {
union {
struct dxil_vs_info vs;
struct dxil_gs_info gs;
struct dxil_ps_info ps;
struct dxil_max_sized_info dummy;
};
uint32_t min_expected_wave_lane_count; // minimum lane count required, 0 if unused
uint32_t max_expected_wave_lane_count; // maximum lane count required, 0xffffffff if unused
};
struct dxil_psv_runtime_info_1 {
struct dxil_psv_runtime_info_0 psv0;
uint8_t shader_stage; // PSVShaderKind
uint8_t uses_view_id;
union {
uint16_t max_vertex_count; // MaxVertexCount for GS only (max 1024)
uint8_t sig_patch_const_or_prim_vectors; // Output for HS; Input for DS; Primitive output for MS (overlaps MS1::SigPrimVectors)
// struct { uint8_t dummy[2]; } fill;
};
// PSVSignatureElement counts
uint8_t sig_input_elements;
uint8_t sig_output_elements;
uint8_t sig_patch_const_or_prim_elements;
// Number of packed vectors per signature
uint8_t sig_input_vectors;
uint8_t sig_output_vectors[4];
};
struct dxil_pipe_state_validation {
unsigned val_major, val_minor;
uint32_t version;
uint32_t resource_count;
uint8_t shader_stage;
struct _mesa_string_buffer *string_table;
struct dxil_psv_sem_index_table semantic_index_table;
uint8_t uses_view_id;
uint8_t sig_input_elements;
uint8_t sig_output_elements;
uint8_t sig_patch_const_or_prim_elements;
uint8_t sig_input_vectors;
uint8_t sig_patch_const_or_prim_vectors;
uint8_t sig_output_vectors[4];
};
struct dxil_mdnode;
struct dxil_module;
#ifdef __cplusplus
extern "C" {
#endif
const struct dxil_mdnode *
get_signatures(struct dxil_module *mod, nir_shader *s);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,57 @@
# Copyright © Microsoft Corporation
# 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 (including the next
# paragraph) 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.
files_libdxil_compiler = files(
'dxil_buffer.c',
'dxil_container.c',
'dxil_dump.c',
'dxil_enums.c',
'dxil_function.c',
'dxil_module.c',
'dxil_signature.c',
)
libdxil_compiler = static_library(
'dxil_compiler',
[files_libdxil_compiler, sha1_h],
include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_compiler, inc_gallium],
dependencies: [idep_nir_headers],
gnu_symbol_visibility : 'hidden',
)
idep_libdxil_compiler = declare_dependency(
link_with : libdxil_compiler,
dependencies : [idep_mesautil],
include_directories : include_directories('.')
)
if with_tests
test(
'dxil_buffer',
executable(
'dxil_buffer_test',
files('dxil_buffer_test.c'),
include_directories : [inc_src],
dependencies : [idep_libdxil_compiler]
),
suite: 'd3d12'
)
endif

22
src/microsoft/meson.build Normal file
View File

@ -0,0 +1,22 @@
# Copyright © Microsoft Corporation
# 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 (including the next
# paragraph) 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.
subdir('compiler')