vkd3d/libs/vkd3d-shader/trace.c

1742 lines
69 KiB
C
Raw Normal View History

/*
* Copyright 2002-2003 Jason Edmeades
* Copyright 2002-2003 Raphael Junqueira
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
* Copyright 2006 Ivan Gyurdiev
* Copyright 2007-2008, 2013 Stefan Dösinger for CodeWeavers
* Copyright 2009-2011 Henri Verbeet for CodeWeavers
*
* 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
*/
#include "vkd3d_shader_private.h"
#include <stdio.h>
static const char * const shader_opcode_names[] =
{
/* VKD3DSIH_ABS */ "abs",
/* VKD3DSIH_ADD */ "add",
/* VKD3DSIH_AND */ "and",
/* VKD3DSIH_ATOMIC_AND */ "atomic_and",
/* VKD3DSIH_ATOMIC_CMP_STORE */ "atomic_cmp_store",
/* VKD3DSIH_ATOMIC_IADD */ "atomic_iadd",
/* VKD3DSIH_ATOMIC_IMAX */ "atomic_imax",
/* VKD3DSIH_ATOMIC_IMIN */ "atomic_imin",
/* VKD3DSIH_ATOMIC_OR */ "atomic_or",
/* VKD3DSIH_ATOMIC_UMAX */ "atomic_umax",
/* VKD3DSIH_ATOMIC_UMIN */ "atomic_umin",
/* VKD3DSIH_ATOMIC_XOR */ "atomic_xor",
/* VKD3DSIH_BEM */ "bem",
/* VKD3DSIH_BFI */ "bfi",
/* VKD3DSIH_BFREV */ "bfrev",
/* VKD3DSIH_BREAK */ "break",
/* VKD3DSIH_BREAKC */ "breakc",
/* VKD3DSIH_BREAKP */ "breakp",
/* VKD3DSIH_BUFINFO */ "bufinfo",
/* VKD3DSIH_CALL */ "call",
/* VKD3DSIH_CALLNZ */ "callnz",
/* VKD3DSIH_CASE */ "case",
/* VKD3DSIH_CMP */ "cmp",
/* VKD3DSIH_CND */ "cnd",
/* VKD3DSIH_CONTINUE */ "continue",
/* VKD3DSIH_CONTINUEP */ "continuec",
/* VKD3DSIH_COUNTBITS */ "countbits",
/* VKD3DSIH_CRS */ "crs",
/* VKD3DSIH_CUT */ "cut",
/* VKD3DSIH_CUT_STREAM */ "cut_stream",
/* VKD3DSIH_DCL */ "dcl",
/* VKD3DSIH_DCL_CONSTANT_BUFFER */ "dcl_constantBuffer",
/* VKD3DSIH_DCL_FUNCTION_BODY */ "dcl_function_body",
/* VKD3DSIH_DCL_FUNCTION_TABLE */ "dcl_function_table",
/* VKD3DSIH_DCL_GLOBAL_FLAGS */ "dcl_globalFlags",
/* VKD3DSIH_DCL_GS_INSTANCES */ "dcl_gs_instances",
/* VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT */ "dcl_hs_fork_phase_instance_count",
/* VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ "dcl_hs_join_phase_instance_count",
/* VKD3DSIH_DCL_HS_MAX_TESSFACTOR */ "dcl_hs_max_tessfactor",
/* VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER */ "dcl_immediateConstantBuffer",
/* VKD3DSIH_DCL_INDEX_RANGE */ "dcl_index_range",
/* VKD3DSIH_DCL_INDEXABLE_TEMP */ "dcl_indexableTemp",
/* VKD3DSIH_DCL_INPUT */ "dcl_input",
/* VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT */ "dcl_input_control_point_count",
/* VKD3DSIH_DCL_INPUT_PRIMITIVE */ "dcl_inputPrimitive",
/* VKD3DSIH_DCL_INPUT_PS */ "dcl_input_ps",
/* VKD3DSIH_DCL_INPUT_PS_SGV */ "dcl_input_ps_sgv",
/* VKD3DSIH_DCL_INPUT_PS_SIV */ "dcl_input_ps_siv",
/* VKD3DSIH_DCL_INPUT_SGV */ "dcl_input_sgv",
/* VKD3DSIH_DCL_INPUT_SIV */ "dcl_input_siv",
/* VKD3DSIH_DCL_INTERFACE */ "dcl_interface",
/* VKD3DSIH_DCL_OUTPUT */ "dcl_output",
/* VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT */ "dcl_output_control_point_count",
/* VKD3DSIH_DCL_OUTPUT_SIV */ "dcl_output_siv",
/* VKD3DSIH_DCL_OUTPUT_TOPOLOGY */ "dcl_outputTopology",
/* VKD3DSIH_DCL_RESOURCE_RAW */ "dcl_resource_raw",
/* VKD3DSIH_DCL_RESOURCE_STRUCTURED */ "dcl_resource_structured",
/* VKD3DSIH_DCL_SAMPLER */ "dcl_sampler",
/* VKD3DSIH_DCL_STREAM */ "dcl_stream",
/* VKD3DSIH_DCL_TEMPS */ "dcl_temps",
/* VKD3DSIH_DCL_TESSELLATOR_DOMAIN */ "dcl_tessellator_domain",
/* VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE */ "dcl_tessellator_output_primitive",
/* VKD3DSIH_DCL_TESSELLATOR_PARTITIONING */ "dcl_tessellator_partitioning",
/* VKD3DSIH_DCL_TGSM_RAW */ "dcl_tgsm_raw",
/* VKD3DSIH_DCL_TGSM_STRUCTURED */ "dcl_tgsm_structured",
/* VKD3DSIH_DCL_THREAD_GROUP */ "dcl_thread_group",
/* VKD3DSIH_DCL_UAV_RAW */ "dcl_uav_raw",
/* VKD3DSIH_DCL_UAV_STRUCTURED */ "dcl_uav_structured",
/* VKD3DSIH_DCL_UAV_TYPED */ "dcl_uav_typed",
/* VKD3DSIH_DCL_VERTICES_OUT */ "dcl_maxOutputVertexCount",
/* VKD3DSIH_DEF */ "def",
/* VKD3DSIH_DEFAULT */ "default",
/* VKD3DSIH_DEFB */ "defb",
/* VKD3DSIH_DEFI */ "defi",
/* VKD3DSIH_DIV */ "div",
/* VKD3DSIH_DP2 */ "dp2",
/* VKD3DSIH_DP2ADD */ "dp2add",
/* VKD3DSIH_DP3 */ "dp3",
/* VKD3DSIH_DP4 */ "dp4",
/* VKD3DSIH_DST */ "dst",
/* VKD3DSIH_DSX */ "dsx",
/* VKD3DSIH_DSX_COARSE */ "deriv_rtx_coarse",
/* VKD3DSIH_DSX_FINE */ "deriv_rtx_fine",
/* VKD3DSIH_DSY */ "dsy",
/* VKD3DSIH_DSY_COARSE */ "deriv_rty_coarse",
/* VKD3DSIH_DSY_FINE */ "deriv_rty_fine",
/* VKD3DSIH_ELSE */ "else",
/* VKD3DSIH_EMIT */ "emit",
/* VKD3DSIH_EMIT_STREAM */ "emit_stream",
/* VKD3DSIH_ENDIF */ "endif",
/* VKD3DSIH_ENDLOOP */ "endloop",
/* VKD3DSIH_ENDREP */ "endrep",
/* VKD3DSIH_ENDSWITCH */ "endswitch",
/* VKD3DSIH_EQ */ "eq",
/* VKD3DSIH_EVAL_CENTROID */ "eval_centroid",
/* VKD3DSIH_EVAL_SAMPLE_INDEX */ "eval_sample_index",
/* VKD3DSIH_EXP */ "exp",
/* VKD3DSIH_EXPP */ "expp",
/* VKD3DSIH_F16TOF32 */ "f16tof32",
/* VKD3DSIH_F32TOF16 */ "f32tof16",
/* VKD3DSIH_FCALL */ "fcall",
/* VKD3DSIH_FIRSTBIT_HI */ "firstbit_hi",
/* VKD3DSIH_FIRSTBIT_LO */ "firstbit_lo",
/* VKD3DSIH_FIRSTBIT_SHI */ "firstbit_shi",
/* VKD3DSIH_FRC */ "frc",
/* VKD3DSIH_FTOI */ "ftoi",
/* VKD3DSIH_FTOU */ "ftou",
/* VKD3DSIH_GATHER4 */ "gather4",
/* VKD3DSIH_GATHER4_C */ "gather4_c",
/* VKD3DSIH_GATHER4_PO */ "gather4_po",
/* VKD3DSIH_GATHER4_PO_C */ "gather4_po_c",
/* VKD3DSIH_GE */ "ge",
/* VKD3DSIH_HS_CONTROL_POINT_PHASE */ "hs_control_point_phase",
/* VKD3DSIH_HS_DECLS */ "hs_decls",
/* VKD3DSIH_HS_FORK_PHASE */ "hs_fork_phase",
/* VKD3DSIH_HS_JOIN_PHASE */ "hs_join_phase",
/* VKD3DSIH_IADD */ "iadd",
/* VKD3DSIH_IBFE */ "ibfe",
/* VKD3DSIH_IEQ */ "ieq",
/* VKD3DSIH_IF */ "if",
/* VKD3DSIH_IFC */ "ifc",
/* VKD3DSIH_IGE */ "ige",
/* VKD3DSIH_ILT */ "ilt",
/* VKD3DSIH_IMAD */ "imad",
/* VKD3DSIH_IMAX */ "imax",
/* VKD3DSIH_IMIN */ "imin",
/* VKD3DSIH_IMM_ATOMIC_ALLOC */ "imm_atomic_alloc",
/* VKD3DSIH_IMM_ATOMIC_AND */ "imm_atomic_and",
/* VKD3DSIH_IMM_ATOMIC_CMP_EXCH */ "imm_atomic_cmp_exch",
/* VKD3DSIH_IMM_ATOMIC_CONSUME */ "imm_atomic_consume",
/* VKD3DSIH_IMM_ATOMIC_EXCH */ "imm_atomic_exch",
/* VKD3DSIH_IMM_ATOMIC_IADD */ "imm_atomic_iadd",
/* VKD3DSIH_IMM_ATOMIC_IMAX */ "imm_atomic_imax",
/* VKD3DSIH_IMM_ATOMIC_IMIN */ "imm_atomic_imin",
/* VKD3DSIH_IMM_ATOMIC_OR */ "imm_atomic_or",
/* VKD3DSIH_IMM_ATOMIC_UMAX */ "imm_atomic_umax",
/* VKD3DSIH_IMM_ATOMIC_UMIN */ "imm_atomic_umin",
/* VKD3DSIH_IMM_ATOMIC_XOR */ "imm_atomic_xor",
/* VKD3DSIH_IMUL */ "imul",
/* VKD3DSIH_INE */ "ine",
/* VKD3DSIH_INEG */ "ineg",
/* VKD3DSIH_ISHL */ "ishl",
/* VKD3DSIH_ISHR */ "ishr",
/* VKD3DSIH_ITOF */ "itof",
/* VKD3DSIH_LABEL */ "label",
/* VKD3DSIH_LD */ "ld",
/* VKD3DSIH_LD2DMS */ "ld2dms",
/* VKD3DSIH_LD_RAW */ "ld_raw",
/* VKD3DSIH_LD_STRUCTURED */ "ld_structured",
/* VKD3DSIH_LD_UAV_TYPED */ "ld_uav_typed",
/* VKD3DSIH_LIT */ "lit",
/* VKD3DSIH_LOD */ "lod",
/* VKD3DSIH_LOG */ "log",
/* VKD3DSIH_LOGP */ "logp",
/* VKD3DSIH_LOOP */ "loop",
/* VKD3DSIH_LRP */ "lrp",
/* VKD3DSIH_LT */ "lt",
/* VKD3DSIH_M3x2 */ "m3x2",
/* VKD3DSIH_M3x3 */ "m3x3",
/* VKD3DSIH_M3x4 */ "m3x4",
/* VKD3DSIH_M4x3 */ "m4x3",
/* VKD3DSIH_M4x4 */ "m4x4",
/* VKD3DSIH_MAD */ "mad",
/* VKD3DSIH_MAX */ "max",
/* VKD3DSIH_MIN */ "min",
/* VKD3DSIH_MOV */ "mov",
/* VKD3DSIH_MOVA */ "mova",
/* VKD3DSIH_MOVC */ "movc",
/* VKD3DSIH_MUL */ "mul",
/* VKD3DSIH_NE */ "ne",
/* VKD3DSIH_NOP */ "nop",
/* VKD3DSIH_NOT */ "not",
/* VKD3DSIH_NRM */ "nrm",
/* VKD3DSIH_OR */ "or",
/* VKD3DSIH_PHASE */ "phase",
/* VKD3DSIH_POW */ "pow",
/* VKD3DSIH_RCP */ "rcp",
/* VKD3DSIH_REP */ "rep",
/* VKD3DSIH_RESINFO */ "resinfo",
/* VKD3DSIH_RET */ "ret",
/* VKD3DSIH_RETP */ "retp",
/* VKD3DSIH_ROUND_NE */ "round_ne",
/* VKD3DSIH_ROUND_NI */ "round_ni",
/* VKD3DSIH_ROUND_PI */ "round_pi",
/* VKD3DSIH_ROUND_Z */ "round_z",
/* VKD3DSIH_RSQ */ "rsq",
/* VKD3DSIH_SAMPLE */ "sample",
/* VKD3DSIH_SAMPLE_B */ "sample_b",
/* VKD3DSIH_SAMPLE_C */ "sample_c",
/* VKD3DSIH_SAMPLE_C_LZ */ "sample_c_lz",
/* VKD3DSIH_SAMPLE_GRAD */ "sample_d",
/* VKD3DSIH_SAMPLE_INFO */ "sample_info",
/* VKD3DSIH_SAMPLE_LOD */ "sample_l",
/* VKD3DSIH_SAMPLE_POS */ "sample_pos",
/* VKD3DSIH_SETP */ "setp",
/* VKD3DSIH_SGE */ "sge",
/* VKD3DSIH_SGN */ "sgn",
/* VKD3DSIH_SINCOS */ "sincos",
/* VKD3DSIH_SLT */ "slt",
/* VKD3DSIH_SQRT */ "sqrt",
/* VKD3DSIH_STORE_RAW */ "store_raw",
/* VKD3DSIH_STORE_STRUCTURED */ "store_structured",
/* VKD3DSIH_STORE_UAV_TYPED */ "store_uav_typed",
/* VKD3DSIH_SUB */ "sub",
/* VKD3DSIH_SWAPC */ "swapc",
/* VKD3DSIH_SWITCH */ "switch",
/* VKD3DSIH_SYNC */ "sync",
/* VKD3DSIH_TEX */ "texld",
/* VKD3DSIH_TEXBEM */ "texbem",
/* VKD3DSIH_TEXBEML */ "texbeml",
/* VKD3DSIH_TEXCOORD */ "texcrd",
/* VKD3DSIH_TEXDEPTH */ "texdepth",
/* VKD3DSIH_TEXDP3 */ "texdp3",
/* VKD3DSIH_TEXDP3TEX */ "texdp3tex",
/* VKD3DSIH_TEXKILL */ "texkill",
/* VKD3DSIH_TEXLDD */ "texldd",
/* VKD3DSIH_TEXLDL */ "texldl",
/* VKD3DSIH_TEXM3x2DEPTH */ "texm3x2depth",
/* VKD3DSIH_TEXM3x2PAD */ "texm3x2pad",
/* VKD3DSIH_TEXM3x2TEX */ "texm3x2tex",
/* VKD3DSIH_TEXM3x3 */ "texm3x3",
/* VKD3DSIH_TEXM3x3DIFF */ "texm3x3diff",
/* VKD3DSIH_TEXM3x3PAD */ "texm3x3pad",
/* VKD3DSIH_TEXM3x3SPEC */ "texm3x3spec",
/* VKD3DSIH_TEXM3x3TEX */ "texm3x3tex",
/* VKD3DSIH_TEXM3x3VSPEC */ "texm3x3vspec",
/* VKD3DSIH_TEXREG2AR */ "texreg2ar",
/* VKD3DSIH_TEXREG2GB */ "texreg2gb",
/* VKD3DSIH_TEXREG2RGB */ "texreg2rgb",
/* VKD3DSIH_UBFE */ "ubfe",
/* VKD3DSIH_UDIV */ "udiv",
/* VKD3DSIH_UGE */ "uge",
/* VKD3DSIH_ULT */ "ult",
/* VKD3DSIH_UMAX */ "umax",
/* VKD3DSIH_UMIN */ "umin",
/* VKD3DSIH_UMUL */ "umul",
/* VKD3DSIH_USHR */ "ushr",
/* VKD3DSIH_UTOF */ "utof",
/* VKD3DSIH_XOR */ "xor",
};
static const struct
{
enum vkd3d_shader_input_sysval_semantic sysval_semantic;
const char *sysval_name;
}
shader_input_sysval_semantic_names[] =
{
{VKD3D_SIV_POSITION, "position"},
{VKD3D_SIV_CLIP_DISTANCE, "clip_distance"},
{VKD3D_SIV_CULL_DISTANCE, "cull_distance"},
{VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX, "render_target_array_index"},
{VKD3D_SIV_VIEWPORT_ARRAY_INDEX, "viewport_array_index"},
{VKD3D_SIV_VERTEX_ID, "vertex_id"},
{VKD3D_SIV_INSTANCE_ID, "instance_id"},
{VKD3D_SIV_PRIMITIVE_ID, "primitive_id"},
{VKD3D_SIV_IS_FRONT_FACE, "is_front_face"},
{VKD3D_SIV_SAMPLE_INDEX, "sample_index"},
{VKD3D_SIV_QUAD_U0_TESS_FACTOR, "finalQuadUeq0EdgeTessFactor"},
{VKD3D_SIV_QUAD_V0_TESS_FACTOR, "finalQuadVeq0EdgeTessFactor"},
{VKD3D_SIV_QUAD_U1_TESS_FACTOR, "finalQuadUeq1EdgeTessFactor"},
{VKD3D_SIV_QUAD_V1_TESS_FACTOR, "finalQuadVeq1EdgeTessFactor"},
{VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR, "finalQuadUInsideTessFactor"},
{VKD3D_SIV_QUAD_V_INNER_TESS_FACTOR, "finalQuadVInsideTessFactor"},
{VKD3D_SIV_TRIANGLE_U_TESS_FACTOR, "finalTriUeq0EdgeTessFactor"},
{VKD3D_SIV_TRIANGLE_V_TESS_FACTOR, "finalTriVeq0EdgeTessFactor"},
{VKD3D_SIV_TRIANGLE_W_TESS_FACTOR, "finalTriWeq0EdgeTessFactor"},
{VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR, "finalTriInsideTessFactor"},
{VKD3D_SIV_LINE_DETAIL_TESS_FACTOR, "finalLineDetailTessFactor"},
{VKD3D_SIV_LINE_DENSITY_TESS_FACTOR, "finalLineDensityTessFactor"},
};
struct vkd3d_d3d_asm_colours
{
const char *reset;
const char *opcode;
const char *reg;
};
struct vkd3d_d3d_asm_compiler
{
struct vkd3d_string_buffer buffer;
struct vkd3d_shader_version shader_version;
struct vkd3d_d3d_asm_colours colours;
};
static int shader_ver_ge(const struct vkd3d_shader_version *v, int major, int minor)
{
return v->major > major || (v->major == major && v->minor >= minor);
}
static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...)
{
va_list args;
int ret;
va_start(args, format);
ret = vkd3d_string_buffer_vprintf(buffer, format, args);
va_end(args);
return ret;
}
/* Convert floating point offset relative to a register file to an absolute
* offset for float constants. */
static unsigned int shader_get_float_offset(enum vkd3d_shader_register_type register_type, UINT register_idx)
{
switch (register_type)
{
case VKD3DSPR_CONST: return register_idx;
case VKD3DSPR_CONST2: return 2048 + register_idx;
case VKD3DSPR_CONST3: return 4096 + register_idx;
case VKD3DSPR_CONST4: return 6144 + register_idx;
default:
FIXME("Unsupported register type: %u.\n", register_type);
return register_idx;
}
}
static void shader_dump_global_flags(struct vkd3d_d3d_asm_compiler *compiler, uint32_t global_flags)
{
unsigned int i;
static const struct
{
unsigned int flag;
const char *name;
}
global_flag_info[] =
{
{VKD3DSGF_REFACTORING_ALLOWED, "refactoringAllowed"},
{VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL, "forceEarlyDepthStencil"},
{VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS, "enableRawAndStructuredBuffers"},
{VKD3DSGF_ENABLE_MINIMUM_PRECISION, "enableMinimumPrecision"},
{VKD3DSGF_SKIP_OPTIMIZATION, "skipOptimization"},
};
for (i = 0; i < ARRAY_SIZE(global_flag_info); ++i)
{
if (global_flags & global_flag_info[i].flag)
{
vkd3d_string_buffer_printf(&compiler->buffer, "%s", global_flag_info[i].name);
global_flags &= ~global_flag_info[i].flag;
if (global_flags)
vkd3d_string_buffer_printf(&compiler->buffer, " | ");
}
}
if (global_flags)
vkd3d_string_buffer_printf(&compiler->buffer, "unknown_flags(%#x)", global_flags);
}
static void shader_dump_sync_flags(struct vkd3d_d3d_asm_compiler *compiler, uint32_t sync_flags)
{
if (sync_flags & VKD3DSSF_GLOBAL_UAV)
{
vkd3d_string_buffer_printf(&compiler->buffer, "_uglobal");
sync_flags &= ~VKD3DSSF_GLOBAL_UAV;
}
if (sync_flags & VKD3DSSF_GROUP_SHARED_MEMORY)
{
vkd3d_string_buffer_printf(&compiler->buffer, "_g");
sync_flags &= ~VKD3DSSF_GROUP_SHARED_MEMORY;
}
if (sync_flags & VKD3DSSF_THREAD_GROUP)
{
vkd3d_string_buffer_printf(&compiler->buffer, "_t");
sync_flags &= ~VKD3DSSF_THREAD_GROUP;
}
if (sync_flags)
vkd3d_string_buffer_printf(&compiler->buffer, "_unknown_flags(%#x)", sync_flags);
}
static void shader_dump_precise_flags(struct vkd3d_d3d_asm_compiler *compiler, uint32_t flags)
{
if (!(flags & VKD3DSI_PRECISE_XYZW))
return;
vkd3d_string_buffer_printf(&compiler->buffer, " [precise");
if (flags != VKD3DSI_PRECISE_XYZW)
{
vkd3d_string_buffer_printf(&compiler->buffer, "(%s%s%s%s)",
flags & VKD3DSI_PRECISE_X ? "x" : "",
flags & VKD3DSI_PRECISE_Y ? "y" : "",
flags & VKD3DSI_PRECISE_Z ? "z" : "",
flags & VKD3DSI_PRECISE_W ? "w" : "");
}
vkd3d_string_buffer_printf(&compiler->buffer, "]");
}
static void shader_dump_uav_flags(struct vkd3d_d3d_asm_compiler *compiler, uint32_t uav_flags)
{
if (uav_flags & VKD3DSUF_GLOBALLY_COHERENT)
{
vkd3d_string_buffer_printf(&compiler->buffer, "_glc");
uav_flags &= ~VKD3DSUF_GLOBALLY_COHERENT;
}
if (uav_flags & VKD3DSUF_ORDER_PRESERVING_COUNTER)
{
vkd3d_string_buffer_printf(&compiler->buffer, "_opc");
uav_flags &= ~VKD3DSUF_ORDER_PRESERVING_COUNTER;
}
if (uav_flags)
vkd3d_string_buffer_printf(&compiler->buffer, "_unknown_flags(%#x)", uav_flags);
}
static void shader_dump_tessellator_domain(struct vkd3d_d3d_asm_compiler *compiler,
enum vkd3d_tessellator_domain domain)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
shader_addline(buffer, "domain_");
switch (domain)
{
case VKD3D_TESSELLATOR_DOMAIN_LINE:
shader_addline(buffer, "isoline");
break;
case VKD3D_TESSELLATOR_DOMAIN_TRIANGLE:
shader_addline(buffer, "tri");
break;
case VKD3D_TESSELLATOR_DOMAIN_QUAD:
shader_addline(buffer, "quad");
break;
default:
shader_addline(buffer, "unknown_tessellator_domain(%#x)", domain);
break;
}
}
static void shader_dump_tessellator_output_primitive(struct vkd3d_d3d_asm_compiler *compiler,
enum vkd3d_shader_tessellator_output_primitive output_primitive)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
shader_addline(buffer, "output_");
switch (output_primitive)
{
case VKD3D_SHADER_TESSELLATOR_OUTPUT_POINT:
shader_addline(buffer, "point");
break;
case VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE:
shader_addline(buffer, "line");
break;
case VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CW:
shader_addline(buffer, "triangle_cw");
break;
case VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW:
shader_addline(buffer, "triangle_ccw");
break;
default:
shader_addline(buffer, "unknown_tessellator_output_primitive(%#x)", output_primitive);
break;
}
}
static void shader_dump_tessellator_partitioning(struct vkd3d_d3d_asm_compiler *compiler,
enum vkd3d_shader_tessellator_partitioning partitioning)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
shader_addline(buffer, "partitioning_");
switch (partitioning)
{
case VKD3D_SHADER_TESSELLATOR_PARTITIONING_INTEGER:
shader_addline(buffer, "integer");
break;
case VKD3D_SHADER_TESSELLATOR_PARTITIONING_POW2:
shader_addline(buffer, "pow2");
break;
case VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD:
shader_addline(buffer, "fractional_odd");
break;
case VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN:
shader_addline(buffer, "fractional_even");
break;
default:
shader_addline(buffer, "unknown_tessellator_partitioning(%#x)", partitioning);
break;
}
}
static void shader_dump_shader_input_sysval_semantic(struct vkd3d_d3d_asm_compiler *compiler,
enum vkd3d_shader_input_sysval_semantic semantic)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(shader_input_sysval_semantic_names); ++i)
{
if (shader_input_sysval_semantic_names[i].sysval_semantic == semantic)
{
vkd3d_string_buffer_printf(&compiler->buffer, "%s", shader_input_sysval_semantic_names[i].sysval_name);
return;
}
}
vkd3d_string_buffer_printf(&compiler->buffer, "unknown_shader_input_sysval_semantic(%#x)", semantic);
}
static void shader_dump_resource_type(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_shader_resource_type type)
{
static const char *const resource_type_names[] =
{
/* VKD3D_SHADER_RESOURCE_NONE */ "none",
/* VKD3D_SHADER_RESOURCE_BUFFER */ "buffer",
/* VKD3D_SHADER_RESOURCE_TEXTURE_1D */ "texture1d",
/* VKD3D_SHADER_RESOURCE_TEXTURE_2D */ "texture2d",
/* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */ "texture2dms",
/* VKD3D_SHADER_RESOURCE_TEXTURE_3D */ "texture3d",
/* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */ "texturecube",
/* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */ "texture1darray",
/* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */ "texture2darray",
/* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */ "texture2dmsarray",
/* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */ "texturecubearray",
};
if (type < ARRAY_SIZE(resource_type_names))
vkd3d_string_buffer_printf(&compiler->buffer, "%s", resource_type_names[type]);
else
vkd3d_string_buffer_printf(&compiler->buffer, "unknown");
}
static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type)
{
static const char *const data_type_names[] =
{
/* VKD3D_DATA_FLOAT */ "float",
/* VKD3D_DATA_INT */ "int",
/* VKD3D_DATA_RESOURCE */ "resource",
/* VKD3D_DATA_SAMPLER */ "sampler",
/* VKD3D_DATA_UAV */ "uav",
/* VKD3D_DATA_UINT */ "uint",
/* VKD3D_DATA_UNORM */ "unorm",
/* VKD3D_DATA_SNORM */ "snorm",
/* VKD3D_DATA_OPAQUE */ "opaque",
/* VKD3D_DATA_MIXED */ "mixed",
/* VKD3D_DATA_DOUBLE */ "double",
/* VKD3D_DATA_CONTINUED */ "<continued>",
/* VKD3D_DATA_UNUSED */ "<unused>",
};
const char *name;
int i;
vkd3d_string_buffer_printf(&compiler->buffer, "(");
for (i = 0; i < 4; i++)
{
if (type[i] < ARRAY_SIZE(data_type_names))
name = data_type_names[type[i]];
else
name = "unknown";
vkd3d_string_buffer_printf(&compiler->buffer, "%s%s", i == 0 ? "" : ",", name);
}
vkd3d_string_buffer_printf(&compiler->buffer, ")");
}
static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_semantic *semantic, uint32_t flags)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
if (semantic->resource.reg.reg.type == VKD3DSPR_SAMPLER)
{
switch (semantic->resource_type)
{
case VKD3D_SHADER_RESOURCE_TEXTURE_2D:
shader_addline(buffer, "_2d");
break;
case VKD3D_SHADER_RESOURCE_TEXTURE_3D:
shader_addline(buffer, "_3d");
break;
case VKD3D_SHADER_RESOURCE_TEXTURE_CUBE:
shader_addline(buffer, "_cube");
break;
default:
shader_addline(buffer, "_unknown_resource_type(%#x)", semantic->resource_type);
break;
}
}
else if (semantic->resource.reg.reg.type == VKD3DSPR_RESOURCE || semantic->resource.reg.reg.type == VKD3DSPR_UAV)
{
if (semantic->resource.reg.reg.type == VKD3DSPR_RESOURCE)
shader_addline(buffer, "_resource_");
shader_dump_resource_type(compiler, semantic->resource_type);
if (semantic->resource.reg.reg.type == VKD3DSPR_UAV)
shader_dump_uav_flags(compiler, flags);
shader_dump_data_type(compiler, semantic->resource_data_type);
}
else
{
/* Pixel shaders 3.0 don't have usage semantics. */
if (!shader_ver_ge(&compiler->shader_version, 3, 0)
&& compiler->shader_version.type == VKD3D_SHADER_TYPE_PIXEL)
return;
else
shader_addline(buffer, "_");
switch (semantic->usage)
{
case VKD3D_DECL_USAGE_POSITION:
shader_addline(buffer, "position%u", semantic->usage_idx);
break;
case VKD3D_DECL_USAGE_BLEND_INDICES:
shader_addline(buffer, "blend");
break;
case VKD3D_DECL_USAGE_BLEND_WEIGHT:
shader_addline(buffer, "weight");
break;
case VKD3D_DECL_USAGE_NORMAL:
shader_addline(buffer, "normal%u", semantic->usage_idx);
break;
case VKD3D_DECL_USAGE_PSIZE:
shader_addline(buffer, "psize");
break;
case VKD3D_DECL_USAGE_COLOR:
if (!semantic->usage_idx)
shader_addline(buffer, "color");
else
shader_addline(buffer, "specular%u", (semantic->usage_idx - 1));
break;
case VKD3D_DECL_USAGE_TEXCOORD:
shader_addline(buffer, "texture%u", semantic->usage_idx);
break;
case VKD3D_DECL_USAGE_TANGENT:
shader_addline(buffer, "tangent");
break;
case VKD3D_DECL_USAGE_BINORMAL:
shader_addline(buffer, "binormal");
break;
case VKD3D_DECL_USAGE_TESS_FACTOR:
shader_addline(buffer, "tessfactor");
break;
case VKD3D_DECL_USAGE_POSITIONT:
shader_addline(buffer, "positionT%u", semantic->usage_idx);
break;
case VKD3D_DECL_USAGE_FOG:
shader_addline(buffer, "fog");
break;
case VKD3D_DECL_USAGE_DEPTH:
shader_addline(buffer, "depth");
break;
case VKD3D_DECL_USAGE_SAMPLE:
shader_addline(buffer, "sample");
break;
default:
shader_addline(buffer, "<unknown_semantic(%#x)>", semantic->usage);
FIXME("Unrecognised semantic usage %#x.\n", semantic->usage);
}
}
}
static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_src_param *param);
static void shader_print_float_literal(struct vkd3d_d3d_asm_compiler *compiler,
const char *prefix, float f, const char *suffix)
{
vkd3d_string_buffer_printf(&compiler->buffer, "%s%.8e%s", prefix, f, suffix);
}
static void shader_print_int_literal(struct vkd3d_d3d_asm_compiler *compiler,
const char *prefix, int i, const char *suffix)
{
vkd3d_string_buffer_printf(&compiler->buffer, "%s%d%s", prefix, i, suffix);
}
static void shader_print_subscript(struct vkd3d_d3d_asm_compiler *compiler,
unsigned int offset, const struct vkd3d_shader_src_param *rel_addr)
{
vkd3d_string_buffer_printf(&compiler->buffer, "[");
if (rel_addr)
{
shader_dump_src_param(compiler, rel_addr);
vkd3d_string_buffer_printf(&compiler->buffer, " + ");
}
vkd3d_string_buffer_printf(&compiler->buffer, "%u]", offset);
}
static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const struct vkd3d_shader_register *reg)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
unsigned int offset = reg->idx[0].offset;
static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"};
static const char * const misctype_reg_names[] = {"vPos", "vFace"};
shader_addline(buffer, "%s", compiler->colours.reg);
switch (reg->type)
{
case VKD3DSPR_TEMP:
shader_addline(buffer, "r");
break;
case VKD3DSPR_INPUT:
shader_addline(buffer, "v");
break;
case VKD3DSPR_CONST:
case VKD3DSPR_CONST2:
case VKD3DSPR_CONST3:
case VKD3DSPR_CONST4:
shader_addline(buffer, "c");
offset = shader_get_float_offset(reg->type, offset);
break;
case VKD3DSPR_TEXTURE: /* vs: case VKD3DSPR_ADDR */
vkd3d_string_buffer_printf(buffer, "%c",
compiler->shader_version.type == VKD3D_SHADER_TYPE_PIXEL ? 't' : 'a');
break;
case VKD3DSPR_RASTOUT:
shader_addline(buffer, "%s", rastout_reg_names[offset]);
break;
case VKD3DSPR_COLOROUT:
shader_addline(buffer, "o");
if (!shader_ver_ge(&compiler->shader_version, 4, 0))
shader_addline(buffer, "C");
break;
case VKD3DSPR_DEPTHOUT:
shader_addline(buffer, "oDepth");
break;
case VKD3DSPR_DEPTHOUTGE:
shader_addline(buffer, "oDepthGE");
break;
case VKD3DSPR_DEPTHOUTLE:
shader_addline(buffer, "oDepthLE");
break;
case VKD3DSPR_ATTROUT:
shader_addline(buffer, "oD");
break;
case VKD3DSPR_TEXCRDOUT:
/* Vertex shaders >= 3.0 use general purpose output registers
* (VKD3DSPR_OUTPUT), which can include an address token. */
if (shader_ver_ge(&compiler->shader_version, 3, 0))
shader_addline(buffer, "o");
else
shader_addline(buffer, "oT");
break;
case VKD3DSPR_CONSTINT:
shader_addline(buffer, "i");
break;
case VKD3DSPR_CONSTBOOL:
shader_addline(buffer, "b");
break;
case VKD3DSPR_LABEL:
shader_addline(buffer, "l");
break;
case VKD3DSPR_LOOP:
shader_addline(buffer, "aL");
break;
case VKD3DSPR_SAMPLER:
shader_addline(buffer, "s");
break;
case VKD3DSPR_MISCTYPE:
if (offset > 1)
{
FIXME("Unhandled misctype register %u.\n", offset);
shader_addline(buffer, "<unhandled misctype %#x>", offset);
}
else
{
shader_addline(buffer, "%s", misctype_reg_names[offset]);
}
break;
case VKD3DSPR_PREDICATE:
shader_addline(buffer, "p");
break;
case VKD3DSPR_IMMCONST:
shader_addline(buffer, "l");
break;
case VKD3DSPR_CONSTBUFFER:
shader_addline(buffer, "cb");
break;
case VKD3DSPR_IMMCONSTBUFFER:
shader_addline(buffer, "icb");
break;
case VKD3DSPR_PRIMID:
shader_addline(buffer, "primID");
break;
case VKD3DSPR_NULL:
shader_addline(buffer, "null");
break;
case VKD3DSPR_RASTERIZER:
shader_addline(buffer, "rasterizer");
break;
case VKD3DSPR_RESOURCE:
shader_addline(buffer, "t");
break;
case VKD3DSPR_UAV:
shader_addline(buffer, "u");
break;
case VKD3DSPR_OUTPOINTID:
shader_addline(buffer, "vOutputControlPointID");
break;
case VKD3DSPR_FORKINSTID:
shader_addline(buffer, "vForkInstanceId");
break;
case VKD3DSPR_JOININSTID:
shader_addline(buffer, "vJoinInstanceId");
break;
case VKD3DSPR_INCONTROLPOINT:
shader_addline(buffer, "vicp");
break;
case VKD3DSPR_OUTCONTROLPOINT:
shader_addline(buffer, "vocp");
break;
case VKD3DSPR_PATCHCONST:
shader_addline(buffer, "vpc");
break;
case VKD3DSPR_TESSCOORD:
shader_addline(buffer, "vDomainLocation");
break;
case VKD3DSPR_GROUPSHAREDMEM:
shader_addline(buffer, "g");
break;
case VKD3DSPR_THREADID:
shader_addline(buffer, "vThreadID");
break;
case VKD3DSPR_THREADGROUPID:
shader_addline(buffer, "vThreadGroupID");
break;
case VKD3DSPR_LOCALTHREADID:
shader_addline(buffer, "vThreadIDInGroup");
break;
case VKD3DSPR_LOCALTHREADINDEX:
shader_addline(buffer, "vThreadIDInGroupFlattened");
break;
case VKD3DSPR_IDXTEMP:
shader_addline(buffer, "x");
break;
case VKD3DSPR_STREAM:
shader_addline(buffer, "m");
break;
case VKD3DSPR_FUNCTIONBODY:
shader_addline(buffer, "fb");
break;
case VKD3DSPR_FUNCTIONPOINTER:
shader_addline(buffer, "fp");
break;
case VKD3DSPR_COVERAGE:
shader_addline(buffer, "vCoverage");
break;
case VKD3DSPR_SAMPLEMASK:
shader_addline(buffer, "oMask");
break;
case VKD3DSPR_GSINSTID:
shader_addline(buffer, "vGSInstanceID");
break;
default:
shader_addline(buffer, "<unhandled_rtype(%#x)>", reg->type);
break;
}
if (reg->type == VKD3DSPR_IMMCONST)
{
shader_addline(buffer, "%s(", compiler->colours.reset);
switch (reg->immconst_type)
{
case VKD3D_IMMCONST_SCALAR:
switch (reg->data_type)
{
case VKD3D_DATA_FLOAT:
shader_print_float_literal(compiler, "", reg->u.immconst_float[0], "");
break;
case VKD3D_DATA_INT:
shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], "");
break;
case VKD3D_DATA_RESOURCE:
case VKD3D_DATA_SAMPLER:
case VKD3D_DATA_UINT:
shader_addline(buffer, "%u", reg->u.immconst_uint[0]);
break;
default:
shader_addline(buffer, "<unhandled data type %#x>", reg->data_type);
break;
}
break;
case VKD3D_IMMCONST_VEC4:
switch (reg->data_type)
{
case VKD3D_DATA_FLOAT:
shader_print_float_literal(compiler, "", reg->u.immconst_float[0], "");
shader_print_float_literal(compiler, ", ", reg->u.immconst_float[1], "");
shader_print_float_literal(compiler, ", ", reg->u.immconst_float[2], "");
shader_print_float_literal(compiler, ", ", reg->u.immconst_float[3], "");
break;
case VKD3D_DATA_INT:
shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], "");
shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[1], "");
shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[2], "");
shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[3], "");
break;
case VKD3D_DATA_RESOURCE:
case VKD3D_DATA_SAMPLER:
case VKD3D_DATA_UINT:
shader_addline(buffer, "%u, %u, %u, %u",
reg->u.immconst_uint[0], reg->u.immconst_uint[1],
reg->u.immconst_uint[2], reg->u.immconst_uint[3]);
break;
default:
shader_addline(buffer, "<unhandled data type %#x>", reg->data_type);
break;
}
break;
default:
shader_addline(buffer, "<unhandled immconst_type %#x>", reg->immconst_type);
break;
}
shader_addline(buffer, ")");
}
else if (reg->type != VKD3DSPR_RASTOUT
&& reg->type != VKD3DSPR_MISCTYPE
&& reg->type != VKD3DSPR_NULL)
{
if (offset != ~0u)
{
if (reg->idx[0].rel_addr || reg->type == VKD3DSPR_IMMCONSTBUFFER
|| reg->type == VKD3DSPR_INCONTROLPOINT || (reg->type == VKD3DSPR_INPUT
&& (compiler->shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY
|| compiler->shader_version.type == VKD3D_SHADER_TYPE_HULL)))
{
vkd3d_string_buffer_printf(buffer, "%s", compiler->colours.reset);
shader_print_subscript(compiler, offset, reg->idx[0].rel_addr);
}
else
{
vkd3d_string_buffer_printf(buffer, "%u%s", offset, compiler->colours.reset);
}
/* For CBs in sm < 5.1 we move the buffer offset from idx[1] to idx[2]
* to normalise it with 5.1.
* Here we should ignore it if it's a CB in sm < 5.1. */
if (reg->idx[1].offset != ~0u &&
(reg->type != VKD3DSPR_CONSTBUFFER || shader_ver_ge(&compiler->shader_version, 5, 1)))
shader_print_subscript(compiler, reg->idx[1].offset, reg->idx[1].rel_addr);
if (reg->idx[2].offset != ~0u)
shader_print_subscript(compiler, reg->idx[2].offset, reg->idx[2].rel_addr);
}
else
{
shader_addline(buffer, "%s", compiler->colours.reset);
}
if (reg->type == VKD3DSPR_FUNCTIONPOINTER)
shader_print_subscript(compiler, reg->u.fp_body_idx, NULL);
}
else
{
shader_addline(buffer, "%s", compiler->colours.reset);
}
}
static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_dst_param *param)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
uint32_t write_mask = param->write_mask;
shader_dump_register(compiler, &param->reg);
if (write_mask)
{
static const char write_mask_chars[] = "xyzw";
shader_addline(buffer, ".");
if (write_mask & VKD3DSP_WRITEMASK_0)
shader_addline(buffer, "%c", write_mask_chars[0]);
if (write_mask & VKD3DSP_WRITEMASK_1)
shader_addline(buffer, "%c", write_mask_chars[1]);
if (write_mask & VKD3DSP_WRITEMASK_2)
shader_addline(buffer, "%c", write_mask_chars[2]);
if (write_mask & VKD3DSP_WRITEMASK_3)
shader_addline(buffer, "%c", write_mask_chars[3]);
}
}
static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_src_param *param)
{
enum vkd3d_shader_src_modifier src_modifier = param->modifiers;
struct vkd3d_string_buffer *buffer = &compiler->buffer;
uint32_t swizzle = param->swizzle;
if (src_modifier == VKD3DSPSM_NEG
|| src_modifier == VKD3DSPSM_BIASNEG
|| src_modifier == VKD3DSPSM_SIGNNEG
|| src_modifier == VKD3DSPSM_X2NEG
|| src_modifier == VKD3DSPSM_ABSNEG)
shader_addline(buffer, "-");
else if (src_modifier == VKD3DSPSM_COMP)
shader_addline(buffer, "1-");
else if (src_modifier == VKD3DSPSM_NOT)
shader_addline(buffer, "!");
if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG)
shader_addline(buffer, "|");
shader_dump_register(compiler, &param->reg);
switch (src_modifier)
{
case VKD3DSPSM_NONE: break;
case VKD3DSPSM_NEG: break;
case VKD3DSPSM_NOT: break;
case VKD3DSPSM_BIAS: shader_addline(buffer, "_bias"); break;
case VKD3DSPSM_BIASNEG: shader_addline(buffer, "_bias"); break;
case VKD3DSPSM_SIGN: shader_addline(buffer, "_bx2"); break;
case VKD3DSPSM_SIGNNEG: shader_addline(buffer, "_bx2"); break;
case VKD3DSPSM_COMP: break;
case VKD3DSPSM_X2: shader_addline(buffer, "_x2"); break;
case VKD3DSPSM_X2NEG: shader_addline(buffer, "_x2"); break;
case VKD3DSPSM_DZ: shader_addline(buffer, "_dz"); break;
case VKD3DSPSM_DW: shader_addline(buffer, "_dw"); break;
case VKD3DSPSM_ABSNEG:
case VKD3DSPSM_ABS: /* handled later */ break;
default: shader_addline(buffer, "_unknown_modifier(%#x)", src_modifier);
}
if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_SAMPLER)
{
static const char swizzle_chars[] = "xyzw";
DWORD swizzle_x = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(0)) & VKD3D_SHADER_SWIZZLE_MASK;
DWORD swizzle_y = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(1)) & VKD3D_SHADER_SWIZZLE_MASK;
DWORD swizzle_z = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(2)) & VKD3D_SHADER_SWIZZLE_MASK;
DWORD swizzle_w = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(3)) & VKD3D_SHADER_SWIZZLE_MASK;
if (swizzle_x == swizzle_y
&& swizzle_x == swizzle_z
&& swizzle_x == swizzle_w)
{
shader_addline(buffer, ".%c", swizzle_chars[swizzle_x]);
}
else
{
shader_addline(buffer, ".%c%c%c%c", swizzle_chars[swizzle_x], swizzle_chars[swizzle_y],
swizzle_chars[swizzle_z], swizzle_chars[swizzle_w]);
}
}
if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG)
shader_addline(buffer, "|");
}
static void shader_dump_ins_modifiers(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_dst_param *dst)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
uint32_t mmask = dst->modifiers;
switch (dst->shift)
{
case 0: break;
case 13: shader_addline(buffer, "_d8"); break;
case 14: shader_addline(buffer, "_d4"); break;
case 15: shader_addline(buffer, "_d2"); break;
case 1: shader_addline(buffer, "_x2"); break;
case 2: shader_addline(buffer, "_x4"); break;
case 3: shader_addline(buffer, "_x8"); break;
default: shader_addline(buffer, "_unhandled_shift(%d)", dst->shift); break;
}
if (mmask & VKD3DSPDM_SATURATE) shader_addline(buffer, "_sat");
if (mmask & VKD3DSPDM_PARTIALPRECISION) shader_addline(buffer, "_pp");
if (mmask & VKD3DSPDM_MSAMPCENTROID) shader_addline(buffer, "_centroid");
mmask &= ~(VKD3DSPDM_SATURATE | VKD3DSPDM_PARTIALPRECISION | VKD3DSPDM_MSAMPCENTROID);
if (mmask) FIXME("Unrecognised modifier %#x.\n", mmask);
}
static void shader_dump_primitive_type(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_primitive_type *primitive_type)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
switch (primitive_type->type)
{
case VKD3D_PT_UNDEFINED:
shader_addline(buffer, "undefined");
break;
case VKD3D_PT_POINTLIST:
shader_addline(buffer, "pointlist");
break;
case VKD3D_PT_LINELIST:
shader_addline(buffer, "linelist");
break;
case VKD3D_PT_LINESTRIP:
shader_addline(buffer, "linestrip");
break;
case VKD3D_PT_TRIANGLELIST:
shader_addline(buffer, "trianglelist");
break;
case VKD3D_PT_TRIANGLESTRIP:
shader_addline(buffer, "trianglestrip");
break;
case VKD3D_PT_TRIANGLEFAN:
shader_addline(buffer, "trianglefan");
break;
case VKD3D_PT_LINELIST_ADJ:
shader_addline(buffer, "linelist_adj");
break;
case VKD3D_PT_LINESTRIP_ADJ:
shader_addline(buffer, "linestrip_adj");
break;
case VKD3D_PT_TRIANGLELIST_ADJ:
shader_addline(buffer, "trianglelist_adj");
break;
case VKD3D_PT_TRIANGLESTRIP_ADJ:
shader_addline(buffer, "trianglestrip_adj");
break;
case VKD3D_PT_PATCH:
shader_addline(buffer, "patch%u", primitive_type->patch_vertex_count);
break;
default:
shader_addline(buffer, "<unrecognized_primitive_type %#x>", primitive_type->type);
break;
}
}
static void shader_dump_interpolation_mode(struct vkd3d_d3d_asm_compiler *compiler,
enum vkd3d_shader_interpolation_mode interpolation_mode)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
switch (interpolation_mode)
{
case VKD3DSIM_CONSTANT:
shader_addline(buffer, "constant");
break;
case VKD3DSIM_LINEAR:
shader_addline(buffer, "linear");
break;
case VKD3DSIM_LINEAR_CENTROID:
shader_addline(buffer, "linear centroid");
break;
case VKD3DSIM_LINEAR_NOPERSPECTIVE:
shader_addline(buffer, "linear noperspective");
break;
case VKD3DSIM_LINEAR_SAMPLE:
shader_addline(buffer, "linear sample");
break;
case VKD3DSIM_LINEAR_NOPERSPECTIVE_CENTROID:
shader_addline(buffer, "linear noperspective centroid");
break;
case VKD3DSIM_LINEAR_NOPERSPECTIVE_SAMPLE:
shader_addline(buffer, "linear noperspective sample");
break;
default:
shader_addline(buffer, "<unrecognized_interpolation_mode %#x>", interpolation_mode);
break;
}
}
const char *shader_get_type_prefix(enum vkd3d_shader_type type)
{
switch (type)
{
case VKD3D_SHADER_TYPE_VERTEX:
return "vs";
case VKD3D_SHADER_TYPE_HULL:
return "hs";
case VKD3D_SHADER_TYPE_DOMAIN:
return "ds";
case VKD3D_SHADER_TYPE_GEOMETRY:
return "gs";
case VKD3D_SHADER_TYPE_PIXEL:
return "ps";
case VKD3D_SHADER_TYPE_COMPUTE:
return "cs";
case VKD3D_SHADER_TYPE_EFFECT:
return "fx";
case VKD3D_SHADER_TYPE_TEXTURE:
return "tx";
case VKD3D_SHADER_TYPE_LIBRARY:
return "lib";
default:
FIXME("Unhandled shader type %#x.\n", type);
return "unknown";
}
}
static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_instruction *ins)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
switch (ins->handler_idx)
{
case VKD3DSIH_BREAKP:
case VKD3DSIH_CONTINUEP:
case VKD3DSIH_IF:
case VKD3DSIH_RETP:
case VKD3DSIH_TEXKILL:
switch (ins->flags)
{
case VKD3D_SHADER_CONDITIONAL_OP_NZ: shader_addline(buffer, "_nz"); break;
case VKD3D_SHADER_CONDITIONAL_OP_Z: shader_addline(buffer, "_z"); break;
default: shader_addline(buffer, "_unrecognized(%#x)", ins->flags); break;
}
break;
case VKD3DSIH_IFC:
case VKD3DSIH_BREAKC:
switch (ins->flags)
{
case VKD3D_SHADER_REL_OP_GT: shader_addline(buffer, "_gt"); break;
case VKD3D_SHADER_REL_OP_EQ: shader_addline(buffer, "_eq"); break;
case VKD3D_SHADER_REL_OP_GE: shader_addline(buffer, "_ge"); break;
case VKD3D_SHADER_REL_OP_LT: shader_addline(buffer, "_lt"); break;
case VKD3D_SHADER_REL_OP_NE: shader_addline(buffer, "_ne"); break;
case VKD3D_SHADER_REL_OP_LE: shader_addline(buffer, "_le"); break;
default: shader_addline(buffer, "_(%u)", ins->flags);
}
break;
case VKD3DSIH_RESINFO:
switch (ins->flags)
{
case VKD3DSI_NONE: break;
case VKD3DSI_RESINFO_RCP_FLOAT: shader_addline(buffer, "_rcpFloat"); break;
case VKD3DSI_RESINFO_UINT: shader_addline(buffer, "_uint"); break;
default: shader_addline(buffer, "_unrecognized(%#x)", ins->flags);
}
break;
case VKD3DSIH_SAMPLE_INFO:
switch (ins->flags)
{
case VKD3DSI_NONE: break;
case VKD3DSI_SAMPLE_INFO_UINT: shader_addline(buffer, "_uint"); break;
default: shader_addline(buffer, "_unrecognized(%#x)", ins->flags);
}
break;
case VKD3DSIH_SYNC:
shader_dump_sync_flags(compiler, ins->flags);
break;
case VKD3DSIH_TEX:
if (shader_ver_ge(&compiler->shader_version, 2, 0) && (ins->flags & VKD3DSI_TEXLD_PROJECT))
shader_addline(buffer, "p");
break;
default:
shader_dump_precise_flags(compiler, ins->flags);
break;
}
}
static void shader_dump_register_space(struct vkd3d_d3d_asm_compiler *compiler, unsigned int register_space)
{
if (shader_ver_ge(&compiler->shader_version, 5, 1))
vkd3d_string_buffer_printf(&compiler->buffer, ", space=%u", register_space);
}
static void shader_print_opcode(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_shader_opcode opcode)
{
vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%s", compiler->colours.opcode,
shader_opcode_names[opcode], compiler->colours.reset);
}
static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_instruction *ins)
{
struct vkd3d_string_buffer *buffer = &compiler->buffer;
unsigned int i;
if (ins->predicate)
{
vkd3d_string_buffer_printf(buffer, "(");
shader_dump_src_param(compiler, ins->predicate);
vkd3d_string_buffer_printf(buffer, ") ");
}
/* PixWin marks instructions with the coissue flag with a '+' */
if (ins->coissue)
vkd3d_string_buffer_printf(buffer, "+");
shader_print_opcode(compiler, ins->handler_idx);
switch (ins->handler_idx)
{
case VKD3DSIH_DCL:
case VKD3DSIH_DCL_UAV_TYPED:
vkd3d_string_buffer_printf(buffer, "%s", compiler->colours.opcode);
shader_dump_decl_usage(compiler, &ins->declaration.semantic, ins->flags);
shader_dump_ins_modifiers(compiler, &ins->declaration.semantic.resource.reg);
vkd3d_string_buffer_printf(buffer, "%s ", compiler->colours.reset);
shader_dump_register(compiler, &ins->declaration.semantic.resource.reg.reg);
shader_dump_register_space(compiler, ins->declaration.semantic.resource.register_space);
break;
case VKD3DSIH_DCL_CONSTANT_BUFFER:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_register(compiler, &ins->declaration.cb.src.reg);
if (shader_ver_ge(&compiler->shader_version, 5, 1))
shader_print_subscript(compiler, ins->declaration.cb.size, NULL);
shader_addline(buffer, ", %s",
ins->flags & VKD3DSI_INDEXED_DYNAMIC ? "dynamicIndexed" : "immediateIndexed");
shader_dump_register_space(compiler, ins->declaration.cb.register_space);
break;
case VKD3DSIH_DCL_FUNCTION_BODY:
vkd3d_string_buffer_printf(buffer, " fb%u", ins->declaration.index);
break;
case VKD3DSIH_DCL_FUNCTION_TABLE:
vkd3d_string_buffer_printf(buffer, " ft%u = {...}", ins->declaration.index);
break;
case VKD3DSIH_DCL_GLOBAL_FLAGS:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_global_flags(compiler, ins->flags);
break;
case VKD3DSIH_DCL_HS_MAX_TESSFACTOR:
shader_print_float_literal(compiler, " ", ins->declaration.max_tessellation_factor, "");
break;
case VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER:
vkd3d_string_buffer_printf(buffer, " {\n");
for (i = 0; i < ins->declaration.icb->vec4_count; ++i)
{
shader_addline(buffer, " {0x%08x, 0x%08x, 0x%08x, 0x%08x},\n",
ins->declaration.icb->data[4 * i + 0],
ins->declaration.icb->data[4 * i + 1],
ins->declaration.icb->data[4 * i + 2],
ins->declaration.icb->data[4 * i + 3]);
}
shader_addline(buffer, "}");
break;
case VKD3DSIH_DCL_INDEX_RANGE:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.index_range.dst);
shader_addline(buffer, " %u", ins->declaration.index_range.register_count);
break;
case VKD3DSIH_DCL_INDEXABLE_TEMP:
vkd3d_string_buffer_printf(buffer, " %sx%u%s", compiler->colours.reg,
ins->declaration.indexable_temp.register_idx, compiler->colours.reset);
shader_print_subscript(compiler, ins->declaration.indexable_temp.register_size, NULL);
vkd3d_string_buffer_printf(buffer, ", %u", ins->declaration.indexable_temp.component_count);
break;
case VKD3DSIH_DCL_INPUT_PS:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_interpolation_mode(compiler, ins->flags);
shader_addline(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.dst);
break;
case VKD3DSIH_DCL_INPUT_PS_SGV:
case VKD3DSIH_DCL_INPUT_SGV:
case VKD3DSIH_DCL_INPUT_SIV:
case VKD3DSIH_DCL_OUTPUT_SIV:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.register_semantic.reg);
shader_addline(buffer, ", ");
shader_dump_shader_input_sysval_semantic(compiler, ins->declaration.register_semantic.sysval_semantic);
break;
case VKD3DSIH_DCL_INPUT_PS_SIV:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_interpolation_mode(compiler, ins->flags);
shader_addline(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.register_semantic.reg);
shader_addline(buffer, ", ");
shader_dump_shader_input_sysval_semantic(compiler, ins->declaration.register_semantic.sysval_semantic);
break;
case VKD3DSIH_DCL_INPUT:
case VKD3DSIH_DCL_OUTPUT:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.dst);
break;
case VKD3DSIH_DCL_INPUT_PRIMITIVE:
case VKD3DSIH_DCL_OUTPUT_TOPOLOGY:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_primitive_type(compiler, &ins->declaration.primitive_type);
break;
case VKD3DSIH_DCL_INTERFACE:
vkd3d_string_buffer_printf(buffer, " fp%u", ins->declaration.fp.index);
shader_print_subscript(compiler, ins->declaration.fp.array_size, NULL);
shader_print_subscript(compiler, ins->declaration.fp.body_count, NULL);
vkd3d_string_buffer_printf(buffer, " = {...}");
break;
case VKD3DSIH_DCL_RESOURCE_RAW:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.raw_resource.resource.reg);
shader_dump_register_space(compiler, ins->declaration.raw_resource.resource.register_space);
break;
case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.structured_resource.resource.reg);
shader_addline(buffer, ", %u", ins->declaration.structured_resource.byte_stride);
shader_dump_register_space(compiler, ins->declaration.structured_resource.resource.register_space);
break;
case VKD3DSIH_DCL_SAMPLER:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_register(compiler, &ins->declaration.sampler.src.reg);
if (ins->flags == VKD3DSI_SAMPLER_COMPARISON_MODE)
shader_addline(buffer, ", comparisonMode");
shader_dump_register_space(compiler, ins->declaration.sampler.register_space);
break;
case VKD3DSIH_DCL_TEMPS:
case VKD3DSIH_DCL_GS_INSTANCES:
case VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT:
case VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT:
case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT:
case VKD3DSIH_DCL_VERTICES_OUT:
vkd3d_string_buffer_printf(buffer, " %u", ins->declaration.count);
break;
case VKD3DSIH_DCL_TESSELLATOR_DOMAIN:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_tessellator_domain(compiler, ins->declaration.tessellator_domain);
break;
case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_tessellator_output_primitive(compiler, ins->declaration.tessellator_output_primitive);
break;
case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_tessellator_partitioning(compiler, ins->declaration.tessellator_partitioning);
break;
case VKD3DSIH_DCL_TGSM_RAW:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.tgsm_raw.reg);
shader_addline(buffer, ", %u", ins->declaration.tgsm_raw.byte_count);
break;
case VKD3DSIH_DCL_TGSM_STRUCTURED:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.tgsm_structured.reg);
shader_addline(buffer, ", %u, %u", ins->declaration.tgsm_structured.byte_stride,
ins->declaration.tgsm_structured.structure_count);
break;
case VKD3DSIH_DCL_THREAD_GROUP:
vkd3d_string_buffer_printf(buffer, " %u, %u, %u",
ins->declaration.thread_group_size.x,
ins->declaration.thread_group_size.y,
ins->declaration.thread_group_size.z);
break;
case VKD3DSIH_DCL_UAV_RAW:
shader_dump_uav_flags(compiler, ins->flags);
shader_addline(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.raw_resource.resource.reg);
shader_dump_register_space(compiler, ins->declaration.raw_resource.resource.register_space);
break;
case VKD3DSIH_DCL_UAV_STRUCTURED:
shader_dump_uav_flags(compiler, ins->flags);
shader_addline(buffer, " ");
shader_dump_dst_param(compiler, &ins->declaration.structured_resource.resource.reg);
shader_addline(buffer, ", %u", ins->declaration.structured_resource.byte_stride);
shader_dump_register_space(compiler, ins->declaration.structured_resource.resource.register_space);
break;
case VKD3DSIH_DEF:
vkd3d_string_buffer_printf(buffer, " %sc%u%s", compiler->colours.reg,
shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset),
compiler->colours.reset);
shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_float[0], "");
shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[1], "");
shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[2], "");
shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[3], "");
break;
case VKD3DSIH_DEFI:
vkd3d_string_buffer_printf(buffer, " %si%u%s", compiler->colours.reg,
ins->dst[0].reg.idx[0].offset, compiler->colours.reset);
shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], "");
shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[1], "");
shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[2], "");
shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[3], "");
break;
case VKD3DSIH_DEFB:
vkd3d_string_buffer_printf(buffer, " %sb%u%s = %s", compiler->colours.reg,
ins->dst[0].reg.idx[0].offset, compiler->colours.reset,
ins->src[0].reg.u.immconst_uint[0] ? "true" : "false");
break;
default:
shader_dump_instruction_flags(compiler, ins);
if (vkd3d_shader_instruction_has_texel_offset(ins))
{
shader_print_int_literal(compiler, "(", ins->texel_offset.u, "");
shader_print_int_literal(compiler, ",", ins->texel_offset.v, "");
shader_print_int_literal(compiler, ",", ins->texel_offset.w, ")");
}
if (ins->resource_type != VKD3D_SHADER_RESOURCE_NONE)
{
shader_addline(buffer, "(");
shader_dump_resource_type(compiler, ins->resource_type);
shader_addline(buffer, ")");
}
if (ins->resource_data_type[0] != VKD3D_DATA_FLOAT
|| ins->resource_data_type[1] != VKD3D_DATA_FLOAT
|| ins->resource_data_type[2] != VKD3D_DATA_FLOAT
|| ins->resource_data_type[3] != VKD3D_DATA_FLOAT)
shader_dump_data_type(compiler, ins->resource_data_type);
for (i = 0; i < ins->dst_count; ++i)
{
shader_dump_ins_modifiers(compiler, &ins->dst[i]);
shader_addline(buffer, !i ? " " : ", ");
shader_dump_dst_param(compiler, &ins->dst[i]);
}
/* Other source tokens */
for (i = ins->dst_count; i < (ins->dst_count + ins->src_count); ++i)
{
shader_addline(buffer, !i ? " " : ", ");
shader_dump_src_param(compiler, &ins->src[i - ins->dst_count]);
}
break;
}
shader_addline(buffer, "\n");
}
enum vkd3d_result vkd3d_dxbc_binary_to_text(void *data,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out)
{
enum vkd3d_shader_compile_option_formatting_flags formatting;
struct vkd3d_shader_version *shader_version;
struct vkd3d_d3d_asm_compiler compiler;
enum vkd3d_result result = VKD3D_OK;
struct vkd3d_string_buffer *buffer;
const DWORD *ptr;
unsigned int i;
void *code;
static const struct vkd3d_d3d_asm_colours no_colours =
{
.reset = "",
.opcode = "",
.reg = "",
};
static const struct vkd3d_d3d_asm_colours colours =
{
.reset = "\x1b[m",
.opcode = "\x1b[96;1m",
.reg = "\x1b[96m",
};
formatting = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT
| VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER;
if (compile_info)
{
for (i = 0; i < compile_info->option_count; ++i)
{
const struct vkd3d_shader_compile_option *option = &compile_info->options[i];
if (option->name == VKD3D_SHADER_COMPILE_OPTION_FORMATTING)
formatting = option->value;
}
}
if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_COLOUR)
compiler.colours = colours;
else
compiler.colours = no_colours;
buffer = &compiler.buffer;
vkd3d_string_buffer_init(buffer);
shader_version = &compiler.shader_version;
shader_sm4_read_header(data, &ptr, shader_version);
vkd3d_string_buffer_printf(buffer, "%s%s_%u_%u\n", compiler.colours.reset,
shader_get_type_prefix(shader_version->type), shader_version->major, shader_version->minor);
while (!shader_sm4_is_end(data, &ptr))
{
struct vkd3d_shader_instruction ins;
shader_sm4_read_instruction(data, &ptr, &ins);
if (ins.handler_idx == VKD3DSIH_INVALID)
{
WARN("Skipping unrecognized instruction.\n");
vkd3d_string_buffer_printf(buffer, "<unrecognized instruction>\n");
result = VKD3D_ERROR;
continue;
}
shader_dump_instruction(&compiler, &ins);
}
if ((code = vkd3d_malloc(buffer->content_size)))
{
memcpy(code, buffer->buffer, buffer->content_size);
out->size = buffer->content_size;
out->code = code;
}
else
{
result = VKD3D_ERROR_OUT_OF_MEMORY;
}
vkd3d_string_buffer_cleanup(buffer);
return result;
}
void vkd3d_shader_trace(void *data)
{
const char *p, *q, *end;
struct vkd3d_shader_code code;
if (vkd3d_dxbc_binary_to_text(data, NULL, &code) != VKD3D_OK)
return;
end = (const char *)code.code + code.size;
for (p = code.code; p < end; p = q)
{
if (!(q = memchr(p, '\n', end - p)))
q = end;
else
++q;
TRACE(" %.*s", (int)(q - p), p);
}
vkd3d_shader_free_shader_code(&code);
}