/******************************************************************************
 * The MIT License (MIT)
 * 
 * Copyright (c) 2014 Crytek
 * 
 * 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 shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/


#pragma once 

#include <string>
#include <vector>
using std::vector;
using std::string;

#include <stdint.h>

namespace DXBC
{

/////////////////////////////////////////////////////////////////////////
// Enums for use below. If you're reading this you might want to skip to
// the main structures after this section.
/////////////////////////////////////////////////////////////////////////

enum ProgramType
{
    TYPE_PIXEL = 0,
    TYPE_VERTEX,
    TYPE_GEOMETRY,
    TYPE_HULL,
    TYPE_DOMAIN,
    TYPE_COMPUTE,

	NUM_TYPES,
};

enum OpcodeType
{
    OPCODE_ADD = 0,
    OPCODE_AND,
    OPCODE_BREAK,
    OPCODE_BREAKC,
    OPCODE_CALL,
    OPCODE_CALLC,
    OPCODE_CASE,
    OPCODE_CONTINUE,
    OPCODE_CONTINUEC,
    OPCODE_CUT,
    OPCODE_DEFAULT,
    OPCODE_DERIV_RTX,
    OPCODE_DERIV_RTY,
    OPCODE_DISCARD,
    OPCODE_DIV,
    OPCODE_DP2,
    OPCODE_DP3,
    OPCODE_DP4,
    OPCODE_ELSE,
    OPCODE_EMIT,
    OPCODE_EMITTHENCUT,
    OPCODE_ENDIF,
    OPCODE_ENDLOOP,
    OPCODE_ENDSWITCH,
    OPCODE_EQ,
    OPCODE_EXP,
    OPCODE_FRC,
    OPCODE_FTOI,
    OPCODE_FTOU,
    OPCODE_GE,
    OPCODE_IADD,
    OPCODE_IF,
    OPCODE_IEQ,
    OPCODE_IGE,
    OPCODE_ILT,
    OPCODE_IMAD,
    OPCODE_IMAX,
    OPCODE_IMIN,
    OPCODE_IMUL,
    OPCODE_INE,
    OPCODE_INEG,
    OPCODE_ISHL,
    OPCODE_ISHR,
    OPCODE_ITOF,
    OPCODE_LABEL,
    OPCODE_LD,
    OPCODE_LD_MS,
    OPCODE_LOG,
    OPCODE_LOOP,
    OPCODE_LT,
    OPCODE_MAD,
    OPCODE_MIN,
    OPCODE_MAX,
    OPCODE_CUSTOMDATA,
    OPCODE_MOV,
    OPCODE_MOVC,
    OPCODE_MUL,
    OPCODE_NE,
    OPCODE_NOP,
    OPCODE_NOT,
    OPCODE_OR,
    OPCODE_RESINFO,
    OPCODE_RET,
    OPCODE_RETC,
    OPCODE_ROUND_NE,
    OPCODE_ROUND_NI,
    OPCODE_ROUND_PI,
    OPCODE_ROUND_Z,
    OPCODE_RSQ,
    OPCODE_SAMPLE,
    OPCODE_SAMPLE_C,
    OPCODE_SAMPLE_C_LZ,
    OPCODE_SAMPLE_L,
    OPCODE_SAMPLE_D,
    OPCODE_SAMPLE_B,
    OPCODE_SQRT,
    OPCODE_SWITCH,
    OPCODE_SINCOS,
    OPCODE_UDIV,
    OPCODE_ULT,
    OPCODE_UGE,
    OPCODE_UMUL,
    OPCODE_UMAD,
    OPCODE_UMAX,
    OPCODE_UMIN,
    OPCODE_USHR,
    OPCODE_UTOF,
    OPCODE_XOR,
    OPCODE_DCL_RESOURCE,
    OPCODE_DCL_CONSTANT_BUFFER,
    OPCODE_DCL_SAMPLER,
    OPCODE_DCL_INDEX_RANGE,
    OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY,
    OPCODE_DCL_GS_INPUT_PRIMITIVE,
    OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT,
    OPCODE_DCL_INPUT,
    OPCODE_DCL_INPUT_SGV,
    OPCODE_DCL_INPUT_SIV,
    OPCODE_DCL_INPUT_PS,
    OPCODE_DCL_INPUT_PS_SGV,
    OPCODE_DCL_INPUT_PS_SIV,
    OPCODE_DCL_OUTPUT,
    OPCODE_DCL_OUTPUT_SGV,
    OPCODE_DCL_OUTPUT_SIV,
    OPCODE_DCL_TEMPS,
    OPCODE_DCL_INDEXABLE_TEMP,
    OPCODE_DCL_GLOBAL_FLAGS,

    OPCODE_RESERVED0,

    OPCODE_LOD,
    OPCODE_GATHER4,
    OPCODE_SAMPLE_POS,
    OPCODE_SAMPLE_INFO,

    OPCODE_RESERVED1,

    OPCODE_HS_DECLS,
    OPCODE_HS_CONTROL_POINT_PHASE,
    OPCODE_HS_FORK_PHASE,
    OPCODE_HS_JOIN_PHASE,

    OPCODE_EMIT_STREAM,
    OPCODE_CUT_STREAM,
    OPCODE_EMITTHENCUT_STREAM,
    OPCODE_INTERFACE_CALL,

    OPCODE_BUFINFO,
    OPCODE_DERIV_RTX_COARSE,
    OPCODE_DERIV_RTX_FINE,
    OPCODE_DERIV_RTY_COARSE,
    OPCODE_DERIV_RTY_FINE,
    OPCODE_GATHER4_C,
    OPCODE_GATHER4_PO,
    OPCODE_GATHER4_PO_C,
    OPCODE_RCP,
    OPCODE_F32TOF16,
    OPCODE_F16TOF32,
    OPCODE_UADDC,
    OPCODE_USUBB,
    OPCODE_COUNTBITS,
    OPCODE_FIRSTBIT_HI,
    OPCODE_FIRSTBIT_LO,
    OPCODE_FIRSTBIT_SHI,
    OPCODE_UBFE,
    OPCODE_IBFE,
    OPCODE_BFI,
    OPCODE_BFREV,
    OPCODE_SWAPC,

    OPCODE_DCL_STREAM,
    OPCODE_DCL_FUNCTION_BODY,
    OPCODE_DCL_FUNCTION_TABLE,
    OPCODE_DCL_INTERFACE,

    OPCODE_DCL_INPUT_CONTROL_POINT_COUNT,
    OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT,
    OPCODE_DCL_TESS_DOMAIN,
    OPCODE_DCL_TESS_PARTITIONING,
    OPCODE_DCL_TESS_OUTPUT_PRIMITIVE,
    OPCODE_DCL_HS_MAX_TESSFACTOR,
    OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT,
    OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT,

    OPCODE_DCL_THREAD_GROUP,
    OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED,
    OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW,
    OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED,
    OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW,
    OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED,
    OPCODE_DCL_RESOURCE_RAW,
    OPCODE_DCL_RESOURCE_STRUCTURED,
    OPCODE_LD_UAV_TYPED,
    OPCODE_STORE_UAV_TYPED,
    OPCODE_LD_RAW,
    OPCODE_STORE_RAW,
    OPCODE_LD_STRUCTURED,
    OPCODE_STORE_STRUCTURED,
    OPCODE_ATOMIC_AND,
    OPCODE_ATOMIC_OR,
    OPCODE_ATOMIC_XOR,
    OPCODE_ATOMIC_CMP_STORE,
    OPCODE_ATOMIC_IADD,
    OPCODE_ATOMIC_IMAX,
    OPCODE_ATOMIC_IMIN,
    OPCODE_ATOMIC_UMAX,
    OPCODE_ATOMIC_UMIN,
    OPCODE_IMM_ATOMIC_ALLOC,
    OPCODE_IMM_ATOMIC_CONSUME,
    OPCODE_IMM_ATOMIC_IADD,
    OPCODE_IMM_ATOMIC_AND,
    OPCODE_IMM_ATOMIC_OR,
    OPCODE_IMM_ATOMIC_XOR,
    OPCODE_IMM_ATOMIC_EXCH,
    OPCODE_IMM_ATOMIC_CMP_EXCH,
    OPCODE_IMM_ATOMIC_IMAX,
    OPCODE_IMM_ATOMIC_IMIN,
    OPCODE_IMM_ATOMIC_UMAX,
    OPCODE_IMM_ATOMIC_UMIN,
    OPCODE_SYNC,

    OPCODE_DADD,
    OPCODE_DMAX,
    OPCODE_DMIN,
    OPCODE_DMUL,
    OPCODE_DEQ,
    OPCODE_DGE,
    OPCODE_DLT,
    OPCODE_DNE,
    OPCODE_DMOV,
    OPCODE_DMOVC,
    OPCODE_DTOF,
    OPCODE_FTOD,

    OPCODE_EVAL_SNAPPED,
    OPCODE_EVAL_SAMPLE_INDEX,
    OPCODE_EVAL_CENTROID,

    OPCODE_DCL_GS_INSTANCE_COUNT,
    
    OPCODE_ABORT,
    OPCODE_DEBUGBREAK,
    
    OPCODE_RESERVED2,
    
    OPCODE_DDIV,
    OPCODE_DFMA,
    OPCODE_DRCP,
    
    OPCODE_MSAD,
    
    OPCODE_DTOI,
    OPCODE_DTOU,
    OPCODE_ITOD,
    OPCODE_UTOD,
    
    OPCODE_RESERVED3,
    
    OPCODE_GATHER4_FEEDBACK,
    OPCODE_GATHER4_C_FEEDBACK,
    OPCODE_GATHER4_PO_FEEDBACK,
    OPCODE_GATHER4_PO_C_FEEDBACK,
    OPCODE_LD_FEEDBACK,
    OPCODE_LD_MS_FEEDBACK,
    OPCODE_LD_UAV_TYPED_FEEDBACK,
    OPCODE_LD_RAW_FEEDBACK,
    OPCODE_LD_STRUCTURED_FEEDBACK,
    OPCODE_SAMPLE_L_FEEDBACK,
    OPCODE_SAMPLE_C_LZ_FEEDBACK,
    
    OPCODE_SAMPLE_CLAMP_FEEDBACK,
    OPCODE_SAMPLE_B_CLAMP_FEEDBACK,
    OPCODE_SAMPLE_D_CLAMP_FEEDBACK,
    OPCODE_SAMPLE_C_CLAMP_FEEDBACK,
    
    OPCODE_CHECK_ACCESS_FULLY_MAPPED,
    
    NUM_OPCODES,
};

enum CustomDataClass
{
    CUSTOMDATA_COMMENT = 0,
    CUSTOMDATA_DEBUGINFO,
    CUSTOMDATA_OPAQUE,
    CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER,
    CUSTOMDATA_SHADER_MESSAGE,
    CUSTOMDATA_SHADER_CLIP_PLANE_CONSTANT_BUFFER_MAPPINGS,

	NUM_CUSTOMDATA_CLASSES,
};

enum ResinfoRetType
{
    RETTYPE_FLOAT = 0,
    RETTYPE_RCPFLOAT,
    RETTYPE_UINT,

	NUM_RETTYPES,
};

enum ExtendedOpcodeType
{
    EXTENDED_OPCODE_EMPTY = 0,
    EXTENDED_OPCODE_SAMPLE_CONTROLS,
    EXTENDED_OPCODE_RESOURCE_DIM,
    EXTENDED_OPCODE_RESOURCE_RETURN_TYPE,

	NUM_EXTENDED_TYPES,
};

enum NumOperandComponents
{
    NUMCOMPS_0 = 0,
    NUMCOMPS_1,
    NUMCOMPS_4,
    NUMCOMPS_N,

	MAX_COMPONENTS,
};

enum SelectionMode
{
    SELECTION_MASK = 0,
    SELECTION_SWIZZLE,
    SELECTION_SELECT_1,
};

enum OperandType
{
    TYPE_TEMP = 0,
    TYPE_INPUT,
    TYPE_OUTPUT,
    TYPE_INDEXABLE_TEMP,
    TYPE_IMMEDIATE32,
    TYPE_IMMEDIATE64,
    TYPE_SAMPLER,
    TYPE_RESOURCE,
    TYPE_CONSTANT_BUFFER,
    TYPE_IMMEDIATE_CONSTANT_BUFFER,
    TYPE_LABEL,
    TYPE_INPUT_PRIMITIVEID,
    TYPE_OUTPUT_DEPTH,
    TYPE_NULL,

    TYPE_RASTERIZER,
    TYPE_OUTPUT_COVERAGE_MASK,

    TYPE_STREAM,
    TYPE_FUNCTION_BODY,
    TYPE_FUNCTION_TABLE,
    TYPE_INTERFACE,
    TYPE_FUNCTION_INPUT,
    TYPE_FUNCTION_OUTPUT,
    TYPE_OUTPUT_CONTROL_POINT_ID,
    TYPE_INPUT_FORK_INSTANCE_ID,
    TYPE_INPUT_JOIN_INSTANCE_ID,
    TYPE_INPUT_CONTROL_POINT,
    TYPE_OUTPUT_CONTROL_POINT,
    TYPE_INPUT_PATCH_CONSTANT,
    TYPE_INPUT_DOMAIN_POINT,
    TYPE_THIS_POINTER,
    TYPE_UNORDERED_ACCESS_VIEW,
    TYPE_THREAD_GROUP_SHARED_MEMORY,
    TYPE_INPUT_THREAD_ID,
    TYPE_INPUT_THREAD_GROUP_ID,
    TYPE_INPUT_THREAD_ID_IN_GROUP,
    TYPE_INPUT_COVERAGE_MASK,
    TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED,
    TYPE_INPUT_GS_INSTANCE_ID,
    TYPE_OUTPUT_DEPTH_GREATER_EQUAL,
    TYPE_OUTPUT_DEPTH_LESS_EQUAL,
    TYPE_CYCLE_COUNTER,

	NUM_OPERAND_TYPES,
};

enum OperandIndexType
{
    INDEX_IMMEDIATE32 = 0,					// 0
    INDEX_IMMEDIATE64,						// 0
    INDEX_RELATIVE,							// [r1]
    INDEX_IMMEDIATE32_PLUS_RELATIVE,		// [r1+0]
    INDEX_IMMEDIATE64_PLUS_RELATIVE,		// [r1+0]

	NUM_INDEX_TYPES
};

enum ExtendedOperandType
{
    EXTENDED_OPERAND_EMPTY = 0,
    EXTENDED_OPERAND_MODIFIER,

	NUM_EXTENDED_OPERAND_TYPES,
};

enum OperandModifier
{
    OPERAND_MODIFIER_NONE = 0,
    OPERAND_MODIFIER_NEG,
    OPERAND_MODIFIER_ABS,
    OPERAND_MODIFIER_ABSNEG,

	NUM_MODIFIERS,
};

enum MinimumPrecision
{
	PRECISION_DEFAULT,
	PRECISION_FLOAT16,
	PRECISION_FLOAT10,
	PRECISION_SINT16,
	PRECISION_UINT16,

	NUM_PRECISIONS,
};

enum SamplerMode
{
    SAMPLER_MODE_DEFAULT = 0,
    SAMPLER_MODE_COMPARISON,
    SAMPLER_MODE_MONO,

	NUM_SAMPLERS,
};

enum CBufferAccessPattern
{
    ACCESS_IMMEDIATE_INDEXED  = 0,
    ACCESS_DYNAMIC_INDEXED,

	NUM_PATTERNS,
};

enum TessellatorDomain
{
    DOMAIN_UNDEFINED = 0,
    DOMAIN_ISOLINE,
    DOMAIN_TRI,
    DOMAIN_QUAD,

	NUM_DOMAINS,
};

enum TessellatorPartitioning
{
    PARTITIONING_UNDEFINED = 0,
    PARTITIONING_INTEGER,
    PARTITIONING_POW2,
    PARTITIONING_FRACTIONAL_ODD,
    PARTITIONING_FRACTIONAL_EVEN,

	NUM_PARTITIONINGS,
};

enum TessellatorOutputPrimitive
{
    OUTPUT_PRIMITIVE_UNDEFINED = 0,
    OUTPUT_PRIMITIVE_POINT,
    OUTPUT_PRIMITIVE_LINE,
    OUTPUT_PRIMITIVE_TRIANGLE_CW,
    OUTPUT_PRIMITIVE_TRIANGLE_CCW,

	NUM_OUTPUT_PRIMITIVES,
};

enum InterpolationMode
{
    INTERPOLATION_UNDEFINED = 0,
    INTERPOLATION_CONSTANT,
    INTERPOLATION_LINEAR,
    INTERPOLATION_LINEAR_CENTROID,
    INTERPOLATION_LINEAR_NOPERSPECTIVE,
    INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID,
    INTERPOLATION_LINEAR_SAMPLE,
    INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE,

	NUM_INTERPOLATIONS,
};

enum PrimitiveTopology
{
    TOPOLOGY_UNDEFINED = 0,
    TOPOLOGY_POINTLIST,
    TOPOLOGY_LINELIST,
    TOPOLOGY_LINESTRIP,
    TOPOLOGY_TRIANGLELIST,
    TOPOLOGY_TRIANGLESTRIP,
    TOPOLOGY_LINELIST_ADJ,
    TOPOLOGY_LINESTRIP_ADJ,
    TOPOLOGY_TRIANGLELIST_ADJ,
    TOPOLOGY_TRIANGLESTRIP_ADJ,

	NUM_TOPOLOGYS,
};

enum PrimitiveType
{
    PRIMITIVE_UNDEFINED = 0,
    PRIMITIVE_POINT,
    PRIMITIVE_LINE,
    PRIMITIVE_TRIANGLE,
    PRIMITIVE_LINE_ADJ,
    PRIMITIVE_TRIANGLE_ADJ,
    PRIMITIVE_1_CONTROL_POINT_PATCH,
    PRIMITIVE_2_CONTROL_POINT_PATCH,
    PRIMITIVE_3_CONTROL_POINT_PATCH,
    PRIMITIVE_4_CONTROL_POINT_PATCH,
    PRIMITIVE_5_CONTROL_POINT_PATCH,
    PRIMITIVE_6_CONTROL_POINT_PATCH,
    PRIMITIVE_7_CONTROL_POINT_PATCH,
    PRIMITIVE_8_CONTROL_POINT_PATCH,
    PRIMITIVE_9_CONTROL_POINT_PATCH,
    PRIMITIVE_10_CONTROL_POINT_PATCH,
    PRIMITIVE_11_CONTROL_POINT_PATCH,
    PRIMITIVE_12_CONTROL_POINT_PATCH,
    PRIMITIVE_13_CONTROL_POINT_PATCH,
    PRIMITIVE_14_CONTROL_POINT_PATCH,
    PRIMITIVE_15_CONTROL_POINT_PATCH,
    PRIMITIVE_16_CONTROL_POINT_PATCH,
    PRIMITIVE_17_CONTROL_POINT_PATCH,
    PRIMITIVE_18_CONTROL_POINT_PATCH,
    PRIMITIVE_19_CONTROL_POINT_PATCH,
    PRIMITIVE_20_CONTROL_POINT_PATCH,
    PRIMITIVE_21_CONTROL_POINT_PATCH,
    PRIMITIVE_22_CONTROL_POINT_PATCH,
    PRIMITIVE_23_CONTROL_POINT_PATCH,
    PRIMITIVE_24_CONTROL_POINT_PATCH,
    PRIMITIVE_25_CONTROL_POINT_PATCH,
    PRIMITIVE_26_CONTROL_POINT_PATCH,
    PRIMITIVE_27_CONTROL_POINT_PATCH,
    PRIMITIVE_28_CONTROL_POINT_PATCH,
    PRIMITIVE_29_CONTROL_POINT_PATCH,
    PRIMITIVE_30_CONTROL_POINT_PATCH,
    PRIMITIVE_31_CONTROL_POINT_PATCH,
    PRIMITIVE_32_CONTROL_POINT_PATCH,

	NUM_PRIMITIVES,
};

enum SemanticName
{
    SEMANTIC_UNDEFINED = 0,
    SEMANTIC_POSITION,
    SEMANTIC_CLIP_DISTANCE,
    SEMANTIC_CULL_DISTANCE,
    SEMANTIC_RENDER_TARGET_ARRAY_INDEX,
    SEMANTIC_VIEWPORT_ARRAY_INDEX,
    SEMANTIC_VERTEX_ID,
    SEMANTIC_PRIMITIVE_ID,
    SEMANTIC_INSTANCE_ID,
    SEMANTIC_IS_FRONT_FACE,
    SEMANTIC_SAMPLE_INDEX,
    SEMANTIC_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR,
    SEMANTIC_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR,
    SEMANTIC_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR,
    SEMANTIC_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR,
    SEMANTIC_FINAL_QUAD_U_INSIDE_TESSFACTOR,
    SEMANTIC_FINAL_QUAD_V_INSIDE_TESSFACTOR,
    SEMANTIC_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR,
    SEMANTIC_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR,
    SEMANTIC_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR,
    SEMANTIC_FINAL_TRI_INSIDE_TESSFACTOR,
    SEMANTIC_FINAL_LINE_DETAIL_TESSFACTOR,
    SEMANTIC_FINAL_LINE_DENSITY_TESSFACTOR,

	NUM_SEMANTICS,
};

enum ResourceDimension
{
    RESOURCE_DIMENSION_UNKNOWN = 0,
    RESOURCE_DIMENSION_BUFFER,
    RESOURCE_DIMENSION_TEXTURE1D,
    RESOURCE_DIMENSION_TEXTURE2D,
    RESOURCE_DIMENSION_TEXTURE2DMS,
    RESOURCE_DIMENSION_TEXTURE3D,
    RESOURCE_DIMENSION_TEXTURECUBE,
    RESOURCE_DIMENSION_TEXTURE1DARRAY,
    RESOURCE_DIMENSION_TEXTURE2DARRAY,
    RESOURCE_DIMENSION_TEXTURE2DMSARRAY,
    RESOURCE_DIMENSION_TEXTURECUBEARRAY,
    RESOURCE_DIMENSION_RAW_BUFFER,
    RESOURCE_DIMENSION_STRUCTURED_BUFFER,

	NUM_DIMENSIONS,
};

enum ResourceRetType
{
    RETURN_TYPE_UNORM = 1,
    RETURN_TYPE_SNORM,
    RETURN_TYPE_SINT,
    RETURN_TYPE_UINT,
    RETURN_TYPE_FLOAT,
    RETURN_TYPE_MIXED,
    RETURN_TYPE_DOUBLE,
    RETURN_TYPE_CONTINUED,
    RETURN_TYPE_UNUSED,

	NUM_RETURN_TYPES,
};

enum ComponentType
{
    COMPONENT_TYPE_UNKNOWN = 0,
    COMPONENT_TYPE_UINT32,
    COMPONENT_TYPE_SINT32,
    COMPONENT_TYPE_FLOAT32,

	NUM_COMP_TYPES,
};

/////////////////////////////////////////////////////////////////////////
// Main structures
/////////////////////////////////////////////////////////////////////////

struct ASMIndex;

struct ASMOperand
{
	ASMOperand()
	{
		type = NUM_OPERAND_TYPES;
		numComponents = MAX_COMPONENTS;
		comps[0] = comps[1] = comps[2] = comps[3] = 0xff;
		values[0] = values[1] = values[2] = values[3] = 0;
		modifier = OPERAND_MODIFIER_NONE;
		precision = PRECISION_DEFAULT;
	}

	bool operator ==(const ASMOperand &o) const;

	string toString(bool swizzle = true) const;

	///////////////////////////////////////

	OperandType type;							// temp register, constant buffer, input, output, other more specialised types
	NumOperandComponents numComponents;			// scalar, 4-vector or N-vector (currently unused)

	uint8_t comps[4];								// the components. each is 0,1,2,3 for x,y,z,w or 0xff if unused.
												// e.g. .x    = {  0, -1, -1, -1 }
												//		.zzw  = {  2,  2,  3, -1 }
												//		.zyx  = {  2,  1,  0, -1 }
												//		.zxxw = {  2,  0,  0,  3 }
												//		.xyzw = {  0,  1,  2,  3 }
												//		.wzyx = {  3,  2,  1,  0 }

	vector<ASMIndex> indices;					// indices for this register.
												// 0 means this is a special register, specified by type alone.
												// 1 is probably most common. Indicates ASMIndex specifies the register
												// 2 is for constant buffers, array inputs etc. [0] indicates the cbuffer, [1] indicates the cbuffer member
												// 3 is rare but follows the above pattern

	uint32_t values[4];						// if this operand is immediate, the values are here

	OperandModifier modifier;					// modifier, neg, abs(), -abs() etc. Could potentially be multiple modifiers in future
	MinimumPrecision precision;

	uint32_t funcNum;								// interface this operand refers to
};

struct ASMIndex
{
	ASMIndex()
	{
		absolute = false;
		relative = false;
		index = 0;
	}

	bool operator !=(const ASMIndex &o) const
	{
		return !(*this == o);
	}

	bool operator ==(const ASMIndex &o) const
	{
		if(absolute == o.absolute && relative == o.relative)
		{
			if(absolute && !relative)
				return index == o.index;
			else if(relative && !absolute)
				return operand == o.operand;

			return index == o.index && operand == o.operand;
		}

		return false;
	}

	string str;

	///////////////////////////////////////

	bool absolute;								// if true, use uint64 index below as an absolute value
	bool relative;								// if true, use the operand below.

	// note, absolute == relative == true IS VALID. It means you must add the two.
	// both cannot be false, at least one must be true.

	uint64_t index;
	ASMOperand operand;
};

struct ASMDecl
{
	ASMDecl()
	{
		offset = 0;
		length = 0;
		instruction = 0;
		declaration = NUM_OPCODES;
		refactoringAllowed = doublePrecisionFloats = forceEarlyDepthStencil = enableRawAndStructuredBuffers = false;
		stride = 0;
		hasCounter = false;
		numTemps = 0;
		count = 0;
		groupSize[0] = groupSize[1] = groupSize[2] = 0;
		resType[0] = resType[1] = resType[2] = resType[3] = NUM_RETURN_TYPES;
		dim = RESOURCE_DIMENSION_UNKNOWN;
		sampleCount = 0;
		interpolation = INTERPOLATION_UNDEFINED;
		systemValue = eAttr_None;
		maxOut = 0;
		samplerMode = NUM_SAMPLERS;
		domain = DOMAIN_UNDEFINED;
		controlPointCount = 0;
		partition = PARTITIONING_UNDEFINED;
		outPrim = OUTPUT_PRIMITIVE_UNDEFINED;
		inPrim = PRIMITIVE_UNDEFINED;
		outTopology = TOPOLOGY_UNDEFINED;
	}

	string str;

	///////////////////////////////////////

	uintptr_t offset;
	uint32_t length;

	size_t instruction;							// happens before this instruction. Usually 0 as all decls are up front,
																	// but can be non-zero for e.g. HS control point and join phase
	OpcodeType declaration;

	ASMOperand operand;							// many decls use an operand to declare things
	
	vector<uint32_t> immediateData;		// raw data (like default value of operand) for immediate constant buffer decl

	// opcode specific data

	// OPCODE_DCL_GLOBAL_FLAGS
	bool refactoringAllowed;
	bool doublePrecisionFloats;
	bool forceEarlyDepthStencil;
	bool enableRawAndStructuredBuffers;
	bool skipOptimisation;
	bool enableMinPrecision;
	bool enableD3D11_1DoubleExtensions;
	bool enableD3D11_1ShaderExtensions;

	// OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED
	uint32_t stride;
	bool hasCounter;

	// OPCODE_DCL_TEMPS, OPCODE_DCL_INDEXABLE_TEMP
	uint32_t numTemps;

	// OPCODE_DCL_INDEXABLE_TEMP
	uint32_t tempReg;
	uint32_t tempComponentCount;

	// OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED
	uint32_t count;

	// OPCODE_DCL_THREAD_GROUP
	uint32_t groupSize[3];

	// OPCODE_DCL_RESOURCE
	ResourceRetType resType[4];
	ResourceDimension dim;
	uint32_t sampleCount;

	// OPCODE_DCL_INPUT_PS
	InterpolationMode interpolation;

	// OPCODE_DCL_INPUT_SIV
	uint32_t systemValue;

	// OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT
	uint32_t maxOut;

	// OPCODE_DCL_SAMPLER
	SamplerMode samplerMode;

	// OPCODE_DCL_TESS_DOMAIN
	TessellatorDomain domain;

	// OPCODE_DCL_INPUT_CONTROL_POINT_COUNT
	uint32_t controlPointCount;

	// OPCODE_DCL_TESS_PARTITIONING
	TessellatorPartitioning partition;

	// OPCODE_DCL_TESS_OUTPUT_PRIMITIVE
	TessellatorOutputPrimitive outPrim;

	// OPCODE_DCL_GS_INPUT_PRIMITIVE
	PrimitiveType inPrim;

	// OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY
	PrimitiveTopology outTopology;

	// OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT
	// OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT
	// OPCODE_DCL_GS_INSTANCE_COUNT
	uint32_t instanceCount;

	// OPCODE_DCL_INDEX_RANGE
	uint32_t indexRange;

	// OPCODE_DCL_HS_MAX_TESSFACTOR
	float maxTessFactor;

	// OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED
	bool globallyCoherant;

	// OPCODE_DCL_FUNCTION_BODY
	uint32_t functionBody;

	// OPCODE_DCL_FUNCTION_TABLE
	uint32_t functionTable;

	// OPCODE_DCL_INTERFACE
	uint32_t interfaceID;
	uint32_t numInterfaces;
	uint32_t numTypes;
};

struct ASMOperation
{
	ASMOperation()
	{
		offset = 0;
		length = 0;
		stride = 0;
		operation = NUM_OPCODES;
		nonzero = false;
		saturate = false;
		preciseValues = 0;
		resinfoRetType = NUM_RETTYPES;
		syncFlags = 0;
		texelOffset[0] = texelOffset[1] = texelOffset[2] = 0;
		resDim = RESOURCE_DIMENSION_UNKNOWN;
		resType[0] = resType[1] = resType[2] = resType[3] = RETURN_TYPE_UNUSED;
	}

	string str;

	///////////////////////////////////////

	uintptr_t offset;
	uint32_t length;

	OpcodeType operation;
	bool nonzero;						// for if, etc. If it checks for zero or nonzero
	bool saturate;						// should the result be saturated.
	uint32_t preciseValues;				// for multiple output operand operations
	ResinfoRetType resinfoRetType;		// return type of resinfo
	uint32_t syncFlags;					// sync flags (for compute shader sync operations)

	int texelOffset[3];					// U,V,W texel offset
	ResourceDimension resDim;			// resource dimension (tex2d etc)
	ResourceRetType resType[4];			// return type (e.g. for a sample operation)
	uint32_t stride;

	vector<ASMOperand> operands;
};

}; // DXBC