mirror of
https://gitee.com/openharmony/third_party_mesa3d
synced 2024-11-23 15:30:09 +00:00
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:
parent
10dfd3cfb4
commit
dd5fe2f3de
104
src/microsoft/compiler/dxil_buffer.c
Normal file
104
src/microsoft/compiler/dxil_buffer.c
Normal 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;
|
||||
}
|
60
src/microsoft/compiler/dxil_buffer.h
Normal file
60
src/microsoft/compiler/dxil_buffer.h
Normal 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
|
129
src/microsoft/compiler/dxil_buffer_test.c
Normal file
129
src/microsoft/compiler/dxil_buffer_test.c
Normal 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;
|
||||
}
|
353
src/microsoft/compiler/dxil_container.c
Normal file
353
src/microsoft/compiler/dxil_container.c
Normal 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;
|
||||
}
|
123
src/microsoft/compiler/dxil_container.h
Normal file
123
src/microsoft/compiler/dxil_container.h
Normal 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
|
778
src/microsoft/compiler/dxil_dump.c
Normal file
778
src/microsoft/compiler/dxil_dump.c
Normal 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");
|
||||
}
|
||||
}
|
53
src/microsoft/compiler/dxil_dump.h
Normal file
53
src/microsoft/compiler/dxil_dump.h
Normal 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
|
179
src/microsoft/compiler/dxil_dump_decls.h
Normal file
179
src/microsoft/compiler/dxil_dump_decls.h
Normal 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"
|
||||
};
|
163
src/microsoft/compiler/dxil_enums.c
Normal file
163
src/microsoft/compiler/dxil_enums.c
Normal 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];
|
||||
}
|
340
src/microsoft/compiler/dxil_enums.h
Normal file
340
src/microsoft/compiler/dxil_enums.h
Normal 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
|
236
src/microsoft/compiler/dxil_function.c
Normal file
236
src/microsoft/compiler/dxil_function.c
Normal 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);
|
||||
}
|
92
src/microsoft/compiler/dxil_function.h
Normal file
92
src/microsoft/compiler/dxil_function.h
Normal 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
|
300
src/microsoft/compiler/dxil_internal.h
Normal file
300
src/microsoft/compiler/dxil_internal.h
Normal 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
|
3320
src/microsoft/compiler/dxil_module.c
Normal file
3320
src/microsoft/compiler/dxil_module.c
Normal file
File diff suppressed because it is too large
Load Diff
469
src/microsoft/compiler/dxil_module.h
Normal file
469
src/microsoft/compiler/dxil_module.h
Normal 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
|
589
src/microsoft/compiler/dxil_signature.c
Normal file
589
src/microsoft/compiler/dxil_signature.c
Normal 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;
|
||||
}
|
161
src/microsoft/compiler/dxil_signature.h
Normal file
161
src/microsoft/compiler/dxil_signature.h
Normal 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
|
57
src/microsoft/compiler/meson.build
Normal file
57
src/microsoft/compiler/meson.build
Normal 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
22
src/microsoft/meson.build
Normal 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')
|
Loading…
Reference in New Issue
Block a user