diff options
author | Luca Barbieri <[email protected]> | 2010-09-12 02:49:36 +0200 |
---|---|---|
committer | Luca Barbieri <[email protected]> | 2010-09-21 10:58:17 +0200 |
commit | 92617aeac109481258f0c3863d09c1b8903d438b (patch) | |
tree | d85d6a04e87d227964386ad1d6b3d6ae6954e179 /src/gallium/state_trackers/d3d1x/d3d1xshader | |
parent | 894a307a91d6437ec418800952da2ec174e092f5 (diff) |
d3d1x: add new Direct3D 10/11 COM state tracker for Gallium
This is a new implementation of the Direct3D 11 COM API for Gallium.
Direct3D 10 and 10.1 implementations are also provided, which are
automatically generated with s/D3D11/D3D10/g plus a bunch of #ifs.
While this is an initial version, most of the code is there (limited
to what Gallium can express), and tri, gears and texturing demos
are working.
The primary goal is to realize Gallium's promise of multiple API
support, and provide an API that can be easily implemented with just
a very thin wrapper over Gallium, instead of the enormous amount of
complex code needed for OpenGL.
The secondary goal is to run Windows Direct3D 10/11 games on Linux
using Wine.
Wine dlls are currently not provided, but adding them should be
quite easy.
Fglrx and nvidia drivers can also be supported by writing a Gallium
driver that talks to them using OpenGL, which is a relatively easy
task.
Thanks to the great design of Direct3D 10/11 and closeness to Gallium,
this approach should not result in detectable overhead, and is the
most maintainable way to do it, providing a path to switch to the
open Gallium drivers once they are on par with the proprietary ones.
Currently Wine has a very limited Direct3D 10 implementation, and
completely lacks a Direct3D 11 implementation.
Note that Direct3D 10/11 are completely different from Direct3D 9
and earlier, and thus warrant a fully separate implementation.
The third goal is to provide a superior alternative to OpenGL for
graphics programming on non-Windows systems, particularly Linux
and other free and open systems.
Thanks to a very clean and well-though design done from scratch,
the Direct3D 10/11 APIs are vastly better than OpenGL and can be
supported with orders of magnitude less code and development time,
as you can see by comparing the lines of code of this commit and
those in the existing Mesa OpenGL implementation.
This would have been true for the Longs Peak proposal as well, but
unfortunately it was abandoned by Khronos, leaving the OpenGL
ecosystem without a graphics API with a modern design.
A binding of Direct3D 10/11 to EGL would solve this issue in the
most economical way possible, and this would be great to provide
in Mesa, since DXGI, the API used to bind Direct3D 10/11 to Windows,
is a bit suboptimal, especially on non-Windows platforms.
Finally, a mature Direct3D 10/11 implementation is intrinsically going
to be faster and more reliable than an OpenGL implementation, thanks
to the dramatically smaller API and the segregation of all nontrivial
work to object creation that the application must perform ahead of
time.
Currently, this commit contains:
- Independently created headers for Direct3D 10, 10.1, 11 and DXGI 1.1,
partially based on the existing Wine headers for D3D10 and DXGI 1.0
- A parser for Direct3D 10/11 DXBC and TokenizedProgramFormat (TPF)
- A shader translator from TokenizedProgramFormat to TGSI
- Implementation of the Direct3D 11 core interfaces
- Automatically generated implementation of Direct3D 10 and 10.1
- Implementation of DXGI using the "native" framework of the EGL st
- Demos, usable either on Windows or on this implementation
- d3d11tri, a clone of tri
- d3d11tex, a (multi)texturing demo
- d3d11gears, an improved version of glxgears
- d3d11spikysphere, a D3D11 tessellation demo (currently Windows-only)
- A downloader for the Microsoft HLSL compiler, needed to recompile
the shaders (compiled shader bytecode is also included)
To compile this, configure at least with these options:
--with-state-trackers=egl,d3d1x --with-egl-platforms=x11
plus some gallium drivers (such as softpipe with --enable-gallium-swrast)
The Wine headers (usually from a wine-dev or wine-devel package) must
be installed.
Only x86-32 has been tested.
You may need to run "make" in the subdirectories of src/gallium/winsys/sw
and you may need to manually run "sudo make install" in
src/gallium/targets/egl
To test it, run the demos in the "progs" directory.
Windows binaries are included to find out how demos should work, and to
test Wine integration when it will be done.
Enjoy, and let me know if you manage to compile and run this, or
which issues you are facing if not.
Using softpipe is recommended for now, and your mileage with hardware
drivers may vary.
However, getting this to work on hardware drivers is also obviously very
important.
Note that currently llvmpipe is buggy and causes all 3 gears to be
drawn with the same color.
Use export GALLIUM_DRIVER=softpipe to avoid this.
Thanks to all the Gallium contributors and especially the VMware
team, whose work made it possible to implement Direct3D 10/11 much
more easily than it would have been otherwise.
Diffstat (limited to 'src/gallium/state_trackers/d3d1x/d3d1xshader')
12 files changed, 2434 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/Makefile b/src/gallium/state_trackers/d3d1x/d3d1xshader/Makefile new file mode 100644 index 00000000000..6ac74d1895f --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/Makefile @@ -0,0 +1,7 @@ +LIBNAME=d3d1xshader +CPP_SOURCES=$(wildcard src/*.cpp) +LIBRARY_INCLUDES=-Iinclude -I../w32api -I../d3dapi +PROGS=tools/fxdis +LIBS=libd3d1xshader.a + +include ../Makefile.inc diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/include/dxbc.h b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/dxbc.h new file mode 100644 index 00000000000..44fce810795 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/dxbc.h @@ -0,0 +1,101 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 DXBC_H_ +#define DXBC_H_ + +#include <stdint.h> +#include <vector> +#include <map> +#include <iostream> +#include "le32.h" + +#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )) +#define FOURCC_DXBC FOURCC('D', 'X', 'B', 'C') +#define FOURCC_RDEF FOURCC('R', 'D', 'E', 'F') +#define FOURCC_ISGN FOURCC('I', 'S', 'G', 'N') +#define FOURCC_OSGN FOURCC('O', 'S', 'G', 'N') +#define FOURCC_SHDR FOURCC('S', 'H', 'D', 'R') +#define FOURCC_SHEX FOURCC('S', 'H', 'E', 'X') +#define FOURCC_STAT FOURCC('S', 'T', 'A', 'T') + +/* this is always little-endian! */ +struct dxbc_chunk_header +{ + unsigned fourcc; + unsigned size; +}; + +/* this is always little-endian! */ +struct dxbc_chunk_signature : public dxbc_chunk_header +{ + uint32_t count; + uint32_t unk; + struct + { + uint32_t name_offset; + uint32_t semantic_index; + uint32_t system_value_type; + uint32_t component_type; + uint32_t register_num; + uint8_t mask; + uint8_t read_write_mask; + uint8_t stream; /* TODO: guess! */ + uint8_t unused; + } elements[]; +}; + +struct dxbc_container +{ + const void* data; + std::vector<dxbc_chunk_header*> chunks; + std::map<unsigned, unsigned> chunk_map; +}; + +dxbc_container* dxbc_parse(const void* data, int size); +std::ostream& operator <<(std::ostream& out, const dxbc_container& container); + +dxbc_chunk_header* dxbc_find_chunk(const void* data, int size, unsigned fourcc); + +static inline dxbc_chunk_header* dxbc_find_shader_bytecode(const void* data, int size) +{ + dxbc_chunk_header* chunk; + chunk = dxbc_find_chunk(data, size, FOURCC_SHDR); + if(!chunk) + chunk = dxbc_find_chunk(data, size, FOURCC_SHEX); + return chunk; +} + +static inline dxbc_chunk_signature* dxbc_find_signature(const void* data, int size, bool output) +{ + return (dxbc_chunk_signature*)dxbc_find_chunk(data, size, output ? FOURCC_OSGN : FOURCC_ISGN); +} + +struct _D3D11_SIGNATURE_PARAMETER_DESC; +typedef struct _D3D11_SIGNATURE_PARAMETER_DESC D3D11_SIGNATURE_PARAMETER_DESC; +int dxbc_parse_signature(dxbc_chunk_signature* sig, D3D11_SIGNATURE_PARAMETER_DESC** params); + +#endif /* DXBC_H_ */ diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/include/le32.h b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/le32.h new file mode 100644 index 00000000000..923942a7786 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/le32.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 LE32_H_ +#define LE32_H_ + +#include <stdint.h> +#include <assert.h> + +#ifdef WORDS_BIGENDIAN +static inline uint32_t bswap_le32(uint32_t v) +{ + return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | ((v & 0xff000000) >> 24); +} +#else +static inline uint32_t bswap_le32(uint32_t v) +{ + return v; +} +#endif + +#endif /* LE32_H_ */ diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/include/tpf.h b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/tpf.h new file mode 100644 index 00000000000..2761b794d59 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/tpf.h @@ -0,0 +1,808 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 TPF_H_ +#define TPF_H_ + +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <memory> +#include <vector> +#include <map> +#include <iostream> +#include "le32.h" + +/* This is an independent implementation of definitions and tools for the + * "tokenized program format" (TPF) bytecode documented in the + * d3d11TokenizedProgramFormat.hpp header in the Windows Driver Development kit + */ + +enum tpf_opcode { + // Shader Model 4.0 (Direct3D 10.0) + + TPF_OPCODE_ADD, + TPF_OPCODE_AND, + TPF_OPCODE_BREAK, + TPF_OPCODE_BREAKC, + TPF_OPCODE_CALL, + TPF_OPCODE_CALLC, + TPF_OPCODE_CASE, + TPF_OPCODE_CONTINUE, + TPF_OPCODE_CONTINUEC, + TPF_OPCODE_CUT, + TPF_OPCODE_DEFAULT, + TPF_OPCODE_DERIV_RTX, + TPF_OPCODE_DERIV_RTY, + TPF_OPCODE_DISCARD, + TPF_OPCODE_DIV, + TPF_OPCODE_DP2, + TPF_OPCODE_DP3, + TPF_OPCODE_DP4, + TPF_OPCODE_ELSE, + TPF_OPCODE_EMIT, + TPF_OPCODE_EMITTHENCUT, + TPF_OPCODE_ENDIF, + TPF_OPCODE_ENDLOOP, + TPF_OPCODE_ENDSWITCH, + TPF_OPCODE_EQ, + TPF_OPCODE_EXP, + TPF_OPCODE_FRC, + TPF_OPCODE_FTOI, + TPF_OPCODE_FTOU, + TPF_OPCODE_GE, + TPF_OPCODE_IADD, + TPF_OPCODE_IF, + TPF_OPCODE_IEQ, + TPF_OPCODE_IGE, + TPF_OPCODE_ILT, + TPF_OPCODE_IMAD, + TPF_OPCODE_IMAX, + TPF_OPCODE_IMIN, + TPF_OPCODE_IMUL, + TPF_OPCODE_INE, + TPF_OPCODE_INEG, + TPF_OPCODE_ISHL, + TPF_OPCODE_ISHR, + TPF_OPCODE_ITOF, + TPF_OPCODE_LABEL, + TPF_OPCODE_LD, + TPF_OPCODE_LD_MS, + TPF_OPCODE_LOG, + TPF_OPCODE_LOOP, + TPF_OPCODE_LT, + TPF_OPCODE_MAD, + TPF_OPCODE_MIN, + TPF_OPCODE_MAX, + TPF_OPCODE_CUSTOMDATA, + TPF_OPCODE_MOV, + TPF_OPCODE_MOVC, + TPF_OPCODE_MUL, + TPF_OPCODE_NE, + TPF_OPCODE_NOP, + TPF_OPCODE_NOT, + TPF_OPCODE_OR, + TPF_OPCODE_RESINFO, + TPF_OPCODE_RET, + TPF_OPCODE_RETC, + TPF_OPCODE_ROUND_NE, + TPF_OPCODE_ROUND_NI, + TPF_OPCODE_ROUND_PI, + TPF_OPCODE_ROUND_Z, + TPF_OPCODE_RSQ, + TPF_OPCODE_SAMPLE, + TPF_OPCODE_SAMPLE_C, + TPF_OPCODE_SAMPLE_C_LZ, + TPF_OPCODE_SAMPLE_L, + TPF_OPCODE_SAMPLE_D, + TPF_OPCODE_SAMPLE_B, + TPF_OPCODE_SQRT, + TPF_OPCODE_SWITCH, + TPF_OPCODE_SINCOS, + TPF_OPCODE_UDIV, + TPF_OPCODE_ULT, + TPF_OPCODE_UGE, + TPF_OPCODE_UMUL, + TPF_OPCODE_UMAD, + TPF_OPCODE_UMAX, + TPF_OPCODE_UMIN, + TPF_OPCODE_USHR, + TPF_OPCODE_UTOF, + TPF_OPCODE_XOR, + + // these have custom formats + TPF_OPCODE_DCL_RESOURCE, + TPF_OPCODE_DCL_CONSTANT_BUFFER, + TPF_OPCODE_DCL_SAMPLER, + TPF_OPCODE_DCL_INDEX_RANGE, + TPF_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY, + TPF_OPCODE_DCL_GS_INPUT_PRIMITIVE, + TPF_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT, + TPF_OPCODE_DCL_INPUT, + TPF_OPCODE_DCL_INPUT_SGV, + TPF_OPCODE_DCL_INPUT_SIV, + TPF_OPCODE_DCL_INPUT_PS, + TPF_OPCODE_DCL_INPUT_PS_SGV, + TPF_OPCODE_DCL_INPUT_PS_SIV, + TPF_OPCODE_DCL_OUTPUT, + TPF_OPCODE_DCL_OUTPUT_SGV, + TPF_OPCODE_DCL_OUTPUT_SIV, + TPF_OPCODE_DCL_TEMPS, + TPF_OPCODE_DCL_INDEXABLE_TEMP, + TPF_OPCODE_DCL_GLOBAL_FLAGS, + + TPF_OPCODE_D3D10_COUNT, // this is really a reserved opcode... + + // Shader Model 4.1 (Direct3D 10.1) + + TPF_OPCODE_LOD, + TPF_OPCODE_GATHER4, + TPF_OPCODE_SAMPLE_POS, + TPF_OPCODE_SAMPLE_INFO, + + TPF_OPCODE_D3D10_1_COUNT, // this is really a reserved opcode... + + // Shader Model 5.0 (Direct3D 11) + + // HS subshader beginning markers + TPF_OPCODE_HS_DECLS, + TPF_OPCODE_HS_CONTROL_POINT_PHASE, + TPF_OPCODE_HS_FORK_PHASE, + TPF_OPCODE_HS_JOIN_PHASE, + + TPF_OPCODE_EMIT_STREAM, + TPF_OPCODE_CUT_STREAM, + TPF_OPCODE_EMITTHENCUT_STREAM, + TPF_OPCODE_INTERFACE_CALL, + + TPF_OPCODE_BUFINFO, + TPF_OPCODE_DERIV_RTX_COARSE, + TPF_OPCODE_DERIV_RTX_FINE, + TPF_OPCODE_DERIV_RTY_COARSE, + TPF_OPCODE_DERIV_RTY_FINE, + TPF_OPCODE_GATHER4_C, + TPF_OPCODE_GATHER4_PO, + TPF_OPCODE_GATHER4_PO_C, + TPF_OPCODE_RCP, + TPF_OPCODE_F32TOF16, + TPF_OPCODE_F16TOF32, + TPF_OPCODE_UADDC, + TPF_OPCODE_USUBB, + TPF_OPCODE_COUNTBITS, + TPF_OPCODE_FIRSTBIT_HI, + TPF_OPCODE_FIRSTBIT_LO, + TPF_OPCODE_FIRSTBIT_SHI, + TPF_OPCODE_UBFE, + TPF_OPCODE_IBFE, + TPF_OPCODE_BFI, + TPF_OPCODE_BFREV, + TPF_OPCODE_SWAPC, + + // these have custom formats + TPF_OPCODE_DCL_STREAM, + TPF_OPCODE_DCL_FUNCTION_BODY, + TPF_OPCODE_DCL_FUNCTION_TABLE, + TPF_OPCODE_DCL_INTERFACE, + + // these have custom formats + TPF_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT, + TPF_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT, + TPF_OPCODE_DCL_TESS_DOMAIN, + TPF_OPCODE_DCL_TESS_PARTITIONING, + TPF_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE, + TPF_OPCODE_DCL_HS_MAX_TESSFACTOR, + TPF_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT, + TPF_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, + + // these have custom formats + TPF_OPCODE_DCL_THREAD_GROUP, + TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED, + TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW, + TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED, + TPF_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW, + TPF_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED, + TPF_OPCODE_DCL_RESOURCE_RAW, + TPF_OPCODE_DCL_RESOURCE_STRUCTURED, + + TPF_OPCODE_LD_UAV_TYPED, + TPF_OPCODE_STORE_UAV_TYPED, + TPF_OPCODE_LD_RAW, + TPF_OPCODE_STORE_RAW, + TPF_OPCODE_LD_STRUCTURED, + TPF_OPCODE_STORE_STRUCTURED, + + TPF_OPCODE_ATOMIC_AND, + TPF_OPCODE_ATOMIC_OR, + TPF_OPCODE_ATOMIC_XOR, + TPF_OPCODE_ATOMIC_CMP_STORE, + TPF_OPCODE_ATOMIC_IADD, + TPF_OPCODE_ATOMIC_IMAX, + TPF_OPCODE_ATOMIC_IMIN, + TPF_OPCODE_ATOMIC_UMAX, + TPF_OPCODE_ATOMIC_UMIN, + + TPF_OPCODE_IMM_ATOMIC_ALLOC, + TPF_OPCODE_IMM_ATOMIC_CONSUME, + TPF_OPCODE_IMM_ATOMIC_IADD, + TPF_OPCODE_IMM_ATOMIC_AND, + TPF_OPCODE_IMM_ATOMIC_OR, + TPF_OPCODE_IMM_ATOMIC_XOR, + TPF_OPCODE_IMM_ATOMIC_EXCH, + TPF_OPCODE_IMM_ATOMIC_CMP_EXCH, + TPF_OPCODE_IMM_ATOMIC_IMAX, + TPF_OPCODE_IMM_ATOMIC_IMIN, + TPF_OPCODE_IMM_ATOMIC_UMAX, + TPF_OPCODE_IMM_ATOMIC_UMIN, + + TPF_OPCODE_SYNC, + + TPF_OPCODE_DADD, + TPF_OPCODE_DMAX, + TPF_OPCODE_DMIN, + TPF_OPCODE_DMUL, + TPF_OPCODE_DEQ, + TPF_OPCODE_DGE, + TPF_OPCODE_DLT, + TPF_OPCODE_DNE, + TPF_OPCODE_DMOV, + TPF_OPCODE_DMOVC, + + TPF_OPCODE_DTOF, + TPF_OPCODE_FTOD, + + TPF_OPCODE_EVAL_SNAPPED, + TPF_OPCODE_EVAL_SAMPLE_INDEX, + TPF_OPCODE_EVAL_CENTROID, + + TPF_OPCODE_DCL_GS_INSTANCE_COUNT, + + TPF_OPCODE_D3D11_COUNT +}; + +extern const char* tpf_opcode_names[]; + +enum tpf_file +{ + TPF_FILE_TEMP = 0, + TPF_FILE_INPUT = 1, + TPF_FILE_OUTPUT = 2, + TPF_FILE_INDEXABLE_TEMP = 3, + TPF_FILE_IMMEDIATE32 = 4, // one 32-bit value for each component follows + TPF_FILE_IMMEDIATE64 = 5, // one 64-bit value for each component follows + TPF_FILE_SAMPLER = 6, + TPF_FILE_RESOURCE = 7, + TPF_FILE_CONSTANT_BUFFER= 8, + TPF_FILE_IMMEDIATE_CONSTANT_BUFFER= 9, + TPF_FILE_LABEL = 10, + TPF_FILE_INPUT_PRIMITIVEID = 11, + TPF_FILE_OUTPUT_DEPTH = 12, + TPF_FILE_NULL = 13, + + // Added in D3D10.1 + + TPF_FILE_RASTERIZER = 14, + TPF_FILE_OUTPUT_COVERAGE_MASK = 15, + + // Added in D3D11 + + TPF_FILE_STREAM = 16, + TPF_FILE_FUNCTION_BODY = 17, + TPF_FILE_FUNCTION_TABLE = 18, + TPF_FILE_INTERFACE = 19, + TPF_FILE_FUNCTION_INPUT = 20, + TPF_FILE_FUNCTION_OUTPUT = 21, + TPF_FILE_OUTPUT_CONTROL_POINT_ID = 22, + TPF_FILE_INPUT_FORK_INSTANCE_ID = 23, + TPF_FILE_INPUT_JOIN_INSTANCE_ID = 24, + TPF_FILE_INPUT_CONTROL_POINT = 25, + TPF_FILE_OUTPUT_CONTROL_POINT = 26, + TPF_FILE_INPUT_PATCH_CONSTANT = 27, + TPF_FILE_INPUT_DOMAIN_POINT = 28, + TPF_FILE_THIS_POINTER = 29, + TPF_FILE_UNORDERED_ACCESS_VIEW = 30, + TPF_FILE_THREAD_GROUP_SHARED_MEMORY = 31, + TPF_FILE_INPUT_THREAD_ID = 32, + TPF_FILE_INPUT_THREAD_GROUP_ID = 33, + TPF_FILE_INPUT_THREAD_ID_IN_GROUP = 34, + TPF_FILE_INPUT_COVERAGE_MASK = 35, + TPF_FILE_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, + TPF_FILE_INPUT_GS_INSTANCE_ID = 37, + TPF_FILE_OUTPUT_DEPTH_GREATER_EQUAL = 38, + TPF_FILE_OUTPUT_DEPTH_LESS_EQUAL = 39, + TPF_FILE_CYCLE_COUNTER = 40, + + TPF_FILE_COUNT = 41, +}; + +extern const char* tpf_file_names[]; +extern const char* tpf_file_ms_names[]; + +enum tpf_target +{ + TPF_TARGET_UNKNOWN = 0, + TPF_TARGET_BUFFER = 1, + TPF_TARGET_TEXTURE1D = 2, + TPF_TARGET_TEXTURE2D = 3, + TPF_TARGET_TEXTURE2DMS = 4, + TPF_TARGET_TEXTURE3D = 5, + TPF_TARGET_TEXTURECUBE = 6, + TPF_TARGET_TEXTURE1DARRAY = 7, + TPF_TARGET_TEXTURE2DARRAY = 8, + TPF_TARGET_TEXTURE2DMSARRAY = 9, + TPF_TARGET_TEXTURECUBEARRAY = 10, + + // Added in D3D11 + TPF_TARGET_RAW_BUFFER = 11, + TPF_TARGET_STRUCTURED_BUFFER = 12, +}; + +extern const char* tpf_target_names[]; + +enum tpf_interpolation +{ + TPF_INTERPOLATION_UNDEFINED = 0, + TPF_INTERPOLATION_CONSTANT = 1, + TPF_INTERPOLATION_LINEAR = 2, + TPF_INTERPOLATION_LINEAR_CENTROID = 3, + TPF_INTERPOLATION_LINEAR_NOPERSPECTIVE = 4, + TPF_INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID = 5, + + // Added in D3D10.1 + TPF_INTERPOLATION_LINEAR_SAMPLE = 6, + TPF_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE = 7, +}; + +extern const char* tpf_interpolation_names[]; + +enum tpf_sv +{ + TPF_SV_UNDEFINED, + TPF_SV_POSITION, + TPF_SV_CLIP_DISTANCE, + TPF_SV_CULL_DISTANCE, + TPF_SV_RENDER_TARGET_ARRAY_INDEX, + TPF_SV_VIEWPORT_ARRAY_INDEX, + TPF_SV_VERTEX_ID, + TPF_SV_PRIMITIVE_ID, + TPF_SV_INSTANCE_ID, + TPF_SV_IS_FRONT_FACE, + TPF_SV_SAMPLE_INDEX, + + // Added in D3D11 + TPF_SV_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR, + TPF_SV_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR, + TPF_SV_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR, + TPF_SV_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR, + TPF_SV_FINAL_QUAD_U_INSIDE_TESSFACTOR, + TPF_SV_FINAL_QUAD_V_INSIDE_TESSFACTOR, + TPF_SV_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR, + TPF_SV_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR, + TPF_SV_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR, + TPF_SV_FINAL_TRI_INSIDE_TESSFACTOR, + TPF_SV_FINAL_LINE_DETAIL_TESSFACTOR, + TPF_SV_FINAL_LINE_DENSITY_TESSFACTOR, +}; + +extern const char* tpf_sv_names[]; + +struct tpf_token_version +{ + unsigned minor : 4; + unsigned major : 4; + unsigned format : 8; + unsigned type : 16; +}; + +struct tpf_token_instruction +{ + // we don't make it an union directly because unions can't be inherited from + union + { + // length and extended are always present, but they are only here to reduce duplication + struct + { + unsigned opcode : 11; + unsigned _11_23 : 13; + unsigned length : 7; + unsigned extended : 1; + }; + struct + { + unsigned opcode : 11; + unsigned resinfo_return_type : 2; + unsigned sat : 1; + unsigned _14_17 : 4; + unsigned test_nz : 1; // bit 18 + unsigned precise_mask : 4; + unsigned _23 : 1; + unsigned length : 7; + unsigned extended : 1; + } insn; + struct + { + unsigned opcode : 11; + unsigned threads_in_group : 1; + unsigned shared_memory : 1; + unsigned uav_group : 1; + unsigned uav_global : 1; + unsigned _15_17 : 3; + } sync; + struct + { + unsigned opcode : 11; + unsigned allow_refactoring : 1; + unsigned fp64 : 1; + unsigned early_depth_stencil : 1; + unsigned enable_raw_and_structured_in_non_cs : 1; + } dcl_global_flags; + struct + { + unsigned opcode : 11; + unsigned target : 5; + unsigned nr_samples : 7; + } dcl_resource; + struct + { + unsigned opcode : 11; + unsigned shadow : 1; + unsigned mono : 1; + } dcl_sampler; + struct + { + unsigned opcode : 11; + unsigned interpolation : 5; + } dcl_input_ps; + struct + { + unsigned opcode : 11; + unsigned dynamic : 1; + } dcl_constant_buffer; + struct + { + unsigned opcode : 11; + unsigned primitive : 6; + } dcl_gs_input_primitive; + struct + { + unsigned opcode : 11; + unsigned primitive_topology : 7; + } dcl_gs_output_primitive_topology; + struct + { + unsigned opcode : 11; + unsigned control_points : 6; + } dcl_input_control_point_count; + struct + { + unsigned opcode : 11; + unsigned control_points : 6; + } dcl_output_control_point_count; + struct + { + unsigned opcode : 11; + unsigned domain : 3; /* D3D_TESSELLATOR_DOMAIN */ + } dcl_tess_domain; + struct + { + unsigned opcode : 11; + unsigned partitioning : 3; /* D3D_TESSELLATOR_PARTITIONING */ + } dcl_tess_partitioning; + struct + { + unsigned opcode : 11; + unsigned primitive : 3; /* D3D_TESSELLATOR_OUTPUT_PRIMITIVE */ + } dcl_tess_output_primitive; + }; +}; + +enum tpf_token_instruction_extended_type +{ + TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_EMPTY = 0, + TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_SAMPLE_CONTROLS = 1, + TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_DIM = 2, + TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_RETURN_TYPE = 3, +}; + +union tpf_token_instruction_extended +{ + struct + { + unsigned type : 6; + unsigned _6_30 : 25; + unsigned extended :1; + }; + struct + { + unsigned type : 6; + unsigned _6_8 : 3; + int offset_u : 4; + int offset_v : 4; + int offset_w : 4; + } sample_controls; + struct + { + unsigned type : 6; + unsigned target : 5; + } resource_target; + struct + { + unsigned type : 6; + unsigned x : 4; + unsigned y : 4; + unsigned z : 4; + unsigned w : 4; + } resource_return_type; +}; + +struct tpf_token_resource_return_type +{ + unsigned x : 4; + unsigned y : 4; + unsigned z : 4; + unsigned w : 4; +}; + +enum tpf_operand_comps +{ + TPF_OPERAND_COMPS_0 = 0, + TPF_OPERAND_COMPS_1 = 1, + TPF_OPERAND_COMPS_4 = 2, + TPF_OPERAND_COMPS_N = 3 +}; + +enum tpf_operand_mode +{ + TPF_OPERAND_MODE_MASK = 0, + TPF_OPERAND_MODE_SWIZZLE = 1, + TPF_OPERAND_MODE_SCALAR = 2 +}; + +enum tpf_operand_index_repr +{ + TPF_OPERAND_INDEX_REPR_IMM32 = 0, + TPF_OPERAND_INDEX_REPR_IMM64 = 1, + TPF_OPERAND_INDEX_REPR_REG = 2, + TPF_OPERAND_INDEX_REPR_REG_IMM32 = 3, + TPF_OPERAND_INDEX_REPR_REG_IMM64 = 4, +}; + +struct tpf_token_operand +{ + unsigned comps_enum : 2; /* tpf_operands_comps */ + unsigned mode : 2; /* tpf_operand_mode */ + unsigned sel : 8; + unsigned file : 8; /* tpf_file */ + unsigned num_indices : 2; + unsigned index0_repr : 3; /* tpf_operand_index_repr */ + unsigned index1_repr : 3; /* tpf_operand_index_repr */ + unsigned index2_repr : 3; /* tpf_operand_index_repr */ + unsigned extended : 1; +}; + +#define TPF_OPERAND_SEL_MASK(sel) ((sel) & 0xf) +#define TPF_OPERAND_SEL_SWZ(sel, i) (((sel) >> ((i) * 2)) & 3) +#define TPF_OPERAND_SEL_SCALAR(sel) ((sel) & 3) + +enum tpf_token_operand_extended_type +{ + TPF_TOKEN_OPERAND_EXTENDED_TYPE_EMPTY = 0, + TPF_TOKEN_OPERAND_EXTENDED_TYPE_MODIFIER = 1, +}; + +struct tpf_token_operand_extended +{ + unsigned type : 6; + unsigned neg : 1; + unsigned abs : 1; +}; + +union tpf_any +{ + double f64; + float f32; + int64_t i64; + int32_t i32; + uint64_t u64; + int64_t u32; +}; + +struct tpf_op; +struct tpf_insn; +struct tpf_dcl; +struct tpf_program; +std::ostream& operator <<(std::ostream& out, const tpf_op& op); +std::ostream& operator <<(std::ostream& out, const tpf_insn& op); +std::ostream& operator <<(std::ostream& out, const tpf_dcl& op); +std::ostream& operator <<(std::ostream& out, const tpf_program& op); + +struct tpf_op +{ + uint8_t mode; + uint8_t comps; + uint8_t mask; + uint8_t num_indices; + uint8_t swizzle[4]; + tpf_file file; + tpf_any imm_values[4]; + bool neg; + bool abs; + struct + { + int64_t disp; + std::auto_ptr<tpf_op> reg; + } indices[3]; + + bool is_index_simple(unsigned i) const + { + return !indices[i].reg.get() && indices[i].disp >= 0 && (int64_t)(int32_t)indices[i].disp == indices[i].disp; + } + + bool has_simple_index() const + { + return num_indices == 1 && is_index_simple(0); + } + + tpf_op() + { + memset(this, 0, sizeof(*this)); + } + + void dump(); + +private: + tpf_op(const tpf_op& op) + {} +}; + +/* for sample_d */ +#define TPF_MAX_OPS 6 + +struct tpf_insn : public tpf_token_instruction +{ + int8_t sample_offset[3]; + uint8_t resource_target; + uint8_t resource_return_type[4]; + + unsigned num; + unsigned num_ops; + std::auto_ptr<tpf_op> ops[TPF_MAX_OPS]; + + tpf_insn() + { + memset(this, 0, sizeof(*this)); + } + + void dump(); + +private: + tpf_insn(const tpf_insn& op) + {} +}; + +struct tpf_dcl : public tpf_token_instruction +{ + std::auto_ptr<tpf_op> op; + union + { + unsigned num; + float f32; + tpf_sv sv; + struct + { + unsigned id; + unsigned expected_function_table_length; + unsigned table_length; + unsigned array_length; + } intf; + unsigned thread_group_size[3]; + tpf_token_resource_return_type rrt; + struct + { + unsigned num; + unsigned comps; + } indexable_temp; + struct + { + unsigned stride; + unsigned count; + } structured; + }; + + void* data; + + tpf_dcl() + { + memset(this, 0, sizeof(*this)); + } + + ~tpf_dcl() + { + free(data); + } + + void dump(); + +private: + tpf_dcl(const tpf_dcl& op) + {} +}; + +struct tpf_program +{ + tpf_token_version version; + std::vector<tpf_dcl*> dcls; + std::vector<tpf_insn*> insns; + + /* for ifs, the insn number of the else or endif if there is no else + * for elses, the insn number of the endif + * for endifs, the insn number of the if + * for loops, the insn number of the endloop + * for endloops, the insn number of the loop + * for all others, -1 + */ + std::vector<int> cf_insn_linked; + + /* NOTE: sampler 0 is the unnormalized nearest sampler for LD/LD_MS, while + * sampler 1 is user-specified sampler 0 + */ + bool resource_sampler_slots_assigned; + std::vector<int> slot_to_resource; + std::vector<int> slot_to_sampler; + std::map<std::pair<int, int>, int> resource_sampler_to_slot; + std::map<int, int> resource_to_slot; + + bool labels_found; + std::vector<int> label_to_insn_num; + + tpf_program() + { + memset(&version, 0, sizeof(version)); + labels_found = false; + resource_sampler_slots_assigned = false; + } + + ~tpf_program() + { + for(std::vector<tpf_dcl*>::iterator i = dcls.begin(), e = dcls.end(); i != e; ++i) + delete *i; + for(std::vector<tpf_insn*>::iterator i = insns.begin(), e = insns.end(); i != e; ++i) + delete *i; + } + + void dump(); + +private: + tpf_program(const tpf_dcl& op) + {} +}; + +tpf_program* tpf_parse(void* tokens, int size); + +bool tpf_link_cf_insns(tpf_program& program); +bool tpf_find_labels(tpf_program& program); +bool tpf_allocate_resource_sampler_pairs(tpf_program& program); + +#endif /* TPF_H_ */ diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/dxbc_dump.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/dxbc_dump.cpp new file mode 100644 index 00000000000..a3feec74463 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/dxbc_dump.cpp @@ -0,0 +1,43 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 <memory> +#include <string.h> +#include <iomanip> +#include "dxbc.h" + +std::ostream& operator <<(std::ostream& out, const dxbc_container& container) +{ + for(unsigned i = 0; i < container.chunks.size(); ++i) + { + struct dxbc_chunk_header* chunk = container.chunks[i]; + char fourcc_str[5]; + memcpy(fourcc_str, &chunk->fourcc, 4); + fourcc_str[4] = 0; + out << "# DXBC chunk " << std::setw(2) << i << ": " << fourcc_str << " offset " << ((char*)chunk - (char*)container.data) << " size " << bswap_le32(chunk->size) << "\n"; + } + return out; +} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/dxbc_parse.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/dxbc_parse.cpp new file mode 100644 index 00000000000..6b696ae1afe --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/dxbc_parse.cpp @@ -0,0 +1,93 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 <memory> +#include "dxbc.h" +#include <d3d11shader.h> +#include <d3dcommon.h> + +struct dxbc_container_header +{ + unsigned fourcc; + uint32_t unk[5]; + uint32_t total_size; + uint32_t chunk_count; + uint32_t chunk_offsets[]; +}; + +dxbc_container* dxbc_parse(const void* data, int size) +{ + std::auto_ptr<dxbc_container> container(new dxbc_container()); + container->data = data; + dxbc_container_header* header = (dxbc_container_header*)data; + if(bswap_le32(header->fourcc) != FOURCC_DXBC) + return 0; + unsigned num_chunks = bswap_le32(header->chunk_count); + for(unsigned i = 0; i < num_chunks; ++i) + { + unsigned offset = bswap_le32(header->chunk_offsets[i]); + dxbc_chunk_header* chunk = (dxbc_chunk_header*)((char*)data + offset); + unsigned fourcc = bswap_le32(chunk->fourcc); + container->chunk_map[fourcc] = i; + container->chunks.push_back(chunk); + } + return container.release(); +} + +dxbc_chunk_header* dxbc_find_chunk(const void* data, int size, unsigned fourcc) +{ + dxbc_container_header* header = (dxbc_container_header*)data; + if(bswap_le32(header->fourcc) != FOURCC_DXBC) + return 0; + unsigned num_chunks = bswap_le32(header->chunk_count); + for(unsigned i = 0; i < num_chunks; ++i) + { + unsigned offset = bswap_le32(header->chunk_offsets[i]); + dxbc_chunk_header* chunk = (dxbc_chunk_header*)((char*)data + offset); + if(bswap_le32(chunk->fourcc) == fourcc) + return chunk; + } + return 0; +} + +int dxbc_parse_signature(dxbc_chunk_signature* sig, D3D11_SIGNATURE_PARAMETER_DESC** params) +{ + unsigned count = bswap_le32(sig->count); + *params = (D3D11_SIGNATURE_PARAMETER_DESC*)malloc(sizeof(D3D11_SIGNATURE_PARAMETER_DESC) * count); + + for (unsigned i = 0; i < count; ++i) + { + D3D11_SIGNATURE_PARAMETER_DESC& param = (*params)[i]; + param.SemanticName = (char*)&sig->count + bswap_le32(sig->elements[i].name_offset); + param.SemanticIndex = bswap_le32(sig->elements[i].semantic_index); + param.SystemValueType = (D3D_NAME)bswap_le32(sig->elements[i].system_value_type); + param.ComponentType = (D3D_REGISTER_COMPONENT_TYPE)bswap_le32(sig->elements[i].component_type); + param.Mask = sig->elements[i].mask; + param.ReadWriteMask = sig->elements[i].read_write_mask; + param.Stream = sig->elements[i].stream; + } + return count; +} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_analyze.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_analyze.cpp new file mode 100644 index 00000000000..a100ee5c3f5 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_analyze.cpp @@ -0,0 +1,186 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 <vector> +#include <set> +#include "tpf.h" + +#define check(x) do {if(!(x)) return false;} while(0) + +bool tpf_link_cf_insns(tpf_program& program) +{ + if(program.cf_insn_linked.size()) + return true; + + program.cf_insn_linked.resize(program.insns.size()); + std::vector<int> cf_insn_linked; + memset(&cf_insn_linked[0], 0xff, cf_insn_linked.size() * sizeof(int)); + std::vector<unsigned> cf_stack; + for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) + { + unsigned v; + switch(program.insns[insn_num]->opcode) + { + case TPF_OPCODE_LOOP: + cf_stack.push_back(insn_num); + break; + case TPF_OPCODE_ENDLOOP: + check(!cf_stack.empty()); + v = cf_stack.back(); + check(program.insns[v]->opcode == TPF_OPCODE_LOOP); + cf_insn_linked[v] = insn_num; + cf_insn_linked[insn_num] = v; + cf_stack.pop_back(); + break; + case TPF_OPCODE_IF: + case TPF_OPCODE_SWITCH: + cf_insn_linked[insn_num] = insn_num; // later changed + cf_stack.push_back(insn_num); + break; + case TPF_OPCODE_ELSE: + case TPF_OPCODE_CASE: + check(!cf_stack.empty()); + v = cf_stack.back(); + if(program.insns[insn_num]->opcode == TPF_OPCODE_ELSE) + check(program.insns[v]->opcode == TPF_OPCODE_IF); + else + check(program.insns[v]->opcode == TPF_OPCODE_SWITCH || program.insns[v]->opcode == TPF_OPCODE_CASE); + cf_insn_linked[insn_num] = cf_insn_linked[v]; // later changed + cf_insn_linked[v] = insn_num; + cf_stack.back() = insn_num; + break; + case TPF_OPCODE_ENDSWITCH: + case TPF_OPCODE_ENDIF: + check(!cf_stack.empty()); + v = cf_stack.back(); + if(program.insns[insn_num]->opcode == TPF_OPCODE_ENDIF) + check(program.insns[v]->opcode == TPF_OPCODE_IF || program.insns[v]->opcode == TPF_OPCODE_ELSE); + else + check(program.insns[v]->opcode == TPF_OPCODE_SWITCH || program.insns[v]->opcode == TPF_OPCODE_CASE); + cf_insn_linked[insn_num] = cf_insn_linked[v]; + cf_insn_linked[v] = insn_num; + cf_stack.pop_back(); + break; + } + } + check(cf_stack.empty()); + program.cf_insn_linked.swap(cf_insn_linked); + return true; +} + +bool tpf_find_labels(tpf_program& program) +{ + if(program.labels_found) + return true; + + std::vector<int> labels; + for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) + { + switch(program.insns[insn_num]->opcode) + { + case TPF_OPCODE_LABEL: + if(program.insns[insn_num]->num_ops > 0) + { + tpf_op& op = *program.insns[insn_num]->ops[0]; + if(op.file == TPF_FILE_LABEL && op.has_simple_index()) + { + unsigned idx = (unsigned)op.indices[0].disp; + if(idx >= labels.size()) + labels.resize(idx + 1); + labels[idx] = insn_num; + } + } + break; + } + } + program.label_to_insn_num.swap(labels); + program.labels_found = true; + return true; +} + +bool tpf_allocate_resource_sampler_pairs(tpf_program& program) +{ + if(program.resource_sampler_slots_assigned) + return true; + + std::set<std::pair<int, int> > pairs; + std::set<int> resinfos; + + for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) + { + int resource = -1; + int sampler = -2; + for(unsigned i = 0; i < program.insns[insn_num]->num_ops; ++i) + { + tpf_op* op = program.insns[insn_num]->ops[i].get(); + if(op) + { + if(op->file == TPF_FILE_RESOURCE) + { + if(!op->has_simple_index() || resource >= 0) + return false; + resource = (int)op->indices[0].disp; + } + if(op->file == TPF_FILE_SAMPLER) + { + if(!op->has_simple_index() || sampler >= 0) + return false; + sampler = (int)op->indices[0].disp; + } + } + } + + unsigned opcode = program.insns[insn_num]->opcode; + if(opcode == TPF_OPCODE_LD || opcode == TPF_OPCODE_LD_MS) + sampler = -1; + if(sampler >= -1 && resource >= 0) + pairs.insert(std::make_pair(resource, sampler)); + if(opcode == TPF_OPCODE_RESINFO) + resinfos.insert(resource); + } + + for(std::set<std::pair<int, int> >::iterator i = pairs.begin(); i != pairs.end(); ++i) + { + program.resource_sampler_to_slot[*i] = program.slot_to_resource.size(); + if(!program.resource_to_slot.count(i->first)) + { + program.resource_to_slot[i->first] = program.slot_to_resource.size(); + resinfos.erase(i->first); + } + program.slot_to_resource.push_back(i->first); + program.slot_to_sampler.push_back(i->second); + } + + for(std::set<int>::iterator i = resinfos.begin(); i != resinfos.end(); ++i) + { + program.resource_sampler_to_slot[std::make_pair(*i, -1)] = program.slot_to_resource.size(); + program.resource_to_slot[*i] = program.slot_to_resource.size(); + program.slot_to_resource.push_back(*i); + program.slot_to_sampler.push_back(-1); + } + program.resource_sampler_slots_assigned = true; + return true; +} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_dump.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_dump.cpp new file mode 100644 index 00000000000..2e6e0949a8a --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_dump.cpp @@ -0,0 +1,222 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "tpf.h" + +// TODO: we should fix this to output the same syntax as fxc, if tpf_dump_ms_syntax is set + +bool tpf_dump_ms_syntax = true; + +std::ostream& operator <<(std::ostream& out, const tpf_op& op) +{ + if(op.neg) + out << '-'; + if(op.abs) + out << '|'; + if(op.file == TPF_FILE_IMMEDIATE32) + { + out << "l("; + for(unsigned i = 0; i < op.comps; ++i) + { + if(i) + out << ", "; + out << op.imm_values[i].f32; + } + out << ")"; + } + else if(op.file == TPF_FILE_IMMEDIATE64) + { + out << "d("; + for(unsigned i = 0; i < op.comps; ++i) + { + if(i) + out << ", "; + out << op.imm_values[i].f64; + } + out << ")"; + return out; + } + else + { + bool naked = false; + if(tpf_dump_ms_syntax) + { + switch(op.file) + { + case TPF_FILE_TEMP: + case TPF_FILE_INPUT: + case TPF_FILE_OUTPUT: + case TPF_FILE_CONSTANT_BUFFER: + case TPF_FILE_INDEXABLE_TEMP: + case TPF_FILE_UNORDERED_ACCESS_VIEW: + case TPF_FILE_THREAD_GROUP_SHARED_MEMORY: + naked = true; + break; + default: + naked = false; + break; + } + } + + out << (tpf_dump_ms_syntax ? tpf_file_ms_names : tpf_file_names)[op.file]; + + if(op.indices[0].reg.get()) + naked = false; + + for(unsigned i = 0; i < op.num_indices; ++i) + { + if(!naked || i) + out << '['; + if(op.indices[i].reg.get()) + { + out << *op.indices[i].reg; + if(op.indices[i].disp) + out << '+' << op.indices[i].disp; + } + else + out << op.indices[i].disp; + if(!naked || i) + out << ']'; + } + if(op.comps) + { + switch(op.mode) + { + case TPF_OPERAND_MODE_MASK: + out << (tpf_dump_ms_syntax ? '.' : '!'); + for(unsigned i = 0; i < op.comps; ++i) + { + if(op.mask & (1 << i)) + out << "xyzw"[i]; + } + break; + case TPF_OPERAND_MODE_SWIZZLE: + out << '.'; + for(unsigned i = 0; i < op.comps; ++i) + out << "xyzw"[op.swizzle[i]]; + break; + case TPF_OPERAND_MODE_SCALAR: + out << (tpf_dump_ms_syntax ? '.' : ':'); + out << "xyzw"[op.swizzle[0]]; + break; + } + } + } + if(op.abs) + out << '|'; + return out; +} + +std::ostream& operator <<(std::ostream& out, const tpf_dcl& dcl) +{ + out << tpf_opcode_names[dcl.opcode]; + switch(dcl.opcode) + { + case TPF_OPCODE_DCL_GLOBAL_FLAGS: + if(dcl.dcl_global_flags.allow_refactoring) + out << " refactoringAllowed"; + if(dcl.dcl_global_flags.early_depth_stencil) + out << " forceEarlyDepthStencil"; + if(dcl.dcl_global_flags.fp64) + out << " enableDoublePrecisionFloatOps"; + if(dcl.dcl_global_flags.enable_raw_and_structured_in_non_cs) + out << " enableRawAndStructuredBuffers"; + break; + case TPF_OPCODE_DCL_INPUT_PS: + case TPF_OPCODE_DCL_INPUT_PS_SIV: + case TPF_OPCODE_DCL_INPUT_PS_SGV: + out << ' ' << tpf_interpolation_names[dcl.dcl_input_ps.interpolation]; + break; + case TPF_OPCODE_DCL_TEMPS: + out << ' ' << dcl.num; + break; + default: + break; + } + if(dcl.op.get()) + out << ' ' << *dcl.op; + switch(dcl.opcode) + { + case TPF_OPCODE_DCL_CONSTANT_BUFFER: + out << ", " << (dcl.dcl_constant_buffer.dynamic ? "dynamicIndexed" : "immediateIndexed"); + break; + case TPF_OPCODE_DCL_INPUT_SIV: + case TPF_OPCODE_DCL_INPUT_SGV: + case TPF_OPCODE_DCL_OUTPUT_SIV: + case TPF_OPCODE_DCL_OUTPUT_SGV: + case TPF_OPCODE_DCL_INPUT_PS_SIV: + case TPF_OPCODE_DCL_INPUT_PS_SGV: + out << ", " << tpf_sv_names[dcl.num]; + break; + } + + return out; +} + +std::ostream& operator <<(std::ostream& out, const tpf_insn& insn) +{ + out << tpf_opcode_names[insn.opcode]; + if(insn.insn.sat) + out << "_sat"; + for(unsigned i = 0; i < insn.num_ops; ++i) + { + if(i) + out << ','; + out << ' ' << *insn.ops[i]; + } + return out; +} + +std::ostream& operator <<(std::ostream& out, const tpf_program& program) +{ + out << "pvghdc"[program.version.type] << "s_" << program.version.major << "_" << program.version.minor << "\n"; + for(unsigned i = 0; i < program.dcls.size(); ++i) + out << *program.dcls[i] << "\n"; + + for(unsigned i = 0; i < program.insns.size(); ++i) + out << *program.insns[i] << "\n"; + return out; +} + +void tpf_op::dump() +{ + std::cout << *this; +} + +void tpf_insn::dump() +{ + std::cout << *this; +} + +void tpf_dcl::dump() +{ + std::cout << *this; +} + +void tpf_program::dump() +{ + std::cout << *this; +} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp new file mode 100644 index 00000000000..a4f6cc6b661 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp @@ -0,0 +1,424 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "tpf.h" +#include "utils.h" + +#if 1 +#define check(x) assert(x) +#define fail(x) assert(0 && (x)) +#else +#define check(x) do {if(!(x)) throw(#x);} while(0) +#define fail(x) throw(x) +#endif + +struct tpf_parser +{ + unsigned* tokens; + unsigned* tokens_end; + tpf_program& program; + + tpf_parser(tpf_program& program, void* p_tokens, unsigned size) + : program(program) + { + tokens = (unsigned*)p_tokens; + tokens_end = (unsigned*)((char*)p_tokens + size); + } + + /* TODO: byteswap if machine is big endian */ + uint32_t read32() + { + check(tokens < tokens_end); + return bswap_le32(*tokens++); + } + + template<typename T> + void read_token(T* tok) + { + *(unsigned*)tok = read32(); + } + + uint64_t read64() + { + unsigned a = read32(); + unsigned b = read32(); + return (uint64_t)a | ((uint64_t)b << 32); + } + + void skip(unsigned toskip) + { + tokens += toskip; + } + + void read_op(tpf_op* pop) + { + tpf_op& op = *pop; + tpf_token_operand optok; + read_token(&optok); + assert(optok.file < TPF_FILE_COUNT); + op.swizzle[0] = 0; + op.swizzle[1] = 1; + op.swizzle[2] = 2; + op.swizzle[3] = 3; + op.mask = 0xf; + switch(optok.comps_enum) + { + case TPF_OPERAND_COMPS_0: + op.comps = 0; + break; + case TPF_OPERAND_COMPS_1: + op.comps = 1; + break; + case TPF_OPERAND_COMPS_4: + op.comps = 4; + op.mode = optok.mode; + switch(optok.mode) + { + case TPF_OPERAND_MODE_MASK: + op.mask = TPF_OPERAND_SEL_MASK(optok.sel); + break; + case TPF_OPERAND_MODE_SWIZZLE: + op.swizzle[0] = TPF_OPERAND_SEL_SWZ(optok.sel, 0); + op.swizzle[1] = TPF_OPERAND_SEL_SWZ(optok.sel, 1); + op.swizzle[2] = TPF_OPERAND_SEL_SWZ(optok.sel, 2); + op.swizzle[3] = TPF_OPERAND_SEL_SWZ(optok.sel, 3); + break; + case TPF_OPERAND_MODE_SCALAR: + op.swizzle[0] = op.swizzle[1] = op.swizzle[2] = op.swizzle[3] = TPF_OPERAND_SEL_SCALAR(optok.sel); + break; + } + break; + case TPF_OPERAND_COMPS_N: + fail("Unhandled operand component type"); + } + op.file = (tpf_file)optok.file; + op.num_indices = optok.num_indices; + + if(optok.extended) + { + tpf_token_operand_extended optokext; + read_token(&optokext); + if(optokext.type == 0) + {} + else if(optokext.type == 1) + { + op.neg = optokext.neg; + op.abs= optokext.abs; + } + else + fail("Unhandled extended operand token type"); + } + + for(unsigned i = 0; i < op.num_indices; ++i) + { + unsigned repr; + if(i == 0) + repr = optok.index0_repr; + else if(i == 1) + repr = optok.index1_repr; + else if(i == 2) + repr = optok.index2_repr; + else + fail("Unhandled operand index representation"); + op.indices[0].disp = 0; + // TODO: is disp supposed to be signed here?? + switch(repr) + { + case TPF_OPERAND_INDEX_REPR_IMM32: + op.indices[i].disp = (int32_t)read32(); + break; + case TPF_OPERAND_INDEX_REPR_IMM64: + op.indices[i].disp = read64(); + break; + case TPF_OPERAND_INDEX_REPR_REG: +relative: + op.indices[i].reg.reset(new tpf_op()); + read_op(&*op.indices[0].reg); + break; + case TPF_OPERAND_INDEX_REPR_REG_IMM32: + op.indices[i].disp = (int32_t)read32(); + goto relative; + case TPF_OPERAND_INDEX_REPR_REG_IMM64: + op.indices[i].disp = read64(); + goto relative; + } + } + + if(op.file == TPF_FILE_IMMEDIATE32) + { + for(unsigned i = 0; i < op.comps; ++i) + op.imm_values[i].i32 = read32(); + } + else if(op.file == TPF_FILE_IMMEDIATE64) + { + for(unsigned i = 0; i < op.comps; ++i) + op.imm_values[i].i64 = read64(); + } + } + + void do_parse() + { + read_token(&program.version); + + unsigned lentok = read32(); + tokens_end = tokens - 2 + lentok; + + while(tokens != tokens_end) + { + tpf_token_instruction insntok; + read_token(&insntok); + unsigned* insn_end = tokens - 1 + insntok.length; + tpf_opcode opcode = (tpf_opcode)insntok.opcode; + check(opcode < TPF_OPCODE_D3D11_COUNT); + + if(opcode == TPF_OPCODE_CUSTOMDATA) + { + unsigned customlen = read32() - 2; + skip(customlen); + continue; + } + + if((opcode >= TPF_OPCODE_DCL_RESOURCE && opcode <= TPF_OPCODE_DCL_GLOBAL_FLAGS) + || (opcode >= TPF_OPCODE_DCL_STREAM && opcode <= TPF_OPCODE_DCL_RESOURCE_STRUCTURED)) + { + tpf_dcl& dcl = *new tpf_dcl; + program.dcls.push_back(&dcl); + (tpf_token_instruction&)dcl = insntok; + + tpf_token_instruction_extended exttok; + memcpy(&exttok, &insntok, sizeof(exttok)); + while(exttok.extended) + { + read_token(&exttok); + } + +#define READ_OP_ANY dcl.op.reset(new tpf_op()); read_op(&*dcl.op); +#define READ_OP(FILE) READ_OP_ANY + //check(dcl.op->file == TPF_FILE_##FILE); + + switch(opcode) + { + case TPF_OPCODE_DCL_GLOBAL_FLAGS: + break; + case TPF_OPCODE_DCL_RESOURCE: + READ_OP(RESOURCE); + read_token(&dcl.rrt); + break; + case TPF_OPCODE_DCL_SAMPLER: + READ_OP(SAMPLER); + break; + case TPF_OPCODE_DCL_INPUT: + case TPF_OPCODE_DCL_INPUT_PS: + READ_OP(INPUT); + break; + case TPF_OPCODE_DCL_INPUT_SIV: + case TPF_OPCODE_DCL_INPUT_SGV: + case TPF_OPCODE_DCL_INPUT_PS_SIV: + case TPF_OPCODE_DCL_INPUT_PS_SGV: + READ_OP(INPUT); + dcl.sv = (tpf_sv)(uint16_t)read32(); + break; + case TPF_OPCODE_DCL_OUTPUT: + READ_OP(OUTPUT); + break; + case TPF_OPCODE_DCL_OUTPUT_SIV: + case TPF_OPCODE_DCL_OUTPUT_SGV: + READ_OP(OUTPUT); + dcl.sv = (tpf_sv)(uint16_t)read32(); + break; + case TPF_OPCODE_DCL_INDEX_RANGE: + READ_OP_ANY; + check(dcl.op->file == TPF_FILE_INPUT || dcl.op->file == TPF_FILE_OUTPUT); + dcl.num = read32(); + break; + case TPF_OPCODE_DCL_TEMPS: + dcl.num = read32(); + break; + case TPF_OPCODE_DCL_INDEXABLE_TEMP: + READ_OP(INDEXABLE_TEMP); + dcl.indexable_temp.num = read32(); + dcl.indexable_temp.comps = read32(); + break; + case TPF_OPCODE_DCL_CONSTANT_BUFFER: + READ_OP(CONSTANT_BUFFER); + break; + case TPF_OPCODE_DCL_GS_INPUT_PRIMITIVE: + case TPF_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + break; + case TPF_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + dcl.num = read32(); + break; + case TPF_OPCODE_DCL_GS_INSTANCE_COUNT: + dcl.num = read32(); + break; + case TPF_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + case TPF_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + case TPF_OPCODE_DCL_TESS_DOMAIN: + case TPF_OPCODE_DCL_TESS_PARTITIONING: + case TPF_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + break; + case TPF_OPCODE_DCL_HS_MAX_TESSFACTOR: + dcl.f32 = read32(); + break; + case TPF_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + dcl.num = read32(); + break; + case TPF_OPCODE_DCL_FUNCTION_BODY: + dcl.num = read32(); + break; + case TPF_OPCODE_DCL_FUNCTION_TABLE: + dcl.num = read32(); + dcl.data = malloc(dcl.num * sizeof(uint32_t)); + for(unsigned i = 0; i < dcl.num; ++i) + ((uint32_t*)dcl.data)[i] = read32(); + break; + case TPF_OPCODE_DCL_INTERFACE: + dcl.intf.id = read32(); + dcl.intf.expected_function_table_length = read32(); + { + uint32_t v = read32(); + dcl.intf.table_length = v & 0xffff; + dcl.intf.array_length = v >> 16; + } + dcl.data = malloc(dcl.intf.table_length * sizeof(uint32_t)); + for(unsigned i = 0; i < dcl.intf.table_length; ++i) + ((uint32_t*)dcl.data)[i] = read32(); + break; + case TPF_OPCODE_DCL_THREAD_GROUP: + dcl.thread_group_size[0] = read32(); + dcl.thread_group_size[1] = read32(); + dcl.thread_group_size[2] = read32(); + break; + case TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + READ_OP(UNORDERED_ACCESS_VIEW); + read_token(&dcl.rrt); + break; + case TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + READ_OP(UNORDERED_ACCESS_VIEW); + break; + case TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + READ_OP(UNORDERED_ACCESS_VIEW); + dcl.structured.stride = read32(); + break; + case TPF_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + READ_OP(THREAD_GROUP_SHARED_MEMORY); + dcl.num = read32(); + break; + case TPF_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + READ_OP(THREAD_GROUP_SHARED_MEMORY); + dcl.structured.stride = read32(); + dcl.structured.count = read32(); + break; + case TPF_OPCODE_DCL_RESOURCE_RAW: + READ_OP(RESOURCE); + break; + case TPF_OPCODE_DCL_RESOURCE_STRUCTURED: + READ_OP(RESOURCE); + dcl.structured.stride = read32(); + break; + case TPF_OPCODE_DCL_STREAM: + /* TODO: dcl_stream is undocumented: what is it? */ + fail("Unhandled dcl_stream since it's undocumented"); + default: + fail("Unhandled declaration"); + } + + check(tokens == insn_end); + } + else + { + tpf_insn& insn = *new tpf_insn; + program.insns.push_back(&insn); + (tpf_token_instruction&)insn = insntok; + + tpf_token_instruction_extended exttok; + memcpy(&exttok, &insntok, sizeof(exttok)); + while(exttok.extended) + { + read_token(&exttok); + if(exttok.type == TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_SAMPLE_CONTROLS) + { + insn.sample_offset[0] = exttok.sample_controls.offset_u; + insn.sample_offset[1] = exttok.sample_controls.offset_v; + insn.sample_offset[2] = exttok.sample_controls.offset_w; + } + else if(exttok.type == TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_DIM) + insn.resource_target = exttok.resource_target.target; + else if(exttok.type == TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_RETURN_TYPE) + { + insn.resource_return_type[0] = exttok.resource_return_type.x; + insn.resource_return_type[1] = exttok.resource_return_type.y; + insn.resource_return_type[2] = exttok.resource_return_type.z; + insn.resource_return_type[3] = exttok.resource_return_type.w; + } + } + + switch(opcode) + { + case TPF_OPCODE_INTERFACE_CALL: + insn.num = read32(); + break; + default: + break; + } + + unsigned op_num = 0; + while(tokens != insn_end) + { + check(tokens < insn_end); + check(op_num < TPF_MAX_OPS); + insn.ops[op_num].reset(new tpf_op); + read_op(&*insn.ops[op_num]); + ++op_num; + } + insn.num_ops = op_num; + } + } + } + + const char* parse() + { + try + { + do_parse(); + return 0; + } + catch(const char* error) + { + return error; + } + } +}; + +tpf_program* tpf_parse(void* tokens, int size) +{ + tpf_program* program = new tpf_program; + tpf_parser parser(*program, tokens, size); + if(!parser.parse()) + return program; + delete program; + return 0; +} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_text.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_text.cpp new file mode 100644 index 00000000000..94192c92792 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_text.cpp @@ -0,0 +1,385 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +// generated with sed -re 's/TPF_WHATEVER_//; s/=.*//; s,//.*,,; s/,//; s/\s*//g;'|tr '[A-Z]' '[a-z]'|tr -s '\n'|sed -re 's/(.*)/\t"\1",/g' + +const char* tpf_opcode_names[] = +{ + "add", + "and", + "break", + "breakc", + "call", + "callc", + "case", + "continue", + "continuec", + "cut", + "default", + "deriv_rtx", + "deriv_rty", + "discard", + "div", + "dp2", + "dp3", + "dp4", + "else", + "emit", + "emitthencut", + "endif", + "endloop", + "endswitch", + "eq", + "exp", + "frc", + "ftoi", + "ftou", + "ge", + "iadd", + "if", + "ieq", + "ige", + "ilt", + "imad", + "imax", + "imin", + "imul", + "ine", + "ineg", + "ishl", + "ishr", + "itof", + "label", + "ld", + "ld_ms", + "log", + "loop", + "lt", + "mad", + "min", + "max", + "customdata", + "mov", + "movc", + "mul", + "ne", + "nop", + "not", + "or", + "resinfo", + "ret", + "retc", + "round_ne", + "round_ni", + "round_pi", + "round_z", + "rsq", + "sample", + "sample_c", + "sample_c_lz", + "sample_l", + "sample_d", + "sample_b", + "sqrt", + "switch", + "sincos", + "udiv", + "ult", + "uge", + "umul", + "umad", + "umax", + "umin", + "ushr", + "utof", + "xor", + "dcl_resource", + "dcl_constant_buffer", + "dcl_sampler", + "dcl_index_range", + "dcl_gs_output_primitive_topology", + "dcl_gs_input_primitive", + "dcl_max_output_vertex_count", + "dcl_input", + "dcl_input_sgv", + "dcl_input_siv", + "dcl_input_ps", + "dcl_input_ps_sgv", + "dcl_input_ps_siv", + "dcl_output", + "dcl_output_sgv", + "dcl_output_siv", + "dcl_temps", + "dcl_indexable_temp", + "dcl_global_flags", + "d3d10_count", + "lod", + "gather4", + "sample_pos", + "sample_info", + "d3d10_1_count", + "hs_decls", + "hs_control_point_phase", + "hs_fork_phase", + "hs_join_phase", + "emit_stream", + "cut_stream", + "emitthencut_stream", + "interface_call", + "bufinfo", + "deriv_rtx_coarse", + "deriv_rtx_fine", + "deriv_rty_coarse", + "deriv_rty_fine", + "gather4_c", + "gather4_po", + "gather4_po_c", + "rcp", + "f32tof16", + "f16tof32", + "uaddc", + "usubb", + "countbits", + "firstbit_hi", + "firstbit_lo", + "firstbit_shi", + "ubfe", + "ibfe", + "bfi", + "bfrev", + "swapc", + "dcl_stream", + "dcl_function_body", + "dcl_function_table", + "dcl_interface", + "dcl_input_control_point_count", + "dcl_output_control_point_count", + "dcl_tess_domain", + "dcl_tess_partitioning", + "dcl_tess_output_primitive", + "dcl_hs_max_tessfactor", + "dcl_hs_fork_phase_instance_count", + "dcl_hs_join_phase_instance_count", + "dcl_thread_group", + "dcl_unordered_access_view_typed", + "dcl_unordered_access_view_raw", + "dcl_unordered_access_view_structured", + "dcl_thread_group_shared_memory_raw", + "dcl_thread_group_shared_memory_structured", + "dcl_resource_raw", + "dcl_resource_structured", + "ld_uav_typed", + "store_uav_typed", + "ld_raw", + "store_raw", + "ld_structured", + "store_structured", + "atomic_and", + "atomic_or", + "atomic_xor", + "atomic_cmp_store", + "atomic_iadd", + "atomic_imax", + "atomic_imin", + "atomic_umax", + "atomic_umin", + "imm_atomic_alloc", + "imm_atomic_consume", + "imm_atomic_iadd", + "imm_atomic_and", + "imm_atomic_or", + "imm_atomic_xor", + "imm_atomic_exch", + "imm_atomic_cmp_exch", + "imm_atomic_imax", + "imm_atomic_imin", + "imm_atomic_umax", + "imm_atomic_umin", + "sync", + "dadd", + "dmax", + "dmin", + "dmul", + "deq", + "dge", + "dlt", + "dne", + "dmov", + "dmovc", + "dtof", + "ftod", + "eval_snapped", + "eval_sample_index", + "eval_centroid", + "dcl_gs_instance_count", + "d3d11_count", +}; + +const char* tpf_file_names[] = +{ + "temp", + "input", + "output", + "indexable_temp", + "immediate32", + "immediate64", + "sampler", + "resource", + "constant_buffer", + "immediate_constant_buffer", + "label", + "input_primitiveid", + "output_depth", + "null", + "rasterizer", + "output_coverage_mask", + "stream", + "function_body", + "function_table", + "interface", + "function_input", + "function_output", + "output_control_point_id", + "input_fork_instance_id", + "input_join_instance_id", + "input_control_point", + "output_control_point", + "input_patch_constant", + "input_domain_point", + "this_pointer", + "unordered_access_view", + "thread_group_shared_memory", + "input_thread_id", + "input_thread_group_id", + "input_thread_id_in_group", + "input_coverage_mask", + "input_thread_id_in_group_flattened", + "input_gs_instance_id", + "output_depth_greater_equal", + "output_depth_less_equal", + "cycle_counter", +}; + +const char* tpf_file_ms_names[] = +{ + "r", + "v", + "o", + "x", + "l", + "d", + "sampler", + "resource", + "cb", + "icb", + "label", + "vPrim", + "oDepth", + "null", + "rasterizer", + "oMask", + "stream", + "function_body", + "function_table", + "interface", + "function_input", + "function_output", + "vOutputControlPointID", + "vForkInstanceID", + "vJoinInstanceID", + "vicp", + "vocp", + "input_patch_constant", + "vDomain", + "this", + "u", + "g", + "vThreadID", + "vThreadGrouID", + "vThreadIDInGroup", + "vCoverage", + "vThreadIDInGroupFlattened", + "vGSInstanceID", + "oDepthGE", + "oDepthLE", + "vCycleCounter", +}; + +const char* tpf_target_names[] = +{ + "unknown", + "buffer", + "texture1d", + "texture2d", + "texture2dms", + "texture3d", + "texturecube", + "texture1darray", + "texture2darray", + "texture2dmsarray", + "texturecubearray", + "raw_buffer", + "structured_buffer", +}; + +const char* tpf_interpolation_names[] = +{ + "undefined", + "constant", + "linear", + "linear centroid", + "linear noperspective", + "linear noperspective centroid", + "linear sample", + "linear noperspective sample", +}; + +const char* tpf_sv_names[] = +{ + "undefined", + "position", + "clip_distance", + "cull_distance", + "render_target_array_index", + "viewport_array_index", + "vertex_id", + "primitive_id", + "instance_id", + "is_front_face", + "sample_index", + "final_quad_u_eq_0_edge_tessfactor", + "final_quad_v_eq_0_edge_tessfactor", + "final_quad_u_eq_1_edge_tessfactor", + "final_quad_v_eq_1_edge_tessfactor", + "final_quad_u_inside_tessfactor", + "final_quad_v_inside_tessfactor", + "final_tri_u_eq_0_edge_tessfactor", + "final_tri_v_eq_0_edge_tessfactor", + "final_tri_w_eq_0_edge_tessfactor", + "final_tri_inside_tessfactor", + "final_line_detail_tessfactor", + "final_line_density_tessfactor", +}; diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/utils.h b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/utils.h new file mode 100644 index 00000000000..6e77b51175d --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/utils.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 BYTESWAP_H_ +#define BYTESWAP_H_ + +#include <stdint.h> +#include <assert.h> + +#ifdef WORDS_BIGENDIAN +static inline uint32_t le32_to_cpu(uint32_t v) +{ + return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | ((v & 0xff000000) >> 24); +} +#else +static inline uint32_t le32_to_cpu(uint32_t v) +{ + return v; +} +#endif + +#endif /* BYTESWAP_H_ */ diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/tools/fxdis.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/tools/fxdis.cpp new file mode 100644 index 00000000000..721f95fc8ac --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/tools/fxdis.cpp @@ -0,0 +1,75 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "dxbc.h" +#include "tpf.h" +#include <iostream> +#include <fstream> + +void usage() +{ + std::cerr << "Gallium Direct3D10/11 Shader Disassembler\n"; + std::cerr << "This program is free software, released under a MIT-like license\n"; + std::cerr << "Not affiliated with or endorsed by Microsoft in any way\n"; + std::cerr << "Latest version available from http://cgit.freedesktop.org/mesa/mesa/\n"; + std::cerr << "\n"; + std::cerr << "Usage: fxdis FILE\n"; + std::cerr << std::endl; +} + +int main(int argc, char** argv) +{ + if(argc < 2) + { + usage(); + return 1; + } + + std::vector<char> data; + std::ifstream in(argv[1]); + char c; + in >> std::noskipws; + while(in >> c) + data.push_back(c); + in.close(); + + dxbc_container* dxbc = dxbc_parse(&data[0], data.size()); + if(dxbc) + { + std::cout << *dxbc; + dxbc_chunk_header* tpf_chunk = dxbc_find_shader_bytecode(&data[0], data.size()); + if(tpf_chunk) + { + tpf_program* tpf = tpf_parse(tpf_chunk + 1, bswap_le32(tpf_chunk->size)); + if(tpf) + { + std::cout << *tpf; + delete tpf; + } + } + delete dxbc; + } +} |