blob: 3f93cd45ef9fae7501502a14253d3028f0a7b90c [file] [edit]
/*
* Copyright 2024 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "vkd3d_common.h"
#include "vkd3d_shader.h"
static bool read_root_signature(struct vkd3d_shader_code *shader, const char *filename)
{
void *code;
FILE *fd;
memset(shader, 0, sizeof(*shader));
if (!(fd = fopen(filename, "rb")))
return false;
fseek(fd, 0, SEEK_END);
shader->size = ftell(fd);
rewind(fd);
if (!(code = malloc(shader->size)))
{
fprintf(stderr, "Out of memory.\n");
fclose(fd);
return false;
}
shader->code = code;
if (fread(code, 1, shader->size, fd) != shader->size)
{
fprintf(stderr, "Could not read shader bytecode from file: '%s'.\n", filename);
free(code);
fclose(fd);
return false;
}
fclose(fd);
return true;
}
#define FLAG(x) { D3D12_ROOT_SIGNATURE_FLAG_##x, #x }
static const struct rs_flag_to_str
{
D3D12_ROOT_SIGNATURE_FLAGS flag;
const char *str;
} rs_flags[] = {
FLAG(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),
FLAG(DENY_VERTEX_SHADER_ROOT_ACCESS),
FLAG(DENY_HULL_SHADER_ROOT_ACCESS),
FLAG(DENY_DOMAIN_SHADER_ROOT_ACCESS),
FLAG(DENY_GEOMETRY_SHADER_ROOT_ACCESS),
FLAG(DENY_PIXEL_SHADER_ROOT_ACCESS),
FLAG(ALLOW_STREAM_OUTPUT),
FLAG(LOCAL_ROOT_SIGNATURE),
FLAG(DENY_AMPLIFICATION_SHADER_ROOT_ACCESS),
FLAG(DENY_MESH_SHADER_ROOT_ACCESS),
FLAG(CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED),
FLAG(SAMPLER_HEAP_DIRECTLY_INDEXED),
};
#undef FLAG
#define FLAG(x) { D3D12_ROOT_DESCRIPTOR_FLAG_##x, #x }
static const struct desc_flag_to_str
{
D3D12_ROOT_DESCRIPTOR_FLAGS flag;
const char *str;
} desc_flags[] = {
FLAG(DATA_VOLATILE),
FLAG(DATA_STATIC_WHILE_SET_AT_EXECUTE),
FLAG(DATA_STATIC),
};
#undef FLAG
#define FLAG(x) { D3D12_DESCRIPTOR_RANGE_FLAG_##x, #x }
static const struct range_flag_to_str
{
D3D12_DESCRIPTOR_RANGE_FLAGS flag;
const char *str;
} range_flags[] = {
FLAG(DESCRIPTORS_VOLATILE),
FLAG(DATA_VOLATILE),
FLAG(DATA_STATIC_WHILE_SET_AT_EXECUTE),
FLAG(DATA_STATIC),
FLAG(DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS),
};
#undef FLAG
static void dump_root_signature(const struct vkd3d_root_signature_desc2 *rs)
{
unsigned int i, j, k;
printf("Flags:\n");
for (i = 0; i < ARRAY_SIZE(rs_flags); i++)
if (rs_flags[i].flag & rs->flags)
printf(" %s\n", rs_flags[i].str);
for (i = 0; i < rs->parameter_count; i++)
{
const struct vkd3d_root_parameter1 *param = &rs->parameters[i];
const char *desc_fmt = NULL;
printf(" [%u] (visibility #%x) || ", i, param->shader_visibility);
switch (param->parameter_type)
{
case VKD3D_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
printf("32BIT_CONSTANTS (b%u, space%u), Num32BitWords = %u\n",
param->constants.shader_register, param->constants.register_space,
param->constants.value_count);
break;
case VKD3D_ROOT_PARAMETER_TYPE_CBV:
desc_fmt = "RootCBV (b%u, space%u)\n";
break;
case VKD3D_ROOT_PARAMETER_TYPE_SRV:
desc_fmt = "RootSRV (t%u, space%u)\n";
break;
case VKD3D_ROOT_PARAMETER_TYPE_UAV:
desc_fmt = "RootUAV (u%u, space%u)\n";
break;
case VKD3D_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
printf("TABLE\n");
for (j = 0; j < param->descriptor_table.descriptor_range_count; j++)
{
const struct vkd3d_descriptor_range1 *range = &param->descriptor_table.descriptor_ranges[j];
const char *table_fmt = NULL;
switch (range->range_type)
{
case VKD3D_DESCRIPTOR_RANGE_TYPE_CBV:
table_fmt = " CBV (b%u, space%u) count %u, offset %u\n";
break;
case VKD3D_DESCRIPTOR_RANGE_TYPE_SRV:
table_fmt = " SRV (t%u, space%u) count %u, offset %u\n";
break;
case VKD3D_DESCRIPTOR_RANGE_TYPE_UAV:
table_fmt = " UAV (u%u, space%u) count %u, offset %u\n";
break;
case VKD3D_DESCRIPTOR_RANGE_TYPE_SAMPLER:
table_fmt = " SAMPLER (s%u, space%u) count %u, offset %u\n";
break;
default:
break;
}
if (table_fmt)
{
printf(table_fmt,
range->base_shader_register, range->register_space,
range->descriptor_count,
range->descriptor_table_offset);
for (k = 0; k < ARRAY_SIZE(range_flags); k++)
if (range_flags[k].flag & range->flags)
printf(" %s\n", range_flags[k].str);
}
}
default:
break;
}
if (desc_fmt)
{
printf(desc_fmt, param->descriptor.shader_register, param->descriptor.register_space);
for (j = 0; j < ARRAY_SIZE(desc_flags); j++)
if (desc_flags[j].flag & param->descriptor.flags)
printf(" %s\n", desc_flags[j].str);
}
}
for (i = 0; i < rs->static_sampler_count; i++)
{
/* TODO: Too lazy to convert all the enums here. Fix as needed. */
const struct vkd3d_static_sampler_desc1 *sampler = &rs->static_samplers[i];
printf("StaticSampler (s%u, space%u):\n", sampler->shader_register, sampler->register_space);
printf(" Filter: #%x\n", sampler->filter);
printf(" AddrU: #%x\n", sampler->address_u);
printf(" AddrV: #%x\n", sampler->address_v);
printf(" AddrW: #%x\n", sampler->address_w);
printf(" MipLODBias: %f\n", sampler->mip_lod_bias);
printf(" MaxAniso: %u\n", sampler->max_anisotropy);
printf(" Comparison: #%x\n", sampler->comparison_func);
printf(" StaticBorderColor: #%x\n", sampler->border_color);
printf(" MinLOD: %f\n", sampler->min_lod);
printf(" MaxLOD: %f\n", sampler->max_lod);
printf(" Visibility: #%x\n", sampler->shader_visibility);
printf(" Flags: #%x\n", sampler->flags);
}
}
int main(int argc, char **argv)
{
struct vkd3d_versioned_root_signature_desc out_rs;
vkd3d_shader_hash_t compat_hash;
struct vkd3d_shader_code rs;
int vr;
if (argc != 2)
{
fprintf(stderr, "Usage: vkd3d-rs-parse hash.rs\n");
return 1;
}
if (!read_root_signature(&rs, argv[1]))
{
fprintf(stderr, "Failed to read root signature.\n");
return 1;
}
vr = vkd3d_shader_parse_root_signature_v_1_2_from_raw_payload(&rs, &out_rs, &compat_hash);
if (vr < 0)
{
fprintf(stderr, "Failed to parse root signature, vr %d.\n", vr);
return 1;
}
printf("Root signature: %016"PRIx64"\n", compat_hash);
dump_root_signature(&out_rs.v_1_2);
vkd3d_shader_free_shader_code(&rs);
vkd3d_shader_free_root_signature(&out_rs);
return 0;
}