Merge pull request #40 from aet/master
bring latest changes from upstream ( 1155504498e0 )
This commit is contained in:
commit
45cd5126a8
73
.editorconfig
Normal file
73
.editorconfig
Normal file
@ -0,0 +1,73 @@
|
||||
# see http://editorconfig.org/ for docs on this file
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
# help with sharing files across os's (i.e. network share or through local vm)
|
||||
end_of_line = lf
|
||||
#charset temporarily disabled due to bug in VS2017 changing to UTF-8 with BOM (https://favro.com/card/c564ede4ed3337f7b17986b6/Uni-17877)
|
||||
#charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
# formattable file extensions (keep in sync with format.ini from unity-meta repo)
|
||||
#
|
||||
# Note: We need to split the formattable files configs into shorter duplicate entries (logically grouped)
|
||||
# due to known issue in VS editorconfig extension where there is a limit of 51 characters (empirically determined).
|
||||
# see: https://github.com/editorconfig/editorconfig-visualstudio/issues/21
|
||||
#
|
||||
## uncrustify
|
||||
[*.{c,h,cpp,hpp,m,mm,cc,cs}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
## generic formatter (shaders)
|
||||
[*.{cg,cginc,glslinc,hlsl,shader,y,ypp,yy}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
## generic formatter (misc)
|
||||
[*.{asm,s,S,pch,pchmm,java,sh,uss}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
## perltidy
|
||||
[*.{pl,pm,t,it}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
## unity special
|
||||
[*.{bindings,mem.xml}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# other filetypes we want to overwrite default configuration to preserve the standard
|
||||
[{Makefile,makefile}]
|
||||
# TAB characters are part of the Makefile format
|
||||
indent_style = tab
|
||||
|
||||
[*.{md,markdown}]
|
||||
# trailing whitespace is significant in markdown (bad choice, bad!)
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# keep these and the VS stuff below in sync with .hgeol's CRLF extensions
|
||||
[*.{vcproj,bat,cmd,xaml,tt,t4,ttinclude}]
|
||||
end_of_line = crlf
|
||||
|
||||
# this VS-specific stuff is based on experiments to see how VS will modify a file after it has been manually edited.
|
||||
# the settings are meant to closely match what VS does to minimize unnecessary diffs. this duplicates some settings in *
|
||||
# but let's be explicit here to be safe (in case someone wants to copy-paste this out to another .editorconfig).
|
||||
[*.{vcxproj,vcxproj.filters,csproj,props,targets}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = crlf
|
||||
charset = utf-8-bom
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = false
|
||||
[*.{sln,sln.template}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
end_of_line = crlf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = false
|
@ -50,9 +50,9 @@ target_include_directories(hlslcc
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/cbstring>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/internal_includes>)
|
||||
set_target_properties(hlslcc PROPERTIES
|
||||
CXX_STANDARD 11
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
PUBLIC_HEADERS ${HLSLCC_HDRS})
|
||||
"CXX_STANDARD" "11"
|
||||
"CXX_STANDARD_REQUIRED" "ON"
|
||||
"PUBLIC_HEADERS" "${HLSLCC_HDRS}")
|
||||
install(TARGETS hlslcc
|
||||
EXPORT hlslccConfig
|
||||
ARCHIVE DESTINATION lib
|
||||
|
@ -5,7 +5,7 @@ Originally based on https://github.com/James-Jones/HLSLCrossCompiler.
|
||||
|
||||
This library takes DirectX bytecode as input, and translates it into the following languages:
|
||||
- GLSL (OpenGL 3.2 and later)
|
||||
- GLSL ES (OpenGL ES 3.0 and later)
|
||||
- GLSL ES (OpenGL ES 2.0 and later)
|
||||
- GLSL for Vulkan consumption (as input for Glslang to generate SPIR-V)
|
||||
- Metal Shading Language
|
||||
|
||||
@ -46,6 +46,8 @@ The main entry point is TranslateHLSLFromMem() function in HLSLcc.cpp (taking DX
|
||||
- Florian Penzkofer
|
||||
- Alexey Orlov
|
||||
- Povilas Kanapickas
|
||||
- Aleksandr Kirillov
|
||||
- Kay Chang
|
||||
|
||||
## License
|
||||
|
||||
|
@ -10,398 +10,401 @@
|
||||
//Reflection
|
||||
#define MAX_RESOURCE_BINDINGS 256
|
||||
|
||||
typedef enum _SHADER_VARIABLE_TYPE {
|
||||
SVT_VOID = 0,
|
||||
SVT_BOOL = 1,
|
||||
SVT_INT = 2,
|
||||
SVT_FLOAT = 3,
|
||||
SVT_STRING = 4,
|
||||
SVT_TEXTURE = 5,
|
||||
SVT_TEXTURE1D = 6,
|
||||
SVT_TEXTURE2D = 7,
|
||||
SVT_TEXTURE3D = 8,
|
||||
SVT_TEXTURECUBE = 9,
|
||||
SVT_SAMPLER = 10,
|
||||
SVT_PIXELSHADER = 15,
|
||||
SVT_VERTEXSHADER = 16,
|
||||
SVT_UINT = 19,
|
||||
SVT_UINT8 = 20,
|
||||
SVT_GEOMETRYSHADER = 21,
|
||||
SVT_RASTERIZER = 22,
|
||||
SVT_DEPTHSTENCIL = 23,
|
||||
SVT_BLEND = 24,
|
||||
SVT_BUFFER = 25,
|
||||
SVT_CBUFFER = 26,
|
||||
SVT_TBUFFER = 27,
|
||||
SVT_TEXTURE1DARRAY = 28,
|
||||
SVT_TEXTURE2DARRAY = 29,
|
||||
SVT_RENDERTARGETVIEW = 30,
|
||||
SVT_DEPTHSTENCILVIEW = 31,
|
||||
SVT_TEXTURE2DMS = 32,
|
||||
SVT_TEXTURE2DMSARRAY = 33,
|
||||
SVT_TEXTURECUBEARRAY = 34,
|
||||
SVT_HULLSHADER = 35,
|
||||
SVT_DOMAINSHADER = 36,
|
||||
SVT_INTERFACE_POINTER = 37,
|
||||
SVT_COMPUTESHADER = 38,
|
||||
SVT_DOUBLE = 39,
|
||||
SVT_RWTEXTURE1D = 40,
|
||||
SVT_RWTEXTURE1DARRAY = 41,
|
||||
SVT_RWTEXTURE2D = 42,
|
||||
SVT_RWTEXTURE2DARRAY = 43,
|
||||
SVT_RWTEXTURE3D = 44,
|
||||
SVT_RWBUFFER = 45,
|
||||
SVT_BYTEADDRESS_BUFFER = 46,
|
||||
SVT_RWBYTEADDRESS_BUFFER = 47,
|
||||
SVT_STRUCTURED_BUFFER = 48,
|
||||
SVT_RWSTRUCTURED_BUFFER = 49,
|
||||
SVT_APPEND_STRUCTURED_BUFFER = 50,
|
||||
SVT_CONSUME_STRUCTURED_BUFFER = 51,
|
||||
typedef enum _SHADER_VARIABLE_TYPE
|
||||
{
|
||||
SVT_VOID = 0,
|
||||
SVT_BOOL = 1,
|
||||
SVT_INT = 2,
|
||||
SVT_FLOAT = 3,
|
||||
SVT_STRING = 4,
|
||||
SVT_TEXTURE = 5,
|
||||
SVT_TEXTURE1D = 6,
|
||||
SVT_TEXTURE2D = 7,
|
||||
SVT_TEXTURE3D = 8,
|
||||
SVT_TEXTURECUBE = 9,
|
||||
SVT_SAMPLER = 10,
|
||||
SVT_PIXELSHADER = 15,
|
||||
SVT_VERTEXSHADER = 16,
|
||||
SVT_UINT = 19,
|
||||
SVT_UINT8 = 20,
|
||||
SVT_GEOMETRYSHADER = 21,
|
||||
SVT_RASTERIZER = 22,
|
||||
SVT_DEPTHSTENCIL = 23,
|
||||
SVT_BLEND = 24,
|
||||
SVT_BUFFER = 25,
|
||||
SVT_CBUFFER = 26,
|
||||
SVT_TBUFFER = 27,
|
||||
SVT_TEXTURE1DARRAY = 28,
|
||||
SVT_TEXTURE2DARRAY = 29,
|
||||
SVT_RENDERTARGETVIEW = 30,
|
||||
SVT_DEPTHSTENCILVIEW = 31,
|
||||
SVT_TEXTURE2DMS = 32,
|
||||
SVT_TEXTURE2DMSARRAY = 33,
|
||||
SVT_TEXTURECUBEARRAY = 34,
|
||||
SVT_HULLSHADER = 35,
|
||||
SVT_DOMAINSHADER = 36,
|
||||
SVT_INTERFACE_POINTER = 37,
|
||||
SVT_COMPUTESHADER = 38,
|
||||
SVT_DOUBLE = 39,
|
||||
SVT_RWTEXTURE1D = 40,
|
||||
SVT_RWTEXTURE1DARRAY = 41,
|
||||
SVT_RWTEXTURE2D = 42,
|
||||
SVT_RWTEXTURE2DARRAY = 43,
|
||||
SVT_RWTEXTURE3D = 44,
|
||||
SVT_RWBUFFER = 45,
|
||||
SVT_BYTEADDRESS_BUFFER = 46,
|
||||
SVT_RWBYTEADDRESS_BUFFER = 47,
|
||||
SVT_STRUCTURED_BUFFER = 48,
|
||||
SVT_RWSTRUCTURED_BUFFER = 49,
|
||||
SVT_APPEND_STRUCTURED_BUFFER = 50,
|
||||
SVT_CONSUME_STRUCTURED_BUFFER = 51,
|
||||
|
||||
|
||||
// Only used as a marker when analyzing register types
|
||||
SVT_FORCED_INT = 152,
|
||||
// Integer that can be either signed or unsigned. Only used as an intermediate step when doing data type analysis
|
||||
SVT_INT_AMBIGUOUS = 153,
|
||||
|
||||
// Only used as a marker when analyzing register types
|
||||
SVT_FORCED_INT = 152,
|
||||
// Integer that can be either signed or unsigned. Only used as an intermediate step when doing data type analysis
|
||||
SVT_INT_AMBIGUOUS = 153,
|
||||
// Partial precision types. Used when doing type analysis
|
||||
SVT_FLOAT10 = 53, // Seems to be used in constant buffers
|
||||
SVT_FLOAT16 = 54,
|
||||
SVT_INT16 = 156,
|
||||
SVT_INT12 = 157,
|
||||
SVT_UINT16 = 158,
|
||||
|
||||
// Partial precision types. Used when doing type analysis
|
||||
SVT_FLOAT10 = 53, // Seems to be used in constant buffers
|
||||
SVT_FLOAT16 = 54,
|
||||
SVT_INT16 = 156,
|
||||
SVT_INT12 = 157,
|
||||
SVT_UINT16 = 158,
|
||||
|
||||
SVT_FORCE_DWORD = 0x7fffffff
|
||||
SVT_FORCE_DWORD = 0x7fffffff
|
||||
} SHADER_VARIABLE_TYPE;
|
||||
|
||||
typedef enum _SHADER_VARIABLE_CLASS {
|
||||
SVC_SCALAR = 0,
|
||||
SVC_VECTOR = (SVC_SCALAR + 1),
|
||||
SVC_MATRIX_ROWS = (SVC_VECTOR + 1),
|
||||
SVC_MATRIX_COLUMNS = (SVC_MATRIX_ROWS + 1),
|
||||
SVC_OBJECT = (SVC_MATRIX_COLUMNS + 1),
|
||||
SVC_STRUCT = (SVC_OBJECT + 1),
|
||||
SVC_INTERFACE_CLASS = (SVC_STRUCT + 1),
|
||||
SVC_INTERFACE_POINTER = (SVC_INTERFACE_CLASS + 1),
|
||||
SVC_FORCE_DWORD = 0x7fffffff
|
||||
typedef enum _SHADER_VARIABLE_CLASS
|
||||
{
|
||||
SVC_SCALAR = 0,
|
||||
SVC_VECTOR = (SVC_SCALAR + 1),
|
||||
SVC_MATRIX_ROWS = (SVC_VECTOR + 1),
|
||||
SVC_MATRIX_COLUMNS = (SVC_MATRIX_ROWS + 1),
|
||||
SVC_OBJECT = (SVC_MATRIX_COLUMNS + 1),
|
||||
SVC_STRUCT = (SVC_OBJECT + 1),
|
||||
SVC_INTERFACE_CLASS = (SVC_STRUCT + 1),
|
||||
SVC_INTERFACE_POINTER = (SVC_INTERFACE_CLASS + 1),
|
||||
SVC_FORCE_DWORD = 0x7fffffff
|
||||
} SHADER_VARIABLE_CLASS;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Types
|
||||
|
||||
enum TESSELLATOR_PARTITIONING
|
||||
{
|
||||
TESSELLATOR_PARTITIONING_UNDEFINED = 0,
|
||||
TESSELLATOR_PARTITIONING_INTEGER = 1,
|
||||
TESSELLATOR_PARTITIONING_POW2 = 2,
|
||||
TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3,
|
||||
TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4
|
||||
TESSELLATOR_PARTITIONING_UNDEFINED = 0,
|
||||
TESSELLATOR_PARTITIONING_INTEGER = 1,
|
||||
TESSELLATOR_PARTITIONING_POW2 = 2,
|
||||
TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3,
|
||||
TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4
|
||||
};
|
||||
|
||||
enum TESSELLATOR_OUTPUT_PRIMITIVE
|
||||
{
|
||||
TESSELLATOR_OUTPUT_UNDEFINED = 0,
|
||||
TESSELLATOR_OUTPUT_POINT = 1,
|
||||
TESSELLATOR_OUTPUT_LINE = 2,
|
||||
TESSELLATOR_OUTPUT_TRIANGLE_CW = 3,
|
||||
TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4
|
||||
TESSELLATOR_OUTPUT_UNDEFINED = 0,
|
||||
TESSELLATOR_OUTPUT_POINT = 1,
|
||||
TESSELLATOR_OUTPUT_LINE = 2,
|
||||
TESSELLATOR_OUTPUT_TRIANGLE_CW = 3,
|
||||
TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4
|
||||
};
|
||||
|
||||
typedef enum TESSELLATOR_DOMAIN
|
||||
{
|
||||
TESSELLATOR_DOMAIN_UNDEFINED = 0,
|
||||
TESSELLATOR_DOMAIN_ISOLINE = 1,
|
||||
TESSELLATOR_DOMAIN_TRI = 2,
|
||||
TESSELLATOR_DOMAIN_QUAD = 3
|
||||
TESSELLATOR_DOMAIN_UNDEFINED = 0,
|
||||
TESSELLATOR_DOMAIN_ISOLINE = 1,
|
||||
TESSELLATOR_DOMAIN_TRI = 2,
|
||||
TESSELLATOR_DOMAIN_QUAD = 3
|
||||
} TESSELLATOR_DOMAIN;
|
||||
|
||||
enum SPECIAL_NAME
|
||||
{
|
||||
NAME_UNDEFINED = 0,
|
||||
NAME_POSITION = 1,
|
||||
NAME_CLIP_DISTANCE = 2,
|
||||
NAME_CULL_DISTANCE = 3,
|
||||
NAME_RENDER_TARGET_ARRAY_INDEX = 4,
|
||||
NAME_VIEWPORT_ARRAY_INDEX = 5,
|
||||
NAME_VERTEX_ID = 6,
|
||||
NAME_PRIMITIVE_ID = 7,
|
||||
NAME_INSTANCE_ID = 8,
|
||||
NAME_IS_FRONT_FACE = 9,
|
||||
NAME_SAMPLE_INDEX = 10,
|
||||
// The following are added for D3D11
|
||||
NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR = 11,
|
||||
NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR = 12,
|
||||
NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR = 13,
|
||||
NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR = 14,
|
||||
NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR = 15,
|
||||
NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR = 16,
|
||||
NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR = 17,
|
||||
NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR = 18,
|
||||
NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR = 19,
|
||||
NAME_FINAL_TRI_INSIDE_TESSFACTOR = 20,
|
||||
NAME_FINAL_LINE_DETAIL_TESSFACTOR = 21,
|
||||
NAME_FINAL_LINE_DENSITY_TESSFACTOR = 22,
|
||||
NAME_UNDEFINED = 0,
|
||||
NAME_POSITION = 1,
|
||||
NAME_CLIP_DISTANCE = 2,
|
||||
NAME_CULL_DISTANCE = 3,
|
||||
NAME_RENDER_TARGET_ARRAY_INDEX = 4,
|
||||
NAME_VIEWPORT_ARRAY_INDEX = 5,
|
||||
NAME_VERTEX_ID = 6,
|
||||
NAME_PRIMITIVE_ID = 7,
|
||||
NAME_INSTANCE_ID = 8,
|
||||
NAME_IS_FRONT_FACE = 9,
|
||||
NAME_SAMPLE_INDEX = 10,
|
||||
// The following are added for D3D11
|
||||
NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR = 11,
|
||||
NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR = 12,
|
||||
NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR = 13,
|
||||
NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR = 14,
|
||||
NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR = 15,
|
||||
NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR = 16,
|
||||
NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR = 17,
|
||||
NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR = 18,
|
||||
NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR = 19,
|
||||
NAME_FINAL_TRI_INSIDE_TESSFACTOR = 20,
|
||||
NAME_FINAL_LINE_DETAIL_TESSFACTOR = 21,
|
||||
NAME_FINAL_LINE_DENSITY_TESSFACTOR = 22,
|
||||
};
|
||||
|
||||
|
||||
enum INOUT_COMPONENT_TYPE {
|
||||
INOUT_COMPONENT_UNKNOWN = 0,
|
||||
INOUT_COMPONENT_UINT32 = 1,
|
||||
INOUT_COMPONENT_SINT32 = 2,
|
||||
INOUT_COMPONENT_FLOAT32 = 3
|
||||
enum INOUT_COMPONENT_TYPE
|
||||
{
|
||||
INOUT_COMPONENT_UNKNOWN = 0,
|
||||
INOUT_COMPONENT_UINT32 = 1,
|
||||
INOUT_COMPONENT_SINT32 = 2,
|
||||
INOUT_COMPONENT_FLOAT32 = 3
|
||||
};
|
||||
|
||||
enum MIN_PRECISION {
|
||||
MIN_PRECISION_DEFAULT = 0,
|
||||
MIN_PRECISION_FLOAT_16 = 1,
|
||||
MIN_PRECISION_FLOAT_2_8 = 2,
|
||||
MIN_PRECISION_RESERVED = 3,
|
||||
MIN_PRECISION_SINT_16 = 4,
|
||||
MIN_PRECISION_UINT_16 = 5,
|
||||
MIN_PRECISION_ANY_16 = 0xf0,
|
||||
MIN_PRECISION_ANY_10 = 0xf1
|
||||
enum MIN_PRECISION
|
||||
{
|
||||
MIN_PRECISION_DEFAULT = 0,
|
||||
MIN_PRECISION_FLOAT_16 = 1,
|
||||
MIN_PRECISION_FLOAT_2_8 = 2,
|
||||
MIN_PRECISION_RESERVED = 3,
|
||||
MIN_PRECISION_SINT_16 = 4,
|
||||
MIN_PRECISION_UINT_16 = 5,
|
||||
MIN_PRECISION_ANY_16 = 0xf0,
|
||||
MIN_PRECISION_ANY_10 = 0xf1
|
||||
};
|
||||
|
||||
enum ResourceType
|
||||
{
|
||||
RTYPE_CBUFFER,//0
|
||||
RTYPE_TBUFFER,//1
|
||||
RTYPE_TEXTURE,//2
|
||||
RTYPE_SAMPLER,//3
|
||||
RTYPE_UAV_RWTYPED,//4
|
||||
RTYPE_STRUCTURED,//5
|
||||
RTYPE_UAV_RWSTRUCTURED,//6
|
||||
RTYPE_BYTEADDRESS,//7
|
||||
RTYPE_UAV_RWBYTEADDRESS,//8
|
||||
RTYPE_UAV_APPEND_STRUCTURED,//9
|
||||
RTYPE_UAV_CONSUME_STRUCTURED,//10
|
||||
RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER,//11
|
||||
RTYPE_COUNT,
|
||||
RTYPE_CBUFFER,//0
|
||||
RTYPE_TBUFFER,//1
|
||||
RTYPE_TEXTURE,//2
|
||||
RTYPE_SAMPLER,//3
|
||||
RTYPE_UAV_RWTYPED,//4
|
||||
RTYPE_STRUCTURED,//5
|
||||
RTYPE_UAV_RWSTRUCTURED,//6
|
||||
RTYPE_BYTEADDRESS,//7
|
||||
RTYPE_UAV_RWBYTEADDRESS,//8
|
||||
RTYPE_UAV_APPEND_STRUCTURED,//9
|
||||
RTYPE_UAV_CONSUME_STRUCTURED,//10
|
||||
RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER,//11
|
||||
RTYPE_COUNT,
|
||||
};
|
||||
|
||||
enum ResourceGroup {
|
||||
RGROUP_CBUFFER,
|
||||
RGROUP_TEXTURE,
|
||||
RGROUP_SAMPLER,
|
||||
RGROUP_UAV,
|
||||
RGROUP_COUNT,
|
||||
enum ResourceGroup
|
||||
{
|
||||
RGROUP_CBUFFER,
|
||||
RGROUP_TEXTURE,
|
||||
RGROUP_SAMPLER,
|
||||
RGROUP_UAV,
|
||||
RGROUP_COUNT,
|
||||
};
|
||||
|
||||
enum REFLECT_RESOURCE_DIMENSION
|
||||
{
|
||||
REFLECT_RESOURCE_DIMENSION_UNKNOWN = 0,
|
||||
REFLECT_RESOURCE_DIMENSION_BUFFER = 1,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE1D = 2,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY = 3,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE2D = 4,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY = 5,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS = 6,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 7,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE3D = 8,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURECUBE = 9,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10,
|
||||
REFLECT_RESOURCE_DIMENSION_BUFFEREX = 11,
|
||||
REFLECT_RESOURCE_DIMENSION_UNKNOWN = 0,
|
||||
REFLECT_RESOURCE_DIMENSION_BUFFER = 1,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE1D = 2,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY = 3,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE2D = 4,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY = 5,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS = 6,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 7,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURE3D = 8,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURECUBE = 9,
|
||||
REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10,
|
||||
REFLECT_RESOURCE_DIMENSION_BUFFEREX = 11,
|
||||
};
|
||||
|
||||
enum REFLECT_RESOURCE_PRECISION
|
||||
{
|
||||
REFLECT_RESOURCE_PRECISION_UNKNOWN = 0,
|
||||
REFLECT_RESOURCE_PRECISION_LOWP = 1,
|
||||
REFLECT_RESOURCE_PRECISION_MEDIUMP = 2,
|
||||
REFLECT_RESOURCE_PRECISION_HIGHP = 3,
|
||||
|
||||
REFLECT_RESOURCE_PRECISION_UNKNOWN = 0,
|
||||
REFLECT_RESOURCE_PRECISION_LOWP = 1,
|
||||
REFLECT_RESOURCE_PRECISION_MEDIUMP = 2,
|
||||
REFLECT_RESOURCE_PRECISION_HIGHP = 3,
|
||||
};
|
||||
|
||||
enum RESOURCE_RETURN_TYPE
|
||||
{
|
||||
RETURN_TYPE_UNORM = 1,
|
||||
RETURN_TYPE_SNORM = 2,
|
||||
RETURN_TYPE_SINT = 3,
|
||||
RETURN_TYPE_UINT = 4,
|
||||
RETURN_TYPE_FLOAT = 5,
|
||||
RETURN_TYPE_MIXED = 6,
|
||||
RETURN_TYPE_DOUBLE = 7,
|
||||
RETURN_TYPE_CONTINUED = 8,
|
||||
RETURN_TYPE_UNUSED = 9,
|
||||
RETURN_TYPE_UNORM = 1,
|
||||
RETURN_TYPE_SNORM = 2,
|
||||
RETURN_TYPE_SINT = 3,
|
||||
RETURN_TYPE_UINT = 4,
|
||||
RETURN_TYPE_FLOAT = 5,
|
||||
RETURN_TYPE_MIXED = 6,
|
||||
RETURN_TYPE_DOUBLE = 7,
|
||||
RETURN_TYPE_CONTINUED = 8,
|
||||
RETURN_TYPE_UNUSED = 9,
|
||||
};
|
||||
|
||||
typedef std::map<std::string, REFLECT_RESOURCE_PRECISION> HLSLccSamplerPrecisionInfo;
|
||||
|
||||
struct ResourceBinding
|
||||
{
|
||||
std::string name;
|
||||
ResourceType eType;
|
||||
uint32_t ui32BindPoint;
|
||||
uint32_t ui32BindCount;
|
||||
uint32_t ui32Flags;
|
||||
REFLECT_RESOURCE_DIMENSION eDimension;
|
||||
RESOURCE_RETURN_TYPE ui32ReturnType;
|
||||
uint32_t ui32NumSamples;
|
||||
REFLECT_RESOURCE_PRECISION ePrecision;
|
||||
int m_SamplerMode; // (SB_SAMPLER_MODE) For samplers, this is the sampler mode this sampler is declared with
|
||||
std::string name;
|
||||
ResourceType eType;
|
||||
uint32_t ui32BindPoint;
|
||||
uint32_t ui32BindCount;
|
||||
uint32_t ui32Flags;
|
||||
uint32_t ui32Space;
|
||||
uint32_t ui32RangeID;
|
||||
REFLECT_RESOURCE_DIMENSION eDimension;
|
||||
RESOURCE_RETURN_TYPE ui32ReturnType;
|
||||
uint32_t ui32NumSamples;
|
||||
REFLECT_RESOURCE_PRECISION ePrecision;
|
||||
int m_SamplerMode; // (SB_SAMPLER_MODE) For samplers, this is the sampler mode this sampler is declared with
|
||||
|
||||
SHADER_VARIABLE_TYPE GetDataType() const
|
||||
{
|
||||
switch (ePrecision)
|
||||
{
|
||||
case REFLECT_RESOURCE_PRECISION_LOWP:
|
||||
switch (ui32ReturnType)
|
||||
{
|
||||
case RETURN_TYPE_UNORM:
|
||||
case RETURN_TYPE_SNORM:
|
||||
case RETURN_TYPE_FLOAT:
|
||||
return SVT_FLOAT10;
|
||||
case RETURN_TYPE_SINT:
|
||||
return SVT_INT16;
|
||||
case RETURN_TYPE_UINT:
|
||||
return SVT_UINT16;
|
||||
default:
|
||||
// ASSERT(0);
|
||||
return SVT_FLOAT10;
|
||||
}
|
||||
SHADER_VARIABLE_TYPE GetDataType() const
|
||||
{
|
||||
switch (ePrecision)
|
||||
{
|
||||
case REFLECT_RESOURCE_PRECISION_LOWP:
|
||||
switch (ui32ReturnType)
|
||||
{
|
||||
case RETURN_TYPE_UNORM:
|
||||
case RETURN_TYPE_SNORM:
|
||||
case RETURN_TYPE_FLOAT:
|
||||
return SVT_FLOAT10;
|
||||
case RETURN_TYPE_SINT:
|
||||
return SVT_INT16;
|
||||
case RETURN_TYPE_UINT:
|
||||
return SVT_UINT16;
|
||||
default:
|
||||
// ASSERT(0);
|
||||
return SVT_FLOAT10;
|
||||
}
|
||||
|
||||
case REFLECT_RESOURCE_PRECISION_MEDIUMP:
|
||||
switch (ui32ReturnType)
|
||||
{
|
||||
case RETURN_TYPE_UNORM:
|
||||
case RETURN_TYPE_SNORM:
|
||||
case RETURN_TYPE_FLOAT:
|
||||
return SVT_FLOAT16;
|
||||
case RETURN_TYPE_SINT:
|
||||
return SVT_INT16;
|
||||
case RETURN_TYPE_UINT:
|
||||
return SVT_UINT16;
|
||||
default:
|
||||
// ASSERT(0);
|
||||
return SVT_FLOAT16;
|
||||
}
|
||||
case REFLECT_RESOURCE_PRECISION_MEDIUMP:
|
||||
switch (ui32ReturnType)
|
||||
{
|
||||
case RETURN_TYPE_UNORM:
|
||||
case RETURN_TYPE_SNORM:
|
||||
case RETURN_TYPE_FLOAT:
|
||||
return SVT_FLOAT16;
|
||||
case RETURN_TYPE_SINT:
|
||||
return SVT_INT16;
|
||||
case RETURN_TYPE_UINT:
|
||||
return SVT_UINT16;
|
||||
default:
|
||||
// ASSERT(0);
|
||||
return SVT_FLOAT16;
|
||||
}
|
||||
|
||||
default:
|
||||
switch (ui32ReturnType)
|
||||
{
|
||||
case RETURN_TYPE_UNORM:
|
||||
case RETURN_TYPE_SNORM:
|
||||
case RETURN_TYPE_FLOAT:
|
||||
return SVT_FLOAT;
|
||||
case RETURN_TYPE_SINT:
|
||||
return SVT_INT;
|
||||
case RETURN_TYPE_UINT:
|
||||
return SVT_UINT;
|
||||
case RETURN_TYPE_DOUBLE:
|
||||
return SVT_DOUBLE;
|
||||
default:
|
||||
// ASSERT(0);
|
||||
return SVT_FLOAT;
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
switch (ui32ReturnType)
|
||||
{
|
||||
case RETURN_TYPE_UNORM:
|
||||
case RETURN_TYPE_SNORM:
|
||||
case RETURN_TYPE_FLOAT:
|
||||
return SVT_FLOAT;
|
||||
case RETURN_TYPE_SINT:
|
||||
return SVT_INT;
|
||||
case RETURN_TYPE_UINT:
|
||||
return SVT_UINT;
|
||||
case RETURN_TYPE_DOUBLE:
|
||||
return SVT_DOUBLE;
|
||||
default:
|
||||
// ASSERT(0);
|
||||
return SVT_FLOAT;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderVarType
|
||||
{
|
||||
ShaderVarType() :
|
||||
Class(),
|
||||
Type(),
|
||||
Rows(),
|
||||
Columns(),
|
||||
Elements(),
|
||||
MemberCount(),
|
||||
Offset(),
|
||||
ParentCount(),
|
||||
Parent(),
|
||||
m_IsUsed(false)
|
||||
{}
|
||||
ShaderVarType() :
|
||||
Class(),
|
||||
Type(),
|
||||
Rows(),
|
||||
Columns(),
|
||||
Elements(),
|
||||
MemberCount(),
|
||||
Offset(),
|
||||
ParentCount(),
|
||||
Parent(),
|
||||
m_IsUsed(false)
|
||||
{}
|
||||
|
||||
SHADER_VARIABLE_CLASS Class;
|
||||
SHADER_VARIABLE_TYPE Type;
|
||||
uint32_t Rows;
|
||||
uint32_t Columns;
|
||||
uint32_t Elements;
|
||||
uint32_t MemberCount;
|
||||
uint32_t Offset;
|
||||
std::string name;
|
||||
SHADER_VARIABLE_CLASS Class;
|
||||
SHADER_VARIABLE_TYPE Type;
|
||||
uint32_t Rows;
|
||||
uint32_t Columns;
|
||||
uint32_t Elements;
|
||||
uint32_t MemberCount;
|
||||
uint32_t Offset;
|
||||
std::string name;
|
||||
|
||||
uint32_t ParentCount;
|
||||
struct ShaderVarType * Parent;
|
||||
//Includes all parent names.
|
||||
std::string fullName;
|
||||
uint32_t ParentCount;
|
||||
struct ShaderVarType * Parent;
|
||||
//Includes all parent names.
|
||||
std::string fullName;
|
||||
|
||||
std::vector<struct ShaderVarType> Members;
|
||||
|
||||
bool m_IsUsed; // If not set, is not used in the shader code
|
||||
std::vector<struct ShaderVarType> Members;
|
||||
|
||||
uint32_t GetMemberCount() const
|
||||
{
|
||||
if (Class == SVC_STRUCT)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
std::vector<struct ShaderVarType>::const_iterator itr;
|
||||
for (itr = Members.begin(); itr != Members.end(); itr++)
|
||||
{
|
||||
res += itr->GetMemberCount();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
bool m_IsUsed; // If not set, is not used in the shader code
|
||||
|
||||
uint32_t GetMemberCount() const
|
||||
{
|
||||
if (Class == SVC_STRUCT)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
std::vector<struct ShaderVarType>::const_iterator itr;
|
||||
for (itr = Members.begin(); itr != Members.end(); itr++)
|
||||
{
|
||||
res += itr->GetMemberCount();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderVar
|
||||
{
|
||||
std::string name;
|
||||
int haveDefaultValue;
|
||||
std::vector<uint32_t> pui32DefaultValues;
|
||||
//Offset/Size in bytes.
|
||||
uint32_t ui32StartOffset;
|
||||
uint32_t ui32Size;
|
||||
std::string name;
|
||||
int haveDefaultValue;
|
||||
std::vector<uint32_t> pui32DefaultValues;
|
||||
//Offset/Size in bytes.
|
||||
uint32_t ui32StartOffset;
|
||||
uint32_t ui32Size;
|
||||
|
||||
ShaderVarType sType;
|
||||
ShaderVarType sType;
|
||||
};
|
||||
|
||||
struct ConstantBuffer
|
||||
{
|
||||
std::string name;
|
||||
std::string name;
|
||||
|
||||
std::vector<ShaderVar> asVars;
|
||||
std::vector<ShaderVar> asVars;
|
||||
|
||||
uint32_t ui32TotalSizeInBytes;
|
||||
uint32_t ui32TotalSizeInBytes;
|
||||
|
||||
uint32_t GetMemberCount(bool stripUnused) const
|
||||
{
|
||||
uint32_t res = 0;
|
||||
std::vector<ShaderVar>::const_iterator itr;
|
||||
for (itr = asVars.begin(); itr != asVars.end(); itr++)
|
||||
{
|
||||
if(stripUnused && !itr->sType.m_IsUsed)
|
||||
continue;
|
||||
res += itr->sType.GetMemberCount();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
uint32_t GetMemberCount(bool stripUnused) const
|
||||
{
|
||||
uint32_t res = 0;
|
||||
std::vector<ShaderVar>::const_iterator itr;
|
||||
for (itr = asVars.begin(); itr != asVars.end(); itr++)
|
||||
{
|
||||
if (stripUnused && !itr->sType.m_IsUsed)
|
||||
continue;
|
||||
res += itr->sType.GetMemberCount();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
struct ClassType
|
||||
{
|
||||
std::string name;
|
||||
uint16_t ui16ID;
|
||||
uint16_t ui16ConstBufStride;
|
||||
uint16_t ui16Texture;
|
||||
uint16_t ui16Sampler;
|
||||
std::string name;
|
||||
uint16_t ui16ID;
|
||||
uint16_t ui16ConstBufStride;
|
||||
uint16_t ui16Texture;
|
||||
uint16_t ui16Sampler;
|
||||
};
|
||||
|
||||
struct ClassInstance
|
||||
{
|
||||
std::string name;
|
||||
uint16_t ui16ID;
|
||||
uint16_t ui16ConstBuf;
|
||||
uint16_t ui16ConstBufOffset;
|
||||
uint16_t ui16Texture;
|
||||
uint16_t ui16Sampler;
|
||||
std::string name;
|
||||
uint16_t ui16ID;
|
||||
uint16_t ui16ConstBuf;
|
||||
uint16_t ui16ConstBufOffset;
|
||||
uint16_t ui16Texture;
|
||||
uint16_t ui16Sampler;
|
||||
};
|
||||
|
||||
class Operand;
|
||||
@ -410,100 +413,98 @@ class ShaderInfo
|
||||
{
|
||||
public:
|
||||
|
||||
struct InOutSignature
|
||||
{
|
||||
std::string semanticName;
|
||||
uint32_t ui32SemanticIndex;
|
||||
SPECIAL_NAME eSystemValueType;
|
||||
INOUT_COMPONENT_TYPE eComponentType;
|
||||
uint32_t ui32Register;
|
||||
uint32_t ui32Mask;
|
||||
uint32_t ui32ReadWriteMask;
|
||||
struct InOutSignature
|
||||
{
|
||||
std::string semanticName;
|
||||
uint32_t ui32SemanticIndex;
|
||||
SPECIAL_NAME eSystemValueType;
|
||||
INOUT_COMPONENT_TYPE eComponentType;
|
||||
uint32_t ui32Register;
|
||||
uint32_t ui32Mask;
|
||||
uint32_t ui32ReadWriteMask;
|
||||
|
||||
int iRebase; // If mask does not start from zero, this indicates the offset that needs to be subtracted from each swizzle
|
||||
int iRebase; // If mask does not start from zero, this indicates the offset that needs to be subtracted from each swizzle
|
||||
|
||||
uint32_t ui32Stream;
|
||||
MIN_PRECISION eMinPrec;
|
||||
uint32_t ui32Stream;
|
||||
MIN_PRECISION eMinPrec;
|
||||
|
||||
std::set<uint32_t> isIndexed; // Set of phases where this input/output is part of a index range.
|
||||
std::map<uint32_t, uint32_t> indexStart; // If indexed, contains the start index for the range
|
||||
std::map<uint32_t, uint32_t> index; // If indexed, contains the current index relative to the index start.
|
||||
std::set<uint32_t> isIndexed; // Set of phases where this input/output is part of a index range.
|
||||
std::map<uint32_t, uint32_t> indexStart; // If indexed, contains the start index for the range
|
||||
std::map<uint32_t, uint32_t> index; // If indexed, contains the current index relative to the index start.
|
||||
};
|
||||
|
||||
};
|
||||
ShaderInfo() :
|
||||
ui32MajorVersion(),
|
||||
ui32MinorVersion(),
|
||||
psResourceBindings(),
|
||||
psConstantBuffers(),
|
||||
psThisPointerConstBuffer(),
|
||||
psClassTypes(),
|
||||
psClassInstances()
|
||||
{}
|
||||
|
||||
ShaderInfo() :
|
||||
ui32MajorVersion(),
|
||||
ui32MinorVersion(),
|
||||
psResourceBindings(),
|
||||
psConstantBuffers(),
|
||||
psThisPointerConstBuffer(),
|
||||
psClassTypes(),
|
||||
psClassInstances()
|
||||
{}
|
||||
SHADER_VARIABLE_TYPE GetTextureDataType(uint32_t regNo);
|
||||
|
||||
SHADER_VARIABLE_TYPE GetTextureDataType(uint32_t regNo);
|
||||
int GetResourceFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ResourceBinding** ppsOutBinding) const;
|
||||
|
||||
int GetResourceFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ResourceBinding** ppsOutBinding) const;
|
||||
void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ConstantBuffer** ppsConstBuf) const;
|
||||
|
||||
void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ConstantBuffer** ppsConstBuf) const;
|
||||
int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderVar** ppsShaderVar) const;
|
||||
|
||||
int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderVar** ppsShaderVar) const;
|
||||
int GetInputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32Mask, const InOutSignature** ppsOut, bool allowNull = false) const;
|
||||
int GetPatchConstantSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32Mask, const InOutSignature** ppsOut, bool allowNull = false) const;
|
||||
int GetOutputSignatureFromRegister(const uint32_t ui32Register,
|
||||
const uint32_t ui32CompMask,
|
||||
const uint32_t ui32Stream,
|
||||
const InOutSignature** ppsOut,
|
||||
bool allowNull = false) const;
|
||||
|
||||
int GetInputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32Mask, const InOutSignature** ppsOut, bool allowNull = false) const;
|
||||
int GetPatchConstantSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32Mask, const InOutSignature** ppsOut, bool allowNull = false) const;
|
||||
int GetOutputSignatureFromRegister(const uint32_t ui32Register,
|
||||
const uint32_t ui32CompMask,
|
||||
const uint32_t ui32Stream,
|
||||
const InOutSignature** ppsOut,
|
||||
bool allowNull = false) const;
|
||||
int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, const InOutSignature** ppsOut) const;
|
||||
|
||||
int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, const InOutSignature** ppsOut) const;
|
||||
|
||||
static ResourceGroup ResourceTypeToResourceGroup(ResourceType);
|
||||
static ResourceGroup ResourceTypeToResourceGroup(ResourceType);
|
||||
|
||||
static uint32_t GetCBVarSize(const ShaderVarType* psType, bool matrixAsVectors, bool wholeArraySize = false);
|
||||
|
||||
static int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset,
|
||||
const uint32_t (&pui32Swizzle)[4],
|
||||
const ConstantBuffer* psCBuf,
|
||||
const ShaderVarType** ppsShaderVar,
|
||||
bool* isArray,
|
||||
std::vector<uint32_t>* arrayIndices,
|
||||
int32_t* pi32Rebase,
|
||||
uint32_t flags);
|
||||
static int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset,
|
||||
const uint32_t(&pui32Swizzle)[4],
|
||||
const ConstantBuffer* psCBuf,
|
||||
const ShaderVarType** ppsShaderVar,
|
||||
bool* isArray,
|
||||
std::vector<uint32_t>* arrayIndices,
|
||||
int32_t* pi32Rebase,
|
||||
uint32_t flags);
|
||||
|
||||
static std::string GetShaderVarIndexedFullName(const ShaderVarType* psShaderVar, const std::vector<uint32_t>& indices, const std::string& dynamicIndex, bool revertDynamicIndexCalc, bool matrixAsVectors);
|
||||
static std::string GetShaderVarIndexedFullName(const ShaderVarType* psShaderVar, const std::vector<uint32_t>& indices, const std::string& dynamicIndex, bool revertDynamicIndexCalc, bool matrixAsVectors);
|
||||
|
||||
// Apply shader precision information to resource bindings
|
||||
void AddSamplerPrecisions(HLSLccSamplerPrecisionInfo &info);
|
||||
// Apply shader precision information to resource bindings
|
||||
void AddSamplerPrecisions(HLSLccSamplerPrecisionInfo &info);
|
||||
|
||||
uint32_t ui32MajorVersion;
|
||||
uint32_t ui32MinorVersion;
|
||||
uint32_t ui32MajorVersion;
|
||||
uint32_t ui32MinorVersion;
|
||||
|
||||
std::vector<InOutSignature> psInputSignatures;
|
||||
std::vector<InOutSignature> psOutputSignatures;
|
||||
std::vector<InOutSignature> psPatchConstantSignatures;
|
||||
std::vector<InOutSignature> psInputSignatures;
|
||||
std::vector<InOutSignature> psOutputSignatures;
|
||||
std::vector<InOutSignature> psPatchConstantSignatures;
|
||||
|
||||
std::vector<ResourceBinding> psResourceBindings;
|
||||
std::vector<ResourceBinding> psResourceBindings;
|
||||
|
||||
std::vector<ConstantBuffer> psConstantBuffers;
|
||||
ConstantBuffer* psThisPointerConstBuffer;
|
||||
std::vector<ConstantBuffer> psConstantBuffers;
|
||||
ConstantBuffer* psThisPointerConstBuffer;
|
||||
|
||||
std::vector<ClassType> psClassTypes;
|
||||
std::vector<ClassInstance> psClassInstances;
|
||||
std::vector<ClassType> psClassTypes;
|
||||
std::vector<ClassInstance> psClassInstances;
|
||||
|
||||
//Func table ID to class name ID.
|
||||
HLSLcc::growing_vector<uint32_t> aui32TableIDToTypeID;
|
||||
//Func table ID to class name ID.
|
||||
HLSLcc::growing_vector<uint32_t> aui32TableIDToTypeID;
|
||||
|
||||
HLSLcc::growing_vector<uint32_t> aui32ResourceMap[RGROUP_COUNT];
|
||||
HLSLcc::growing_vector<uint32_t> aui32ResourceMap[RGROUP_COUNT];
|
||||
|
||||
HLSLcc::growing_vector<ShaderVarType> sGroupSharedVarType;
|
||||
HLSLcc::growing_vector<ShaderVarType> sGroupSharedVarType;
|
||||
|
||||
TESSELLATOR_PARTITIONING eTessPartitioning;
|
||||
TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim;
|
||||
uint32_t ui32TessInputControlPointCount;
|
||||
uint32_t ui32TessOutputControlPointCount;
|
||||
TESSELLATOR_DOMAIN eTessDomain;
|
||||
bool bEarlyFragmentTests;
|
||||
TESSELLATOR_PARTITIONING eTessPartitioning;
|
||||
TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim;
|
||||
uint32_t ui32TessInputControlPointCount;
|
||||
uint32_t ui32TessOutputControlPointCount;
|
||||
TESSELLATOR_DOMAIN eTessDomain;
|
||||
bool bEarlyFragmentTests;
|
||||
};
|
||||
|
||||
|
@ -2,46 +2,44 @@
|
||||
|
||||
namespace HLSLcc
|
||||
{
|
||||
// A vector that automatically grows when written to, fills the intermediate ones with default value.
|
||||
// Reading from an index returns the default value if attempting to access out of bounds.
|
||||
template <class T> class growing_vector
|
||||
{
|
||||
public:
|
||||
growing_vector() : data() {}
|
||||
// A vector that automatically grows when written to, fills the intermediate ones with default value.
|
||||
// Reading from an index returns the default value if attempting to access out of bounds.
|
||||
template<class T> class growing_vector
|
||||
{
|
||||
public:
|
||||
growing_vector() : data() {}
|
||||
|
||||
std::vector<T> data;
|
||||
std::vector<T> data;
|
||||
|
||||
T & operator[](std::size_t idx)
|
||||
{
|
||||
if (idx >= data.size())
|
||||
data.resize((idx + 1) * 2);
|
||||
return data[idx];
|
||||
}
|
||||
T & operator[](std::size_t idx)
|
||||
{
|
||||
if (idx >= data.size())
|
||||
data.resize((idx + 1) * 2);
|
||||
return data[idx];
|
||||
}
|
||||
|
||||
const T & operator[](std::size_t idx) const
|
||||
{
|
||||
static T defaultValue = T();
|
||||
if (idx >= data.size())
|
||||
return defaultValue;
|
||||
return data[idx];
|
||||
}
|
||||
const T & operator[](std::size_t idx) const
|
||||
{
|
||||
static T defaultValue = T();
|
||||
if (idx >= data.size())
|
||||
return defaultValue;
|
||||
return data[idx];
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
// Same but with bool specialization
|
||||
template<> class growing_vector<bool>
|
||||
{
|
||||
public:
|
||||
growing_vector() : data() {}
|
||||
|
||||
// Same but with bool specialization
|
||||
template <> class growing_vector<bool>
|
||||
{
|
||||
public:
|
||||
growing_vector() : data() {}
|
||||
std::vector<bool> data;
|
||||
|
||||
std::vector<bool> data;
|
||||
|
||||
std::vector<bool>::reference operator[](std::size_t idx)
|
||||
{
|
||||
if (idx >= data.size())
|
||||
data.resize((idx + 1) * 2, false);
|
||||
return data[idx];
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
std::vector<bool>::reference operator[](std::size_t idx)
|
||||
{
|
||||
if (idx >= data.size())
|
||||
data.resize((idx + 1) * 2, false);
|
||||
return data[idx];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
620
include/hlslcc.h
620
include/hlslcc.h
@ -6,7 +6,7 @@
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#if defined (_WIN32) && defined(HLSLCC_DYNLIB)
|
||||
#if defined(_WIN32) && defined(HLSLCC_DYNLIB)
|
||||
#define HLSLCC_APIENTRY __stdcall
|
||||
#if defined(libHLSLcc_EXPORTS)
|
||||
#define HLSLCC_API __declspec(dllexport)
|
||||
@ -24,9 +24,9 @@
|
||||
typedef enum
|
||||
{
|
||||
LANG_DEFAULT,// Depends on the HLSL shader model.
|
||||
LANG_ES_100, LANG_ES_FIRST=LANG_ES_100,
|
||||
LANG_ES_100, LANG_ES_FIRST = LANG_ES_100,
|
||||
LANG_ES_300,
|
||||
LANG_ES_310, LANG_ES_LAST = LANG_ES_310,
|
||||
LANG_ES_310, LANG_ES_LAST = LANG_ES_310,
|
||||
LANG_120, LANG_GL_FIRST = LANG_120,
|
||||
LANG_130,
|
||||
LANG_140,
|
||||
@ -37,15 +37,16 @@ typedef enum
|
||||
LANG_420,
|
||||
LANG_430,
|
||||
LANG_440, LANG_GL_LAST = LANG_440,
|
||||
LANG_METAL,
|
||||
LANG_METAL,
|
||||
} GLLang;
|
||||
|
||||
typedef struct GlExtensions {
|
||||
uint32_t ARB_explicit_attrib_location : 1;
|
||||
uint32_t ARB_explicit_uniform_location : 1;
|
||||
uint32_t ARB_shading_language_420pack : 1;
|
||||
uint32_t OVR_multiview : 1;
|
||||
uint32_t EXT_shader_framebuffer_fetch : 1;
|
||||
typedef struct GlExtensions
|
||||
{
|
||||
uint32_t ARB_explicit_attrib_location : 1;
|
||||
uint32_t ARB_explicit_uniform_location : 1;
|
||||
uint32_t ARB_shading_language_420pack : 1;
|
||||
uint32_t OVR_multiview : 1;
|
||||
uint32_t EXT_shader_framebuffer_fetch : 1;
|
||||
} GlExtensions;
|
||||
|
||||
#include "ShaderInfo.h"
|
||||
@ -65,11 +66,11 @@ typedef enum INTERPOLATION_MODE
|
||||
INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE = 7,
|
||||
} INTERPOLATION_MODE;
|
||||
|
||||
#define PS_FLAG_VERTEX_SHADER 0x1
|
||||
#define PS_FLAG_HULL_SHADER 0x2
|
||||
#define PS_FLAG_DOMAIN_SHADER 0x4
|
||||
#define PS_FLAG_VERTEX_SHADER 0x1
|
||||
#define PS_FLAG_HULL_SHADER 0x2
|
||||
#define PS_FLAG_DOMAIN_SHADER 0x4
|
||||
#define PS_FLAG_GEOMETRY_SHADER 0x8
|
||||
#define PS_FLAG_PIXEL_SHADER 0x10
|
||||
#define PS_FLAG_PIXEL_SHADER 0x10
|
||||
|
||||
#define TO_FLAG_NONE 0x0
|
||||
#define TO_FLAG_INTEGER 0x1
|
||||
@ -99,42 +100,42 @@ typedef enum INTERPOLATION_MODE
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INVALID_SHADER = -1,
|
||||
PIXEL_SHADER,
|
||||
VERTEX_SHADER,
|
||||
GEOMETRY_SHADER,
|
||||
HULL_SHADER,
|
||||
DOMAIN_SHADER,
|
||||
COMPUTE_SHADER,
|
||||
INVALID_SHADER = -1,
|
||||
PIXEL_SHADER,
|
||||
VERTEX_SHADER,
|
||||
GEOMETRY_SHADER,
|
||||
HULL_SHADER,
|
||||
DOMAIN_SHADER,
|
||||
COMPUTE_SHADER,
|
||||
} SHADER_TYPE;
|
||||
|
||||
// Enum for texture dimension reflection data
|
||||
// Enum for texture dimension reflection data
|
||||
typedef enum
|
||||
{
|
||||
TD_FLOAT = 0,
|
||||
TD_INT,
|
||||
TD_2D,
|
||||
TD_3D,
|
||||
TD_CUBE,
|
||||
TD_2DSHADOW,
|
||||
TD_2DARRAY,
|
||||
TD_CUBEARRAY
|
||||
TD_FLOAT = 0,
|
||||
TD_INT,
|
||||
TD_2D,
|
||||
TD_3D,
|
||||
TD_CUBE,
|
||||
TD_2DSHADOW,
|
||||
TD_2DARRAY,
|
||||
TD_CUBEARRAY
|
||||
} HLSLCC_TEX_DIMENSION;
|
||||
|
||||
// The prefix for all temporary variables used by the generated code.
|
||||
// Using a texture or uniform name like this will cause conflicts
|
||||
#define HLSLCC_TEMP_PREFIX "u_xlat"
|
||||
|
||||
typedef std::vector<std::pair<std::string, std::string>> MemberDefinitions;
|
||||
typedef std::vector<std::pair<std::string, std::string> > MemberDefinitions;
|
||||
|
||||
// We store struct definition contents inside a vector of strings
|
||||
struct StructDefinition
|
||||
{
|
||||
StructDefinition() : m_Members(), m_Dependencies(), m_IsPrinted(false) {}
|
||||
StructDefinition() : m_Members(), m_Dependencies(), m_IsPrinted(false) {}
|
||||
|
||||
MemberDefinitions m_Members; // A vector of strings with the struct members
|
||||
std::vector<std::string> m_Dependencies; // A vector of struct names this struct depends on.
|
||||
bool m_IsPrinted; // Has this struct been printed out yet?
|
||||
MemberDefinitions m_Members; // A vector of strings with the struct members
|
||||
std::vector<std::string> m_Dependencies; // A vector of struct names this struct depends on.
|
||||
bool m_IsPrinted; // Has this struct been printed out yet?
|
||||
};
|
||||
|
||||
typedef std::map<std::string, StructDefinition> StructDefinitions;
|
||||
@ -146,65 +147,65 @@ typedef std::map<std::string, std::string> FunctionDefinitions;
|
||||
// (because both UAVs and textures use the same slots in Metal, also constant buffers and other buffers etc)
|
||||
class BindingSlotAllocator
|
||||
{
|
||||
typedef std::map<uint32_t, uint32_t> SlotMap;
|
||||
SlotMap m_Allocations;
|
||||
uint32_t m_ShaderStageAllocations;
|
||||
typedef std::map<uint32_t, uint32_t> SlotMap;
|
||||
SlotMap m_Allocations;
|
||||
uint32_t m_ShaderStageAllocations;
|
||||
public:
|
||||
BindingSlotAllocator() : m_Allocations(), m_ShaderStageAllocations(0)
|
||||
{
|
||||
for(int i = MAX_RESOURCE_BINDINGS-1; i >= 0; i --)
|
||||
m_FreeSlots.push_back(i);
|
||||
}
|
||||
BindingSlotAllocator() : m_Allocations(), m_ShaderStageAllocations(0)
|
||||
{
|
||||
for (int i = MAX_RESOURCE_BINDINGS - 1; i >= 0; i--)
|
||||
m_FreeSlots.push_back(i);
|
||||
}
|
||||
|
||||
enum BindType
|
||||
{
|
||||
ConstantBuffer = 0,
|
||||
RWBuffer,
|
||||
Texture,
|
||||
UAV
|
||||
};
|
||||
enum BindType
|
||||
{
|
||||
ConstantBuffer = 0,
|
||||
RWBuffer,
|
||||
Texture,
|
||||
UAV
|
||||
};
|
||||
|
||||
uint32_t GetBindingSlot(uint32_t regNo, BindType type)
|
||||
{
|
||||
// The key is regNumber with the bindtype stored to highest 16 bits
|
||||
uint32_t key = (m_ShaderStageAllocations + regNo) | (uint32_t(type) << 16);
|
||||
SlotMap::iterator itr = m_Allocations.find(key);
|
||||
if(itr == m_Allocations.end())
|
||||
{
|
||||
uint32_t slot = m_FreeSlots.back();
|
||||
m_FreeSlots.pop_back();
|
||||
m_Allocations.insert(std::make_pair(key, slot));
|
||||
return slot;
|
||||
}
|
||||
return itr->second;
|
||||
}
|
||||
uint32_t GetBindingSlot(uint32_t regNo, BindType type)
|
||||
{
|
||||
// The key is regNumber with the bindtype stored to highest 16 bits
|
||||
uint32_t key = (m_ShaderStageAllocations + regNo) | (uint32_t(type) << 16);
|
||||
SlotMap::iterator itr = m_Allocations.find(key);
|
||||
if (itr == m_Allocations.end())
|
||||
{
|
||||
uint32_t slot = m_FreeSlots.back();
|
||||
m_FreeSlots.pop_back();
|
||||
m_Allocations.insert(std::make_pair(key, slot));
|
||||
return slot;
|
||||
}
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// Func for reserving binding slots with the original reg number.
|
||||
// Used for fragment shader UAVs (SetRandomWriteTarget etc).
|
||||
void ReserveBindingSlot(uint32_t regNo, BindType type)
|
||||
{
|
||||
uint32_t key = regNo | (uint32_t(type) << 16);
|
||||
m_Allocations.insert(std::make_pair(key, regNo));
|
||||
// Func for reserving binding slots with the original reg number.
|
||||
// Used for fragment shader UAVs (SetRandomWriteTarget etc).
|
||||
void ReserveBindingSlot(uint32_t regNo, BindType type)
|
||||
{
|
||||
uint32_t key = regNo | (uint32_t(type) << 16);
|
||||
m_Allocations.insert(std::make_pair(key, regNo));
|
||||
|
||||
// Remove regNo from free slots
|
||||
for (int i = m_FreeSlots.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (m_FreeSlots[i] == regNo)
|
||||
{
|
||||
m_FreeSlots.erase(m_FreeSlots.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove regNo from free slots
|
||||
for (int i = m_FreeSlots.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (m_FreeSlots[i] == regNo)
|
||||
{
|
||||
m_FreeSlots.erase(m_FreeSlots.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SaveTotalShaderStageAllocationsCount()
|
||||
{
|
||||
m_ShaderStageAllocations = m_Allocations.size();
|
||||
return m_ShaderStageAllocations;
|
||||
}
|
||||
uint32_t SaveTotalShaderStageAllocationsCount()
|
||||
{
|
||||
m_ShaderStageAllocations = m_Allocations.size();
|
||||
return m_ShaderStageAllocations;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint32_t> m_FreeSlots;
|
||||
std::vector<uint32_t> m_FreeSlots;
|
||||
};
|
||||
|
||||
//The shader stages (Vertex, Pixel et al) do not depend on each other
|
||||
@ -220,156 +221,155 @@ private:
|
||||
class GLSLCrossDependencyData
|
||||
{
|
||||
public:
|
||||
// A container for a single Vulkan resource binding (<set, binding> pair)
|
||||
typedef std::pair<uint32_t, uint32_t> VulkanResourceBinding;
|
||||
// A container for a single Vulkan resource binding (<set, binding> pair)
|
||||
typedef std::pair<uint32_t, uint32_t> VulkanResourceBinding;
|
||||
|
||||
private:
|
||||
//Required if PixelInterpDependency is true
|
||||
std::vector<INTERPOLATION_MODE> pixelInterpolation;
|
||||
|
||||
// Map of varying locations, indexed by varying names.
|
||||
typedef std::map<std::string, uint32_t> VaryingLocations;
|
||||
//Required if PixelInterpDependency is true
|
||||
std::vector<INTERPOLATION_MODE> pixelInterpolation;
|
||||
|
||||
static const int MAX_NAMESPACES = 6; // Max namespaces: vert input, hull input, domain input, geom input, ps input, (ps output)
|
||||
// Map of varying locations, indexed by varying names.
|
||||
typedef std::map<std::string, uint32_t> VaryingLocations;
|
||||
|
||||
VaryingLocations varyingLocationsMap[MAX_NAMESPACES];
|
||||
uint32_t nextAvailableVaryingLocation[MAX_NAMESPACES];
|
||||
static const int MAX_NAMESPACES = 6; // Max namespaces: vert input, hull input, domain input, geom input, ps input, (ps output)
|
||||
|
||||
typedef std::map<std::string, VulkanResourceBinding> VulkanResourceBindings;
|
||||
VulkanResourceBindings m_VulkanResourceBindings;
|
||||
uint32_t m_NextAvailableVulkanResourceBinding[8]; // one per set.
|
||||
VaryingLocations varyingLocationsMap[MAX_NAMESPACES];
|
||||
uint32_t nextAvailableVaryingLocation[MAX_NAMESPACES];
|
||||
|
||||
inline int GetVaryingNamespace(SHADER_TYPE eShaderType, bool isInput)
|
||||
{
|
||||
switch (eShaderType)
|
||||
{
|
||||
case VERTEX_SHADER:
|
||||
return isInput ? 0 : 1;
|
||||
typedef std::map<std::string, VulkanResourceBinding> VulkanResourceBindings;
|
||||
VulkanResourceBindings m_VulkanResourceBindings;
|
||||
uint32_t m_NextAvailableVulkanResourceBinding[8]; // one per set.
|
||||
|
||||
case HULL_SHADER:
|
||||
return isInput ? 1 : 2;
|
||||
inline int GetVaryingNamespace(SHADER_TYPE eShaderType, bool isInput)
|
||||
{
|
||||
switch (eShaderType)
|
||||
{
|
||||
case VERTEX_SHADER:
|
||||
return isInput ? 0 : 1;
|
||||
|
||||
case DOMAIN_SHADER:
|
||||
return isInput ? 2 : 3;
|
||||
case HULL_SHADER:
|
||||
return isInput ? 1 : 2;
|
||||
|
||||
case GEOMETRY_SHADER:
|
||||
// The input depends on whether there's a tessellation shader before us
|
||||
if (isInput)
|
||||
{
|
||||
return ui32ProgramStages & PS_FLAG_DOMAIN_SHADER ? 3 : 1;
|
||||
}
|
||||
return 4;
|
||||
case DOMAIN_SHADER:
|
||||
return isInput ? 2 : 3;
|
||||
|
||||
case PIXEL_SHADER:
|
||||
// The inputs can come from geom shader, domain shader or directly from vertex shader
|
||||
if (isInput)
|
||||
{
|
||||
if (ui32ProgramStages & PS_FLAG_GEOMETRY_SHADER)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else if (ui32ProgramStages & PS_FLAG_DOMAIN_SHADER)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 5; // This value never really used
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
case GEOMETRY_SHADER:
|
||||
// The input depends on whether there's a tessellation shader before us
|
||||
if (isInput)
|
||||
{
|
||||
return ui32ProgramStages & PS_FLAG_DOMAIN_SHADER ? 3 : 1;
|
||||
}
|
||||
return 4;
|
||||
|
||||
typedef std::map<std::string, uint32_t> SpecializationConstantMap;
|
||||
SpecializationConstantMap m_SpecConstantMap;
|
||||
uint32_t m_NextSpecID;
|
||||
case PIXEL_SHADER:
|
||||
// The inputs can come from geom shader, domain shader or directly from vertex shader
|
||||
if (isInput)
|
||||
{
|
||||
if (ui32ProgramStages & PS_FLAG_GEOMETRY_SHADER)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else if (ui32ProgramStages & PS_FLAG_DOMAIN_SHADER)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 5; // This value never really used
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::map<std::string, uint32_t> SpecializationConstantMap;
|
||||
SpecializationConstantMap m_SpecConstantMap;
|
||||
uint32_t m_NextSpecID;
|
||||
|
||||
public:
|
||||
GLSLCrossDependencyData()
|
||||
: eTessPartitioning(),
|
||||
eTessOutPrim(),
|
||||
fMaxTessFactor(64.0),
|
||||
numPatchesInThreadGroup(0),
|
||||
hasControlPoint(false),
|
||||
hasPatchConstant(false),
|
||||
ui32ProgramStages(0),
|
||||
m_ExtBlendModes(),
|
||||
m_NextSpecID(0)
|
||||
{
|
||||
memset(nextAvailableVaryingLocation, 0, sizeof(nextAvailableVaryingLocation));
|
||||
memset(m_NextAvailableVulkanResourceBinding, 0, sizeof(m_NextAvailableVulkanResourceBinding));
|
||||
}
|
||||
GLSLCrossDependencyData()
|
||||
: eTessPartitioning(),
|
||||
eTessOutPrim(),
|
||||
fMaxTessFactor(64.0),
|
||||
numPatchesInThreadGroup(0),
|
||||
hasControlPoint(false),
|
||||
hasPatchConstant(false),
|
||||
ui32ProgramStages(0),
|
||||
m_ExtBlendModes(),
|
||||
m_NextSpecID(0)
|
||||
{
|
||||
memset(nextAvailableVaryingLocation, 0, sizeof(nextAvailableVaryingLocation));
|
||||
memset(m_NextAvailableVulkanResourceBinding, 0, sizeof(m_NextAvailableVulkanResourceBinding));
|
||||
}
|
||||
|
||||
// Retrieve the location for a varying with a given name.
|
||||
// If the name doesn't already have an allocated location, allocate one
|
||||
// and store it into the map.
|
||||
inline uint32_t GetVaryingLocation(const std::string &name, SHADER_TYPE eShaderType, bool isInput)
|
||||
{
|
||||
int nspace = GetVaryingNamespace(eShaderType, isInput);
|
||||
VaryingLocations::iterator itr = varyingLocationsMap[nspace].find(name);
|
||||
if (itr != varyingLocationsMap[nspace].end())
|
||||
return itr->second;
|
||||
|
||||
// Retrieve the location for a varying with a given name.
|
||||
// If the name doesn't already have an allocated location, allocate one
|
||||
// and store it into the map.
|
||||
inline uint32_t GetVaryingLocation(const std::string &name, SHADER_TYPE eShaderType, bool isInput)
|
||||
{
|
||||
int nspace = GetVaryingNamespace(eShaderType, isInput);
|
||||
VaryingLocations::iterator itr = varyingLocationsMap[nspace].find(name);
|
||||
if (itr != varyingLocationsMap[nspace].end())
|
||||
return itr->second;
|
||||
uint32_t newKey = nextAvailableVaryingLocation[nspace];
|
||||
nextAvailableVaryingLocation[nspace]++;
|
||||
varyingLocationsMap[nspace].insert(std::make_pair(name, newKey));
|
||||
return newKey;
|
||||
}
|
||||
|
||||
uint32_t newKey = nextAvailableVaryingLocation[nspace];
|
||||
nextAvailableVaryingLocation[nspace]++;
|
||||
varyingLocationsMap[nspace].insert(std::make_pair(name, newKey));
|
||||
return newKey;
|
||||
}
|
||||
// Retrieve the binding for a resource (texture, constant buffer, image) with a given name
|
||||
// If not found, allocate a new one (in set 0) and return that
|
||||
// The returned value is a pair of <set, binding>
|
||||
// If the name contains "hlslcc_set_X_bind_Y", those values (from the first found occurence in the name)
|
||||
// will be used instead, and all occurences of that string will be removed from name, so name parameter can be modified
|
||||
// if allocRoomForCounter is true, the following binding number in the same set will be allocated with name + '_counter'
|
||||
inline std::pair<uint32_t, uint32_t> GetVulkanResourceBinding(std::string &name, bool allocRoomForCounter = false, uint32_t preferredSet = 0)
|
||||
{
|
||||
// scan for the special marker
|
||||
const char *marker = "Xhlslcc_set_%d_bind_%dX";
|
||||
uint32_t Set = 0, Binding = 0;
|
||||
size_t startLoc = name.find("Xhlslcc");
|
||||
if ((startLoc != std::string::npos) && (sscanf(name.c_str() + startLoc, marker, &Set, &Binding) == 2))
|
||||
{
|
||||
// Get rid of all markers
|
||||
while ((startLoc = name.find("Xhlslcc")) != std::string::npos)
|
||||
{
|
||||
size_t endLoc = name.find('X', startLoc + 1);
|
||||
if (endLoc == std::string::npos)
|
||||
break;
|
||||
name.erase(startLoc, endLoc - startLoc + 1);
|
||||
}
|
||||
// Add to map
|
||||
VulkanResourceBinding newBind = std::make_pair(Set, Binding);
|
||||
m_VulkanResourceBindings.insert(std::make_pair(name, newBind));
|
||||
if (allocRoomForCounter)
|
||||
{
|
||||
VulkanResourceBinding counterBind = std::make_pair(Set, Binding + 1);
|
||||
m_VulkanResourceBindings.insert(std::make_pair(name + "_counter", counterBind));
|
||||
}
|
||||
|
||||
// Retrieve the binding for a resource (texture, constant buffer, image) with a given name
|
||||
// If not found, allocate a new one (in set 0) and return that
|
||||
// The returned value is a pair of <set, binding>
|
||||
// If the name contains "hlslcc_set_X_bind_Y", those values (from the first found occurence in the name)
|
||||
// will be used instead, and all occurences of that string will be removed from name, so name parameter can be modified
|
||||
// if allocRoomForCounter is true, the following binding number in the same set will be allocated with name + '_counter'
|
||||
inline std::pair<uint32_t, uint32_t> GetVulkanResourceBinding(std::string &name, bool allocRoomForCounter = false, uint32_t preferredSet = 0)
|
||||
{
|
||||
// scan for the special marker
|
||||
const char *marker = "Xhlslcc_set_%d_bind_%dX";
|
||||
uint32_t Set = 0, Binding = 0;
|
||||
size_t startLoc = name.find("Xhlslcc");
|
||||
if ((startLoc != std::string::npos) && (sscanf(name.c_str() + startLoc, marker, &Set, &Binding) == 2))
|
||||
{
|
||||
// Get rid of all markers
|
||||
while ((startLoc = name.find("Xhlslcc")) != std::string::npos)
|
||||
{
|
||||
size_t endLoc = name.find('X', startLoc + 1);
|
||||
if (endLoc == std::string::npos)
|
||||
break;
|
||||
name.erase(startLoc, endLoc - startLoc + 1);
|
||||
}
|
||||
// Add to map
|
||||
VulkanResourceBinding newBind = std::make_pair(Set, Binding);
|
||||
m_VulkanResourceBindings.insert(std::make_pair(name, newBind));
|
||||
if (allocRoomForCounter)
|
||||
{
|
||||
VulkanResourceBinding counterBind = std::make_pair(Set, Binding+1);
|
||||
m_VulkanResourceBindings.insert(std::make_pair(name + "_counter", counterBind));
|
||||
}
|
||||
return newBind;
|
||||
}
|
||||
|
||||
return newBind;
|
||||
}
|
||||
VulkanResourceBindings::iterator itr = m_VulkanResourceBindings.find(name);
|
||||
if (itr != m_VulkanResourceBindings.end())
|
||||
return itr->second;
|
||||
|
||||
VulkanResourceBindings::iterator itr = m_VulkanResourceBindings.find(name);
|
||||
if (itr != m_VulkanResourceBindings.end())
|
||||
return itr->second;
|
||||
|
||||
// Allocate a new one
|
||||
VulkanResourceBinding newBind = std::make_pair(preferredSet, m_NextAvailableVulkanResourceBinding[preferredSet]);
|
||||
m_NextAvailableVulkanResourceBinding[preferredSet]++;
|
||||
m_VulkanResourceBindings.insert(std::make_pair(name, newBind));
|
||||
if (allocRoomForCounter)
|
||||
{
|
||||
VulkanResourceBinding counterBind = std::make_pair(preferredSet, m_NextAvailableVulkanResourceBinding[preferredSet]);
|
||||
m_NextAvailableVulkanResourceBinding[preferredSet]++;
|
||||
m_VulkanResourceBindings.insert(std::make_pair(name + "_counter", counterBind));
|
||||
}
|
||||
return newBind;
|
||||
}
|
||||
// Allocate a new one
|
||||
VulkanResourceBinding newBind = std::make_pair(preferredSet, m_NextAvailableVulkanResourceBinding[preferredSet]);
|
||||
m_NextAvailableVulkanResourceBinding[preferredSet]++;
|
||||
m_VulkanResourceBindings.insert(std::make_pair(name, newBind));
|
||||
if (allocRoomForCounter)
|
||||
{
|
||||
VulkanResourceBinding counterBind = std::make_pair(preferredSet, m_NextAvailableVulkanResourceBinding[preferredSet]);
|
||||
m_NextAvailableVulkanResourceBinding[preferredSet]++;
|
||||
m_VulkanResourceBindings.insert(std::make_pair(name + "_counter", counterBind));
|
||||
}
|
||||
return newBind;
|
||||
}
|
||||
|
||||
//dcl_tessellator_partitioning and dcl_tessellator_output_primitive appear in hull shader for D3D,
|
||||
//but they appear on inputs inside domain shaders for GL.
|
||||
@ -383,74 +383,77 @@ public:
|
||||
bool hasControlPoint;
|
||||
bool hasPatchConstant;
|
||||
|
||||
// Bitfield for the shader stages this program is going to include (see PS_FLAG_*).
|
||||
// Needed so we can construct proper shader input and output names
|
||||
uint32_t ui32ProgramStages;
|
||||
// Bitfield for the shader stages this program is going to include (see PS_FLAG_*).
|
||||
// Needed so we can construct proper shader input and output names
|
||||
uint32_t ui32ProgramStages;
|
||||
|
||||
std::vector<std::string> m_ExtBlendModes; // The blend modes (from KHR_blend_equation_advanced) requested for this shader. See ext spec for list.
|
||||
|
||||
inline INTERPOLATION_MODE GetInterpolationMode(uint32_t regNo)
|
||||
{
|
||||
if (regNo >= pixelInterpolation.size())
|
||||
return INTERPOLATION_UNDEFINED;
|
||||
else
|
||||
return pixelInterpolation[regNo];
|
||||
}
|
||||
std::vector<std::string> m_ExtBlendModes; // The blend modes (from KHR_blend_equation_advanced) requested for this shader. See ext spec for list.
|
||||
|
||||
inline void SetInterpolationMode(uint32_t regNo, INTERPOLATION_MODE mode)
|
||||
{
|
||||
if (regNo >= pixelInterpolation.size())
|
||||
pixelInterpolation.resize((regNo + 1) * 2, INTERPOLATION_UNDEFINED);
|
||||
inline INTERPOLATION_MODE GetInterpolationMode(uint32_t regNo)
|
||||
{
|
||||
if (regNo >= pixelInterpolation.size())
|
||||
return INTERPOLATION_UNDEFINED;
|
||||
else
|
||||
return pixelInterpolation[regNo];
|
||||
}
|
||||
|
||||
pixelInterpolation[regNo] = mode;
|
||||
}
|
||||
inline void SetInterpolationMode(uint32_t regNo, INTERPOLATION_MODE mode)
|
||||
{
|
||||
if (regNo >= pixelInterpolation.size())
|
||||
pixelInterpolation.resize((regNo + 1) * 2, INTERPOLATION_UNDEFINED);
|
||||
|
||||
struct CompareFirst
|
||||
{
|
||||
CompareFirst(std::string val) : m_Val (val) {}
|
||||
bool operator()(const std::pair<std::string, std::string>& elem) const
|
||||
{
|
||||
return m_Val == elem.first;
|
||||
}
|
||||
private:
|
||||
std::string m_Val;
|
||||
};
|
||||
pixelInterpolation[regNo] = mode;
|
||||
}
|
||||
|
||||
inline bool IsMemberDeclared(const std::string &name)
|
||||
{
|
||||
if (std::find_if(m_SharedFunctionMembers.begin(), m_SharedFunctionMembers.end(), CompareFirst(name)) != m_SharedFunctionMembers.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
struct CompareFirst
|
||||
{
|
||||
CompareFirst(std::string val) : m_Val(val) {}
|
||||
bool operator()(const std::pair<std::string, std::string>& elem) const
|
||||
{
|
||||
return m_Val == elem.first;
|
||||
}
|
||||
|
||||
MemberDefinitions m_SharedFunctionMembers;
|
||||
BindingSlotAllocator m_SharedTextureSlots, m_SharedSamplerSlots;
|
||||
BindingSlotAllocator m_SharedBufferSlots;
|
||||
private:
|
||||
std::string m_Val;
|
||||
};
|
||||
|
||||
inline void ClearCrossDependencyData()
|
||||
{
|
||||
pixelInterpolation.clear();
|
||||
for (int i = 0; i < MAX_NAMESPACES; i++)
|
||||
{
|
||||
varyingLocationsMap[i].clear();
|
||||
nextAvailableVaryingLocation[i] = 0;
|
||||
}
|
||||
m_NextSpecID = kArraySizeConstantID + 1;
|
||||
m_SpecConstantMap.clear();
|
||||
m_SharedFunctionMembers.clear();
|
||||
}
|
||||
inline bool IsMemberDeclared(const std::string &name)
|
||||
{
|
||||
if (std::find_if(m_SharedFunctionMembers.begin(), m_SharedFunctionMembers.end(), CompareFirst(name)) != m_SharedFunctionMembers.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve or allocate a layout slot for Vulkan specialization constant
|
||||
inline uint32_t GetSpecializationConstantSlot(const std::string &name)
|
||||
{
|
||||
SpecializationConstantMap::iterator itr = m_SpecConstantMap.find(name);
|
||||
if (itr != m_SpecConstantMap.end())
|
||||
return itr->second;
|
||||
MemberDefinitions m_SharedFunctionMembers;
|
||||
std::vector<std::string> m_SharedDependencies;
|
||||
BindingSlotAllocator m_SharedTextureSlots, m_SharedSamplerSlots;
|
||||
BindingSlotAllocator m_SharedBufferSlots;
|
||||
|
||||
m_SpecConstantMap.insert(std::make_pair(std::string(name), m_NextSpecID));
|
||||
inline void ClearCrossDependencyData()
|
||||
{
|
||||
pixelInterpolation.clear();
|
||||
for (int i = 0; i < MAX_NAMESPACES; i++)
|
||||
{
|
||||
varyingLocationsMap[i].clear();
|
||||
nextAvailableVaryingLocation[i] = 0;
|
||||
}
|
||||
m_NextSpecID = kArraySizeConstantID + 1;
|
||||
m_SpecConstantMap.clear();
|
||||
m_SharedFunctionMembers.clear();
|
||||
m_SharedDependencies.clear();
|
||||
}
|
||||
|
||||
return m_NextSpecID++;
|
||||
}
|
||||
// Retrieve or allocate a layout slot for Vulkan specialization constant
|
||||
inline uint32_t GetSpecializationConstantSlot(const std::string &name)
|
||||
{
|
||||
SpecializationConstantMap::iterator itr = m_SpecConstantMap.find(name);
|
||||
if (itr != m_SpecConstantMap.end())
|
||||
return itr->second;
|
||||
|
||||
m_SpecConstantMap.insert(std::make_pair(std::string(name), m_NextSpecID));
|
||||
|
||||
return m_NextSpecID++;
|
||||
}
|
||||
};
|
||||
|
||||
struct GLSLShader
|
||||
@ -466,28 +469,28 @@ struct GLSLShader
|
||||
class HLSLccReflection
|
||||
{
|
||||
public:
|
||||
HLSLccReflection() {}
|
||||
virtual ~HLSLccReflection() {}
|
||||
HLSLccReflection() {}
|
||||
virtual ~HLSLccReflection() {}
|
||||
|
||||
// Called on errors or diagnostic messages
|
||||
virtual void OnDiagnostics(const std::string &error, int line, bool isError) {}
|
||||
// Called on errors or diagnostic messages
|
||||
virtual void OnDiagnostics(const std::string &error, int line, bool isError) {}
|
||||
|
||||
virtual void OnInputBinding(const std::string &name, int bindIndex) {}
|
||||
virtual void OnInputBinding(const std::string &name, int bindIndex) {}
|
||||
|
||||
// Returns false if this constant buffer is not needed for this shader. This info can be used for pruning unused
|
||||
// constant buffers and vars from compute shaders where we need broader context than a single kernel to know
|
||||
// if something can be dropped, as the constant buffers are shared between all kernels in a .compute file.
|
||||
virtual bool OnConstantBuffer(const std::string &name, size_t bufferSize, size_t memberCount) { return true; }
|
||||
// Returns false if this constant buffer is not needed for this shader. This info can be used for pruning unused
|
||||
// constant buffers and vars from compute shaders where we need broader context than a single kernel to know
|
||||
// if something can be dropped, as the constant buffers are shared between all kernels in a .compute file.
|
||||
virtual bool OnConstantBuffer(const std::string &name, size_t bufferSize, size_t memberCount) { return true; }
|
||||
|
||||
// Returns false if this constant var is not needed for this shader. See above.
|
||||
virtual bool OnConstant(const std::string &name, int bindIndex, SHADER_VARIABLE_TYPE cType, int rows, int cols, bool isMatrix, int arraySize) { return true; }
|
||||
// Returns false if this constant var is not needed for this shader. See above.
|
||||
virtual bool OnConstant(const std::string &name, int bindIndex, SHADER_VARIABLE_TYPE cType, int rows, int cols, bool isMatrix, int arraySize, bool isUsed) { return true; }
|
||||
|
||||
virtual void OnConstantBufferBinding(const std::string &name, int bindIndex) {}
|
||||
virtual void OnTextureBinding(const std::string &name, int bindIndex, int samplerIndex, bool multisampled, HLSLCC_TEX_DIMENSION dim, bool isUAV) {}
|
||||
virtual void OnBufferBinding(const std::string &name, int bindIndex, bool isUAV) {}
|
||||
virtual void OnThreadGroupSize(unsigned int xSize, unsigned int ySize, unsigned int zSize) {}
|
||||
virtual void OnTessellationInfo(uint32_t tessPartitionMode, uint32_t tessOutputWindingOrder, uint32_t tessMaxFactor, uint32_t tessNumPatchesInThreadGroup) {}
|
||||
virtual void OnTessellationKernelInfo(uint32_t patchKernelBufferCount) {}
|
||||
virtual void OnConstantBufferBinding(const std::string &name, int bindIndex) {}
|
||||
virtual void OnTextureBinding(const std::string &name, int bindIndex, int samplerIndex, bool multisampled, HLSLCC_TEX_DIMENSION dim, bool isUAV) {}
|
||||
virtual void OnBufferBinding(const std::string &name, int bindIndex, bool isUAV) {}
|
||||
virtual void OnThreadGroupSize(unsigned int xSize, unsigned int ySize, unsigned int zSize) {}
|
||||
virtual void OnTessellationInfo(uint32_t tessPartitionMode, uint32_t tessOutputWindingOrder, uint32_t tessMaxFactor, uint32_t tessNumPatchesInThreadGroup) {}
|
||||
virtual void OnTessellationKernelInfo(uint32_t patchKernelBufferCount) {}
|
||||
};
|
||||
|
||||
|
||||
@ -562,7 +565,7 @@ static const unsigned int HLSLCC_FLAG_VULKAN_BINDINGS = 0x40000;
|
||||
static const unsigned int HLSLCC_FLAG_METAL_SHADOW_SAMPLER_LINEAR = 0x80000;
|
||||
|
||||
// If set, avoid emit atomic counter (ARB_shader_atomic_counters) and use atomic functions provided by ARB_shader_storage_buffer_object instead.
|
||||
static const unsigned int HLSLCC_FLAG_AVOID_SHADER_ATOMIC_COUNTERS = 0x100000;
|
||||
static const unsigned int HLSLCC_FLAG_AVOID_SHADER_ATOMIC_COUNTERS = 0x100000;
|
||||
|
||||
// If set, and generating Vulkan shaders, attempts to detect static branching and transforms them into specialization constants
|
||||
static const unsigned int HLSLCC_FLAG_VULKAN_SPECIALIZATION_CONSTANTS = 0x200000;
|
||||
@ -588,27 +591,26 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFile(const char* filename,
|
||||
unsigned int flags,
|
||||
GLLang language,
|
||||
const GlExtensions *extensions,
|
||||
GLSLCrossDependencyData* dependencies,
|
||||
HLSLccSamplerPrecisionInfo& samplerPrecisions,
|
||||
HLSLccReflection& reflectionCallbacks,
|
||||
GLSLShader* result
|
||||
);
|
||||
unsigned int flags,
|
||||
GLLang language,
|
||||
const GlExtensions *extensions,
|
||||
GLSLCrossDependencyData* dependencies,
|
||||
HLSLccSamplerPrecisionInfo& samplerPrecisions,
|
||||
HLSLccReflection& reflectionCallbacks,
|
||||
GLSLShader* result
|
||||
);
|
||||
|
||||
HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader,
|
||||
unsigned int flags,
|
||||
GLLang language,
|
||||
const GlExtensions *extensions,
|
||||
GLSLCrossDependencyData* dependencies,
|
||||
HLSLccSamplerPrecisionInfo& samplerPrecisions,
|
||||
HLSLccReflection& reflectionCallbacks,
|
||||
GLSLShader* result);
|
||||
unsigned int flags,
|
||||
GLLang language,
|
||||
const GlExtensions *extensions,
|
||||
GLSLCrossDependencyData* dependencies,
|
||||
HLSLccSamplerPrecisionInfo& samplerPrecisions,
|
||||
HLSLccReflection& reflectionCallbacks,
|
||||
GLSLShader* result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
extern "C" {
|
||||
#include "hlslcc.h"
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,11 @@
|
||||
*
|
||||
* Copyright (c) 2005-2011 Paul Hsieh
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
@ -17,7 +17,7 @@
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
@ -191,7 +191,7 @@
|
||||
* do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
|
||||
*/
|
||||
|
||||
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
|
||||
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)))) && !defined(_PSTDINT_H_INCLUDED)
|
||||
#include <stdint.h>
|
||||
#define _PSTDINT_H_INCLUDED
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
@ -242,47 +242,47 @@
|
||||
* these duplicated definitions from Open Watcom's stdint.h file for now.
|
||||
*/
|
||||
|
||||
# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
|
||||
# if !defined (INT64_C)
|
||||
# if defined(__WATCOMC__) && __WATCOMC__ >= 1250
|
||||
# if !defined(INT64_C)
|
||||
# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
|
||||
# endif
|
||||
# if !defined (UINT64_C)
|
||||
# if !defined(UINT64_C)
|
||||
# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
|
||||
# endif
|
||||
# if !defined (INT32_C)
|
||||
# if !defined(INT32_C)
|
||||
# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
|
||||
# endif
|
||||
# if !defined (UINT32_C)
|
||||
# if !defined(UINT32_C)
|
||||
# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
|
||||
# endif
|
||||
# if !defined (INT16_C)
|
||||
# if !defined(INT16_C)
|
||||
# define INT16_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT16_C)
|
||||
# if !defined(UINT16_C)
|
||||
# define UINT16_C(x) (x)
|
||||
# endif
|
||||
# if !defined (INT8_C)
|
||||
# if !defined(INT8_C)
|
||||
# define INT8_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT8_C)
|
||||
# if !defined(UINT8_C)
|
||||
# define UINT8_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT64_MAX)
|
||||
# if !defined(UINT64_MAX)
|
||||
# define UINT64_MAX 18446744073709551615ULL
|
||||
# endif
|
||||
# if !defined (INT64_MAX)
|
||||
# if !defined(INT64_MAX)
|
||||
# define INT64_MAX 9223372036854775807LL
|
||||
# endif
|
||||
# if !defined (UINT32_MAX)
|
||||
# if !defined(UINT32_MAX)
|
||||
# define UINT32_MAX 4294967295UL
|
||||
# endif
|
||||
# if !defined (INT32_MAX)
|
||||
# if !defined(INT32_MAX)
|
||||
# define INT32_MAX 2147483647L
|
||||
# endif
|
||||
# if !defined (INTMAX_MAX)
|
||||
# if !defined(INTMAX_MAX)
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# endif
|
||||
# if !defined (INTMAX_MIN)
|
||||
# if !defined(INTMAX_MIN)
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# endif
|
||||
# endif
|
||||
@ -305,8 +305,8 @@
|
||||
# define UINT8_MAX 0xff
|
||||
#endif
|
||||
#ifndef uint8_t
|
||||
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned char uint8_t;
|
||||
# if (UCHAR_MAX == UINT8_MAX) || defined(S_SPLINT_S)
|
||||
typedef unsigned char uint8_t;
|
||||
# define UINT8_C(v) ((uint8_t) v)
|
||||
# else
|
||||
# error "Platform not supported"
|
||||
@ -320,8 +320,8 @@
|
||||
# define INT8_MIN INT8_C(0x80)
|
||||
#endif
|
||||
#ifndef int8_t
|
||||
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed char int8_t;
|
||||
# if (SCHAR_MAX == INT8_MAX) || defined(S_SPLINT_S)
|
||||
typedef signed char int8_t;
|
||||
# define INT8_C(v) ((int8_t) v)
|
||||
# else
|
||||
# error "Platform not supported"
|
||||
@ -332,14 +332,14 @@
|
||||
# define UINT16_MAX 0xffff
|
||||
#endif
|
||||
#ifndef uint16_t
|
||||
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned int uint16_t;
|
||||
#if (UINT_MAX == UINT16_MAX) || defined(S_SPLINT_S)
|
||||
typedef unsigned int uint16_t;
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER ""
|
||||
# endif
|
||||
# define UINT16_C(v) ((uint16_t) (v))
|
||||
#elif (USHRT_MAX == UINT16_MAX)
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
# define UINT16_C(v) ((uint16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
@ -356,14 +356,14 @@
|
||||
# define INT16_MIN INT16_C(0x8000)
|
||||
#endif
|
||||
#ifndef int16_t
|
||||
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed int int16_t;
|
||||
#if (INT_MAX == INT16_MAX) || defined(S_SPLINT_S)
|
||||
typedef signed int int16_t;
|
||||
# define INT16_C(v) ((int16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER ""
|
||||
# endif
|
||||
#elif (SHRT_MAX == INT16_MAX)
|
||||
typedef signed short int16_t;
|
||||
typedef signed short int16_t;
|
||||
# define INT16_C(v) ((int16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
@ -377,20 +377,20 @@
|
||||
# define UINT32_MAX (0xffffffffUL)
|
||||
#endif
|
||||
#ifndef uint32_t
|
||||
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned long uint32_t;
|
||||
#if (ULONG_MAX == UINT32_MAX) || defined(S_SPLINT_S)
|
||||
typedef unsigned long uint32_t;
|
||||
# define UINT32_C(v) v ## UL
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
#elif (UINT_MAX == UINT32_MAX)
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
# define UINT32_C(v) v ## U
|
||||
#elif (USHRT_MAX == UINT32_MAX)
|
||||
typedef unsigned short uint32_t;
|
||||
typedef unsigned short uint32_t;
|
||||
# define UINT32_C(v) ((unsigned short) (v))
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
@ -407,20 +407,20 @@
|
||||
# define INT32_MIN INT32_C(0x80000000)
|
||||
#endif
|
||||
#ifndef int32_t
|
||||
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed long int32_t;
|
||||
#if (LONG_MAX == INT32_MAX) || defined(S_SPLINT_S)
|
||||
typedef signed long int32_t;
|
||||
# define INT32_C(v) v ## L
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
#elif (INT_MAX == INT32_MAX)
|
||||
typedef signed int int32_t;
|
||||
typedef signed int int32_t;
|
||||
# define INT32_C(v) v
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#elif (SHRT_MAX == INT32_MAX)
|
||||
typedef signed short int32_t;
|
||||
typedef signed short int32_t;
|
||||
# define INT32_C(v) ((short) (v))
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
@ -438,11 +438,11 @@
|
||||
*/
|
||||
|
||||
#undef stdint_int64_defined
|
||||
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
|
||||
# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
|
||||
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined(S_SPLINT_S)
|
||||
# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined(S_SPLINT_S)
|
||||
# define stdint_int64_defined
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
@ -451,29 +451,29 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (stdint_int64_defined)
|
||||
#if !defined(stdint_int64_defined)
|
||||
# if defined(__GNUC__)
|
||||
# define stdint_int64_defined
|
||||
__extension__ typedef long long int64_t;
|
||||
__extension__ typedef unsigned long long uint64_t;
|
||||
__extension__ typedef long long int64_t;
|
||||
__extension__ typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
|
||||
# elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC) || defined(S_SPLINT_S)
|
||||
# define stdint_int64_defined
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
|
||||
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC)
|
||||
# define stdint_int64_defined
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# define UINT64_C(v) v ## UI64
|
||||
# define INT64_C(v) v ## I64
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
@ -482,20 +482,20 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (LONG_LONG_MAX) && defined (INT64_C)
|
||||
#if !defined(LONG_LONG_MAX) && defined(INT64_C)
|
||||
# define LONG_LONG_MAX INT64_C (9223372036854775807)
|
||||
#endif
|
||||
#ifndef ULONG_LONG_MAX
|
||||
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
|
||||
#endif
|
||||
|
||||
#if !defined (INT64_MAX) && defined (INT64_C)
|
||||
#if !defined(INT64_MAX) && defined(INT64_C)
|
||||
# define INT64_MAX INT64_C (9223372036854775807)
|
||||
#endif
|
||||
#if !defined (INT64_MIN) && defined (INT64_C)
|
||||
#if !defined(INT64_MIN) && defined(INT64_C)
|
||||
# define INT64_MIN INT64_C (-9223372036854775808)
|
||||
#endif
|
||||
#if !defined (UINT64_MAX) && defined (INT64_C)
|
||||
#if !defined(UINT64_MAX) && defined(INT64_C)
|
||||
# define UINT64_MAX UINT64_C (18446744073709551615)
|
||||
#endif
|
||||
|
||||
@ -536,8 +536,8 @@
|
||||
*/
|
||||
|
||||
#ifdef stdint_int64_defined
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# define UINTMAX_MAX UINT64_MAX
|
||||
@ -553,8 +553,8 @@
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
|
||||
# endif
|
||||
#else
|
||||
typedef int32_t intmax_t;
|
||||
typedef uint32_t uintmax_t;
|
||||
typedef int32_t intmax_t;
|
||||
typedef uint32_t uintmax_t;
|
||||
# define INTMAX_MAX INT32_MAX
|
||||
# define UINTMAX_MAX UINT32_MAX
|
||||
# define UINTMAX_C(v) UINT32_C(v)
|
||||
@ -578,12 +578,12 @@
|
||||
*/
|
||||
|
||||
#ifndef stdint_least_defined
|
||||
typedef int8_t int_least8_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef int8_t int_least8_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
|
||||
# define UINT_LEAST8_MAX UINT8_MAX
|
||||
@ -596,8 +596,8 @@
|
||||
# define INT_LEAST16_MIN INT16_MIN
|
||||
# define INT_LEAST32_MIN INT32_MIN
|
||||
# ifdef stdint_int64_defined
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# define UINT_LEAST64_MAX UINT64_MAX
|
||||
# define INT_LEAST64_MAX INT64_MAX
|
||||
@ -633,8 +633,8 @@ typedef uint_least32_t uint_fast32_t;
|
||||
#define INT_FAST16_MIN INT_LEAST16_MIN
|
||||
#define INT_FAST32_MIN INT_LEAST32_MIN
|
||||
#ifdef stdint_int64_defined
|
||||
typedef int_least64_t int_fast64_t;
|
||||
typedef uint_least64_t uint_fast64_t;
|
||||
typedef int_least64_t int_fast64_t;
|
||||
typedef uint_least64_t uint_fast64_t;
|
||||
# define UINT_FAST64_MAX UINT_LEAST64_MAX
|
||||
# define INT_FAST64_MAX INT_LEAST64_MAX
|
||||
# define INT_FAST64_MIN INT_LEAST64_MIN
|
||||
@ -647,7 +647,7 @@ typedef uint_least32_t uint_fast32_t;
|
||||
* type limits.
|
||||
*/
|
||||
|
||||
#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
|
||||
#if defined(__WATCOMC__) || defined(_MSC_VER) || defined(__GNUC__)
|
||||
# include <wchar.h>
|
||||
# ifndef WCHAR_MIN
|
||||
# define WCHAR_MIN 0
|
||||
@ -662,28 +662,28 @@ typedef uint_least32_t uint_fast32_t;
|
||||
* (u)intptr_t types and limits.
|
||||
*/
|
||||
|
||||
#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
|
||||
#if defined(_MSC_VER) && defined(_UINTPTR_T_DEFINED)
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#ifndef STDINT_H_UINTPTR_T_DEFINED
|
||||
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
|
||||
# if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__) || defined(_WIN64)
|
||||
# define stdint_intptr_bits 64
|
||||
# elif defined (__WATCOMC__) || defined (__TURBOC__)
|
||||
# elif defined(__WATCOMC__) || defined(__TURBOC__)
|
||||
# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
|
||||
# define stdint_intptr_bits 16
|
||||
# else
|
||||
# define stdint_intptr_bits 32
|
||||
# endif
|
||||
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
|
||||
# elif defined(__i386__) || defined(_WIN32) || defined(WIN32)
|
||||
# define stdint_intptr_bits 32
|
||||
# elif defined (__INTEL_COMPILER)
|
||||
# elif defined(__INTEL_COMPILER)
|
||||
/* TODO -- what did Intel do about x86-64? */
|
||||
# endif
|
||||
|
||||
# ifdef stdint_intptr_bits
|
||||
# define stdint_intptr_glue3_i(a,b,c) a##b##c
|
||||
# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
|
||||
# define stdint_intptr_glue3_i(a, b, c) a##b##c
|
||||
# define stdint_intptr_glue3(a, b, c) stdint_intptr_glue3_i(a,b,c)
|
||||
# ifndef PRINTF_INTPTR_MODIFIER
|
||||
# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
|
||||
# endif
|
||||
@ -708,12 +708,12 @@ typedef uint_least32_t uint_fast32_t;
|
||||
# ifndef UINTPTR_C
|
||||
# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
|
||||
# endif
|
||||
typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
|
||||
typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
|
||||
typedef stdint_intptr_glue3 (uint, stdint_intptr_bits, _t) uintptr_t;
|
||||
typedef stdint_intptr_glue3 (int, stdint_intptr_bits, _t) intptr_t;
|
||||
# else
|
||||
/* TODO -- This following is likely wrong for some platforms, and does
|
||||
nothing for the definition of uintptr_t. */
|
||||
typedef ptrdiff_t intptr_t;
|
||||
typedef ptrdiff_t intptr_t;
|
||||
# endif
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#endif
|
||||
@ -728,73 +728,74 @@ typedef uint_least32_t uint_fast32_t;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
|
||||
#if defined(__TEST_PSTDINT_FOR_CORRECTNESS)
|
||||
|
||||
/*
|
||||
/*
|
||||
* Please compile with the maximum warning settings to make sure macros are not
|
||||
* defined more than once.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define glue3_aux(x,y,z) x ## y ## z
|
||||
#define glue3(x,y,z) glue3_aux(x,y,z)
|
||||
|
||||
#define glue3_aux(x, y, z) x ## y ## z
|
||||
#define glue3(x, y, z) glue3_aux(x,y,z)
|
||||
|
||||
#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0);
|
||||
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0);
|
||||
|
||||
#define DECL(us,bits) glue3(DECL,us,) (bits)
|
||||
#define DECL(us, bits) glue3(DECL,us,) (bits)
|
||||
|
||||
#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits)
|
||||
|
||||
int main () {
|
||||
DECL(I,8)
|
||||
DECL(U,8)
|
||||
DECL(I,16)
|
||||
DECL(U,16)
|
||||
DECL(I,32)
|
||||
DECL(U,32)
|
||||
#ifdef INT64_MAX
|
||||
DECL(I,64)
|
||||
DECL(U,64)
|
||||
#endif
|
||||
intmax_t imax = INTMAX_C(0);
|
||||
uintmax_t umax = UINTMAX_C(0);
|
||||
char str0[256], str1[256];
|
||||
|
||||
sprintf (str0, "%d %x\n", 0, ~0);
|
||||
|
||||
sprintf (str1, "%d %x\n", i8, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1);
|
||||
sprintf (str1, "%u %x\n", u8, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1);
|
||||
sprintf (str1, "%d %x\n", i16, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1);
|
||||
sprintf (str1, "%u %x\n", u16, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1);
|
||||
#ifdef INT64_MAX
|
||||
sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1);
|
||||
#endif
|
||||
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1);
|
||||
|
||||
TESTUMAX(8);
|
||||
TESTUMAX(16);
|
||||
TESTUMAX(32);
|
||||
int main()
|
||||
{
|
||||
DECL(I, 8)
|
||||
DECL(U, 8)
|
||||
DECL(I, 16)
|
||||
DECL(U, 16)
|
||||
DECL(I, 32)
|
||||
DECL(U, 32)
|
||||
#ifdef INT64_MAX
|
||||
TESTUMAX(64);
|
||||
DECL(I, 64)
|
||||
DECL(U, 64)
|
||||
#endif
|
||||
intmax_t imax = INTMAX_C(0);
|
||||
uintmax_t umax = UINTMAX_C(0);
|
||||
char str0[256], str1[256];
|
||||
|
||||
sprintf(str0, "%d %x\n", 0, ~0);
|
||||
|
||||
sprintf(str1, "%d %x\n", i8, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with i8 : %s\n", str1);
|
||||
sprintf(str1, "%u %x\n", u8, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with u8 : %s\n", str1);
|
||||
sprintf(str1, "%d %x\n", i16, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with i16 : %s\n", str1);
|
||||
sprintf(str1, "%u %x\n", u16, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with u16 : %s\n", str1);
|
||||
sprintf(str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with i32 : %s\n", str1);
|
||||
sprintf(str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with u32 : %s\n", str1);
|
||||
#ifdef INT64_MAX
|
||||
sprintf(str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with i64 : %s\n", str1);
|
||||
#endif
|
||||
sprintf(str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with imax : %s\n", str1);
|
||||
sprintf(str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
|
||||
if (0 != strcmp(str0, str1)) printf("Something wrong with umax : %s\n", str1);
|
||||
|
||||
TESTUMAX(8);
|
||||
TESTUMAX(16);
|
||||
TESTUMAX(32);
|
||||
#ifdef INT64_MAX
|
||||
TESTUMAX(64);
|
||||
#endif
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
|
||||
#include "ControlFlowGraphUtils.h"
|
||||
|
||||
#include "internal_includes/debug.h"
|
||||
@ -6,22 +5,20 @@
|
||||
#include "internal_includes/Operand.h"
|
||||
|
||||
|
||||
|
||||
// Get the next instruction that's not one of CASE, DEFAULT, LOOP, ENDSWITCH
|
||||
const Instruction *HLSLcc::ControlFlow::Utils::GetNextNonLabelInstruction(const Instruction *psStart, bool *sawEndSwitch /*= 0*/)
|
||||
{
|
||||
const Instruction *inst = psStart;
|
||||
// Skip CASE/DEFAULT/ENDSWITCH/LOOP labels
|
||||
while (inst->eOpcode == OPCODE_CASE || inst->eOpcode == OPCODE_DEFAULT || inst->eOpcode == OPCODE_ENDSWITCH || inst->eOpcode == OPCODE_LOOP)
|
||||
{
|
||||
// We really shouldn't be seeing ENDSWITCH without sawEndSwitch being set (as in, we're expecting it)
|
||||
ASSERT(inst->eOpcode != OPCODE_ENDSWITCH || sawEndSwitch != NULL);
|
||||
if (inst->eOpcode == OPCODE_ENDSWITCH && sawEndSwitch != NULL)
|
||||
*sawEndSwitch = true;
|
||||
inst++;
|
||||
}
|
||||
return inst;
|
||||
|
||||
const Instruction *inst = psStart;
|
||||
// Skip CASE/DEFAULT/ENDSWITCH/LOOP labels
|
||||
while (inst->eOpcode == OPCODE_CASE || inst->eOpcode == OPCODE_DEFAULT || inst->eOpcode == OPCODE_ENDSWITCH || inst->eOpcode == OPCODE_LOOP)
|
||||
{
|
||||
// We really shouldn't be seeing ENDSWITCH without sawEndSwitch being set (as in, we're expecting it)
|
||||
ASSERT(inst->eOpcode != OPCODE_ENDSWITCH || sawEndSwitch != NULL);
|
||||
if (inst->eOpcode == OPCODE_ENDSWITCH && sawEndSwitch != NULL)
|
||||
*sawEndSwitch = true;
|
||||
inst++;
|
||||
}
|
||||
return inst;
|
||||
}
|
||||
|
||||
// For a given flow-control instruction, find the corresponding jump location:
|
||||
@ -37,85 +34,83 @@ const Instruction *HLSLcc::ControlFlow::Utils::GetNextNonLabelInstruction(const
|
||||
// Always returns the beginning of the next block, so skip multiple CASE/DEFAULT labels etc.
|
||||
const Instruction * HLSLcc::ControlFlow::Utils::GetJumpPoint(const Instruction *psStart, bool *sawEndSwitch /*= 0*/, bool *needConnectToParent /* = 0*/)
|
||||
{
|
||||
const Instruction *inst = psStart;
|
||||
int depth = 0;
|
||||
OPCODE_TYPE op = psStart->eOpcode;
|
||||
ASSERT(op == OPCODE_IF || op == OPCODE_ELSE || op == OPCODE_BREAK || op == OPCODE_BREAKC
|
||||
|| op == OPCODE_SWITCH || op == OPCODE_CASE || op == OPCODE_DEFAULT
|
||||
|| op == OPCODE_ENDLOOP || op == OPCODE_CONTINUE || op == OPCODE_CONTINUEC);
|
||||
const Instruction *inst = psStart;
|
||||
int depth = 0;
|
||||
OPCODE_TYPE op = psStart->eOpcode;
|
||||
ASSERT(op == OPCODE_IF || op == OPCODE_ELSE || op == OPCODE_BREAK || op == OPCODE_BREAKC
|
||||
|| op == OPCODE_SWITCH || op == OPCODE_CASE || op == OPCODE_DEFAULT
|
||||
|| op == OPCODE_ENDLOOP || op == OPCODE_CONTINUE || op == OPCODE_CONTINUEC);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
case OPCODE_IF:
|
||||
case OPCODE_ELSE:
|
||||
while (1)
|
||||
{
|
||||
inst++;
|
||||
if ((inst->eOpcode == OPCODE_ELSE || inst->eOpcode == OPCODE_ENDIF) && (depth == 0))
|
||||
{
|
||||
return GetNextNonLabelInstruction(inst + 1, sawEndSwitch);
|
||||
}
|
||||
if (inst->eOpcode == OPCODE_IF)
|
||||
depth++;
|
||||
if (inst->eOpcode == OPCODE_ENDIF)
|
||||
depth--;
|
||||
}
|
||||
case OPCODE_BREAK:
|
||||
case OPCODE_BREAKC:
|
||||
while (1)
|
||||
{
|
||||
inst++;
|
||||
if ((inst->eOpcode == OPCODE_ENDLOOP || inst->eOpcode == OPCODE_ENDSWITCH) && (depth == 0))
|
||||
{
|
||||
return GetNextNonLabelInstruction(inst + 1, sawEndSwitch);
|
||||
}
|
||||
if (inst->eOpcode == OPCODE_SWITCH || inst->eOpcode == OPCODE_LOOP)
|
||||
depth++;
|
||||
if (inst->eOpcode == OPCODE_ENDSWITCH || inst->eOpcode == OPCODE_ENDLOOP)
|
||||
depth--;
|
||||
}
|
||||
case OPCODE_CONTINUE:
|
||||
case OPCODE_CONTINUEC:
|
||||
case OPCODE_ENDLOOP:
|
||||
while (1)
|
||||
{
|
||||
inst--;
|
||||
if ((inst->eOpcode == OPCODE_LOOP) && (depth == 0))
|
||||
{
|
||||
return GetNextNonLabelInstruction(inst + 1, sawEndSwitch);
|
||||
}
|
||||
if (inst->eOpcode == OPCODE_LOOP)
|
||||
depth--;
|
||||
if (inst->eOpcode == OPCODE_ENDLOOP)
|
||||
depth++;
|
||||
}
|
||||
case OPCODE_SWITCH:
|
||||
case OPCODE_CASE:
|
||||
case OPCODE_DEFAULT:
|
||||
while (1)
|
||||
{
|
||||
inst++;
|
||||
if ((inst->eOpcode == OPCODE_CASE || inst->eOpcode == OPCODE_DEFAULT || inst->eOpcode == OPCODE_ENDSWITCH) && (depth == 0))
|
||||
{
|
||||
// Note that we'll skip setting sawEndSwitch if inst->eOpcode = OPCODE_ENDSWITCH
|
||||
// so that BasicBlock::Build can distinguish between there being a direct route
|
||||
// from SWITCH->ENDSWITCH (CASE followed directly by ENDSWITCH) and not.
|
||||
switch (op)
|
||||
{
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
case OPCODE_IF:
|
||||
case OPCODE_ELSE:
|
||||
while (1)
|
||||
{
|
||||
inst++;
|
||||
if ((inst->eOpcode == OPCODE_ELSE || inst->eOpcode == OPCODE_ENDIF) && (depth == 0))
|
||||
{
|
||||
return GetNextNonLabelInstruction(inst + 1, sawEndSwitch);
|
||||
}
|
||||
if (inst->eOpcode == OPCODE_IF)
|
||||
depth++;
|
||||
if (inst->eOpcode == OPCODE_ENDIF)
|
||||
depth--;
|
||||
}
|
||||
case OPCODE_BREAK:
|
||||
case OPCODE_BREAKC:
|
||||
while (1)
|
||||
{
|
||||
inst++;
|
||||
if ((inst->eOpcode == OPCODE_ENDLOOP || inst->eOpcode == OPCODE_ENDSWITCH) && (depth == 0))
|
||||
{
|
||||
return GetNextNonLabelInstruction(inst + 1, sawEndSwitch);
|
||||
}
|
||||
if (inst->eOpcode == OPCODE_SWITCH || inst->eOpcode == OPCODE_LOOP)
|
||||
depth++;
|
||||
if (inst->eOpcode == OPCODE_ENDSWITCH || inst->eOpcode == OPCODE_ENDLOOP)
|
||||
depth--;
|
||||
}
|
||||
case OPCODE_CONTINUE:
|
||||
case OPCODE_CONTINUEC:
|
||||
case OPCODE_ENDLOOP:
|
||||
while (1)
|
||||
{
|
||||
inst--;
|
||||
if ((inst->eOpcode == OPCODE_LOOP) && (depth == 0))
|
||||
{
|
||||
return GetNextNonLabelInstruction(inst + 1, sawEndSwitch);
|
||||
}
|
||||
if (inst->eOpcode == OPCODE_LOOP)
|
||||
depth--;
|
||||
if (inst->eOpcode == OPCODE_ENDLOOP)
|
||||
depth++;
|
||||
}
|
||||
case OPCODE_SWITCH:
|
||||
case OPCODE_CASE:
|
||||
case OPCODE_DEFAULT:
|
||||
while (1)
|
||||
{
|
||||
inst++;
|
||||
if ((inst->eOpcode == OPCODE_CASE || inst->eOpcode == OPCODE_DEFAULT || inst->eOpcode == OPCODE_ENDSWITCH) && (depth == 0))
|
||||
{
|
||||
// Note that we'll skip setting sawEndSwitch if inst->eOpcode = OPCODE_ENDSWITCH
|
||||
// so that BasicBlock::Build can distinguish between there being a direct route
|
||||
// from SWITCH->ENDSWITCH (CASE followed directly by ENDSWITCH) and not.
|
||||
|
||||
if (inst->eOpcode == OPCODE_ENDSWITCH && sawEndSwitch != 0)
|
||||
*sawEndSwitch = true;
|
||||
if (inst->eOpcode == OPCODE_ENDSWITCH && sawEndSwitch != 0)
|
||||
*sawEndSwitch = true;
|
||||
|
||||
return GetNextNonLabelInstruction(inst + 1, needConnectToParent);
|
||||
}
|
||||
if (inst->eOpcode == OPCODE_SWITCH)
|
||||
depth++;
|
||||
if (inst->eOpcode == OPCODE_ENDSWITCH)
|
||||
depth--;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
return GetNextNonLabelInstruction(inst + 1, needConnectToParent);
|
||||
}
|
||||
if (inst->eOpcode == OPCODE_SWITCH)
|
||||
depth++;
|
||||
if (inst->eOpcode == OPCODE_ENDSWITCH)
|
||||
depth--;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,2 +1 @@
|
||||
|
||||
#include "internal_includes/Declaration.h"
|
||||
#include "internal_includes/Declaration.h"
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#include "internal_includes/HLSLCrossCompilerContext.h"
|
||||
#include "internal_includes/HLSLccToolkit.h"
|
||||
#include "internal_includes/Shader.h"
|
||||
@ -13,287 +12,289 @@
|
||||
|
||||
void HLSLCrossCompilerContext::DoDataTypeAnalysis(ShaderPhase *psPhase)
|
||||
{
|
||||
size_t ui32DeclCount = psPhase->psDecl.size();
|
||||
uint32_t i;
|
||||
size_t ui32DeclCount = psPhase->psDecl.size();
|
||||
uint32_t i;
|
||||
|
||||
psPhase->psTempDeclaration = NULL;
|
||||
psPhase->ui32OrigTemps = 0;
|
||||
psPhase->ui32TotalTemps = 0;
|
||||
psPhase->psTempDeclaration = NULL;
|
||||
psPhase->ui32OrigTemps = 0;
|
||||
psPhase->ui32TotalTemps = 0;
|
||||
|
||||
// Retrieve the temp decl count
|
||||
for (i = 0; i < ui32DeclCount; ++i)
|
||||
{
|
||||
if (psPhase->psDecl[i].eOpcode == OPCODE_DCL_TEMPS)
|
||||
{
|
||||
psPhase->ui32TotalTemps = psPhase->psDecl[i].value.ui32NumTemps;
|
||||
psPhase->psTempDeclaration = &psPhase->psDecl[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Retrieve the temp decl count
|
||||
for (i = 0; i < ui32DeclCount; ++i)
|
||||
{
|
||||
if (psPhase->psDecl[i].eOpcode == OPCODE_DCL_TEMPS)
|
||||
{
|
||||
psPhase->ui32TotalTemps = psPhase->psDecl[i].value.ui32NumTemps;
|
||||
psPhase->psTempDeclaration = &psPhase->psDecl[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (psPhase->ui32TotalTemps == 0)
|
||||
return;
|
||||
if (psPhase->ui32TotalTemps == 0)
|
||||
return;
|
||||
|
||||
psPhase->ui32OrigTemps = psPhase->ui32TotalTemps;
|
||||
psPhase->ui32OrigTemps = psPhase->ui32TotalTemps;
|
||||
|
||||
// The split table is a table containing the index of the original register this register was split out from, or 0xffffffff
|
||||
// Format: lowest 16 bits: original register. bits 16-23: rebase (eg value of 1 means .yzw was changed to .xyz): bits 24-31: component count
|
||||
psPhase->pui32SplitInfo.clear();
|
||||
psPhase->pui32SplitInfo.resize(psPhase->ui32TotalTemps * 2, 0xffffffff);
|
||||
// The split table is a table containing the index of the original register this register was split out from, or 0xffffffff
|
||||
// Format: lowest 16 bits: original register. bits 16-23: rebase (eg value of 1 means .yzw was changed to .xyz): bits 24-31: component count
|
||||
psPhase->pui32SplitInfo.clear();
|
||||
psPhase->pui32SplitInfo.resize(psPhase->ui32TotalTemps * 2, 0xffffffff);
|
||||
|
||||
// Build use-define chains and split temps based on those.
|
||||
{
|
||||
DefineUseChains duChains;
|
||||
UseDefineChains udChains;
|
||||
// Build use-define chains and split temps based on those.
|
||||
{
|
||||
DefineUseChains duChains;
|
||||
UseDefineChains udChains;
|
||||
|
||||
BuildUseDefineChains(psPhase->psInst, psPhase->ui32TotalTemps, duChains, udChains, psPhase->GetCFG());
|
||||
BuildUseDefineChains(psPhase->psInst, psPhase->ui32TotalTemps, duChains, udChains, psPhase->GetCFG());
|
||||
|
||||
CalculateStandaloneDefinitions(duChains, psPhase->ui32TotalTemps);
|
||||
CalculateStandaloneDefinitions(duChains, psPhase->ui32TotalTemps);
|
||||
|
||||
// Only do sampler precision downgrade on pixel shaders.
|
||||
if (psShader->eShaderType == PIXEL_SHADER)
|
||||
UpdateSamplerPrecisions(psShader->sInfo, duChains, psPhase->ui32TotalTemps);
|
||||
// Only do sampler precision downgrade on pixel shaders.
|
||||
if (psShader->eShaderType == PIXEL_SHADER)
|
||||
UpdateSamplerPrecisions(psShader->sInfo, duChains, psPhase->ui32TotalTemps);
|
||||
|
||||
UDSplitTemps(&psPhase->ui32TotalTemps, duChains, udChains, psPhase->pui32SplitInfo);
|
||||
UDSplitTemps(&psPhase->ui32TotalTemps, duChains, udChains, psPhase->pui32SplitInfo);
|
||||
|
||||
WriteBackUsesAndDefines(duChains);
|
||||
}
|
||||
|
||||
HLSLcc::DataTypeAnalysis::SetDataTypes(this, psPhase->psInst, psPhase->ui32TotalTemps, psPhase->peTempTypes);
|
||||
WriteBackUsesAndDefines(duChains);
|
||||
}
|
||||
|
||||
if (psPhase->psTempDeclaration && (psPhase->ui32OrigTemps != psPhase->ui32TotalTemps))
|
||||
psPhase->psTempDeclaration->value.ui32NumTemps = psPhase->ui32TotalTemps;
|
||||
HLSLcc::DataTypeAnalysis::SetDataTypes(this, psPhase->psInst, psPhase->ui32TotalTemps, psPhase->peTempTypes);
|
||||
|
||||
if (psPhase->psTempDeclaration && (psPhase->ui32OrigTemps != psPhase->ui32TotalTemps))
|
||||
psPhase->psTempDeclaration->value.ui32NumTemps = psPhase->ui32TotalTemps;
|
||||
}
|
||||
|
||||
void HLSLCrossCompilerContext::ClearDependencyData()
|
||||
{
|
||||
|
||||
switch (psShader->eShaderType)
|
||||
{
|
||||
case PIXEL_SHADER:
|
||||
{
|
||||
psDependencies->ClearCrossDependencyData();
|
||||
break;
|
||||
}
|
||||
case HULL_SHADER:
|
||||
{
|
||||
psDependencies->eTessPartitioning = TESSELLATOR_PARTITIONING_UNDEFINED;
|
||||
psDependencies->eTessOutPrim = TESSELLATOR_OUTPUT_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (psShader->eShaderType)
|
||||
{
|
||||
case PIXEL_SHADER:
|
||||
{
|
||||
psDependencies->ClearCrossDependencyData();
|
||||
break;
|
||||
}
|
||||
case HULL_SHADER:
|
||||
{
|
||||
psDependencies->eTessPartitioning = TESSELLATOR_PARTITIONING_UNDEFINED;
|
||||
psDependencies->eTessOutPrim = TESSELLATOR_OUTPUT_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HLSLCrossCompilerContext::AddIndentation()
|
||||
{
|
||||
int i;
|
||||
bstring glsl = *currentGLSLString;
|
||||
for (i = 0; i < indent; ++i)
|
||||
{
|
||||
bcatcstr(glsl, " ");
|
||||
}
|
||||
int i;
|
||||
bstring glsl = *currentGLSLString;
|
||||
for (i = 0; i < indent; ++i)
|
||||
{
|
||||
bcatcstr(glsl, " ");
|
||||
}
|
||||
}
|
||||
|
||||
bool HLSLCrossCompilerContext::RequireExtension(const std::string &extName)
|
||||
{
|
||||
if (m_EnabledExtensions.find(extName) != m_EnabledExtensions.end())
|
||||
return true;
|
||||
if (m_EnabledExtensions.find(extName) != m_EnabledExtensions.end())
|
||||
return true;
|
||||
|
||||
m_EnabledExtensions.insert(extName);
|
||||
bformata(extensions, "#extension %s : require\n", extName.c_str());
|
||||
return false;
|
||||
m_EnabledExtensions.insert(extName);
|
||||
bformata(extensions, "#extension %s : require\n", extName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HLSLCrossCompilerContext::EnableExtension(const std::string &extName)
|
||||
{
|
||||
if (m_EnabledExtensions.find(extName) != m_EnabledExtensions.end())
|
||||
return true;
|
||||
if (m_EnabledExtensions.find(extName) != m_EnabledExtensions.end())
|
||||
return true;
|
||||
|
||||
m_EnabledExtensions.insert(extName);
|
||||
bformata(extensions, "#ifdef %s\n", extName.c_str());
|
||||
bformata(extensions, "#extension %s : enable\n", extName.c_str());
|
||||
bcatcstr(extensions, "#endif\n");
|
||||
return false;
|
||||
m_EnabledExtensions.insert(extName);
|
||||
bformata(extensions, "#ifdef %s\n", extName.c_str());
|
||||
bformata(extensions, "#extension %s : enable\n", extName.c_str());
|
||||
bcatcstr(extensions, "#endif\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string HLSLCrossCompilerContext::GetDeclaredInputName(const Operand* psOperand, int *piRebase, int iIgnoreRedirect, uint32_t *puiIgnoreSwizzle) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
const ShaderInfo::InOutSignature* psIn = NULL;
|
||||
int regSpace = psOperand->GetRegisterSpace(this);
|
||||
std::ostringstream oss;
|
||||
const ShaderInfo::InOutSignature* psIn = NULL;
|
||||
int regSpace = psOperand->GetRegisterSpace(this);
|
||||
|
||||
if (iIgnoreRedirect == 0)
|
||||
{
|
||||
if ((regSpace == 0 && psShader->asPhases[currentPhase].acInputNeedsRedirect[psOperand->ui32RegisterNumber] == 0xfe)
|
||||
||
|
||||
(regSpace == 1 && psShader->asPhases[currentPhase].acPatchConstantsNeedsRedirect[psOperand->ui32RegisterNumber] == 0xfe))
|
||||
{
|
||||
oss << "phase" << currentPhase << "_Input" << regSpace << "_" << psOperand->ui32RegisterNumber;
|
||||
if (piRebase)
|
||||
*piRebase = 0;
|
||||
return oss.str();
|
||||
}
|
||||
}
|
||||
if (iIgnoreRedirect == 0)
|
||||
{
|
||||
if ((regSpace == 0 && psShader->asPhases[currentPhase].acInputNeedsRedirect[psOperand->ui32RegisterNumber] == 0xfe)
|
||||
||
|
||||
(regSpace == 1 && psShader->asPhases[currentPhase].acPatchConstantsNeedsRedirect[psOperand->ui32RegisterNumber] == 0xfe))
|
||||
{
|
||||
oss << "phase" << currentPhase << "_Input" << regSpace << "_" << psOperand->ui32RegisterNumber;
|
||||
if (piRebase)
|
||||
*piRebase = 0;
|
||||
return oss.str();
|
||||
}
|
||||
}
|
||||
|
||||
if (regSpace == 0)
|
||||
psShader->sInfo.GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->GetAccessMask(), &psIn, true);
|
||||
else
|
||||
psShader->sInfo.GetPatchConstantSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->GetAccessMask(), &psIn, true);
|
||||
if (regSpace == 0)
|
||||
psShader->sInfo.GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->GetAccessMask(), &psIn, true);
|
||||
else
|
||||
psShader->sInfo.GetPatchConstantSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->GetAccessMask(), &psIn, true);
|
||||
|
||||
if (psIn && piRebase)
|
||||
*piRebase = psIn->iRebase;
|
||||
if (psIn && piRebase)
|
||||
*piRebase = psIn->iRebase;
|
||||
|
||||
const std::string patchPrefix = psShader->eTargetLanguage == LANG_METAL ? "patch." : "patch";
|
||||
std::string res = "";
|
||||
const std::string patchPrefix = psShader->eTargetLanguage == LANG_METAL ? "patch." : "patch";
|
||||
std::string res = "";
|
||||
|
||||
bool skipPrefix = false;
|
||||
if (psTranslator->TranslateSystemValue(psOperand, psIn, res, puiIgnoreSwizzle, psShader->aIndexedInput[regSpace][psOperand->ui32RegisterNumber] != 0, true, &skipPrefix, &iIgnoreRedirect))
|
||||
{
|
||||
if (psShader->eTargetLanguage == LANG_METAL && (iIgnoreRedirect == 0) && !skipPrefix)
|
||||
return inputPrefix + res;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
bool skipPrefix = false;
|
||||
if (psTranslator->TranslateSystemValue(psOperand, psIn, res, puiIgnoreSwizzle, psShader->aIndexedInput[regSpace][psOperand->ui32RegisterNumber] != 0, true, &skipPrefix, &iIgnoreRedirect))
|
||||
{
|
||||
if (psShader->eTargetLanguage == LANG_METAL && (iIgnoreRedirect == 0) && !skipPrefix)
|
||||
return inputPrefix + res;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
|
||||
ASSERT(psIn != NULL);
|
||||
oss << inputPrefix << (regSpace == 1 ? patchPrefix : "") << psIn->semanticName << psIn->ui32SemanticIndex;
|
||||
return oss.str();
|
||||
ASSERT(psIn != NULL);
|
||||
oss << inputPrefix << (regSpace == 1 ? patchPrefix : "") << psIn->semanticName << psIn->ui32SemanticIndex;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
std::string HLSLCrossCompilerContext::GetDeclaredOutputName(const Operand* psOperand,
|
||||
int* piStream,
|
||||
uint32_t *puiIgnoreSwizzle,
|
||||
int *piRebase,
|
||||
int iIgnoreRedirect) const
|
||||
int* piStream,
|
||||
uint32_t *puiIgnoreSwizzle,
|
||||
int *piRebase,
|
||||
int iIgnoreRedirect) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
const ShaderInfo::InOutSignature* psOut = NULL;
|
||||
int regSpace = psOperand->GetRegisterSpace(this);
|
||||
std::ostringstream oss;
|
||||
const ShaderInfo::InOutSignature* psOut = NULL;
|
||||
int regSpace = psOperand->GetRegisterSpace(this);
|
||||
|
||||
if (iIgnoreRedirect == 0)
|
||||
{
|
||||
if ((regSpace == 0 && psShader->asPhases[currentPhase].acOutputNeedsRedirect[psOperand->ui32RegisterNumber] == 0xfe)
|
||||
|| (regSpace == 1 && psShader->asPhases[currentPhase].acPatchConstantsNeedsRedirect[psOperand->ui32RegisterNumber] == 0xfe))
|
||||
{
|
||||
oss << "phase" << currentPhase << "_Output" << regSpace << "_" << psOperand->ui32RegisterNumber;
|
||||
if (piRebase)
|
||||
*piRebase = 0;
|
||||
return oss.str();
|
||||
}
|
||||
}
|
||||
if (iIgnoreRedirect == 0)
|
||||
{
|
||||
if ((regSpace == 0 && psShader->asPhases[currentPhase].acOutputNeedsRedirect[psOperand->ui32RegisterNumber] == 0xfe)
|
||||
|| (regSpace == 1 && psShader->asPhases[currentPhase].acPatchConstantsNeedsRedirect[psOperand->ui32RegisterNumber] == 0xfe))
|
||||
{
|
||||
oss << "phase" << currentPhase << "_Output" << regSpace << "_" << psOperand->ui32RegisterNumber;
|
||||
if (piRebase)
|
||||
*piRebase = 0;
|
||||
return oss.str();
|
||||
}
|
||||
}
|
||||
|
||||
if (regSpace == 0)
|
||||
psShader->sInfo.GetOutputSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->GetAccessMask(), psShader->ui32CurrentVertexOutputStream, &psOut, true);
|
||||
else
|
||||
psShader->sInfo.GetPatchConstantSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->GetAccessMask(), &psOut, true);
|
||||
if (regSpace == 0)
|
||||
psShader->sInfo.GetOutputSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->GetAccessMask(), psShader->ui32CurrentVertexOutputStream, &psOut, true);
|
||||
else
|
||||
psShader->sInfo.GetPatchConstantSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->GetAccessMask(), &psOut, true);
|
||||
|
||||
|
||||
if (psOut && piRebase)
|
||||
*piRebase = psOut->iRebase;
|
||||
if (psOut && piRebase)
|
||||
*piRebase = psOut->iRebase;
|
||||
|
||||
if (psOut && (psOut->isIndexed.find(currentPhase) != psOut->isIndexed.end()))
|
||||
{
|
||||
// Need to route through temp output variable
|
||||
oss << "phase" << currentPhase << "_Output" << regSpace << "_" << psOut->indexStart.find(currentPhase)->second;
|
||||
if (!psOperand->m_SubOperands[0].get())
|
||||
{
|
||||
oss << "[" << psOperand->ui32RegisterNumber << "]";
|
||||
}
|
||||
if (piRebase)
|
||||
*piRebase = 0;
|
||||
return oss.str();
|
||||
}
|
||||
if (psOut && (psOut->isIndexed.find(currentPhase) != psOut->isIndexed.end()))
|
||||
{
|
||||
// Need to route through temp output variable
|
||||
oss << "phase" << currentPhase << "_Output" << regSpace << "_" << psOut->indexStart.find(currentPhase)->second;
|
||||
if (!psOperand->m_SubOperands[0].get())
|
||||
{
|
||||
oss << "[" << psOperand->ui32RegisterNumber << "]";
|
||||
}
|
||||
if (piRebase)
|
||||
*piRebase = 0;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
const std::string patchPrefix = psShader->eTargetLanguage == LANG_METAL ? "patch." : "patch";
|
||||
std::string res = "";
|
||||
const std::string patchPrefix = psShader->eTargetLanguage == LANG_METAL ? "patch." : "patch";
|
||||
std::string res = "";
|
||||
|
||||
if (psTranslator->TranslateSystemValue(psOperand, psOut, res, puiIgnoreSwizzle, psShader->aIndexedOutput[regSpace][psOperand->ui32RegisterNumber], false, NULL, &iIgnoreRedirect))
|
||||
{
|
||||
// clip/cull planes will always have interim variable, as HLSL operates on float4 but we need to size output accordingly with actual planes count
|
||||
// with tessellation factor buffers, a separate buffer from output is used. for some reason TranslateSystemValue return *outSkipPrefix = true
|
||||
// for ALL system vars and then we simply ignore it here, so opt to modify iIgnoreRedirect for these special cases
|
||||
if (psTranslator->TranslateSystemValue(psOperand, psOut, res, puiIgnoreSwizzle, psShader->aIndexedOutput[regSpace][psOperand->ui32RegisterNumber], false, NULL, &iIgnoreRedirect))
|
||||
{
|
||||
// clip/cull planes will always have interim variable, as HLSL operates on float4 but we need to size output accordingly with actual planes count
|
||||
// with tessellation factor buffers, a separate buffer from output is used. for some reason TranslateSystemValue return *outSkipPrefix = true
|
||||
// for ALL system vars and then we simply ignore it here, so opt to modify iIgnoreRedirect for these special cases
|
||||
|
||||
if (psShader->eTargetLanguage == LANG_METAL && regSpace == 0 && (iIgnoreRedirect == 0))
|
||||
return outputPrefix + res;
|
||||
else if (psShader->eTargetLanguage == LANG_METAL && (iIgnoreRedirect == 0))
|
||||
return patchPrefix + res;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
ASSERT(psOut != NULL);
|
||||
if (psShader->eTargetLanguage == LANG_METAL && regSpace == 0 && (iIgnoreRedirect == 0))
|
||||
return outputPrefix + res;
|
||||
else if (psShader->eTargetLanguage == LANG_METAL && (iIgnoreRedirect == 0))
|
||||
return patchPrefix + res;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
ASSERT(psOut != NULL);
|
||||
|
||||
oss << outputPrefix << (regSpace == 1 ? patchPrefix : "") << psOut->semanticName << psOut->ui32SemanticIndex;
|
||||
return oss.str();
|
||||
oss << outputPrefix << (regSpace == 1 ? patchPrefix : "") << psOut->semanticName << psOut->ui32SemanticIndex;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
bool HLSLCrossCompilerContext::OutputNeedsDeclaring(const Operand* psOperand, const int count)
|
||||
{
|
||||
char compMask = (char)psOperand->ui32CompMask;
|
||||
int regSpace = psOperand->GetRegisterSpace(this);
|
||||
uint32_t startIndex = psOperand->ui32RegisterNumber + (psShader->ui32CurrentVertexOutputStream * 1024); // Assume less than 1K input streams
|
||||
ASSERT(psShader->ui32CurrentVertexOutputStream < 4);
|
||||
char compMask = (char)psOperand->ui32CompMask;
|
||||
int regSpace = psOperand->GetRegisterSpace(this);
|
||||
uint32_t startIndex = psOperand->ui32RegisterNumber + (psShader->ui32CurrentVertexOutputStream * 1024); // Assume less than 1K input streams
|
||||
ASSERT(psShader->ui32CurrentVertexOutputStream < 4);
|
||||
|
||||
// First check for various builtins, mostly depth-output ones.
|
||||
if (psShader->eShaderType == PIXEL_SHADER)
|
||||
{
|
||||
if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL ||
|
||||
psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// First check for various builtins, mostly depth-output ones.
|
||||
if (psShader->eShaderType == PIXEL_SHADER)
|
||||
{
|
||||
if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL ||
|
||||
psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH)
|
||||
{
|
||||
// GL doesn't need declaration, Metal does.
|
||||
return psShader->eTargetLanguage == LANG_METAL;
|
||||
}
|
||||
}
|
||||
if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH)
|
||||
{
|
||||
// GL doesn't need declaration, Metal does.
|
||||
return psShader->eTargetLanguage == LANG_METAL;
|
||||
}
|
||||
}
|
||||
|
||||
// Needs declaring if any of the components hasn't been already declared
|
||||
if ((compMask & ~psShader->acOutputDeclared[regSpace][startIndex]) != 0)
|
||||
{
|
||||
int offset;
|
||||
const ShaderInfo::InOutSignature* psSignature = NULL;
|
||||
// Needs declaring if any of the components hasn't been already declared
|
||||
if ((compMask & ~psShader->acOutputDeclared[regSpace][startIndex]) != 0)
|
||||
{
|
||||
int offset;
|
||||
const ShaderInfo::InOutSignature* psSignature = NULL;
|
||||
|
||||
if (psOperand->eSpecialName == NAME_UNDEFINED)
|
||||
{
|
||||
// Need to fetch the actual comp mask
|
||||
if (regSpace == 0)
|
||||
psShader->sInfo.GetOutputSignatureFromRegister(
|
||||
psOperand->ui32RegisterNumber,
|
||||
psOperand->ui32CompMask,
|
||||
psShader->ui32CurrentVertexOutputStream,
|
||||
&psSignature);
|
||||
else
|
||||
psShader->sInfo.GetPatchConstantSignatureFromRegister(
|
||||
psOperand->ui32RegisterNumber,
|
||||
psOperand->ui32CompMask,
|
||||
&psSignature);
|
||||
if (psOperand->eSpecialName == NAME_UNDEFINED)
|
||||
{
|
||||
// Need to fetch the actual comp mask
|
||||
if (regSpace == 0)
|
||||
psShader->sInfo.GetOutputSignatureFromRegister(
|
||||
psOperand->ui32RegisterNumber,
|
||||
psOperand->ui32CompMask,
|
||||
psShader->ui32CurrentVertexOutputStream,
|
||||
&psSignature);
|
||||
else
|
||||
psShader->sInfo.GetPatchConstantSignatureFromRegister(
|
||||
psOperand->ui32RegisterNumber,
|
||||
psOperand->ui32CompMask,
|
||||
&psSignature);
|
||||
|
||||
compMask = (char)psSignature->ui32Mask;
|
||||
}
|
||||
for (offset = 0; offset < count; offset++)
|
||||
{
|
||||
psShader->acOutputDeclared[regSpace][startIndex + offset] |= compMask;
|
||||
}
|
||||
compMask = (char)psSignature->ui32Mask;
|
||||
}
|
||||
for (offset = 0; offset < count; offset++)
|
||||
{
|
||||
psShader->acOutputDeclared[regSpace][startIndex + offset] |= compMask;
|
||||
}
|
||||
|
||||
if (psSignature && (psSignature->semanticName == "PSIZE") && (psShader->eTargetLanguage != LANG_METAL))
|
||||
{
|
||||
// gl_PointSize, doesn't need declaring. TODO: Metal doesn't have pointsize at all?
|
||||
return false;
|
||||
}
|
||||
if (psSignature && (psSignature->semanticName == "PSIZE") && (psShader->eTargetLanguage != LANG_METAL))
|
||||
{
|
||||
// gl_PointSize, doesn't need declaring. TODO: Metal doesn't have pointsize at all?
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HLSLCrossCompilerContext::IsVulkan() const
|
||||
{
|
||||
return (flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0;
|
||||
return (flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0;
|
||||
}
|
||||
|
||||
bool HLSLCrossCompilerContext::IsSwitch() const
|
||||
{
|
||||
return (flags & HLSLCC_FLAG_NVN_TARGET) != 0;
|
||||
}
|
||||
|
306
src/HLSLcc.cpp
306
src/HLSLcc.cpp
@ -1,4 +1,3 @@
|
||||
|
||||
#include "hlslcc.h"
|
||||
|
||||
#include <memory>
|
||||
@ -30,192 +29,191 @@
|
||||
|
||||
|
||||
HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader,
|
||||
unsigned int flags,
|
||||
GLLang language,
|
||||
const GlExtensions *extensions,
|
||||
GLSLCrossDependencyData* dependencies,
|
||||
HLSLccSamplerPrecisionInfo& samplerPrecisions,
|
||||
HLSLccReflection& reflectionCallbacks,
|
||||
GLSLShader* result)
|
||||
unsigned int flags,
|
||||
GLLang language,
|
||||
const GlExtensions *extensions,
|
||||
GLSLCrossDependencyData* dependencies,
|
||||
HLSLccSamplerPrecisionInfo& samplerPrecisions,
|
||||
HLSLccReflection& reflectionCallbacks,
|
||||
GLSLShader* result)
|
||||
{
|
||||
uint32_t* tokens;
|
||||
char* glslcstr = NULL;
|
||||
int GLSLShaderType = GL_FRAGMENT_SHADER_ARB;
|
||||
int success = 0;
|
||||
uint32_t i;
|
||||
uint32_t* tokens;
|
||||
char* glslcstr = NULL;
|
||||
int GLSLShaderType = GL_FRAGMENT_SHADER_ARB;
|
||||
int success = 0;
|
||||
uint32_t i;
|
||||
|
||||
tokens = (uint32_t*)shader;
|
||||
tokens = (uint32_t*)shader;
|
||||
|
||||
std::auto_ptr<Shader> psShader(DecodeDXBC(tokens, flags));
|
||||
std::auto_ptr<Shader> psShader(DecodeDXBC(tokens, flags));
|
||||
|
||||
if (psShader.get())
|
||||
{
|
||||
HLSLCrossCompilerContext sContext(reflectionCallbacks);
|
||||
if (psShader.get())
|
||||
{
|
||||
HLSLCrossCompilerContext sContext(reflectionCallbacks);
|
||||
|
||||
// Add shader precisions from the list
|
||||
psShader->sInfo.AddSamplerPrecisions(samplerPrecisions);
|
||||
// Add shader precisions from the list
|
||||
psShader->sInfo.AddSamplerPrecisions(samplerPrecisions);
|
||||
|
||||
if (psShader->ui32MajorVersion <= 3)
|
||||
{
|
||||
flags &= ~HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS;
|
||||
}
|
||||
if (psShader->ui32MajorVersion <= 3)
|
||||
{
|
||||
flags &= ~HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS;
|
||||
}
|
||||
|
||||
sContext.psShader = psShader.get();
|
||||
sContext.flags = flags;
|
||||
sContext.psShader = psShader.get();
|
||||
sContext.flags = flags;
|
||||
|
||||
// If dependencies == NULL, we'll create a dummy object for it so that there's always something there.
|
||||
std::auto_ptr<GLSLCrossDependencyData> depPtr(NULL);
|
||||
if (dependencies == NULL)
|
||||
{
|
||||
depPtr.reset(new GLSLCrossDependencyData());
|
||||
sContext.psDependencies = depPtr.get();
|
||||
}
|
||||
else
|
||||
sContext.psDependencies = dependencies;
|
||||
// If dependencies == NULL, we'll create a dummy object for it so that there's always something there.
|
||||
std::auto_ptr<GLSLCrossDependencyData> depPtr(NULL);
|
||||
if (dependencies == NULL)
|
||||
{
|
||||
depPtr.reset(new GLSLCrossDependencyData());
|
||||
sContext.psDependencies = depPtr.get();
|
||||
}
|
||||
else
|
||||
sContext.psDependencies = dependencies;
|
||||
|
||||
for (i = 0; i < psShader->asPhases.size(); ++i)
|
||||
{
|
||||
psShader->asPhases[i].hasPostShaderCode = 0;
|
||||
}
|
||||
for (i = 0; i < psShader->asPhases.size(); ++i)
|
||||
{
|
||||
psShader->asPhases[i].hasPostShaderCode = 0;
|
||||
}
|
||||
|
||||
if (language == LANG_METAL)
|
||||
{
|
||||
// Geometry shader is not supported
|
||||
if (psShader->eShaderType == GEOMETRY_SHADER)
|
||||
{
|
||||
result->sourceCode = "";
|
||||
return 0;
|
||||
}
|
||||
ToMetal translator(&sContext);
|
||||
if(!translator.Translate())
|
||||
{
|
||||
bdestroy(sContext.glsl);
|
||||
for (i = 0; i < psShader->asPhases.size(); ++i)
|
||||
{
|
||||
bdestroy(psShader->asPhases[i].postShaderCode);
|
||||
bdestroy(psShader->asPhases[i].earlyMain);
|
||||
}
|
||||
if (language == LANG_METAL)
|
||||
{
|
||||
// Geometry shader is not supported
|
||||
if (psShader->eShaderType == GEOMETRY_SHADER)
|
||||
{
|
||||
result->sourceCode = "";
|
||||
return 0;
|
||||
}
|
||||
ToMetal translator(&sContext);
|
||||
if (!translator.Translate())
|
||||
{
|
||||
bdestroy(sContext.glsl);
|
||||
for (i = 0; i < psShader->asPhases.size(); ++i)
|
||||
{
|
||||
bdestroy(psShader->asPhases[i].postShaderCode);
|
||||
bdestroy(psShader->asPhases[i].earlyMain);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ToGLSL translator(&sContext);
|
||||
language = translator.SetLanguage(language);
|
||||
translator.SetExtensions(extensions);
|
||||
if (!translator.Translate())
|
||||
{
|
||||
bdestroy(sContext.glsl);
|
||||
for (i = 0; i < psShader->asPhases.size(); ++i)
|
||||
{
|
||||
bdestroy(psShader->asPhases[i].postShaderCode);
|
||||
bdestroy(psShader->asPhases[i].earlyMain);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ToGLSL translator(&sContext);
|
||||
language = translator.SetLanguage(language);
|
||||
translator.SetExtensions(extensions);
|
||||
if (!translator.Translate())
|
||||
{
|
||||
bdestroy(sContext.glsl);
|
||||
for (i = 0; i < psShader->asPhases.size(); ++i)
|
||||
{
|
||||
bdestroy(psShader->asPhases[i].postShaderCode);
|
||||
bdestroy(psShader->asPhases[i].earlyMain);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (psShader->eShaderType)
|
||||
{
|
||||
case VERTEX_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_VERTEX_SHADER_ARB;
|
||||
break;
|
||||
}
|
||||
case GEOMETRY_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_GEOMETRY_SHADER;
|
||||
break;
|
||||
}
|
||||
case DOMAIN_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_TESS_EVALUATION_SHADER;
|
||||
break;
|
||||
}
|
||||
case HULL_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_TESS_CONTROL_SHADER;
|
||||
break;
|
||||
}
|
||||
case COMPUTE_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_COMPUTE_SHADER;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (psShader->eShaderType)
|
||||
{
|
||||
case VERTEX_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_VERTEX_SHADER_ARB;
|
||||
break;
|
||||
}
|
||||
case GEOMETRY_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_GEOMETRY_SHADER;
|
||||
break;
|
||||
}
|
||||
case DOMAIN_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_TESS_EVALUATION_SHADER;
|
||||
break;
|
||||
}
|
||||
case HULL_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_TESS_CONTROL_SHADER;
|
||||
break;
|
||||
}
|
||||
case COMPUTE_SHADER:
|
||||
{
|
||||
GLSLShaderType = GL_COMPUTE_SHADER;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glslcstr = bstr2cstr(sContext.glsl, '\0');
|
||||
result->sourceCode = glslcstr;
|
||||
bcstrfree(glslcstr);
|
||||
glslcstr = bstr2cstr(sContext.glsl, '\0');
|
||||
result->sourceCode = glslcstr;
|
||||
bcstrfree(glslcstr);
|
||||
|
||||
bdestroy(sContext.glsl);
|
||||
for (i = 0; i < psShader->asPhases.size(); ++i)
|
||||
{
|
||||
bdestroy(psShader->asPhases[i].postShaderCode);
|
||||
bdestroy(psShader->asPhases[i].earlyMain);
|
||||
}
|
||||
bdestroy(sContext.glsl);
|
||||
for (i = 0; i < psShader->asPhases.size(); ++i)
|
||||
{
|
||||
bdestroy(psShader->asPhases[i].postShaderCode);
|
||||
bdestroy(psShader->asPhases[i].earlyMain);
|
||||
}
|
||||
|
||||
result->reflection = psShader->sInfo;
|
||||
result->reflection = psShader->sInfo;
|
||||
|
||||
result->textureSamplers = psShader->textureSamplers;
|
||||
result->textureSamplers = psShader->textureSamplers;
|
||||
|
||||
success = 1;
|
||||
}
|
||||
success = 1;
|
||||
}
|
||||
|
||||
shader = 0;
|
||||
tokens = 0;
|
||||
shader = 0;
|
||||
tokens = 0;
|
||||
|
||||
/* Fill in the result struct */
|
||||
/* Fill in the result struct */
|
||||
|
||||
result->shaderType = GLSLShaderType;
|
||||
result->GLSLLanguage = language;
|
||||
result->shaderType = GLSLShaderType;
|
||||
result->GLSLLanguage = language;
|
||||
|
||||
return success;
|
||||
return success;
|
||||
}
|
||||
|
||||
HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFile(const char* filename,
|
||||
unsigned int flags,
|
||||
GLLang language,
|
||||
const GlExtensions *extensions,
|
||||
GLSLCrossDependencyData* dependencies,
|
||||
HLSLccSamplerPrecisionInfo& samplerPrecisions,
|
||||
HLSLccReflection& reflectionCallbacks,
|
||||
GLSLShader* result)
|
||||
unsigned int flags,
|
||||
GLLang language,
|
||||
const GlExtensions *extensions,
|
||||
GLSLCrossDependencyData* dependencies,
|
||||
HLSLccSamplerPrecisionInfo& samplerPrecisions,
|
||||
HLSLccReflection& reflectionCallbacks,
|
||||
GLSLShader* result)
|
||||
{
|
||||
FILE* shaderFile;
|
||||
int length;
|
||||
size_t readLength;
|
||||
std::vector<char> shader;
|
||||
int success = 0;
|
||||
FILE* shaderFile;
|
||||
int length;
|
||||
size_t readLength;
|
||||
std::vector<char> shader;
|
||||
int success = 0;
|
||||
|
||||
shaderFile = fopen(filename, "rb");
|
||||
shaderFile = fopen(filename, "rb");
|
||||
|
||||
if (!shaderFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!shaderFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
fseek(shaderFile, 0, SEEK_END);
|
||||
length = ftell(shaderFile);
|
||||
fseek(shaderFile, 0, SEEK_SET);
|
||||
fseek(shaderFile, 0, SEEK_END);
|
||||
length = ftell(shaderFile);
|
||||
fseek(shaderFile, 0, SEEK_SET);
|
||||
|
||||
shader.reserve(length + 1);
|
||||
shader.resize(length + 1);
|
||||
|
||||
readLength = fread(&shader[0], 1, length, shaderFile);
|
||||
readLength = fread(&shader[0], 1, length, shaderFile);
|
||||
|
||||
fclose(shaderFile);
|
||||
shaderFile = 0;
|
||||
fclose(shaderFile);
|
||||
shaderFile = 0;
|
||||
|
||||
shader[readLength] = '\0';
|
||||
shader[readLength] = '\0';
|
||||
|
||||
success = TranslateHLSLFromMem(&shader[0], flags, language, extensions, dependencies, samplerPrecisions, reflectionCallbacks, result);
|
||||
success = TranslateHLSLFromMem(&shader[0], flags, language, extensions, dependencies, samplerPrecisions, reflectionCallbacks, result);
|
||||
|
||||
return success;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#include "internal_includes/HLSLccToolkit.h"
|
||||
#include "internal_includes/debug.h"
|
||||
#include "internal_includes/toGLSLOperand.h"
|
||||
@ -11,460 +10,457 @@
|
||||
|
||||
namespace HLSLcc
|
||||
{
|
||||
uint32_t GetNumberBitsSet(uint32_t a)
|
||||
{
|
||||
// Calculate number of bits in a
|
||||
// Taken from https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64
|
||||
// Works only up to 14 bits (we're only using up to 4)
|
||||
return (a * 0x200040008001ULL & 0x111111111111111ULL) % 0xf;
|
||||
}
|
||||
uint32_t GetNumberBitsSet(uint32_t a)
|
||||
{
|
||||
// Calculate number of bits in a
|
||||
// Taken from https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64
|
||||
// Works only up to 14 bits (we're only using up to 4)
|
||||
return (a * 0x200040008001ULL & 0x111111111111111ULL) % 0xf;
|
||||
}
|
||||
|
||||
uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType)
|
||||
{
|
||||
if (eType == SVT_FLOAT16)
|
||||
{
|
||||
return TO_FLAG_FORCE_HALF;
|
||||
}
|
||||
if (eType == SVT_UINT || eType == SVT_UINT16)
|
||||
{
|
||||
return TO_FLAG_UNSIGNED_INTEGER;
|
||||
}
|
||||
else if (eType == SVT_INT || eType == SVT_INT16 || eType == SVT_INT12)
|
||||
{
|
||||
return TO_FLAG_INTEGER;
|
||||
}
|
||||
else if (eType == SVT_BOOL)
|
||||
{
|
||||
return TO_FLAG_BOOL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TO_FLAG_NONE;
|
||||
}
|
||||
}
|
||||
uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType)
|
||||
{
|
||||
if (eType == SVT_FLOAT16)
|
||||
{
|
||||
return TO_FLAG_FORCE_HALF;
|
||||
}
|
||||
if (eType == SVT_UINT || eType == SVT_UINT16)
|
||||
{
|
||||
return TO_FLAG_UNSIGNED_INTEGER;
|
||||
}
|
||||
else if (eType == SVT_INT || eType == SVT_INT16 || eType == SVT_INT12)
|
||||
{
|
||||
return TO_FLAG_INTEGER;
|
||||
}
|
||||
else if (eType == SVT_BOOL)
|
||||
{
|
||||
return TO_FLAG_BOOL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TO_FLAG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags)
|
||||
{
|
||||
if (typeflags & TO_FLAG_FORCE_HALF)
|
||||
return SVT_FLOAT16;
|
||||
if (typeflags & (TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT))
|
||||
return SVT_INT;
|
||||
if (typeflags & (TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT))
|
||||
return SVT_UINT;
|
||||
if (typeflags & TO_FLAG_BOOL)
|
||||
return SVT_BOOL;
|
||||
return SVT_FLOAT;
|
||||
}
|
||||
SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags)
|
||||
{
|
||||
if (typeflags & TO_FLAG_FORCE_HALF)
|
||||
return SVT_FLOAT16;
|
||||
if (typeflags & (TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT))
|
||||
return SVT_INT;
|
||||
if (typeflags & (TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT))
|
||||
return SVT_UINT;
|
||||
if (typeflags & TO_FLAG_BOOL)
|
||||
return SVT_BOOL;
|
||||
return SVT_FLOAT;
|
||||
}
|
||||
|
||||
const char * GetConstructorForTypeGLSL(const HLSLCrossCompilerContext *context, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision)
|
||||
{
|
||||
static const char * const uintTypes[] = { " ", "uint", "uvec2", "uvec3", "uvec4" };
|
||||
static const char * const uint16Types[] = { " ", "mediump uint", "mediump uvec2", "mediump uvec3", "mediump uvec4" };
|
||||
static const char * const intTypes[] = { " ", "int", "ivec2", "ivec3", "ivec4" };
|
||||
static const char * const int16Types[] = { " ", "mediump int", "mediump ivec2", "mediump ivec3", "mediump ivec4" };
|
||||
static const char * const int12Types[] = { " ", "lowp int", "lowp ivec2", "lowp ivec3", "lowp ivec4" };
|
||||
static const char * const floatTypes[] = { " ", "float", "vec2", "vec3", "vec4" };
|
||||
static const char * const float16Types[] = { " ", "mediump float", "mediump vec2", "mediump vec3", "mediump vec4" };
|
||||
static const char * const float10Types[] = { " ", "lowp float", "lowp vec2", "lowp vec3", "lowp vec4" };
|
||||
static const char * const boolTypes[] = { " ", "bool", "bvec2", "bvec3", "bvec4" };
|
||||
const char * GetConstructorForTypeGLSL(const HLSLCrossCompilerContext *context, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision)
|
||||
{
|
||||
static const char * const uintTypes[] = { " ", "uint", "uvec2", "uvec3", "uvec4" };
|
||||
static const char * const uint16Types[] = { " ", "mediump uint", "mediump uvec2", "mediump uvec3", "mediump uvec4" };
|
||||
static const char * const intTypes[] = { " ", "int", "ivec2", "ivec3", "ivec4" };
|
||||
static const char * const int16Types[] = { " ", "mediump int", "mediump ivec2", "mediump ivec3", "mediump ivec4" };
|
||||
static const char * const int12Types[] = { " ", "lowp int", "lowp ivec2", "lowp ivec3", "lowp ivec4" };
|
||||
static const char * const floatTypes[] = { " ", "float", "vec2", "vec3", "vec4" };
|
||||
static const char * const float16Types[] = { " ", "mediump float", "mediump vec2", "mediump vec3", "mediump vec4" };
|
||||
static const char * const float10Types[] = { " ", "lowp float", "lowp vec2", "lowp vec3", "lowp vec4" };
|
||||
static const char * const boolTypes[] = { " ", "bool", "bvec2", "bvec3", "bvec4" };
|
||||
|
||||
ASSERT(components >= 1 && components <= 4);
|
||||
ASSERT(components >= 1 && components <= 4);
|
||||
bool emitLowp = EmitLowp(context);
|
||||
|
||||
switch (eType)
|
||||
{
|
||||
case SVT_UINT:
|
||||
return HaveUnsignedTypes(context->psShader->eTargetLanguage) ? uintTypes[components] : intTypes[components];
|
||||
case SVT_UINT16:
|
||||
return useGLSLPrecision ? uint16Types[components] : uintTypes[components];
|
||||
case SVT_INT:
|
||||
return intTypes[components];
|
||||
case SVT_INT16:
|
||||
return useGLSLPrecision ? int16Types[components] : intTypes[components];
|
||||
case SVT_INT12:
|
||||
return useGLSLPrecision ? (emitLowp ? int12Types[components] : int16Types[components]) : intTypes[components];
|
||||
case SVT_FLOAT:
|
||||
return floatTypes[components];
|
||||
case SVT_FLOAT16:
|
||||
return useGLSLPrecision ? float16Types[components] : floatTypes[components];
|
||||
case SVT_FLOAT10:
|
||||
return useGLSLPrecision ? (emitLowp ? float10Types[components] : float16Types[components]) : floatTypes[components];
|
||||
case SVT_BOOL:
|
||||
return boolTypes[components];
|
||||
default:
|
||||
ASSERT(0);
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
switch (eType)
|
||||
{
|
||||
case SVT_UINT:
|
||||
return HaveUnsignedTypes(context->psShader->eTargetLanguage) ? uintTypes[components] : intTypes[components];
|
||||
case SVT_UINT16:
|
||||
return useGLSLPrecision ? uint16Types[components] : uintTypes[components];
|
||||
case SVT_INT:
|
||||
return intTypes[components];
|
||||
case SVT_INT16:
|
||||
return useGLSLPrecision ? int16Types[components] : intTypes[components];
|
||||
case SVT_INT12:
|
||||
return useGLSLPrecision ? (emitLowp ? int12Types[components] : int16Types[components]) : intTypes[components];
|
||||
case SVT_FLOAT:
|
||||
return floatTypes[components];
|
||||
case SVT_FLOAT16:
|
||||
return useGLSLPrecision ? float16Types[components] : floatTypes[components];
|
||||
case SVT_FLOAT10:
|
||||
return useGLSLPrecision ? (emitLowp ? float10Types[components] : float16Types[components]) : floatTypes[components];
|
||||
case SVT_BOOL:
|
||||
return boolTypes[components];
|
||||
default:
|
||||
ASSERT(0);
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
|
||||
const char * GetConstructorForTypeMetal(const SHADER_VARIABLE_TYPE eType,
|
||||
const int components)
|
||||
{
|
||||
static const char * const uintTypes[] = { " ", "uint", "uint2", "uint3", "uint4" };
|
||||
static const char * const ushortTypes[] = { " ", "ushort", "ushort2", "ushort3", "ushort4" };
|
||||
static const char * const intTypes[] = { " ", "int", "int2", "int3", "int4" };
|
||||
static const char * const shortTypes[] = { " ", "short", "short2", "short3", "short4" };
|
||||
static const char * const floatTypes[] = { " ", "float", "float2", "float3", "float4" };
|
||||
static const char * const halfTypes[] = { " ", "half", "half2", "half3", "half4" };
|
||||
static const char * const boolTypes[] = { " ", "bool", "bool2", "bool3", "bool4" };
|
||||
const char * GetConstructorForTypeMetal(const SHADER_VARIABLE_TYPE eType,
|
||||
const int components)
|
||||
{
|
||||
static const char * const uintTypes[] = { " ", "uint", "uint2", "uint3", "uint4" };
|
||||
static const char * const ushortTypes[] = { " ", "ushort", "ushort2", "ushort3", "ushort4" };
|
||||
static const char * const intTypes[] = { " ", "int", "int2", "int3", "int4" };
|
||||
static const char * const shortTypes[] = { " ", "short", "short2", "short3", "short4" };
|
||||
static const char * const floatTypes[] = { " ", "float", "float2", "float3", "float4" };
|
||||
static const char * const halfTypes[] = { " ", "half", "half2", "half3", "half4" };
|
||||
static const char * const boolTypes[] = { " ", "bool", "bool2", "bool3", "bool4" };
|
||||
|
||||
ASSERT(components >= 1 && components <= 4);
|
||||
ASSERT(components >= 1 && components <= 4);
|
||||
|
||||
switch (eType)
|
||||
{
|
||||
case SVT_UINT:
|
||||
return uintTypes[components];
|
||||
case SVT_UINT16:
|
||||
return ushortTypes[components];
|
||||
case SVT_INT:
|
||||
return intTypes[components];
|
||||
case SVT_INT16:
|
||||
case SVT_INT12:
|
||||
return shortTypes[components];
|
||||
case SVT_FLOAT:
|
||||
return floatTypes[components];
|
||||
case SVT_FLOAT16:
|
||||
case SVT_FLOAT10:
|
||||
return halfTypes[components];
|
||||
case SVT_BOOL:
|
||||
return boolTypes[components];
|
||||
default:
|
||||
ASSERT(0);
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
switch (eType)
|
||||
{
|
||||
case SVT_UINT:
|
||||
return uintTypes[components];
|
||||
case SVT_UINT16:
|
||||
return ushortTypes[components];
|
||||
case SVT_INT:
|
||||
return intTypes[components];
|
||||
case SVT_INT16:
|
||||
case SVT_INT12:
|
||||
return shortTypes[components];
|
||||
case SVT_FLOAT:
|
||||
return floatTypes[components];
|
||||
case SVT_FLOAT16:
|
||||
case SVT_FLOAT10:
|
||||
return halfTypes[components];
|
||||
case SVT_BOOL:
|
||||
return boolTypes[components];
|
||||
default:
|
||||
ASSERT(0);
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
|
||||
const char * GetConstructorForType(const HLSLCrossCompilerContext *psContext, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision /* = true*/)
|
||||
{
|
||||
if (psContext->psShader->eTargetLanguage == LANG_METAL)
|
||||
return GetConstructorForTypeMetal(eType, components);
|
||||
else
|
||||
return GetConstructorForTypeGLSL(psContext, eType, components, useGLSLPrecision);
|
||||
}
|
||||
const char * GetConstructorForType(const HLSLCrossCompilerContext *psContext, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision /* = true*/)
|
||||
{
|
||||
if (psContext->psShader->eTargetLanguage == LANG_METAL)
|
||||
return GetConstructorForTypeMetal(eType, components);
|
||||
else
|
||||
return GetConstructorForTypeGLSL(psContext, eType, components, useGLSLPrecision);
|
||||
}
|
||||
|
||||
std::string GetMatrixTypeName(const HLSLCrossCompilerContext *psContext, const SHADER_VARIABLE_TYPE eBaseType, const int columns, const int rows)
|
||||
{
|
||||
std::string result;
|
||||
std::ostringstream oss;
|
||||
if (psContext->psShader->eTargetLanguage == LANG_METAL)
|
||||
{
|
||||
switch (eBaseType)
|
||||
{
|
||||
case SVT_FLOAT:
|
||||
oss << "float" << columns << "x" << rows;
|
||||
break;
|
||||
case SVT_FLOAT16:
|
||||
case SVT_FLOAT10:
|
||||
oss << "half" << columns << "x" << rows;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (eBaseType)
|
||||
{
|
||||
case SVT_FLOAT:
|
||||
oss << "mat" << columns << "x" << rows;
|
||||
break;
|
||||
case SVT_FLOAT16:
|
||||
oss << "mediump mat" << columns << "x" << rows;
|
||||
break;
|
||||
case SVT_FLOAT10:
|
||||
oss << "lowp mat" << columns << "x" << rows;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
std::string GetMatrixTypeName(const HLSLCrossCompilerContext *psContext, const SHADER_VARIABLE_TYPE eBaseType, const int columns, const int rows)
|
||||
{
|
||||
std::string result;
|
||||
std::ostringstream oss;
|
||||
if (psContext->psShader->eTargetLanguage == LANG_METAL)
|
||||
{
|
||||
switch (eBaseType)
|
||||
{
|
||||
case SVT_FLOAT:
|
||||
oss << "float" << columns << "x" << rows;
|
||||
break;
|
||||
case SVT_FLOAT16:
|
||||
case SVT_FLOAT10:
|
||||
oss << "half" << columns << "x" << rows;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (eBaseType)
|
||||
{
|
||||
case SVT_FLOAT:
|
||||
oss << "mat" << columns << "x" << rows;
|
||||
break;
|
||||
case SVT_FLOAT16:
|
||||
oss << "mediump mat" << columns << "x" << rows;
|
||||
break;
|
||||
case SVT_FLOAT10:
|
||||
oss << "lowp mat" << columns << "x" << rows;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = oss.str();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
result = oss.str();
|
||||
return result;
|
||||
}
|
||||
void AddSwizzleUsingElementCount(bstring dest, uint32_t count)
|
||||
{
|
||||
if (count == 4)
|
||||
return;
|
||||
if (count)
|
||||
{
|
||||
bcatcstr(dest, ".");
|
||||
bcatcstr(dest, "x");
|
||||
count--;
|
||||
}
|
||||
if (count)
|
||||
{
|
||||
bcatcstr(dest, "y");
|
||||
count--;
|
||||
}
|
||||
if (count)
|
||||
{
|
||||
bcatcstr(dest, "z");
|
||||
count--;
|
||||
}
|
||||
if (count)
|
||||
{
|
||||
bcatcstr(dest, "w");
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
void AddSwizzleUsingElementCount(bstring dest, uint32_t count)
|
||||
{
|
||||
if (count == 4)
|
||||
return;
|
||||
if (count)
|
||||
{
|
||||
bcatcstr(dest, ".");
|
||||
bcatcstr(dest, "x");
|
||||
count--;
|
||||
}
|
||||
if (count)
|
||||
{
|
||||
bcatcstr(dest, "y");
|
||||
count--;
|
||||
}
|
||||
if (count)
|
||||
{
|
||||
bcatcstr(dest, "z");
|
||||
count--;
|
||||
}
|
||||
if (count)
|
||||
{
|
||||
bcatcstr(dest, "w");
|
||||
count--;
|
||||
}
|
||||
}
|
||||
// Calculate the bits set in mask
|
||||
int WriteMaskToComponentCount(uint32_t writeMask)
|
||||
{
|
||||
// In HLSL bytecode writemask 0 also means everything
|
||||
if (writeMask == 0)
|
||||
return 4;
|
||||
|
||||
// Calculate the bits set in mask
|
||||
int WriteMaskToComponentCount(uint32_t writeMask)
|
||||
{
|
||||
// In HLSL bytecode writemask 0 also means everything
|
||||
if (writeMask == 0)
|
||||
return 4;
|
||||
|
||||
return (int)GetNumberBitsSet(writeMask);
|
||||
}
|
||||
return (int)GetNumberBitsSet(writeMask);
|
||||
}
|
||||
|
||||
uint32_t BuildComponentMaskFromElementCount(int count)
|
||||
{
|
||||
// Translate numComponents into bitmask
|
||||
// 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15
|
||||
return (1 << count) - 1;
|
||||
}
|
||||
uint32_t BuildComponentMaskFromElementCount(int count)
|
||||
{
|
||||
// Translate numComponents into bitmask
|
||||
// 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15
|
||||
return (1 << count) - 1;
|
||||
}
|
||||
|
||||
// Returns true if we can do direct assignment between types (mostly for mediump<->highp floats etc)
|
||||
bool DoAssignmentDataTypesMatch(SHADER_VARIABLE_TYPE dest, SHADER_VARIABLE_TYPE src)
|
||||
{
|
||||
if (src == dest)
|
||||
return true;
|
||||
// Returns true if we can do direct assignment between types (mostly for mediump<->highp floats etc)
|
||||
bool DoAssignmentDataTypesMatch(SHADER_VARIABLE_TYPE dest, SHADER_VARIABLE_TYPE src)
|
||||
{
|
||||
if (src == dest)
|
||||
return true;
|
||||
|
||||
if ((dest == SVT_FLOAT || dest == SVT_FLOAT10 || dest == SVT_FLOAT16) &&
|
||||
(src == SVT_FLOAT || src == SVT_FLOAT10 || src == SVT_FLOAT16))
|
||||
return true;
|
||||
if ((dest == SVT_FLOAT || dest == SVT_FLOAT10 || dest == SVT_FLOAT16) &&
|
||||
(src == SVT_FLOAT || src == SVT_FLOAT10 || src == SVT_FLOAT16))
|
||||
return true;
|
||||
|
||||
if ((dest == SVT_INT || dest == SVT_INT12 || dest == SVT_INT16) &&
|
||||
(src == SVT_INT || src == SVT_INT12 || src == SVT_INT16))
|
||||
return true;
|
||||
if ((dest == SVT_INT || dest == SVT_INT12 || dest == SVT_INT16) &&
|
||||
(src == SVT_INT || src == SVT_INT12 || src == SVT_INT16))
|
||||
return true;
|
||||
|
||||
if ((dest == SVT_UINT || dest == SVT_UINT16) &&
|
||||
(src == SVT_UINT || src == SVT_UINT16))
|
||||
return true;
|
||||
if ((dest == SVT_UINT || dest == SVT_UINT16) &&
|
||||
(src == SVT_UINT || src == SVT_UINT16))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ResourceReturnTypeToFlag(const RESOURCE_RETURN_TYPE eType)
|
||||
{
|
||||
if (eType == RETURN_TYPE_SINT)
|
||||
{
|
||||
return TO_FLAG_INTEGER;
|
||||
}
|
||||
else if (eType == RETURN_TYPE_UINT)
|
||||
{
|
||||
return TO_FLAG_UNSIGNED_INTEGER;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TO_FLAG_NONE;
|
||||
}
|
||||
}
|
||||
uint32_t ResourceReturnTypeToFlag(const RESOURCE_RETURN_TYPE eType)
|
||||
{
|
||||
if (eType == RETURN_TYPE_SINT)
|
||||
{
|
||||
return TO_FLAG_INTEGER;
|
||||
}
|
||||
else if (eType == RETURN_TYPE_UINT)
|
||||
{
|
||||
return TO_FLAG_UNSIGNED_INTEGER;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TO_FLAG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
SHADER_VARIABLE_TYPE ResourceReturnTypeToSVTType(const RESOURCE_RETURN_TYPE eType, const REFLECT_RESOURCE_PRECISION ePrec)
|
||||
{
|
||||
if (eType == RETURN_TYPE_SINT)
|
||||
{
|
||||
switch (ePrec)
|
||||
{
|
||||
default:
|
||||
return SVT_INT;
|
||||
case REFLECT_RESOURCE_PRECISION_LOWP:
|
||||
return SVT_INT12;
|
||||
case REFLECT_RESOURCE_PRECISION_MEDIUMP:
|
||||
return SVT_INT16;
|
||||
}
|
||||
}
|
||||
else if (eType == RETURN_TYPE_UINT)
|
||||
{
|
||||
switch (ePrec)
|
||||
{
|
||||
default:
|
||||
return SVT_UINT;
|
||||
case REFLECT_RESOURCE_PRECISION_LOWP:
|
||||
return SVT_UINT8;
|
||||
case REFLECT_RESOURCE_PRECISION_MEDIUMP:
|
||||
return SVT_UINT16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ePrec)
|
||||
{
|
||||
default:
|
||||
return SVT_FLOAT;
|
||||
case REFLECT_RESOURCE_PRECISION_LOWP:
|
||||
return SVT_FLOAT10;
|
||||
case REFLECT_RESOURCE_PRECISION_MEDIUMP:
|
||||
return SVT_FLOAT16;
|
||||
}
|
||||
}
|
||||
}
|
||||
SHADER_VARIABLE_TYPE ResourceReturnTypeToSVTType(const RESOURCE_RETURN_TYPE eType, const REFLECT_RESOURCE_PRECISION ePrec)
|
||||
{
|
||||
if (eType == RETURN_TYPE_SINT)
|
||||
{
|
||||
switch (ePrec)
|
||||
{
|
||||
default:
|
||||
return SVT_INT;
|
||||
case REFLECT_RESOURCE_PRECISION_LOWP:
|
||||
return SVT_INT12;
|
||||
case REFLECT_RESOURCE_PRECISION_MEDIUMP:
|
||||
return SVT_INT16;
|
||||
}
|
||||
}
|
||||
else if (eType == RETURN_TYPE_UINT)
|
||||
{
|
||||
switch (ePrec)
|
||||
{
|
||||
default:
|
||||
return SVT_UINT;
|
||||
case REFLECT_RESOURCE_PRECISION_LOWP:
|
||||
return SVT_UINT8;
|
||||
case REFLECT_RESOURCE_PRECISION_MEDIUMP:
|
||||
return SVT_UINT16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ePrec)
|
||||
{
|
||||
default:
|
||||
return SVT_FLOAT;
|
||||
case REFLECT_RESOURCE_PRECISION_LOWP:
|
||||
return SVT_FLOAT10;
|
||||
case REFLECT_RESOURCE_PRECISION_MEDIUMP:
|
||||
return SVT_FLOAT16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ElemCountToAutoExpandFlag(uint32_t elemCount)
|
||||
{
|
||||
return TO_AUTO_EXPAND_TO_VEC2 << (elemCount - 2);
|
||||
}
|
||||
|
||||
uint32_t ElemCountToAutoExpandFlag(uint32_t elemCount)
|
||||
{
|
||||
return TO_AUTO_EXPAND_TO_VEC2 << (elemCount - 2);
|
||||
}
|
||||
// Returns true if the operation is commutative
|
||||
bool IsOperationCommutative(int eOpCode)
|
||||
{
|
||||
switch ((OPCODE_TYPE)eOpCode)
|
||||
{
|
||||
case OPCODE_DADD:
|
||||
case OPCODE_IADD:
|
||||
case OPCODE_ADD:
|
||||
case OPCODE_MUL:
|
||||
case OPCODE_IMUL:
|
||||
case OPCODE_OR:
|
||||
case OPCODE_AND:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the operation is commutative
|
||||
bool IsOperationCommutative(int eOpCode)
|
||||
{
|
||||
switch ((OPCODE_TYPE)eOpCode)
|
||||
{
|
||||
case OPCODE_DADD:
|
||||
case OPCODE_IADD:
|
||||
case OPCODE_ADD:
|
||||
case OPCODE_MUL:
|
||||
case OPCODE_IMUL:
|
||||
case OPCODE_OR:
|
||||
case OPCODE_AND:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
// Returns true if operands are identical, only cares about temp registers currently.
|
||||
bool AreTempOperandsIdentical(const Operand * psA, const Operand * psB)
|
||||
{
|
||||
if (!psA || !psB)
|
||||
return 0;
|
||||
|
||||
// Returns true if operands are identical, only cares about temp registers currently.
|
||||
bool AreTempOperandsIdentical(const Operand * psA, const Operand * psB)
|
||||
{
|
||||
if (!psA || !psB)
|
||||
return 0;
|
||||
if (psA->eType != OPERAND_TYPE_TEMP || psB->eType != OPERAND_TYPE_TEMP)
|
||||
return 0;
|
||||
|
||||
if (psA->eType != OPERAND_TYPE_TEMP || psB->eType != OPERAND_TYPE_TEMP)
|
||||
return 0;
|
||||
if (psA->eModifier != psB->eModifier)
|
||||
return 0;
|
||||
|
||||
if (psA->eModifier != psB->eModifier)
|
||||
return 0;
|
||||
if (psA->iNumComponents != psB->iNumComponents)
|
||||
return 0;
|
||||
|
||||
if (psA->iNumComponents != psB->iNumComponents)
|
||||
return 0;
|
||||
if (psA->ui32RegisterNumber != psB->ui32RegisterNumber)
|
||||
return 0;
|
||||
|
||||
if (psA->ui32RegisterNumber != psB->ui32RegisterNumber)
|
||||
return 0;
|
||||
if (psA->eSelMode != psB->eSelMode)
|
||||
return 0;
|
||||
|
||||
if (psA->eSelMode != psB->eSelMode)
|
||||
return 0;
|
||||
if (psA->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && psA->ui32CompMask != psB->ui32CompMask)
|
||||
return 0;
|
||||
|
||||
if (psA->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && psA->ui32CompMask != psB->ui32CompMask)
|
||||
return 0;
|
||||
if (psA->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE && psA->aui32Swizzle[0] != psB->aui32Swizzle[0])
|
||||
return 0;
|
||||
|
||||
if (psA->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE && psA->aui32Swizzle[0] != psB->aui32Swizzle[0])
|
||||
return 0;
|
||||
if (psA->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && std::equal(&psA->aui32Swizzle[0], &psA->aui32Swizzle[4], &psB->aui32Swizzle[0]))
|
||||
return 0;
|
||||
|
||||
if (psA->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && std::equal(&psA->aui32Swizzle[0], &psA->aui32Swizzle[4], &psB->aui32Swizzle[0]))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
bool IsAddOneInstruction(const Instruction *psInst)
|
||||
{
|
||||
if (psInst->eOpcode != OPCODE_IADD)
|
||||
return false;
|
||||
if (psInst->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return false;
|
||||
|
||||
bool IsAddOneInstruction(const Instruction *psInst)
|
||||
{
|
||||
if (psInst->eOpcode != OPCODE_IADD)
|
||||
return false;
|
||||
if (psInst->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return false;
|
||||
if (psInst->asOperands[1].eType == OPERAND_TYPE_TEMP)
|
||||
{
|
||||
if (psInst->asOperands[1].ui32RegisterNumber != psInst->asOperands[0].ui32RegisterNumber)
|
||||
return false;
|
||||
if (psInst->asOperands[2].eType != OPERAND_TYPE_IMMEDIATE32)
|
||||
return false;
|
||||
|
||||
if (psInst->asOperands[1].eType == OPERAND_TYPE_TEMP)
|
||||
{
|
||||
if (psInst->asOperands[1].ui32RegisterNumber != psInst->asOperands[0].ui32RegisterNumber)
|
||||
return false;
|
||||
if (psInst->asOperands[2].eType != OPERAND_TYPE_IMMEDIATE32)
|
||||
return false;
|
||||
if (*(int *)&psInst->asOperands[2].afImmediates[0] != 1)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (psInst->asOperands[1].eType != OPERAND_TYPE_IMMEDIATE32)
|
||||
return false;
|
||||
if (psInst->asOperands[2].eType != OPERAND_TYPE_TEMP)
|
||||
return false;
|
||||
|
||||
if (*(int *)&psInst->asOperands[2].afImmediates[0] != 1)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (psInst->asOperands[1].eType != OPERAND_TYPE_IMMEDIATE32)
|
||||
return false;
|
||||
if (psInst->asOperands[2].eType != OPERAND_TYPE_TEMP)
|
||||
return false;
|
||||
if (psInst->asOperands[2].ui32RegisterNumber != psInst->asOperands[0].ui32RegisterNumber)
|
||||
return false;
|
||||
|
||||
if (psInst->asOperands[2].ui32RegisterNumber != psInst->asOperands[0].ui32RegisterNumber)
|
||||
return false;
|
||||
if (*(int *)&psInst->asOperands[1].afImmediates[0] != 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*(int *)&psInst->asOperands[1].afImmediates[0] != 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int GetNumTextureDimensions(int /* RESOURCE_DIMENSION */ eResDim)
|
||||
{
|
||||
switch ((RESOURCE_DIMENSION)eResDim)
|
||||
{
|
||||
case RESOURCE_DIMENSION_TEXTURE1D:
|
||||
return 1;
|
||||
case RESOURCE_DIMENSION_TEXTURE2D:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DMS:
|
||||
case RESOURCE_DIMENSION_TEXTURE1DARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURECUBE:
|
||||
return 2;
|
||||
case RESOURCE_DIMENSION_TEXTURE3D:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
|
||||
return 3;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int GetNumTextureDimensions(int /* RESOURCE_DIMENSION */ eResDim)
|
||||
{
|
||||
switch ((RESOURCE_DIMENSION)eResDim)
|
||||
{
|
||||
case RESOURCE_DIMENSION_TEXTURE1D:
|
||||
return 1;
|
||||
case RESOURCE_DIMENSION_TEXTURE2D:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DMS:
|
||||
case RESOURCE_DIMENSION_TEXTURE1DARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURECUBE:
|
||||
return 2;
|
||||
case RESOURCE_DIMENSION_TEXTURE3D:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
|
||||
return 3;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the "more important" type of a and b, currently int < uint < float
|
||||
SHADER_VARIABLE_TYPE SelectHigherType(SHADER_VARIABLE_TYPE a, SHADER_VARIABLE_TYPE b)
|
||||
{
|
||||
// Returns the "more important" type of a and b, currently int < uint < float
|
||||
SHADER_VARIABLE_TYPE SelectHigherType(SHADER_VARIABLE_TYPE a, SHADER_VARIABLE_TYPE b)
|
||||
{
|
||||
#define DO_CHECK(type) if( a == type || b == type ) return type
|
||||
|
||||
// Priority ordering
|
||||
DO_CHECK(SVT_FLOAT16);
|
||||
DO_CHECK(SVT_FLOAT10);
|
||||
DO_CHECK(SVT_UINT16);
|
||||
DO_CHECK(SVT_UINT8);
|
||||
DO_CHECK(SVT_INT16);
|
||||
DO_CHECK(SVT_INT12);
|
||||
DO_CHECK(SVT_FORCED_INT);
|
||||
DO_CHECK(SVT_FLOAT);
|
||||
DO_CHECK(SVT_UINT);
|
||||
DO_CHECK(SVT_INT);
|
||||
DO_CHECK(SVT_INT_AMBIGUOUS);
|
||||
// Priority ordering
|
||||
DO_CHECK(SVT_FLOAT16);
|
||||
DO_CHECK(SVT_FLOAT10);
|
||||
DO_CHECK(SVT_UINT16);
|
||||
DO_CHECK(SVT_UINT8);
|
||||
DO_CHECK(SVT_INT16);
|
||||
DO_CHECK(SVT_INT12);
|
||||
DO_CHECK(SVT_FORCED_INT);
|
||||
DO_CHECK(SVT_FLOAT);
|
||||
DO_CHECK(SVT_UINT);
|
||||
DO_CHECK(SVT_INT);
|
||||
DO_CHECK(SVT_INT_AMBIGUOUS);
|
||||
|
||||
#undef DO_CHECK
|
||||
// After these just rely on ordering.
|
||||
return a > b ? a : b;
|
||||
}
|
||||
// After these just rely on ordering.
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
// Returns true if a direct constructor can convert src->dest
|
||||
bool CanDoDirectCast(const HLSLCrossCompilerContext *context, SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest)
|
||||
{
|
||||
// uint<->int<->bool conversions possible
|
||||
if ((src == SVT_INT || src == SVT_UINT || src == SVT_BOOL || src == SVT_INT12 || src == SVT_INT16 || src == SVT_UINT16) &&
|
||||
(dest == SVT_INT || dest == SVT_UINT || dest == SVT_BOOL || dest == SVT_INT12 || dest == SVT_INT16 || dest == SVT_UINT16))
|
||||
return true;
|
||||
// Returns true if a direct constructor can convert src->dest
|
||||
bool CanDoDirectCast(const HLSLCrossCompilerContext *context, SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest)
|
||||
{
|
||||
// uint<->int<->bool conversions possible
|
||||
if ((src == SVT_INT || src == SVT_UINT || src == SVT_BOOL || src == SVT_INT12 || src == SVT_INT16 || src == SVT_UINT16) &&
|
||||
(dest == SVT_INT || dest == SVT_UINT || dest == SVT_BOOL || dest == SVT_INT12 || dest == SVT_INT16 || dest == SVT_UINT16))
|
||||
return true;
|
||||
|
||||
// float<->double possible
|
||||
if ((src == SVT_FLOAT || src == SVT_DOUBLE || src == SVT_FLOAT16 || src == SVT_FLOAT10) &&
|
||||
(dest == SVT_FLOAT || dest == SVT_DOUBLE || dest == SVT_FLOAT16 || dest == SVT_FLOAT10))
|
||||
return true;
|
||||
// float<->double possible
|
||||
if ((src == SVT_FLOAT || src == SVT_DOUBLE || src == SVT_FLOAT16 || src == SVT_FLOAT10) &&
|
||||
(dest == SVT_FLOAT || dest == SVT_DOUBLE || dest == SVT_FLOAT16 || dest == SVT_FLOAT10))
|
||||
return true;
|
||||
|
||||
if (context->psShader->eTargetLanguage == LANG_METAL)
|
||||
{
|
||||
// avoid compiler error: cannot use as_type to cast from 'half' to 'unsigned int', types of different size
|
||||
if ((src == SVT_FLOAT16 || src == SVT_FLOAT10) && (dest == SVT_UINT))
|
||||
return true;
|
||||
}
|
||||
if (context->psShader->eTargetLanguage == LANG_METAL)
|
||||
{
|
||||
// avoid compiler error: cannot use as_type to cast from 'half' to 'unsigned int', types of different size
|
||||
if ((src == SVT_FLOAT16 || src == SVT_FLOAT10) && (dest == SVT_UINT))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsUnityFlexibleInstancingBuffer(const ConstantBuffer* psCBuf)
|
||||
{
|
||||
@ -481,22 +477,57 @@ namespace HLSLcc
|
||||
#endif
|
||||
#endif // #ifndef fpcheck
|
||||
|
||||
// Helper function to print floats with full precision
|
||||
void PrintFloat(bstring b, float f)
|
||||
{
|
||||
bstring temp;
|
||||
int ePos;
|
||||
int pointPos;
|
||||
// Helper function to print floats with full precision
|
||||
void PrintFloat(bstring b, float f)
|
||||
{
|
||||
bstring temp;
|
||||
int ePos;
|
||||
int pointPos;
|
||||
|
||||
temp = bformat("%.9g", f);
|
||||
ePos = bstrchrp(temp, 'e', 0);
|
||||
pointPos = bstrchrp(temp, '.', 0);
|
||||
temp = bformat("%.9g", f);
|
||||
ePos = bstrchrp(temp, 'e', 0);
|
||||
pointPos = bstrchrp(temp, '.', 0);
|
||||
|
||||
bconcat(b, temp);
|
||||
bdestroy(temp);
|
||||
bconcat(b, temp);
|
||||
bdestroy(temp);
|
||||
|
||||
if (ePos < 0 && pointPos < 0 && !fpcheck(f))
|
||||
bcatcstr(b, ".0");
|
||||
}
|
||||
};
|
||||
if (ePos < 0 && pointPos < 0 && !fpcheck(f))
|
||||
bcatcstr(b, ".0");
|
||||
}
|
||||
|
||||
bstring GetEarlyMain(HLSLCrossCompilerContext *psContext)
|
||||
{
|
||||
bstring *oldString = psContext->currentGLSLString;
|
||||
bstring *str = &psContext->psShader->asPhases[psContext->currentPhase].earlyMain;
|
||||
int indent = psContext->indent;
|
||||
|
||||
if (psContext->psShader->eTargetLanguage == LANG_METAL && !psContext->indent)
|
||||
++psContext->indent;
|
||||
|
||||
psContext->currentGLSLString = str;
|
||||
psContext->AddIndentation();
|
||||
psContext->currentGLSLString = oldString;
|
||||
psContext->indent = indent;
|
||||
|
||||
return *str;
|
||||
}
|
||||
|
||||
bstring GetPostShaderCode(HLSLCrossCompilerContext *psContext)
|
||||
{
|
||||
bstring *oldString = psContext->currentGLSLString;
|
||||
bstring *str = &psContext->psShader->asPhases[psContext->currentPhase].postShaderCode;
|
||||
int indent = psContext->indent;
|
||||
|
||||
if (psContext->psShader->eTargetLanguage == LANG_METAL && !psContext->indent)
|
||||
++psContext->indent;
|
||||
|
||||
psContext->psShader->asPhases[psContext->currentPhase].hasPostShaderCode = 1;
|
||||
|
||||
psContext->currentGLSLString = str;
|
||||
psContext->AddIndentation();
|
||||
psContext->currentGLSLString = oldString;
|
||||
psContext->indent = indent;
|
||||
|
||||
return *str;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<Type Name="Instruction">
|
||||
<DisplayString>{{ id={id} op={eOpcode} o0={asOperands[0]}, o1={asOperands[1]}}}</DisplayString>
|
||||
<DisplayString>{{ id={id} op={eOpcode} o0={asOperands[0]}, o1={asOperands[1]}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="Operand">
|
||||
<DisplayString>{{ type={eType}, reg={ui32RegisterNumber} }}</DisplayString>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
||||
</AutoVisualizer>
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#include "internal_includes/Instruction.h"
|
||||
#include "internal_includes/debug.h"
|
||||
#include "include/ShaderInfo.h"
|
||||
@ -6,353 +5,345 @@
|
||||
// Returns the result swizzle operand for an instruction, or NULL if all src operands have swizzles
|
||||
static Operand *GetSrcSwizzleOperand(Instruction *psInst)
|
||||
{
|
||||
switch (psInst->eOpcode)
|
||||
{
|
||||
case OPCODE_DP2:
|
||||
case OPCODE_DP3:
|
||||
case OPCODE_DP4:
|
||||
case OPCODE_NOP:
|
||||
case OPCODE_SWAPC:
|
||||
case OPCODE_SAMPLE_C:
|
||||
case OPCODE_SAMPLE_C_LZ:
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
switch (psInst->eOpcode)
|
||||
{
|
||||
case OPCODE_DP2:
|
||||
case OPCODE_DP3:
|
||||
case OPCODE_DP4:
|
||||
case OPCODE_NOP:
|
||||
case OPCODE_SWAPC:
|
||||
case OPCODE_SAMPLE_C:
|
||||
case OPCODE_SAMPLE_C_LZ:
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
|
||||
// Normal arithmetics, all srcs have swizzles
|
||||
case OPCODE_ADD:
|
||||
case OPCODE_AND:
|
||||
case OPCODE_DERIV_RTX:
|
||||
case OPCODE_DERIV_RTX_COARSE:
|
||||
case OPCODE_DERIV_RTX_FINE:
|
||||
case OPCODE_DERIV_RTY:
|
||||
case OPCODE_DERIV_RTY_COARSE:
|
||||
case OPCODE_DERIV_RTY_FINE:
|
||||
case OPCODE_DIV:
|
||||
case OPCODE_EQ:
|
||||
case OPCODE_EXP:
|
||||
case OPCODE_FRC:
|
||||
case OPCODE_FTOI:
|
||||
case OPCODE_FTOU:
|
||||
case OPCODE_GE:
|
||||
case OPCODE_IADD:
|
||||
case OPCODE_IEQ:
|
||||
case OPCODE_IGE:
|
||||
case OPCODE_ILT:
|
||||
case OPCODE_IMAD:
|
||||
case OPCODE_IMAX:
|
||||
case OPCODE_IMIN:
|
||||
case OPCODE_IMUL:
|
||||
case OPCODE_INE:
|
||||
case OPCODE_INEG:
|
||||
case OPCODE_ITOF:
|
||||
case OPCODE_LOG:
|
||||
case OPCODE_LT:
|
||||
case OPCODE_MAD:
|
||||
case OPCODE_MAX:
|
||||
case OPCODE_MIN:
|
||||
case OPCODE_MOV:
|
||||
case OPCODE_MUL:
|
||||
case OPCODE_NE:
|
||||
case OPCODE_NOT:
|
||||
case OPCODE_OR:
|
||||
case OPCODE_ROUND_NE:
|
||||
case OPCODE_ROUND_NI:
|
||||
case OPCODE_ROUND_PI:
|
||||
case OPCODE_ROUND_Z:
|
||||
case OPCODE_RSQ:
|
||||
case OPCODE_SINCOS:
|
||||
case OPCODE_SQRT:
|
||||
case OPCODE_UDIV:
|
||||
case OPCODE_UGE:
|
||||
case OPCODE_ULT:
|
||||
case OPCODE_UMAD:
|
||||
case OPCODE_UMAX:
|
||||
case OPCODE_UMIN:
|
||||
case OPCODE_UMUL:
|
||||
case OPCODE_UTOF:
|
||||
case OPCODE_XOR:
|
||||
// Normal arithmetics, all srcs have swizzles
|
||||
case OPCODE_ADD:
|
||||
case OPCODE_AND:
|
||||
case OPCODE_DERIV_RTX:
|
||||
case OPCODE_DERIV_RTX_COARSE:
|
||||
case OPCODE_DERIV_RTX_FINE:
|
||||
case OPCODE_DERIV_RTY:
|
||||
case OPCODE_DERIV_RTY_COARSE:
|
||||
case OPCODE_DERIV_RTY_FINE:
|
||||
case OPCODE_DIV:
|
||||
case OPCODE_EQ:
|
||||
case OPCODE_EXP:
|
||||
case OPCODE_FRC:
|
||||
case OPCODE_FTOI:
|
||||
case OPCODE_FTOU:
|
||||
case OPCODE_GE:
|
||||
case OPCODE_IADD:
|
||||
case OPCODE_IEQ:
|
||||
case OPCODE_IGE:
|
||||
case OPCODE_ILT:
|
||||
case OPCODE_IMAD:
|
||||
case OPCODE_IMAX:
|
||||
case OPCODE_IMIN:
|
||||
case OPCODE_IMUL:
|
||||
case OPCODE_INE:
|
||||
case OPCODE_INEG:
|
||||
case OPCODE_ITOF:
|
||||
case OPCODE_LOG:
|
||||
case OPCODE_LT:
|
||||
case OPCODE_MAD:
|
||||
case OPCODE_MAX:
|
||||
case OPCODE_MIN:
|
||||
case OPCODE_MOV:
|
||||
case OPCODE_MUL:
|
||||
case OPCODE_NE:
|
||||
case OPCODE_NOT:
|
||||
case OPCODE_OR:
|
||||
case OPCODE_ROUND_NE:
|
||||
case OPCODE_ROUND_NI:
|
||||
case OPCODE_ROUND_PI:
|
||||
case OPCODE_ROUND_Z:
|
||||
case OPCODE_RSQ:
|
||||
case OPCODE_SINCOS:
|
||||
case OPCODE_SQRT:
|
||||
case OPCODE_UDIV:
|
||||
case OPCODE_UGE:
|
||||
case OPCODE_ULT:
|
||||
case OPCODE_UMAD:
|
||||
case OPCODE_UMAX:
|
||||
case OPCODE_UMIN:
|
||||
case OPCODE_UMUL:
|
||||
case OPCODE_UTOF:
|
||||
case OPCODE_XOR:
|
||||
|
||||
case OPCODE_BFI:
|
||||
case OPCODE_BFREV:
|
||||
case OPCODE_COUNTBITS:
|
||||
case OPCODE_DADD:
|
||||
case OPCODE_DDIV:
|
||||
case OPCODE_DEQ:
|
||||
case OPCODE_DFMA:
|
||||
case OPCODE_DGE:
|
||||
case OPCODE_DLT:
|
||||
case OPCODE_DMAX:
|
||||
case OPCODE_DMIN:
|
||||
case OPCODE_DMUL:
|
||||
case OPCODE_DMOV:
|
||||
case OPCODE_DNE:
|
||||
case OPCODE_DRCP:
|
||||
case OPCODE_DTOF:
|
||||
case OPCODE_F16TOF32:
|
||||
case OPCODE_F32TOF16:
|
||||
case OPCODE_FIRSTBIT_HI:
|
||||
case OPCODE_FIRSTBIT_LO:
|
||||
case OPCODE_FIRSTBIT_SHI:
|
||||
case OPCODE_FTOD:
|
||||
case OPCODE_IBFE:
|
||||
case OPCODE_RCP:
|
||||
case OPCODE_UADDC:
|
||||
case OPCODE_UBFE:
|
||||
case OPCODE_USUBB:
|
||||
case OPCODE_MOVC:
|
||||
case OPCODE_DMOVC:
|
||||
return NULL;
|
||||
case OPCODE_BFI:
|
||||
case OPCODE_BFREV:
|
||||
case OPCODE_COUNTBITS:
|
||||
case OPCODE_DADD:
|
||||
case OPCODE_DDIV:
|
||||
case OPCODE_DEQ:
|
||||
case OPCODE_DFMA:
|
||||
case OPCODE_DGE:
|
||||
case OPCODE_DLT:
|
||||
case OPCODE_DMAX:
|
||||
case OPCODE_DMIN:
|
||||
case OPCODE_DMUL:
|
||||
case OPCODE_DMOV:
|
||||
case OPCODE_DNE:
|
||||
case OPCODE_DRCP:
|
||||
case OPCODE_DTOF:
|
||||
case OPCODE_F16TOF32:
|
||||
case OPCODE_F32TOF16:
|
||||
case OPCODE_FIRSTBIT_HI:
|
||||
case OPCODE_FIRSTBIT_LO:
|
||||
case OPCODE_FIRSTBIT_SHI:
|
||||
case OPCODE_FTOD:
|
||||
case OPCODE_IBFE:
|
||||
case OPCODE_RCP:
|
||||
case OPCODE_UADDC:
|
||||
case OPCODE_UBFE:
|
||||
case OPCODE_USUBB:
|
||||
case OPCODE_MOVC:
|
||||
case OPCODE_DMOVC:
|
||||
return NULL;
|
||||
|
||||
// Special cases:
|
||||
case OPCODE_GATHER4:
|
||||
case OPCODE_GATHER4_C:
|
||||
case OPCODE_LD:
|
||||
case OPCODE_LD_MS:
|
||||
case OPCODE_LOD:
|
||||
case OPCODE_LD_UAV_TYPED:
|
||||
case OPCODE_LD_RAW:
|
||||
case OPCODE_SAMPLE:
|
||||
case OPCODE_SAMPLE_B:
|
||||
case OPCODE_SAMPLE_L:
|
||||
case OPCODE_SAMPLE_D:
|
||||
case OPCODE_RESINFO:
|
||||
return &psInst->asOperands[2];
|
||||
// Special cases:
|
||||
case OPCODE_GATHER4:
|
||||
case OPCODE_GATHER4_C:
|
||||
case OPCODE_LD:
|
||||
case OPCODE_LD_MS:
|
||||
case OPCODE_LOD:
|
||||
case OPCODE_LD_UAV_TYPED:
|
||||
case OPCODE_LD_RAW:
|
||||
case OPCODE_SAMPLE:
|
||||
case OPCODE_SAMPLE_B:
|
||||
case OPCODE_SAMPLE_L:
|
||||
case OPCODE_SAMPLE_D:
|
||||
case OPCODE_RESINFO:
|
||||
return &psInst->asOperands[2];
|
||||
|
||||
case OPCODE_GATHER4_PO:
|
||||
case OPCODE_GATHER4_PO_C:
|
||||
case OPCODE_LD_STRUCTURED:
|
||||
return &psInst->asOperands[3];
|
||||
case OPCODE_GATHER4_PO:
|
||||
case OPCODE_GATHER4_PO_C:
|
||||
case OPCODE_LD_STRUCTURED:
|
||||
return &psInst->asOperands[3];
|
||||
|
||||
case OPCODE_SAMPLE_INFO:
|
||||
return &psInst->asOperands[1];
|
||||
case OPCODE_SAMPLE_INFO:
|
||||
return &psInst->asOperands[1];
|
||||
|
||||
case OPCODE_ISHL:
|
||||
case OPCODE_ISHR:
|
||||
case OPCODE_USHR:
|
||||
// sm4 variant has single component selection on src1 -> only src0 has swizzle
|
||||
if (psInst->asOperands[2].eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE)
|
||||
return &psInst->asOperands[1];
|
||||
else // whereas sm5 variant has swizzle also on src1
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
|
||||
|
||||
}
|
||||
case OPCODE_ISHL:
|
||||
case OPCODE_ISHR:
|
||||
case OPCODE_USHR:
|
||||
// sm4 variant has single component selection on src1 -> only src0 has swizzle
|
||||
if (psInst->asOperands[2].eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE)
|
||||
return &psInst->asOperands[1];
|
||||
else // whereas sm5 variant has swizzle also on src1
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Tweak the source operands of an instruction so that the rebased write mask will still work
|
||||
static void DoSrcOperandRebase(Operand *psOperand, uint32_t rebase)
|
||||
{
|
||||
uint32_t i;
|
||||
switch (psOperand->eSelMode)
|
||||
{
|
||||
default:
|
||||
case OPERAND_4_COMPONENT_MASK_MODE:
|
||||
ASSERT(psOperand->ui32CompMask == 0 || psOperand->ui32CompMask == OPERAND_4_COMPONENT_MASK_ALL);
|
||||
uint32_t i;
|
||||
switch (psOperand->eSelMode)
|
||||
{
|
||||
default:
|
||||
case OPERAND_4_COMPONENT_MASK_MODE:
|
||||
ASSERT(psOperand->ui32CompMask == 0 || psOperand->ui32CompMask == OPERAND_4_COMPONENT_MASK_ALL);
|
||||
|
||||
// Special case for immediates, they do not have swizzles
|
||||
if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32)
|
||||
{
|
||||
if (psOperand->iNumComponents > 1)
|
||||
std::copy(&psOperand->afImmediates[rebase], &psOperand->afImmediates[4], &psOperand->afImmediates[0]);
|
||||
return;
|
||||
}
|
||||
if (psOperand->eType == OPERAND_TYPE_IMMEDIATE64)
|
||||
{
|
||||
if (psOperand->iNumComponents > 1)
|
||||
std::copy(&psOperand->adImmediates[rebase], &psOperand->adImmediates[4], &psOperand->adImmediates[0]);
|
||||
return;
|
||||
}
|
||||
// Special case for immediates, they do not have swizzles
|
||||
if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32)
|
||||
{
|
||||
if (psOperand->iNumComponents > 1)
|
||||
std::copy(&psOperand->afImmediates[rebase], &psOperand->afImmediates[4], &psOperand->afImmediates[0]);
|
||||
return;
|
||||
}
|
||||
if (psOperand->eType == OPERAND_TYPE_IMMEDIATE64)
|
||||
{
|
||||
if (psOperand->iNumComponents > 1)
|
||||
std::copy(&psOperand->adImmediates[rebase], &psOperand->adImmediates[4], &psOperand->adImmediates[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Need to change this to swizzle
|
||||
psOperand->eSelMode = OPERAND_4_COMPONENT_SWIZZLE_MODE;
|
||||
psOperand->ui32Swizzle = 0;
|
||||
for (i = 0; i < 4 - rebase; i++)
|
||||
psOperand->aui32Swizzle[i] = i + rebase;
|
||||
for (; i < 4; i++)
|
||||
psOperand->aui32Swizzle[i] = rebase; // The first actual input.
|
||||
break;
|
||||
case OPERAND_4_COMPONENT_SELECT_1_MODE:
|
||||
// Nothing to do
|
||||
break;
|
||||
case OPERAND_4_COMPONENT_SWIZZLE_MODE:
|
||||
for (i = rebase; i < 4; i++)
|
||||
psOperand->aui32Swizzle[i - rebase] = psOperand->aui32Swizzle[i];
|
||||
break;
|
||||
}
|
||||
// Need to change this to swizzle
|
||||
psOperand->eSelMode = OPERAND_4_COMPONENT_SWIZZLE_MODE;
|
||||
psOperand->ui32Swizzle = 0;
|
||||
for (i = 0; i < 4 - rebase; i++)
|
||||
psOperand->aui32Swizzle[i] = i + rebase;
|
||||
for (; i < 4; i++)
|
||||
psOperand->aui32Swizzle[i] = rebase; // The first actual input.
|
||||
break;
|
||||
case OPERAND_4_COMPONENT_SELECT_1_MODE:
|
||||
// Nothing to do
|
||||
break;
|
||||
case OPERAND_4_COMPONENT_SWIZZLE_MODE:
|
||||
for (i = rebase; i < 4; i++)
|
||||
psOperand->aui32Swizzle[i - rebase] = psOperand->aui32Swizzle[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Instruction::ChangeOperandTempRegister(Operand *psOperand, uint32_t oldReg, uint32_t newReg, uint32_t compMask, uint32_t flags, uint32_t rebase)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t accessMask = 0;
|
||||
int isDestination = 0;
|
||||
Operand *psSwizzleOperand = NULL;
|
||||
uint32_t i = 0;
|
||||
uint32_t accessMask = 0;
|
||||
int isDestination = 0;
|
||||
Operand *psSwizzleOperand = NULL;
|
||||
|
||||
if (flags & UD_CHANGE_SUBOPERANDS)
|
||||
{
|
||||
for (i = 0; i < MAX_SUB_OPERANDS; i++)
|
||||
{
|
||||
if (psOperand->m_SubOperands[i].get())
|
||||
ChangeOperandTempRegister(psOperand->m_SubOperands[i].get(), oldReg, newReg, compMask, UD_CHANGE_ALL, rebase);
|
||||
}
|
||||
}
|
||||
if (flags & UD_CHANGE_SUBOPERANDS)
|
||||
{
|
||||
for (i = 0; i < MAX_SUB_OPERANDS; i++)
|
||||
{
|
||||
if (psOperand->m_SubOperands[i].get())
|
||||
ChangeOperandTempRegister(psOperand->m_SubOperands[i].get(), oldReg, newReg, compMask, UD_CHANGE_ALL, rebase);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & UD_CHANGE_MAIN_OPERAND) == 0)
|
||||
return;
|
||||
if ((flags & UD_CHANGE_MAIN_OPERAND) == 0)
|
||||
return;
|
||||
|
||||
if (psOperand->eType != OPERAND_TYPE_TEMP)
|
||||
return;
|
||||
if (psOperand->eType != OPERAND_TYPE_TEMP)
|
||||
return;
|
||||
|
||||
if (psOperand->ui32RegisterNumber != oldReg)
|
||||
return;
|
||||
if (psOperand->ui32RegisterNumber != oldReg)
|
||||
return;
|
||||
|
||||
accessMask = psOperand->GetAccessMask();
|
||||
// If this operation touches other components than the one(s) we're splitting, skip it
|
||||
if ((accessMask & (~compMask)) != 0)
|
||||
{
|
||||
// Verify that we've not messed up in reachability analysis.
|
||||
// This would mean that we've encountered an instruction that accesses
|
||||
// a component in multi-component mode and we're supposed to treat it as single-use only.
|
||||
// Now that we track operands we can bring this back
|
||||
ASSERT((accessMask & compMask) == 0);
|
||||
return;
|
||||
}
|
||||
accessMask = psOperand->GetAccessMask();
|
||||
// If this operation touches other components than the one(s) we're splitting, skip it
|
||||
if ((accessMask & (~compMask)) != 0)
|
||||
{
|
||||
// Verify that we've not messed up in reachability analysis.
|
||||
// This would mean that we've encountered an instruction that accesses
|
||||
// a component in multi-component mode and we're supposed to treat it as single-use only.
|
||||
// Now that we track operands we can bring this back
|
||||
ASSERT((accessMask & compMask) == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("Updating operand %d with access mask %X\n", (int)psOperand->id, accessMask);
|
||||
printf("Updating operand %d with access mask %X\n", (int)psOperand->id, accessMask);
|
||||
#endif
|
||||
psOperand->ui32RegisterNumber = newReg;
|
||||
psOperand->ui32RegisterNumber = newReg;
|
||||
|
||||
if (rebase == 0)
|
||||
return;
|
||||
if (rebase == 0)
|
||||
return;
|
||||
|
||||
// Update component mask. Note that we don't need to do anything to the suboperands. They do not affect destination writemask.
|
||||
switch (psOperand->eSelMode)
|
||||
{
|
||||
case OPERAND_4_COMPONENT_MASK_MODE:
|
||||
{
|
||||
uint32_t oldMask = psOperand->ui32CompMask;
|
||||
if (oldMask == 0)
|
||||
oldMask = OPERAND_4_COMPONENT_MASK_ALL;
|
||||
// Update component mask. Note that we don't need to do anything to the suboperands. They do not affect destination writemask.
|
||||
switch (psOperand->eSelMode)
|
||||
{
|
||||
case OPERAND_4_COMPONENT_MASK_MODE:
|
||||
{
|
||||
uint32_t oldMask = psOperand->ui32CompMask;
|
||||
if (oldMask == 0)
|
||||
oldMask = OPERAND_4_COMPONENT_MASK_ALL;
|
||||
|
||||
// Check that we're not losing any information
|
||||
ASSERT((oldMask >> rebase) << rebase == oldMask);
|
||||
psOperand->ui32CompMask = (oldMask >> rebase);
|
||||
break;
|
||||
}
|
||||
case OPERAND_4_COMPONENT_SELECT_1_MODE:
|
||||
ASSERT(psOperand->aui32Swizzle[0] >= rebase);
|
||||
psOperand->aui32Swizzle[0] -= rebase;
|
||||
break;
|
||||
case OPERAND_4_COMPONENT_SWIZZLE_MODE:
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
// Note that this rebase is different from the one done for source operands
|
||||
ASSERT(psOperand->aui32Swizzle[i] >= rebase);
|
||||
psOperand->aui32Swizzle[i] -= rebase;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT(0);
|
||||
// Check that we're not losing any information
|
||||
ASSERT((oldMask >> rebase) << rebase == oldMask);
|
||||
psOperand->ui32CompMask = (oldMask >> rebase);
|
||||
break;
|
||||
}
|
||||
case OPERAND_4_COMPONENT_SELECT_1_MODE:
|
||||
ASSERT(psOperand->aui32Swizzle[0] >= rebase);
|
||||
psOperand->aui32Swizzle[0] -= rebase;
|
||||
break;
|
||||
case OPERAND_4_COMPONENT_SWIZZLE_MODE:
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
// Note that this rebase is different from the one done for source operands
|
||||
ASSERT(psOperand->aui32Swizzle[i] >= rebase);
|
||||
psOperand->aui32Swizzle[i] -= rebase;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
}
|
||||
// Tweak operand datatypes
|
||||
std::copy(&psOperand->aeDataType[rebase], &psOperand->aeDataType[4], &psOperand->aeDataType[0]);
|
||||
|
||||
// Tweak operand datatypes
|
||||
std::copy(&psOperand->aeDataType[rebase], &psOperand->aeDataType[4], &psOperand->aeDataType[0]);
|
||||
// If this operand is a destination, we'll need to tweak sources as well
|
||||
for (i = 0; i < ui32FirstSrc; i++)
|
||||
{
|
||||
if (psOperand == &asOperands[i])
|
||||
{
|
||||
isDestination = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If this operand is a destination, we'll need to tweak sources as well
|
||||
for (i = 0; i < ui32FirstSrc; i++)
|
||||
{
|
||||
if (psOperand == &asOperands[i])
|
||||
{
|
||||
isDestination = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isDestination == 0)
|
||||
return;
|
||||
|
||||
if (isDestination == 0)
|
||||
return;
|
||||
// Nasty corner case of 2 destinations, not supported if both targets are written
|
||||
ASSERT((ui32FirstSrc < 2) || (asOperands[0].eType == OPERAND_TYPE_NULL) || (asOperands[1].eType == OPERAND_TYPE_NULL));
|
||||
|
||||
// Nasty corner case of 2 destinations, not supported if both targets are written
|
||||
ASSERT((ui32FirstSrc < 2) || (asOperands[0].eType == OPERAND_TYPE_NULL) || (asOperands[1].eType == OPERAND_TYPE_NULL));
|
||||
|
||||
// If we made it this far, we're rebasing a destination temp (and the only destination), need to tweak sources depending on the instruction
|
||||
switch (eOpcode)
|
||||
{
|
||||
// The opcodes that do not need tweaking:
|
||||
case OPCODE_DP2:
|
||||
case OPCODE_DP3:
|
||||
case OPCODE_DP4:
|
||||
case OPCODE_BUFINFO:
|
||||
case OPCODE_SAMPLE_C:
|
||||
case OPCODE_SAMPLE_C_LZ:
|
||||
return;
|
||||
|
||||
default:
|
||||
psSwizzleOperand = GetSrcSwizzleOperand(this); // Null means tweak all source operands
|
||||
if (psSwizzleOperand)
|
||||
{
|
||||
DoSrcOperandRebase(psSwizzleOperand, rebase);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = ui32FirstSrc; i < ui32NumOperands; i++)
|
||||
{
|
||||
DoSrcOperandRebase(&asOperands[i], rebase);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// If we made it this far, we're rebasing a destination temp (and the only destination), need to tweak sources depending on the instruction
|
||||
switch (eOpcode)
|
||||
{
|
||||
// The opcodes that do not need tweaking:
|
||||
case OPCODE_DP2:
|
||||
case OPCODE_DP3:
|
||||
case OPCODE_DP4:
|
||||
case OPCODE_BUFINFO:
|
||||
case OPCODE_SAMPLE_C:
|
||||
case OPCODE_SAMPLE_C_LZ:
|
||||
return;
|
||||
|
||||
default:
|
||||
psSwizzleOperand = GetSrcSwizzleOperand(this); // Null means tweak all source operands
|
||||
if (psSwizzleOperand)
|
||||
{
|
||||
DoSrcOperandRebase(psSwizzleOperand, rebase);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = ui32FirstSrc; i < ui32NumOperands; i++)
|
||||
{
|
||||
DoSrcOperandRebase(&asOperands[i], rebase);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns nonzero if psInst is a sample instruction and the sampler has medium or low precision
|
||||
bool Instruction::IsPartialPrecisionSamplerInstruction(const ShaderInfo &info, OPERAND_MIN_PRECISION *pType) const
|
||||
{
|
||||
const Operand *op;
|
||||
const ResourceBinding *psBinding = NULL;
|
||||
OPERAND_MIN_PRECISION sType = OPERAND_MIN_PRECISION_DEFAULT;
|
||||
switch (eOpcode)
|
||||
{
|
||||
default:
|
||||
return false;
|
||||
case OPCODE_SAMPLE:
|
||||
case OPCODE_SAMPLE_B:
|
||||
case OPCODE_SAMPLE_L:
|
||||
case OPCODE_SAMPLE_D:
|
||||
case OPCODE_SAMPLE_C:
|
||||
case OPCODE_SAMPLE_C_LZ:
|
||||
break;
|
||||
}
|
||||
const Operand *op;
|
||||
const ResourceBinding *psBinding = NULL;
|
||||
OPERAND_MIN_PRECISION sType = OPERAND_MIN_PRECISION_DEFAULT;
|
||||
switch (eOpcode)
|
||||
{
|
||||
default:
|
||||
return false;
|
||||
case OPCODE_SAMPLE:
|
||||
case OPCODE_SAMPLE_B:
|
||||
case OPCODE_SAMPLE_L:
|
||||
case OPCODE_SAMPLE_D:
|
||||
case OPCODE_SAMPLE_C:
|
||||
case OPCODE_SAMPLE_C_LZ:
|
||||
break;
|
||||
}
|
||||
|
||||
op = &asOperands[3];
|
||||
ASSERT(op->eType == OPERAND_TYPE_SAMPLER);
|
||||
op = &asOperands[3];
|
||||
ASSERT(op->eType == OPERAND_TYPE_SAMPLER);
|
||||
|
||||
info.GetResourceFromBindingPoint(RGROUP_SAMPLER, op->ui32RegisterNumber, &psBinding);
|
||||
if (!psBinding)
|
||||
{
|
||||
/* Try to look from texture group */
|
||||
info.GetResourceFromBindingPoint(RGROUP_TEXTURE, op->ui32RegisterNumber, &psBinding);
|
||||
}
|
||||
info.GetResourceFromBindingPoint(RGROUP_SAMPLER, op->ui32RegisterNumber, &psBinding);
|
||||
if (!psBinding)
|
||||
{
|
||||
/* Try to look from texture group */
|
||||
info.GetResourceFromBindingPoint(RGROUP_TEXTURE, op->ui32RegisterNumber, &psBinding);
|
||||
}
|
||||
|
||||
sType = Operand::ResourcePrecisionToOperandPrecision(psBinding ? psBinding->ePrecision : REFLECT_RESOURCE_PRECISION_UNKNOWN);
|
||||
sType = Operand::ResourcePrecisionToOperandPrecision(psBinding ? psBinding->ePrecision : REFLECT_RESOURCE_PRECISION_UNKNOWN);
|
||||
|
||||
if (sType == OPERAND_MIN_PRECISION_DEFAULT)
|
||||
return false;
|
||||
if (sType == OPERAND_MIN_PRECISION_DEFAULT)
|
||||
return false;
|
||||
|
||||
if (pType)
|
||||
*pType = sType;
|
||||
if (pType)
|
||||
*pType = sType;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#include "src/internal_includes/HLSLCrossCompilerContext.h"
|
||||
#include "src/internal_includes/LoopTransform.h"
|
||||
#include "src/internal_includes/Shader.h"
|
||||
@ -9,366 +8,363 @@
|
||||
|
||||
namespace HLSLcc
|
||||
{
|
||||
struct LoopInfo
|
||||
{
|
||||
public:
|
||||
LoopInfo() : m_StartLoop(0), m_EndLoop(0), m_ExitPoints(), m_IsSwitch(false) {}
|
||||
|
||||
struct LoopInfo
|
||||
{
|
||||
public:
|
||||
LoopInfo() : m_StartLoop(0), m_EndLoop(0), m_ExitPoints(), m_IsSwitch(false) {}
|
||||
Instruction * m_StartLoop; // OPCODE_LOOP
|
||||
Instruction * m_EndLoop; // OPCODE_ENDLOOP that matches the LOOP above.
|
||||
std::vector<Instruction *> m_ExitPoints; // Any BREAK/RET/BREAKC instructions within the same loop depth
|
||||
bool m_IsSwitch; // True if this is a switch-case and not a LOOP/ENDLOOP pair. Used as a helper when parsing.
|
||||
};
|
||||
|
||||
Instruction * m_StartLoop; // OPCODE_LOOP
|
||||
Instruction * m_EndLoop; // OPCODE_ENDLOOP that matches the LOOP above.
|
||||
std::vector<Instruction *> m_ExitPoints; // Any BREAK/RET/BREAKC instructions within the same loop depth
|
||||
bool m_IsSwitch; // True if this is a switch-case and not a LOOP/ENDLOOP pair. Used as a helper when parsing.
|
||||
};
|
||||
|
||||
typedef std::list<LoopInfo> Loops;
|
||||
typedef std::list<LoopInfo> Loops;
|
||||
|
||||
// Build a loopinfo array of all the loops in this shader phase
|
||||
void BuildLoopInfo(ShaderPhase &phase, Loops &res)
|
||||
{
|
||||
using namespace std;
|
||||
res.clear();
|
||||
// Build a loopinfo array of all the loops in this shader phase
|
||||
void BuildLoopInfo(ShaderPhase &phase, Loops &res)
|
||||
{
|
||||
using namespace std;
|
||||
res.clear();
|
||||
|
||||
// A stack of loopinfo elements (stored in res)
|
||||
list<LoopInfo *> loopStack;
|
||||
// A stack of loopinfo elements (stored in res)
|
||||
list<LoopInfo *> loopStack;
|
||||
|
||||
// Storage for dummy LoopInfo elements to be used for switch-cases. We don't want them cluttering the Loops list so store them here.
|
||||
list<LoopInfo> dummyLIForSwitches;
|
||||
// Storage for dummy LoopInfo elements to be used for switch-cases. We don't want them cluttering the Loops list so store them here.
|
||||
list<LoopInfo> dummyLIForSwitches;
|
||||
|
||||
for (std::vector<Instruction>::iterator instItr = phase.psInst.begin(); instItr != phase.psInst.end(); instItr++)
|
||||
{
|
||||
Instruction *i = &*instItr;
|
||||
for (std::vector<Instruction>::iterator instItr = phase.psInst.begin(); instItr != phase.psInst.end(); instItr++)
|
||||
{
|
||||
Instruction *i = &*instItr;
|
||||
|
||||
if (i->eOpcode == OPCODE_LOOP)
|
||||
{
|
||||
LoopInfo *currLoopInfo = &*res.insert(res.end(), LoopInfo());
|
||||
currLoopInfo->m_StartLoop = i;
|
||||
loopStack.push_front(currLoopInfo);
|
||||
}
|
||||
else if(i->eOpcode == OPCODE_ENDLOOP)
|
||||
{
|
||||
ASSERT(!loopStack.empty());
|
||||
LoopInfo *li = *loopStack.begin();
|
||||
loopStack.pop_front();
|
||||
li->m_EndLoop = i;
|
||||
}
|
||||
else if (i->eOpcode == OPCODE_SWITCH)
|
||||
{
|
||||
// Create a dummy entry into the stack
|
||||
LoopInfo *li = &*dummyLIForSwitches.insert(dummyLIForSwitches.end(), LoopInfo());
|
||||
li->m_IsSwitch = true;
|
||||
loopStack.push_front(li);
|
||||
}
|
||||
else if (i->eOpcode == OPCODE_ENDSWITCH)
|
||||
{
|
||||
ASSERT(!loopStack.empty());
|
||||
LoopInfo *li = *loopStack.begin();
|
||||
loopStack.pop_front();
|
||||
ASSERT(li->m_IsSwitch);
|
||||
}
|
||||
else if (i->eOpcode == OPCODE_BREAK || i->eOpcode == OPCODE_BREAKC)
|
||||
{
|
||||
// Get the current loopstack head
|
||||
ASSERT(!loopStack.empty());
|
||||
LoopInfo *li = *loopStack.begin();
|
||||
// Ignore breaks from switch-cases
|
||||
if(!li->m_IsSwitch)
|
||||
{
|
||||
li->m_ExitPoints.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i->eOpcode == OPCODE_LOOP)
|
||||
{
|
||||
LoopInfo *currLoopInfo = &*res.insert(res.end(), LoopInfo());
|
||||
currLoopInfo->m_StartLoop = i;
|
||||
loopStack.push_front(currLoopInfo);
|
||||
}
|
||||
else if (i->eOpcode == OPCODE_ENDLOOP)
|
||||
{
|
||||
ASSERT(!loopStack.empty());
|
||||
LoopInfo *li = *loopStack.begin();
|
||||
loopStack.pop_front();
|
||||
li->m_EndLoop = i;
|
||||
}
|
||||
else if (i->eOpcode == OPCODE_SWITCH)
|
||||
{
|
||||
// Create a dummy entry into the stack
|
||||
LoopInfo *li = &*dummyLIForSwitches.insert(dummyLIForSwitches.end(), LoopInfo());
|
||||
li->m_IsSwitch = true;
|
||||
loopStack.push_front(li);
|
||||
}
|
||||
else if (i->eOpcode == OPCODE_ENDSWITCH)
|
||||
{
|
||||
ASSERT(!loopStack.empty());
|
||||
LoopInfo *li = *loopStack.begin();
|
||||
loopStack.pop_front();
|
||||
ASSERT(li->m_IsSwitch);
|
||||
}
|
||||
else if (i->eOpcode == OPCODE_BREAK || i->eOpcode == OPCODE_BREAKC)
|
||||
{
|
||||
// Get the current loopstack head
|
||||
ASSERT(!loopStack.empty());
|
||||
LoopInfo *li = *loopStack.begin();
|
||||
// Ignore breaks from switch-cases
|
||||
if (!li->m_IsSwitch)
|
||||
{
|
||||
li->m_ExitPoints.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Returns true if the given instruction is a non-vectorized int or uint comparison instruction that reads from at least one temp and writes to a temp
|
||||
static bool IsScalarTempComparisonInstruction(const Instruction *i)
|
||||
{
|
||||
switch (i->eOpcode)
|
||||
{
|
||||
default:
|
||||
return false;
|
||||
case OPCODE_IGE:
|
||||
case OPCODE_ILT:
|
||||
case OPCODE_IEQ:
|
||||
case OPCODE_INE:
|
||||
case OPCODE_UGE:
|
||||
case OPCODE_ULT:
|
||||
break;
|
||||
}
|
||||
|
||||
// Returns true if the given instruction is a non-vectorized int or uint comparison instruction that reads from at least one temp and writes to a temp
|
||||
static bool IsScalarTempComparisonInstruction(const Instruction *i)
|
||||
{
|
||||
switch (i->eOpcode)
|
||||
{
|
||||
default:
|
||||
return false;
|
||||
case OPCODE_IGE:
|
||||
case OPCODE_ILT:
|
||||
case OPCODE_IEQ:
|
||||
case OPCODE_INE:
|
||||
case OPCODE_UGE:
|
||||
case OPCODE_ULT:
|
||||
break;
|
||||
}
|
||||
if (i->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return false;
|
||||
|
||||
if (i->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return false;
|
||||
int tempOp = -1;
|
||||
if (i->asOperands[1].eType == OPERAND_TYPE_TEMP)
|
||||
tempOp = 1;
|
||||
else if (i->asOperands[2].eType == OPERAND_TYPE_TEMP)
|
||||
tempOp = 2;
|
||||
|
||||
int tempOp = -1;
|
||||
if (i->asOperands[1].eType == OPERAND_TYPE_TEMP)
|
||||
tempOp = 1;
|
||||
else if (i->asOperands[2].eType == OPERAND_TYPE_TEMP)
|
||||
tempOp = 2;
|
||||
// Also reject comparisons where we compare temp.x vs temp.y
|
||||
if (i->asOperands[1].eType == OPERAND_TYPE_TEMP && i->asOperands[2].eType == OPERAND_TYPE_TEMP && i->asOperands[1].ui32RegisterNumber == i->asOperands[2].ui32RegisterNumber)
|
||||
return false;
|
||||
|
||||
// Also reject comparisons where we compare temp.x vs temp.y
|
||||
if (i->asOperands[1].eType == OPERAND_TYPE_TEMP && i->asOperands[2].eType == OPERAND_TYPE_TEMP && i->asOperands[1].ui32RegisterNumber == i->asOperands[2].ui32RegisterNumber)
|
||||
return false;
|
||||
if (tempOp == -1)
|
||||
return false;
|
||||
|
||||
if (tempOp == -1)
|
||||
return false;
|
||||
if (i->asOperands[0].GetNumSwizzleElements() != 1)
|
||||
return false;
|
||||
|
||||
if (i->asOperands[0].GetNumSwizzleElements() != 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// Returns true iff both instructions perform identical operation. For the purposes of Loop transformation, we only consider operations of type tX = tX <op> imm32
|
||||
static bool AreInstructionsIdentical(const Instruction *a, const Instruction *b)
|
||||
{
|
||||
if (a->eOpcode != b->eOpcode)
|
||||
return false;
|
||||
ASSERT(a->ui32NumOperands == b->ui32NumOperands);
|
||||
uint32_t dstReg = 0;
|
||||
if (a->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return false;
|
||||
dstReg = a->asOperands[0].ui32RegisterNumber;
|
||||
|
||||
// Returns true iff both instructions perform identical operation. For the purposes of Loop transformation, we only consider operations of type tX = tX <op> imm32
|
||||
static bool AreInstructionsIdentical(const Instruction *a, const Instruction *b)
|
||||
{
|
||||
if (a->eOpcode != b->eOpcode)
|
||||
return false;
|
||||
ASSERT(a->ui32NumOperands == b->ui32NumOperands);
|
||||
uint32_t dstReg = 0;
|
||||
if (a->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return false;
|
||||
dstReg = a->asOperands[0].ui32RegisterNumber;
|
||||
for (uint32_t i = 0; i < a->ui32NumOperands; i++)
|
||||
{
|
||||
const Operand &aop = a->asOperands[i];
|
||||
const Operand &bop = b->asOperands[i];
|
||||
if (aop.eType != bop.eType)
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < a->ui32NumOperands; i++)
|
||||
{
|
||||
const Operand &aop = a->asOperands[i];
|
||||
const Operand &bop = b->asOperands[i];
|
||||
if (aop.eType != bop.eType)
|
||||
return false;
|
||||
if (aop.GetAccessMask() != bop.GetAccessMask())
|
||||
return false;
|
||||
|
||||
if (aop.GetAccessMask() != bop.GetAccessMask())
|
||||
return false;
|
||||
if (aop.GetNumSwizzleElements() != 1)
|
||||
return false;
|
||||
|
||||
if (aop.GetNumSwizzleElements() != 1)
|
||||
return false;
|
||||
if (aop.eType == OPERAND_TYPE_TEMP)
|
||||
{
|
||||
if (aop.ui32RegisterNumber != bop.ui32RegisterNumber)
|
||||
return false;
|
||||
if (aop.ui32RegisterNumber != dstReg)
|
||||
return false;
|
||||
}
|
||||
else if (aop.eType == OPERAND_TYPE_IMMEDIATE32)
|
||||
{
|
||||
if (memcmp(aop.afImmediates, bop.afImmediates, 4 * sizeof(float)) != 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aop.eType == OPERAND_TYPE_TEMP)
|
||||
{
|
||||
if (aop.ui32RegisterNumber != bop.ui32RegisterNumber)
|
||||
return false;
|
||||
if (aop.ui32RegisterNumber != dstReg)
|
||||
return false;
|
||||
}
|
||||
else if (aop.eType == OPERAND_TYPE_IMMEDIATE32)
|
||||
{
|
||||
if (memcmp(aop.afImmediates, bop.afImmediates, 4 * sizeof(float)) != 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Attempt to transform a single loop into a for-statement
|
||||
static void AttemptLoopTransform(HLSLCrossCompilerContext *psContext, ShaderPhase &phase, LoopInfo &li)
|
||||
{
|
||||
// In order to transform a loop into a for, the following has to hold:
|
||||
// - The loop must start with a comparison instruction where one of the src operands is a temp (induction variable), followed by OPCODE_BREAKC.
|
||||
// - The loop must end with an arithmetic operation (SUB or ADD) where the dest operand is the same temp as one of the sources in the comparison instruction above
|
||||
// Additionally, if the loop induction variable is initialized before the start of the loop and it has only uses inside the LOOP/ENDLOOP pair, we can declare that inside the for statement.
|
||||
// Also, the loop induction variable must be standalone (as in, never used as part of a larger vector)
|
||||
|
||||
// Attempt to transform a single loop into a for-statement
|
||||
static void AttemptLoopTransform(HLSLCrossCompilerContext *psContext, ShaderPhase &phase, LoopInfo &li)
|
||||
{
|
||||
// In order to transform a loop into a for, the following has to hold:
|
||||
// - The loop must start with a comparison instruction where one of the src operands is a temp (induction variable), followed by OPCODE_BREAKC.
|
||||
// - The loop must end with an arithmetic operation (SUB or ADD) where the dest operand is the same temp as one of the sources in the comparison instruction above
|
||||
// Additionally, if the loop induction variable is initialized before the start of the loop and it has only uses inside the LOOP/ENDLOOP pair, we can declare that inside the for statement.
|
||||
// Also, the loop induction variable must be standalone (as in, never used as part of a larger vector)
|
||||
Instruction *cmpInst = li.m_StartLoop + 1;
|
||||
|
||||
Instruction *cmpInst = li.m_StartLoop + 1;
|
||||
if (!IsScalarTempComparisonInstruction(cmpInst))
|
||||
return;
|
||||
|
||||
if (!IsScalarTempComparisonInstruction(cmpInst))
|
||||
return;
|
||||
Instruction *breakInst = li.m_StartLoop + 2;
|
||||
if (breakInst->eOpcode != OPCODE_BREAKC)
|
||||
return;
|
||||
if (breakInst->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return;
|
||||
if (breakInst->asOperands[0].ui32RegisterNumber != cmpInst->asOperands[0].ui32RegisterNumber)
|
||||
return;
|
||||
|
||||
Instruction *breakInst = li.m_StartLoop + 2;
|
||||
if (breakInst->eOpcode != OPCODE_BREAKC)
|
||||
return;
|
||||
if (breakInst->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return;
|
||||
if (breakInst->asOperands[0].ui32RegisterNumber != cmpInst->asOperands[0].ui32RegisterNumber)
|
||||
return;
|
||||
// Check that the comparison result isn't used anywhere else
|
||||
if (cmpInst->m_Uses.size() != 1)
|
||||
return;
|
||||
|
||||
// Check that the comparison result isn't used anywhere else
|
||||
if (cmpInst->m_Uses.size() != 1)
|
||||
return;
|
||||
ASSERT(cmpInst->m_Uses[0].m_Inst == breakInst);
|
||||
|
||||
ASSERT(cmpInst->m_Uses[0].m_Inst == breakInst);
|
||||
// Ok, at least we have the comparison + breakc combo at top. Try to find the induction variable
|
||||
uint32_t inductionVarIdx = 0;
|
||||
|
||||
// Ok, at least we have the comparison + breakc combo at top. Try to find the induction variable
|
||||
uint32_t inductionVarIdx = 0;
|
||||
Instruction *lastInst = li.m_EndLoop - 1;
|
||||
if (lastInst->eOpcode != OPCODE_IADD)
|
||||
return;
|
||||
if (lastInst->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return;
|
||||
|
||||
Instruction *lastInst = li.m_EndLoop - 1;
|
||||
if (lastInst->eOpcode != OPCODE_IADD)
|
||||
return;
|
||||
if (lastInst->asOperands[0].eType != OPERAND_TYPE_TEMP)
|
||||
return;
|
||||
if (lastInst->asOperands[0].GetNumSwizzleElements() != 1)
|
||||
return;
|
||||
|
||||
if (lastInst->asOperands[0].GetNumSwizzleElements() != 1)
|
||||
return;
|
||||
uint32_t indVar = lastInst->asOperands[0].ui32RegisterNumber;
|
||||
// Verify that the induction variable actually matches.
|
||||
if (cmpInst->asOperands[1].eType == OPERAND_TYPE_TEMP && cmpInst->asOperands[1].ui32RegisterNumber == indVar)
|
||||
inductionVarIdx = 1;
|
||||
else if (cmpInst->asOperands[2].eType == OPERAND_TYPE_TEMP && cmpInst->asOperands[2].ui32RegisterNumber == indVar)
|
||||
inductionVarIdx = 2;
|
||||
else
|
||||
return;
|
||||
|
||||
uint32_t indVar = lastInst->asOperands[0].ui32RegisterNumber;
|
||||
// Verify that the induction variable actually matches.
|
||||
if (cmpInst->asOperands[1].eType == OPERAND_TYPE_TEMP && cmpInst->asOperands[1].ui32RegisterNumber == indVar)
|
||||
inductionVarIdx = 1;
|
||||
else if (cmpInst->asOperands[2].eType == OPERAND_TYPE_TEMP && cmpInst->asOperands[2].ui32RegisterNumber == indVar)
|
||||
inductionVarIdx = 2;
|
||||
else
|
||||
return;
|
||||
// Verify that we also read from the induction variable in the last instruction
|
||||
if (!((lastInst->asOperands[1].eType == OPERAND_TYPE_TEMP && lastInst->asOperands[1].ui32RegisterNumber == indVar) ||
|
||||
(lastInst->asOperands[2].eType == OPERAND_TYPE_TEMP && lastInst->asOperands[2].ui32RegisterNumber == indVar)))
|
||||
return;
|
||||
|
||||
// Verify that we also read from the induction variable in the last instruction
|
||||
if (!((lastInst->asOperands[1].eType == OPERAND_TYPE_TEMP && lastInst->asOperands[1].ui32RegisterNumber == indVar) ||
|
||||
(lastInst->asOperands[2].eType == OPERAND_TYPE_TEMP && lastInst->asOperands[2].ui32RegisterNumber == indVar)))
|
||||
return;
|
||||
// Nvidia compiler bug workaround: The shader compiler tries to be smart and unrolls constant loops,
|
||||
// but then fails miserably if the loop variable is used as an index to UAV loads/stores or some other cases ("array access too complex")
|
||||
// This is also triggered when the driver optimizer sees "simple enough" arithmetics (whatever that is) done on the loop variable before indexing.
|
||||
// So, disable for-loop transformation altogether whenever we see a UAV load or store inside a loop.
|
||||
if (psContext->psShader->eTargetLanguage >= LANG_400 && psContext->psShader->eTargetLanguage < LANG_GL_LAST && !psContext->IsVulkan())
|
||||
{
|
||||
for (auto itr = li.m_StartLoop; itr != li.m_EndLoop; itr++)
|
||||
{
|
||||
switch (itr->eOpcode)
|
||||
{
|
||||
case OPCODE_LD_RAW:
|
||||
case OPCODE_LD_STRUCTURED:
|
||||
case OPCODE_LD_UAV_TYPED:
|
||||
case OPCODE_STORE_RAW:
|
||||
case OPCODE_STORE_STRUCTURED:
|
||||
case OPCODE_STORE_UAV_TYPED:
|
||||
return; // Nope, can't do a for, not even a partial one.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nvidia compiler bug workaround: The shader compiler tries to be smart and unrolls constant loops,
|
||||
// but then fails miserably if the loop variable is used as an index to UAV loads/stores or some other cases ("array access too complex")
|
||||
// This is also triggered when the driver optimizer sees "simple enough" arithmetics (whatever that is) done on the loop variable before indexing.
|
||||
// So, disable for-loop transformation altogether whenever we see a UAV load or store inside a loop.
|
||||
if(psContext->psShader->eTargetLanguage >= LANG_400 && psContext->psShader->eTargetLanguage < LANG_GL_LAST && !psContext->IsVulkan())
|
||||
{
|
||||
for (auto itr = li.m_StartLoop; itr != li.m_EndLoop; itr++)
|
||||
{
|
||||
switch (itr->eOpcode)
|
||||
{
|
||||
case OPCODE_LD_RAW:
|
||||
case OPCODE_LD_STRUCTURED:
|
||||
case OPCODE_LD_UAV_TYPED:
|
||||
case OPCODE_STORE_RAW:
|
||||
case OPCODE_STORE_STRUCTURED:
|
||||
case OPCODE_STORE_UAV_TYPED:
|
||||
return; // Nope, can't do a for, not even a partial one.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// One more thing to check: The comparison input may only see 1 definition that originates from inside the loop range: the one in lastInst.
|
||||
// Anything else means that there's a continue statement, or another break/breakc and that means that lastInst wouldn't get called.
|
||||
// Of course, if all those instructions are identical, then it's fine.
|
||||
// Ideally, if there's only one definition that's from outside the loop range, then we can use that as the initializer, as well.
|
||||
|
||||
// One more thing to check: The comparison input may only see 1 definition that originates from inside the loop range: the one in lastInst.
|
||||
// Anything else means that there's a continue statement, or another break/breakc and that means that lastInst wouldn't get called.
|
||||
// Of course, if all those instructions are identical, then it's fine.
|
||||
// Ideally, if there's only one definition that's from outside the loop range, then we can use that as the initializer, as well.
|
||||
Instruction *initializer = NULL;
|
||||
std::vector<const Operand::Define *> definitionsOutsideRange;
|
||||
std::vector<const Operand::Define *> definitionsInsideRange;
|
||||
std::for_each(cmpInst->asOperands[inductionVarIdx].m_Defines.begin(), cmpInst->asOperands[inductionVarIdx].m_Defines.end(), [&](const Operand::Define &def)
|
||||
{
|
||||
if (def.m_Inst < li.m_StartLoop || def.m_Inst > li.m_EndLoop)
|
||||
definitionsOutsideRange.push_back(&def);
|
||||
else
|
||||
definitionsInsideRange.push_back(&def);
|
||||
});
|
||||
|
||||
Instruction *initializer = NULL;
|
||||
std::vector<const Operand::Define *> definitionsOutsideRange;
|
||||
std::vector<const Operand::Define *> definitionsInsideRange;
|
||||
std::for_each(cmpInst->asOperands[inductionVarIdx].m_Defines.begin(), cmpInst->asOperands[inductionVarIdx].m_Defines.end(), [&](const Operand::Define &def)
|
||||
{
|
||||
if (def.m_Inst < li.m_StartLoop || def.m_Inst > li.m_EndLoop)
|
||||
definitionsOutsideRange.push_back(&def);
|
||||
else
|
||||
definitionsInsideRange.push_back(&def);
|
||||
});
|
||||
if (definitionsInsideRange.size() != 1)
|
||||
{
|
||||
// All definitions must be identical
|
||||
for (std::vector<const Operand::Define*>::iterator itr = definitionsInsideRange.begin() + 1; itr != definitionsInsideRange.end(); itr++)
|
||||
{
|
||||
if (!AreInstructionsIdentical((*itr)->m_Inst, definitionsInsideRange[0]->m_Inst))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (definitionsInsideRange.size() != 1)
|
||||
{
|
||||
// All definitions must be identical
|
||||
for (std::vector<const Operand::Define*>::iterator itr = definitionsInsideRange.begin()+1; itr != definitionsInsideRange.end(); itr++)
|
||||
{
|
||||
if (!AreInstructionsIdentical((*itr)->m_Inst, definitionsInsideRange[0]->m_Inst))
|
||||
return;
|
||||
}
|
||||
}
|
||||
ASSERT(definitionsOutsideRange.size() > 0);
|
||||
if (definitionsOutsideRange.size() == 1)
|
||||
initializer = definitionsOutsideRange[0]->m_Inst;
|
||||
|
||||
ASSERT(definitionsOutsideRange.size() > 0);
|
||||
if (definitionsOutsideRange.size() == 1)
|
||||
initializer = definitionsOutsideRange[0]->m_Inst;
|
||||
// Initializer must only write to one component
|
||||
if (initializer && initializer->asOperands[0].GetNumSwizzleElements() != 1)
|
||||
initializer = 0;
|
||||
// Initializer data type must be int or uint
|
||||
if (initializer)
|
||||
{
|
||||
SHADER_VARIABLE_TYPE dataType = initializer->asOperands[0].GetDataType(psContext);
|
||||
if (dataType != SVT_INT && dataType != SVT_UINT)
|
||||
return;
|
||||
}
|
||||
|
||||
// Initializer must only write to one component
|
||||
if (initializer && initializer->asOperands[0].GetNumSwizzleElements() != 1)
|
||||
initializer = 0;
|
||||
// Initializer data type must be int or uint
|
||||
if (initializer)
|
||||
{
|
||||
SHADER_VARIABLE_TYPE dataType = initializer->asOperands[0].GetDataType(psContext);
|
||||
if (dataType != SVT_INT && dataType != SVT_UINT)
|
||||
return;
|
||||
}
|
||||
// Check that the initializer is only used within the range so we can move it to for statement
|
||||
if (initializer)
|
||||
{
|
||||
bool hasUsesOutsideRange = false;
|
||||
std::for_each(initializer->m_Uses.begin(), initializer->m_Uses.end(), [&](const Instruction::Use &u)
|
||||
{
|
||||
if (u.m_Inst < li.m_StartLoop || u.m_Inst > li.m_EndLoop)
|
||||
hasUsesOutsideRange = true;
|
||||
});
|
||||
// Has outside uses? we cannot pull that up to the for statement
|
||||
if (hasUsesOutsideRange)
|
||||
initializer = 0;
|
||||
}
|
||||
|
||||
// Check that the initializer is only used within the range so we can move it to for statement
|
||||
if (initializer)
|
||||
{
|
||||
bool hasUsesOutsideRange = false;
|
||||
std::for_each(initializer->m_Uses.begin(), initializer->m_Uses.end(), [&](const Instruction::Use &u)
|
||||
{
|
||||
if (u.m_Inst < li.m_StartLoop || u.m_Inst > li.m_EndLoop)
|
||||
hasUsesOutsideRange = true;
|
||||
});
|
||||
// Has outside uses? we cannot pull that up to the for statement
|
||||
if (hasUsesOutsideRange)
|
||||
initializer = 0;
|
||||
}
|
||||
|
||||
// Check that the loop adder instruction only has uses inside the loop range, otherwise we cannot move the initializer either
|
||||
if (initializer)
|
||||
{
|
||||
bool cannotDoInitializer = false;
|
||||
for (auto itr = lastInst->m_Uses.begin(); itr != lastInst->m_Uses.end(); itr++)
|
||||
{
|
||||
const Instruction::Use &u = *itr;
|
||||
if (u.m_Inst < li.m_StartLoop || u.m_Inst > li.m_EndLoop)
|
||||
{
|
||||
cannotDoInitializer = true;
|
||||
break;
|
||||
}
|
||||
// Also check that the uses are not vector ops (temp splitting has already pulled everything to .x if this is a standalone var)
|
||||
if (u.m_Op->GetAccessMask() != 1)
|
||||
{
|
||||
cannotDoInitializer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Has outside uses? we cannot pull that up to the for statement
|
||||
if (cannotDoInitializer)
|
||||
initializer = 0;
|
||||
}
|
||||
// Check that the loop adder instruction only has uses inside the loop range, otherwise we cannot move the initializer either
|
||||
if (initializer)
|
||||
{
|
||||
bool cannotDoInitializer = false;
|
||||
for (auto itr = lastInst->m_Uses.begin(); itr != lastInst->m_Uses.end(); itr++)
|
||||
{
|
||||
const Instruction::Use &u = *itr;
|
||||
if (u.m_Inst < li.m_StartLoop || u.m_Inst > li.m_EndLoop)
|
||||
{
|
||||
cannotDoInitializer = true;
|
||||
break;
|
||||
}
|
||||
// Also check that the uses are not vector ops (temp splitting has already pulled everything to .x if this is a standalone var)
|
||||
if (u.m_Op->GetAccessMask() != 1)
|
||||
{
|
||||
cannotDoInitializer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Has outside uses? we cannot pull that up to the for statement
|
||||
if (cannotDoInitializer)
|
||||
initializer = 0;
|
||||
}
|
||||
|
||||
|
||||
if (initializer)
|
||||
{
|
||||
// We can declare the initializer in the for loop header, allocate a new number for it and change all uses into that.
|
||||
uint32_t newRegister = phase.m_NextFreeTempRegister++;
|
||||
li.m_StartLoop->m_InductorRegister = newRegister;
|
||||
std::for_each(initializer->m_Uses.begin(), initializer->m_Uses.end(), [newRegister](const Instruction::Use &u)
|
||||
{
|
||||
u.m_Op->m_ForLoopInductorName = newRegister;
|
||||
});
|
||||
// Also tweak the destinations for cmpInst, and lastInst
|
||||
if (cmpInst->asOperands[1].eType == OPERAND_TYPE_TEMP && cmpInst->asOperands[1].ui32RegisterNumber == initializer->asOperands[0].ui32RegisterNumber)
|
||||
cmpInst->asOperands[1].m_ForLoopInductorName = newRegister;
|
||||
else
|
||||
cmpInst->asOperands[2].m_ForLoopInductorName = newRegister;
|
||||
if (initializer)
|
||||
{
|
||||
// We can declare the initializer in the for loop header, allocate a new number for it and change all uses into that.
|
||||
uint32_t newRegister = phase.m_NextFreeTempRegister++;
|
||||
li.m_StartLoop->m_InductorRegister = newRegister;
|
||||
std::for_each(initializer->m_Uses.begin(), initializer->m_Uses.end(), [newRegister](const Instruction::Use &u)
|
||||
{
|
||||
u.m_Op->m_ForLoopInductorName = newRegister;
|
||||
});
|
||||
// Also tweak the destinations for cmpInst, and lastInst
|
||||
if (cmpInst->asOperands[1].eType == OPERAND_TYPE_TEMP && cmpInst->asOperands[1].ui32RegisterNumber == initializer->asOperands[0].ui32RegisterNumber)
|
||||
cmpInst->asOperands[1].m_ForLoopInductorName = newRegister;
|
||||
else
|
||||
cmpInst->asOperands[2].m_ForLoopInductorName = newRegister;
|
||||
|
||||
if (lastInst->asOperands[1].eType == OPERAND_TYPE_TEMP && lastInst->asOperands[1].ui32RegisterNumber == initializer->asOperands[0].ui32RegisterNumber)
|
||||
lastInst->asOperands[1].m_ForLoopInductorName = newRegister;
|
||||
else
|
||||
lastInst->asOperands[2].m_ForLoopInductorName = newRegister;
|
||||
if (lastInst->asOperands[1].eType == OPERAND_TYPE_TEMP && lastInst->asOperands[1].ui32RegisterNumber == initializer->asOperands[0].ui32RegisterNumber)
|
||||
lastInst->asOperands[1].m_ForLoopInductorName = newRegister;
|
||||
else
|
||||
lastInst->asOperands[2].m_ForLoopInductorName = newRegister;
|
||||
|
||||
lastInst->asOperands[0].m_ForLoopInductorName = newRegister;
|
||||
initializer->asOperands[0].m_ForLoopInductorName = newRegister;
|
||||
}
|
||||
lastInst->asOperands[0].m_ForLoopInductorName = newRegister;
|
||||
initializer->asOperands[0].m_ForLoopInductorName = newRegister;
|
||||
}
|
||||
|
||||
// This loop can be transformed to for-loop. Do the necessary magicks.
|
||||
li.m_StartLoop->m_LoopInductors[0] = initializer;
|
||||
li.m_StartLoop->m_LoopInductors[1] = cmpInst;
|
||||
li.m_StartLoop->m_LoopInductors[2] = breakInst;
|
||||
li.m_StartLoop->m_LoopInductors[3] = lastInst;
|
||||
// This loop can be transformed to for-loop. Do the necessary magicks.
|
||||
li.m_StartLoop->m_LoopInductors[0] = initializer;
|
||||
li.m_StartLoop->m_LoopInductors[1] = cmpInst;
|
||||
li.m_StartLoop->m_LoopInductors[2] = breakInst;
|
||||
li.m_StartLoop->m_LoopInductors[3] = lastInst;
|
||||
|
||||
if (initializer)
|
||||
initializer->m_SkipTranslation = true;
|
||||
cmpInst->m_SkipTranslation = true;
|
||||
breakInst->m_SkipTranslation = true;
|
||||
lastInst->m_SkipTranslation = true;
|
||||
if (initializer)
|
||||
initializer->m_SkipTranslation = true;
|
||||
cmpInst->m_SkipTranslation = true;
|
||||
breakInst->m_SkipTranslation = true;
|
||||
lastInst->m_SkipTranslation = true;
|
||||
}
|
||||
|
||||
}
|
||||
void DoLoopTransform(HLSLCrossCompilerContext *psContext, ShaderPhase &phase)
|
||||
{
|
||||
Loops loops;
|
||||
BuildLoopInfo(phase, loops);
|
||||
|
||||
void DoLoopTransform(HLSLCrossCompilerContext *psContext, ShaderPhase &phase)
|
||||
{
|
||||
Loops loops;
|
||||
BuildLoopInfo(phase, loops);
|
||||
|
||||
std::for_each(loops.begin(), loops.end(), [&phase, psContext](LoopInfo &li)
|
||||
{
|
||||
// Some sanity checks: start and end points must be initialized, we shouldn't have any switches here, and each loop must have at least one exit point
|
||||
// Also that there's at least 2 instructions in loop body
|
||||
ASSERT(li.m_StartLoop != 0);
|
||||
ASSERT(li.m_EndLoop != 0);
|
||||
ASSERT(li.m_EndLoop > li.m_StartLoop + 2);
|
||||
ASSERT(!li.m_IsSwitch);
|
||||
ASSERT(!li.m_ExitPoints.empty());
|
||||
AttemptLoopTransform(psContext, phase, li);
|
||||
});
|
||||
}
|
||||
};
|
||||
std::for_each(loops.begin(), loops.end(), [&phase, psContext](LoopInfo &li)
|
||||
{
|
||||
// Some sanity checks: start and end points must be initialized, we shouldn't have any switches here, and each loop must have at least one exit point
|
||||
// Also that there's at least 2 instructions in loop body
|
||||
ASSERT(li.m_StartLoop != 0);
|
||||
ASSERT(li.m_EndLoop != 0);
|
||||
ASSERT(li.m_EndLoop > li.m_StartLoop + 2);
|
||||
ASSERT(!li.m_IsSwitch);
|
||||
ASSERT(!li.m_ExitPoints.empty());
|
||||
AttemptLoopTransform(psContext, phase, li);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
985
src/Operand.cpp
985
src/Operand.cpp
File diff suppressed because it is too large
Load Diff
1629
src/Shader.cpp
1629
src/Shader.cpp
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
|
||||
#include "ShaderInfo.h"
|
||||
#include "internal_includes/debug.h"
|
||||
#include "internal_includes/tokens.h"
|
||||
@ -8,170 +7,170 @@
|
||||
|
||||
SHADER_VARIABLE_TYPE ShaderInfo::GetTextureDataType(uint32_t regNo)
|
||||
{
|
||||
const ResourceBinding* psBinding = 0;
|
||||
int found;
|
||||
found = GetResourceFromBindingPoint(RGROUP_TEXTURE, regNo, &psBinding);
|
||||
ASSERT(found != 0);
|
||||
return psBinding->GetDataType();
|
||||
const ResourceBinding* psBinding = 0;
|
||||
int found;
|
||||
found = GetResourceFromBindingPoint(RGROUP_TEXTURE, regNo, &psBinding);
|
||||
ASSERT(found != 0);
|
||||
return psBinding->GetDataType();
|
||||
}
|
||||
|
||||
void ShaderInfo::GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ConstantBuffer** ppsConstBuf) const
|
||||
{
|
||||
ASSERT(ui32MajorVersion > 3);
|
||||
*ppsConstBuf = &psConstantBuffers[aui32ResourceMap[eGroup][ui32BindPoint]];
|
||||
ASSERT(ui32MajorVersion > 3);
|
||||
*ppsConstBuf = &psConstantBuffers[aui32ResourceMap[eGroup][ui32BindPoint]];
|
||||
}
|
||||
|
||||
int ShaderInfo::GetResourceFromBindingPoint(const ResourceGroup eGroup, uint32_t const ui32BindPoint, const ResourceBinding** ppsOutBinding) const
|
||||
{
|
||||
size_t i;
|
||||
const size_t ui32NumBindings = psResourceBindings.size();
|
||||
const ResourceBinding* psBindings = &psResourceBindings[0];
|
||||
size_t i;
|
||||
const size_t ui32NumBindings = psResourceBindings.size();
|
||||
const ResourceBinding* psBindings = &psResourceBindings[0];
|
||||
|
||||
for (i = 0; i < ui32NumBindings; ++i)
|
||||
{
|
||||
if (ResourceTypeToResourceGroup(psBindings[i].eType) == eGroup)
|
||||
{
|
||||
if (ui32BindPoint >= psBindings[i].ui32BindPoint && ui32BindPoint < (psBindings[i].ui32BindPoint + psBindings[i].ui32BindCount))
|
||||
{
|
||||
*ppsOutBinding = psBindings + i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
for (i = 0; i < ui32NumBindings; ++i)
|
||||
{
|
||||
if (ResourceTypeToResourceGroup(psBindings[i].eType) == eGroup)
|
||||
{
|
||||
if (ui32BindPoint >= psBindings[i].ui32BindPoint && ui32BindPoint < (psBindings[i].ui32BindPoint + psBindings[i].ui32BindCount))
|
||||
{
|
||||
*ppsOutBinding = psBindings + i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ShaderInfo::GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderVar** ppsShaderVar) const
|
||||
{
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psThisPointerConstBuffer->asVars.size();
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psThisPointerConstBuffer->asVars.size();
|
||||
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if (ui32Offset >= psThisPointerConstBuffer->asVars[i].ui32StartOffset &&
|
||||
ui32Offset < (psThisPointerConstBuffer->asVars[i].ui32StartOffset + psThisPointerConstBuffer->asVars[i].ui32Size))
|
||||
{
|
||||
*ppsShaderVar = &psThisPointerConstBuffer->asVars[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if (ui32Offset >= psThisPointerConstBuffer->asVars[i].ui32StartOffset &&
|
||||
ui32Offset < (psThisPointerConstBuffer->asVars[i].ui32StartOffset + psThisPointerConstBuffer->asVars[i].ui32Size))
|
||||
{
|
||||
*ppsShaderVar = &psThisPointerConstBuffer->asVars[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ShaderInfo::GetInputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32Mask, const InOutSignature** ppsOut, bool allowNull /* == false */) const
|
||||
{
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psInputSignatures.size();
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psInputSignatures.size();
|
||||
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if ((ui32Register == psInputSignatures[i].ui32Register) && (((~psInputSignatures[i].ui32Mask) & ui32Mask) == 0))
|
||||
{
|
||||
*ppsOut = &psInputSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ASSERT(allowNull);
|
||||
return 0;
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if ((ui32Register == psInputSignatures[i].ui32Register) && (((~psInputSignatures[i].ui32Mask) & ui32Mask) == 0))
|
||||
{
|
||||
*ppsOut = &psInputSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ASSERT(allowNull);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ShaderInfo::GetPatchConstantSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32Mask, const InOutSignature** ppsOut, bool allowNull /* == false */) const
|
||||
{
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psPatchConstantSignatures.size();
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psPatchConstantSignatures.size();
|
||||
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if ((ui32Register == psPatchConstantSignatures[i].ui32Register) && (((~psPatchConstantSignatures[i].ui32Mask) & ui32Mask) == 0))
|
||||
{
|
||||
*ppsOut = &psPatchConstantSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if ((ui32Register == psPatchConstantSignatures[i].ui32Register) && (((~psPatchConstantSignatures[i].ui32Mask) & ui32Mask) == 0))
|
||||
{
|
||||
*ppsOut = &psPatchConstantSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// There are situations (especially when using dcl_indexrange) where the compiler happily writes outside the actual masks.
|
||||
// In those situations just take the last signature that uses that register (it's typically the "highest" one)
|
||||
for( i = ui32NumVars - 1; i-- > 0; )
|
||||
{
|
||||
if (ui32Register == psPatchConstantSignatures[i].ui32Register)
|
||||
{
|
||||
*ppsOut = &psPatchConstantSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// There are situations (especially when using dcl_indexrange) where the compiler happily writes outside the actual masks.
|
||||
// In those situations just take the last signature that uses that register (it's typically the "highest" one)
|
||||
for (i = ui32NumVars - 1; i-- > 0;)
|
||||
{
|
||||
if (ui32Register == psPatchConstantSignatures[i].ui32Register)
|
||||
{
|
||||
*ppsOut = &psPatchConstantSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(allowNull);
|
||||
return 0;
|
||||
ASSERT(allowNull);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ShaderInfo::GetOutputSignatureFromRegister(const uint32_t ui32Register,
|
||||
const uint32_t ui32CompMask,
|
||||
const uint32_t ui32Stream,
|
||||
const InOutSignature** ppsOut,
|
||||
bool allowNull /* = false */) const
|
||||
const uint32_t ui32CompMask,
|
||||
const uint32_t ui32Stream,
|
||||
const InOutSignature** ppsOut,
|
||||
bool allowNull /* = false */) const
|
||||
{
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psOutputSignatures.size();
|
||||
ASSERT(ui32CompMask != 0);
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psOutputSignatures.size();
|
||||
ASSERT(ui32CompMask != 0);
|
||||
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if (ui32Register == psOutputSignatures[i].ui32Register &&
|
||||
(ui32CompMask & psOutputSignatures[i].ui32Mask) &&
|
||||
ui32Stream == psOutputSignatures[i].ui32Stream)
|
||||
{
|
||||
*ppsOut = &psOutputSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ASSERT(allowNull);
|
||||
return 0;
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if (ui32Register == psOutputSignatures[i].ui32Register &&
|
||||
(ui32CompMask & psOutputSignatures[i].ui32Mask) &&
|
||||
ui32Stream == psOutputSignatures[i].ui32Stream)
|
||||
{
|
||||
*ppsOut = &psOutputSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ASSERT(allowNull);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ShaderInfo::GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, const InOutSignature** ppsOut) const
|
||||
{
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psOutputSignatures.size();
|
||||
size_t i;
|
||||
const size_t ui32NumVars = psOutputSignatures.size();
|
||||
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if (eSystemValueType == psOutputSignatures[i].eSystemValueType &&
|
||||
ui32SemanticIndex == psOutputSignatures[i].ui32SemanticIndex)
|
||||
{
|
||||
*ppsOut = &psOutputSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ASSERT(0);
|
||||
return 0;
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
if (eSystemValueType == psOutputSignatures[i].eSystemValueType &&
|
||||
ui32SemanticIndex == psOutputSignatures[i].ui32SemanticIndex)
|
||||
{
|
||||
*ppsOut = &psOutputSignatures[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ShaderInfo::GetCBVarSize(const ShaderVarType* psType, bool matrixAsVectors, bool wholeArraySize)
|
||||
{
|
||||
// Default is regular matrices, vectors and scalars
|
||||
// Default is regular matrices, vectors and scalars
|
||||
uint32_t size = psType->Columns * psType->Rows * 4;
|
||||
|
||||
// Struct size is calculated from the offset and size of its last member.
|
||||
// Struct size is calculated from the offset and size of its last member.
|
||||
// Need to take into account that members could be arrays.
|
||||
if (psType->Class == SVC_STRUCT)
|
||||
{
|
||||
if (psType->Class == SVC_STRUCT)
|
||||
{
|
||||
size = psType->Members.back().Offset + GetCBVarSize(&psType->Members.back(), matrixAsVectors, true);
|
||||
}
|
||||
// Matrices represented as vec4 arrays have special size calculation
|
||||
else if (matrixAsVectors)
|
||||
{
|
||||
if (psType->Class == SVC_MATRIX_ROWS)
|
||||
{
|
||||
}
|
||||
// Matrices represented as vec4 arrays have special size calculation
|
||||
else if (matrixAsVectors)
|
||||
{
|
||||
if (psType->Class == SVC_MATRIX_ROWS)
|
||||
{
|
||||
size = psType->Rows * 16;
|
||||
}
|
||||
else if (psType->Class == SVC_MATRIX_COLUMNS)
|
||||
{
|
||||
size = psType->Columns * 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (psType->Class == SVC_MATRIX_COLUMNS)
|
||||
{
|
||||
size = psType->Columns * 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (wholeArraySize && psType->Elements > 1)
|
||||
{
|
||||
{
|
||||
uint32_t paddedSize = ((size + 15) / 16) * 16; // Arrays are padded to float4 size
|
||||
size = (psType->Elements - 1) * paddedSize + size; // Except the last element
|
||||
}
|
||||
@ -180,146 +179,146 @@ uint32_t ShaderInfo::GetCBVarSize(const ShaderVarType* psType, bool matrixAsVect
|
||||
}
|
||||
|
||||
static const ShaderVarType* IsOffsetInType(const ShaderVarType* psType,
|
||||
uint32_t parentOffset,
|
||||
uint32_t offsetToFind,
|
||||
bool* isArray,
|
||||
std::vector<uint32_t>* arrayIndices,
|
||||
int32_t* pi32Rebase,
|
||||
uint32_t flags)
|
||||
uint32_t parentOffset,
|
||||
uint32_t offsetToFind,
|
||||
bool* isArray,
|
||||
std::vector<uint32_t>* arrayIndices,
|
||||
int32_t* pi32Rebase,
|
||||
uint32_t flags)
|
||||
{
|
||||
uint32_t thisOffset = parentOffset + psType->Offset;
|
||||
uint32_t thisSize = ShaderInfo::GetCBVarSize(psType, (flags & HLSLCC_FLAG_TRANSLATE_MATRICES) != 0);
|
||||
uint32_t paddedSize = ((thisSize + 15) / 16) * 16;
|
||||
uint32_t arraySize = thisSize;
|
||||
uint32_t thisOffset = parentOffset + psType->Offset;
|
||||
uint32_t thisSize = ShaderInfo::GetCBVarSize(psType, (flags & HLSLCC_FLAG_TRANSLATE_MATRICES) != 0);
|
||||
uint32_t paddedSize = ((thisSize + 15) / 16) * 16;
|
||||
uint32_t arraySize = thisSize;
|
||||
|
||||
// Array elements are padded to align on vec4 size, except for the last one
|
||||
if (psType->Elements)
|
||||
arraySize = (paddedSize * (psType->Elements - 1)) + thisSize;
|
||||
// Array elements are padded to align on vec4 size, except for the last one
|
||||
if (psType->Elements)
|
||||
arraySize = (paddedSize * (psType->Elements - 1)) + thisSize;
|
||||
|
||||
if ((offsetToFind >= thisOffset) &&
|
||||
offsetToFind < (thisOffset + arraySize))
|
||||
{
|
||||
*isArray = false;
|
||||
if (psType->Class == SVC_STRUCT)
|
||||
{
|
||||
if (psType->Elements > 1 && arrayIndices != NULL)
|
||||
arrayIndices->push_back((offsetToFind - thisOffset) / thisSize);
|
||||
if ((offsetToFind >= thisOffset) &&
|
||||
offsetToFind < (thisOffset + arraySize))
|
||||
{
|
||||
*isArray = false;
|
||||
if (psType->Class == SVC_STRUCT)
|
||||
{
|
||||
if (psType->Elements > 1 && arrayIndices != NULL)
|
||||
arrayIndices->push_back((offsetToFind - thisOffset) / thisSize);
|
||||
|
||||
// Need to bring offset back to element zero in case of array of structs
|
||||
uint32_t offsetInStruct = (offsetToFind - thisOffset) % paddedSize;
|
||||
uint32_t m = 0;
|
||||
// Need to bring offset back to element zero in case of array of structs
|
||||
uint32_t offsetInStruct = (offsetToFind - thisOffset) % paddedSize;
|
||||
uint32_t m = 0;
|
||||
|
||||
for (m = 0; m < psType->MemberCount; ++m)
|
||||
{
|
||||
const ShaderVarType* psMember = &psType->Members[m];
|
||||
for (m = 0; m < psType->MemberCount; ++m)
|
||||
{
|
||||
const ShaderVarType* psMember = &psType->Members[m];
|
||||
|
||||
const ShaderVarType* foundType = IsOffsetInType(psMember, thisOffset, thisOffset + offsetInStruct, isArray, arrayIndices, pi32Rebase, flags);
|
||||
if (foundType != NULL)
|
||||
return foundType;
|
||||
}
|
||||
}
|
||||
// Check for array of scalars or vectors (both take up 16 bytes per element).
|
||||
// Matrices are also treated as arrays of vectors.
|
||||
else if ((psType->Class == SVC_MATRIX_ROWS || psType->Class == SVC_MATRIX_COLUMNS) ||
|
||||
((psType->Class == SVC_SCALAR || psType->Class == SVC_VECTOR) && psType->Elements > 1))
|
||||
{
|
||||
*isArray = true;
|
||||
if (arrayIndices != NULL)
|
||||
arrayIndices->push_back((offsetToFind - thisOffset) / 16);
|
||||
}
|
||||
else if (psType->Class == SVC_VECTOR)
|
||||
{
|
||||
//Check for vector starting at a non-vec4 offset.
|
||||
const ShaderVarType* foundType = IsOffsetInType(psMember, thisOffset, thisOffset + offsetInStruct, isArray, arrayIndices, pi32Rebase, flags);
|
||||
if (foundType != NULL)
|
||||
return foundType;
|
||||
}
|
||||
}
|
||||
// Check for array of scalars or vectors (both take up 16 bytes per element).
|
||||
// Matrices are also treated as arrays of vectors.
|
||||
else if ((psType->Class == SVC_MATRIX_ROWS || psType->Class == SVC_MATRIX_COLUMNS) ||
|
||||
((psType->Class == SVC_SCALAR || psType->Class == SVC_VECTOR) && psType->Elements > 1))
|
||||
{
|
||||
*isArray = true;
|
||||
if (arrayIndices != NULL)
|
||||
arrayIndices->push_back((offsetToFind - thisOffset) / 16);
|
||||
}
|
||||
else if (psType->Class == SVC_VECTOR)
|
||||
{
|
||||
//Check for vector starting at a non-vec4 offset.
|
||||
|
||||
// cbuffer $Globals
|
||||
// {
|
||||
//
|
||||
// float angle; // Offset: 0 Size: 4
|
||||
// float2 angle2; // Offset: 4 Size: 8
|
||||
//
|
||||
// }
|
||||
// cbuffer $Globals
|
||||
// {
|
||||
//
|
||||
// float angle; // Offset: 0 Size: 4
|
||||
// float2 angle2; // Offset: 4 Size: 8
|
||||
//
|
||||
// }
|
||||
|
||||
//cb0[0].x = angle
|
||||
//cb0[0].yzyy = angle2.xyxx
|
||||
//cb0[0].x = angle
|
||||
//cb0[0].yzyy = angle2.xyxx
|
||||
|
||||
//Rebase angle2 so that .y maps to .x, .z maps to .y
|
||||
//Rebase angle2 so that .y maps to .x, .z maps to .y
|
||||
|
||||
pi32Rebase[0] = thisOffset % 16;
|
||||
}
|
||||
pi32Rebase[0] = thisOffset % 16;
|
||||
}
|
||||
|
||||
return psType;
|
||||
}
|
||||
return NULL;
|
||||
return psType;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ShaderInfo::GetShaderVarFromOffset(const uint32_t ui32Vec4Offset,
|
||||
const uint32_t(&pui32Swizzle)[4],
|
||||
const ConstantBuffer* psCBuf,
|
||||
const ShaderVarType** ppsShaderVar, // Output the found var
|
||||
bool* isArray, // Output bool that tells if the found var is an array
|
||||
std::vector<uint32_t>* arrayIndices, // Output vector of array indices in order from root parent to the found var
|
||||
int32_t* pi32Rebase, // Output swizzle rebase
|
||||
uint32_t flags)
|
||||
const uint32_t(&pui32Swizzle)[4],
|
||||
const ConstantBuffer* psCBuf,
|
||||
const ShaderVarType** ppsShaderVar, // Output the found var
|
||||
bool* isArray, // Output bool that tells if the found var is an array
|
||||
std::vector<uint32_t>* arrayIndices, // Output vector of array indices in order from root parent to the found var
|
||||
int32_t* pi32Rebase, // Output swizzle rebase
|
||||
uint32_t flags)
|
||||
{
|
||||
size_t i;
|
||||
size_t i;
|
||||
|
||||
uint32_t ui32ByteOffset = ui32Vec4Offset * 16;
|
||||
uint32_t ui32ByteOffset = ui32Vec4Offset * 16;
|
||||
|
||||
//Swizzle can point to another variable. In the example below
|
||||
//cbUIUpdates.g_uMaxFaces would be cb1[2].z. The scalars are combined
|
||||
//into vectors. psCBuf->ui32NumVars will be 3.
|
||||
//Swizzle can point to another variable. In the example below
|
||||
//cbUIUpdates.g_uMaxFaces would be cb1[2].z. The scalars are combined
|
||||
//into vectors. psCBuf->ui32NumVars will be 3.
|
||||
|
||||
// cbuffer cbUIUpdates
|
||||
// {
|
||||
// float g_fLifeSpan; // Offset: 0 Size: 4
|
||||
// float g_fLifeSpanVar; // Offset: 4 Size: 4 [unused]
|
||||
// float g_fRadiusMin; // Offset: 8 Size: 4 [unused]
|
||||
// float g_fRadiusMax; // Offset: 12 Size: 4 [unused]
|
||||
// float g_fGrowTime; // Offset: 16 Size: 4 [unused]
|
||||
// float g_fStepSize; // Offset: 20 Size: 4
|
||||
// float g_fTurnRate; // Offset: 24 Size: 4
|
||||
// float g_fTurnSpeed; // Offset: 28 Size: 4 [unused]
|
||||
// float g_fLeafRate; // Offset: 32 Size: 4
|
||||
// float g_fShrinkTime; // Offset: 36 Size: 4 [unused]
|
||||
// uint g_uMaxFaces; // Offset: 40 Size: 4
|
||||
// }
|
||||
if (pui32Swizzle[0] == OPERAND_4_COMPONENT_Y)
|
||||
{
|
||||
ui32ByteOffset += 4;
|
||||
}
|
||||
else if (pui32Swizzle[0] == OPERAND_4_COMPONENT_Z)
|
||||
{
|
||||
ui32ByteOffset += 8;
|
||||
}
|
||||
else if (pui32Swizzle[0] == OPERAND_4_COMPONENT_W)
|
||||
{
|
||||
ui32ByteOffset += 12;
|
||||
}
|
||||
// cbuffer cbUIUpdates
|
||||
// {
|
||||
// float g_fLifeSpan; // Offset: 0 Size: 4
|
||||
// float g_fLifeSpanVar; // Offset: 4 Size: 4 [unused]
|
||||
// float g_fRadiusMin; // Offset: 8 Size: 4 [unused]
|
||||
// float g_fRadiusMax; // Offset: 12 Size: 4 [unused]
|
||||
// float g_fGrowTime; // Offset: 16 Size: 4 [unused]
|
||||
// float g_fStepSize; // Offset: 20 Size: 4
|
||||
// float g_fTurnRate; // Offset: 24 Size: 4
|
||||
// float g_fTurnSpeed; // Offset: 28 Size: 4 [unused]
|
||||
// float g_fLeafRate; // Offset: 32 Size: 4
|
||||
// float g_fShrinkTime; // Offset: 36 Size: 4 [unused]
|
||||
// uint g_uMaxFaces; // Offset: 40 Size: 4
|
||||
// }
|
||||
if (pui32Swizzle[0] == OPERAND_4_COMPONENT_Y)
|
||||
{
|
||||
ui32ByteOffset += 4;
|
||||
}
|
||||
else if (pui32Swizzle[0] == OPERAND_4_COMPONENT_Z)
|
||||
{
|
||||
ui32ByteOffset += 8;
|
||||
}
|
||||
else if (pui32Swizzle[0] == OPERAND_4_COMPONENT_W)
|
||||
{
|
||||
ui32ByteOffset += 12;
|
||||
}
|
||||
|
||||
const size_t ui32NumVars = psCBuf->asVars.size();
|
||||
const size_t ui32NumVars = psCBuf->asVars.size();
|
||||
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
ppsShaderVar[0] = IsOffsetInType(&psCBuf->asVars[i].sType, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, isArray, arrayIndices, pi32Rebase, flags);
|
||||
|
||||
if (ppsShaderVar[0] != NULL)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
for (i = 0; i < ui32NumVars; ++i)
|
||||
{
|
||||
ppsShaderVar[0] = IsOffsetInType(&psCBuf->asVars[i].sType, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, isArray, arrayIndices, pi32Rebase, flags);
|
||||
|
||||
if (ppsShaderVar[0] != NULL)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Patches the fullName of the var with given array indices. Does not insert the indexing for the var itself if it is an array.
|
||||
// Searches for brackets and inserts indices one by one.
|
||||
std::string ShaderInfo::GetShaderVarIndexedFullName(const ShaderVarType* psShaderVar, const std::vector<uint32_t>& indices, const std::string& dynamicIndex, bool revertDynamicIndexCalc, bool matrixAsVectors)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
size_t prevpos = 0;
|
||||
size_t pos = psShaderVar->fullName.find('[', 0);
|
||||
uint32_t i = 0;
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
pos++;
|
||||
oss << psShaderVar->fullName.substr(prevpos, pos - prevpos);
|
||||
std::ostringstream oss;
|
||||
size_t prevpos = 0;
|
||||
size_t pos = psShaderVar->fullName.find('[', 0);
|
||||
uint32_t i = 0;
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
pos++;
|
||||
oss << psShaderVar->fullName.substr(prevpos, pos - prevpos);
|
||||
|
||||
// Add possibly given dynamic index for the root array.
|
||||
if (i == 0 && !dynamicIndex.empty())
|
||||
@ -340,71 +339,71 @@ std::string ShaderInfo::GetShaderVarIndexedFullName(const ShaderVarType* psShade
|
||||
if (!indices.empty() && indices[i] != 0)
|
||||
oss << " + " << indices[i];
|
||||
}
|
||||
else if (i < indices.size())
|
||||
oss << indices[i];
|
||||
else if (i < indices.size())
|
||||
oss << indices[i];
|
||||
|
||||
prevpos = pos;
|
||||
i++;
|
||||
pos = psShaderVar->fullName.find('[', prevpos);
|
||||
}
|
||||
oss << psShaderVar->fullName.substr(prevpos);
|
||||
prevpos = pos;
|
||||
i++;
|
||||
pos = psShaderVar->fullName.find('[', prevpos);
|
||||
}
|
||||
oss << psShaderVar->fullName.substr(prevpos);
|
||||
|
||||
return oss.str();
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
ResourceGroup ShaderInfo::ResourceTypeToResourceGroup(ResourceType eType)
|
||||
{
|
||||
switch (eType)
|
||||
{
|
||||
case RTYPE_CBUFFER:
|
||||
return RGROUP_CBUFFER;
|
||||
switch (eType)
|
||||
{
|
||||
case RTYPE_CBUFFER:
|
||||
return RGROUP_CBUFFER;
|
||||
|
||||
case RTYPE_SAMPLER:
|
||||
return RGROUP_SAMPLER;
|
||||
case RTYPE_SAMPLER:
|
||||
return RGROUP_SAMPLER;
|
||||
|
||||
case RTYPE_TEXTURE:
|
||||
case RTYPE_BYTEADDRESS:
|
||||
case RTYPE_STRUCTURED:
|
||||
return RGROUP_TEXTURE;
|
||||
case RTYPE_TEXTURE:
|
||||
case RTYPE_BYTEADDRESS:
|
||||
case RTYPE_STRUCTURED:
|
||||
return RGROUP_TEXTURE;
|
||||
|
||||
case RTYPE_UAV_RWTYPED:
|
||||
case RTYPE_UAV_RWSTRUCTURED:
|
||||
case RTYPE_UAV_RWBYTEADDRESS:
|
||||
case RTYPE_UAV_APPEND_STRUCTURED:
|
||||
case RTYPE_UAV_CONSUME_STRUCTURED:
|
||||
case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER:
|
||||
return RGROUP_UAV;
|
||||
case RTYPE_UAV_RWTYPED:
|
||||
case RTYPE_UAV_RWSTRUCTURED:
|
||||
case RTYPE_UAV_RWBYTEADDRESS:
|
||||
case RTYPE_UAV_APPEND_STRUCTURED:
|
||||
case RTYPE_UAV_CONSUME_STRUCTURED:
|
||||
case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER:
|
||||
return RGROUP_UAV;
|
||||
|
||||
case RTYPE_TBUFFER:
|
||||
ASSERT(0); // Need to find out which group this belongs to
|
||||
return RGROUP_TEXTURE;
|
||||
default:
|
||||
case RTYPE_TBUFFER:
|
||||
ASSERT(0); // Need to find out which group this belongs to
|
||||
return RGROUP_TEXTURE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(0);
|
||||
return RGROUP_CBUFFER;
|
||||
ASSERT(0);
|
||||
return RGROUP_CBUFFER;
|
||||
}
|
||||
|
||||
void ShaderInfo::AddSamplerPrecisions(HLSLccSamplerPrecisionInfo &info)
|
||||
{
|
||||
if (info.empty())
|
||||
return;
|
||||
if (info.empty())
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < psResourceBindings.size(); i++)
|
||||
{
|
||||
ResourceBinding *rb = &psResourceBindings[i];
|
||||
if (rb->eType != RTYPE_SAMPLER && rb->eType != RTYPE_TEXTURE)
|
||||
continue;
|
||||
for (size_t i = 0; i < psResourceBindings.size(); i++)
|
||||
{
|
||||
ResourceBinding *rb = &psResourceBindings[i];
|
||||
if (rb->eType != RTYPE_SAMPLER && rb->eType != RTYPE_TEXTURE)
|
||||
continue;
|
||||
|
||||
HLSLccSamplerPrecisionInfo::iterator j = info.find(rb->name); // Try finding exact match
|
||||
HLSLccSamplerPrecisionInfo::iterator j = info.find(rb->name); // Try finding exact match
|
||||
|
||||
// If match not found, check if name has "sampler" prefix
|
||||
// -> try finding a match without the prefix (DX11 style sampler case)
|
||||
if (j == info.end() && rb->name.compare(0, 7, "sampler") == 0)
|
||||
j = info.find(rb->name.substr(7, rb->name.size() - 7));
|
||||
// If match not found, check if name has "sampler" prefix
|
||||
// -> try finding a match without the prefix (DX11 style sampler case)
|
||||
if (j == info.end() && rb->name.compare(0, 7, "sampler") == 0)
|
||||
j = info.find(rb->name.substr(7, rb->name.size() - 7));
|
||||
|
||||
if (j != info.end())
|
||||
rb->ePrecision = j->second;
|
||||
}
|
||||
if (j != info.end())
|
||||
rb->ePrecision = j->second;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This source file is part of the bstring string library. This code was
|
||||
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
|
||||
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
|
||||
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
|
||||
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
|
||||
* for details on usage and license.
|
||||
*/
|
||||
|
||||
@ -18,68 +18,70 @@
|
||||
#include <stdlib.h>
|
||||
#include "bsafe.h"
|
||||
|
||||
#if 0
|
||||
static int bsafeShouldExit = 1;
|
||||
|
||||
#if 0
|
||||
char * strcpy (char *dst, const char *src);
|
||||
char * strcat (char *dst, const char *src);
|
||||
char * strcpy(char *dst, const char *src);
|
||||
char * strcat(char *dst, const char *src);
|
||||
|
||||
char * strcpy (char *dst, const char *src) {
|
||||
dst = dst;
|
||||
src = src;
|
||||
fprintf (stderr, "bsafe error: strcpy() is not safe, use bstrcpy instead.\n");
|
||||
if (bsafeShouldExit) exit (-1);
|
||||
return NULL;
|
||||
char * strcpy(char *dst, const char *src)
|
||||
{
|
||||
dst = dst;
|
||||
src = src;
|
||||
fprintf(stderr, "bsafe error: strcpy() is not safe, use bstrcpy instead.\n");
|
||||
if (bsafeShouldExit) exit(-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * strcat (char *dst, const char *src) {
|
||||
dst = dst;
|
||||
src = src;
|
||||
fprintf (stderr, "bsafe error: strcat() is not safe, use bstrcat instead.\n");
|
||||
if (bsafeShouldExit) exit (-1);
|
||||
return NULL;
|
||||
char * strcat(char *dst, const char *src)
|
||||
{
|
||||
dst = dst;
|
||||
src = src;
|
||||
fprintf(stderr, "bsafe error: strcat() is not safe, use bstrcat instead.\n");
|
||||
if (bsafeShouldExit) exit(-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if !defined (__GNUC__) && (!defined(_MSC_VER) || (_MSC_VER <= 1310))
|
||||
char * (gets) (char * buf) {
|
||||
buf = buf;
|
||||
fprintf (stderr, "bsafe error: gets() is not safe, use bgets.\n");
|
||||
if (bsafeShouldExit) exit (-1);
|
||||
return NULL;
|
||||
#if !defined(__GNUC__) && (!defined(_MSC_VER) || (_MSC_VER <= 1310))
|
||||
char * (gets)(char * buf) {
|
||||
buf = buf;
|
||||
fprintf(stderr, "bsafe error: gets() is not safe, use bgets.\n");
|
||||
if (bsafeShouldExit) exit(-1);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
char * (strncpy) (char *dst, const char *src, size_t n) {
|
||||
dst = dst;
|
||||
src = src;
|
||||
n = n;
|
||||
fprintf (stderr, "bsafe error: strncpy() is not safe, use bmidstr instead.\n");
|
||||
if (bsafeShouldExit) exit (-1);
|
||||
return NULL;
|
||||
char * (strncpy)(char *dst, const char *src, size_t n) {
|
||||
dst = dst;
|
||||
src = src;
|
||||
n = n;
|
||||
fprintf(stderr, "bsafe error: strncpy() is not safe, use bmidstr instead.\n");
|
||||
if (bsafeShouldExit) exit(-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * (strncat) (char *dst, const char *src, size_t n) {
|
||||
dst = dst;
|
||||
src = src;
|
||||
n = n;
|
||||
fprintf (stderr, "bsafe error: strncat() is not safe, use bstrcat then btrunc\n\tor cstr2tbstr, btrunc then bstrcat instead.\n");
|
||||
if (bsafeShouldExit) exit (-1);
|
||||
return NULL;
|
||||
char * (strncat)(char *dst, const char *src, size_t n) {
|
||||
dst = dst;
|
||||
src = src;
|
||||
n = n;
|
||||
fprintf(stderr, "bsafe error: strncat() is not safe, use bstrcat then btrunc\n\tor cstr2tbstr, btrunc then bstrcat instead.\n");
|
||||
if (bsafeShouldExit) exit(-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * (strtok) (char *s1, const char *s2) {
|
||||
s1 = s1;
|
||||
s2 = s2;
|
||||
fprintf (stderr, "bsafe error: strtok() is not safe, use bsplit or bsplits instead.\n");
|
||||
if (bsafeShouldExit) exit (-1);
|
||||
return NULL;
|
||||
char * (strtok)(char *s1, const char *s2) {
|
||||
s1 = s1;
|
||||
s2 = s2;
|
||||
fprintf(stderr, "bsafe error: strtok() is not safe, use bsplit or bsplits instead.\n");
|
||||
if (bsafeShouldExit) exit(-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * (strdup) (const char *s) {
|
||||
s = s;
|
||||
fprintf (stderr, "bsafe error: strdup() is not safe, use bstrcpy.\n");
|
||||
if (bsafeShouldExit) exit (-1);
|
||||
return NULL;
|
||||
char * (strdup)(const char *s) {
|
||||
s = s;
|
||||
fprintf(stderr, "bsafe error: strdup() is not safe, use bstrcpy.\n");
|
||||
if (bsafeShouldExit) exit(-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This source file is part of the bstring string library. This code was
|
||||
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
|
||||
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
|
||||
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
|
||||
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
|
||||
* for details on usage and license.
|
||||
*/
|
||||
|
||||
@ -21,20 +21,20 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined (__GNUC__) && (!defined(_MSC_VER) || (_MSC_VER <= 1310))
|
||||
#if !defined(__GNUC__) && (!defined(_MSC_VER) || (_MSC_VER <= 1310))
|
||||
/* This is caught in the linker, so its not necessary for gcc. */
|
||||
extern char * (gets) (char * buf);
|
||||
extern char * (gets)(char * buf);
|
||||
#endif
|
||||
|
||||
extern char * (strncpy) (char *dst, const char *src, size_t n);
|
||||
extern char * (strncat) (char *dst, const char *src, size_t n);
|
||||
extern char * (strtok) (char *s1, const char *s2);
|
||||
extern char * (strdup) (const char *s);
|
||||
extern char * (strncpy)(char *dst, const char *src, size_t n);
|
||||
extern char * (strncat)(char *dst, const char *src, size_t n);
|
||||
extern char * (strtok)(char *s1, const char *s2);
|
||||
extern char * (strdup)(const char *s);
|
||||
|
||||
#undef strcpy
|
||||
#undef strcat
|
||||
#define strcpy(a,b) bsafe_strcpy(a,b)
|
||||
#define strcat(a,b) bsafe_strcat(a,b)
|
||||
#define strcpy(a, b) bsafe_strcpy(a,b)
|
||||
#define strcat(a, b) bsafe_strcat(a,b)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This source file is part of the bstring string library. This code was
|
||||
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
|
||||
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
|
||||
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
|
||||
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
|
||||
* for details on usage and license.
|
||||
*/
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
* bstraux.h
|
||||
*
|
||||
* This file is not a necessary part of the core bstring library itself, but
|
||||
* is just an auxilliary module which includes miscellaneous or trivial
|
||||
* is just an auxilliary module which includes miscellaneous or trivial
|
||||
* functions.
|
||||
*/
|
||||
|
||||
@ -24,86 +24,86 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Safety mechanisms */
|
||||
#define bstrDeclare(b) bstring (b) = NULL;
|
||||
#define bstrDeclare(b) bstring (b) = NULL;
|
||||
#define bstrFree(b) {if ((b) != NULL && (b)->slen >= 0 && (b)->mlen >= (b)->slen) { bdestroy (b); (b) = NULL; }}
|
||||
|
||||
/* Backward compatibilty with previous versions of Bstrlib */
|
||||
#define bAssign(a,b) ((bassign)((a), (b)))
|
||||
#define bSubs(b,pos,len,a,c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c)))
|
||||
#define bStrchr(b,c) ((bstrchr)((b), (c)))
|
||||
#define bStrchrFast(b,c) ((bstrchr)((b), (c)))
|
||||
#define bCatCstr(b,s) ((bcatcstr)((b), (s)))
|
||||
#define bCatBlk(b,s,len) ((bcatblk)((b),(s),(len)))
|
||||
#define bCatStatic(b,s) bCatBlk ((b), ("" s ""), sizeof (s) - 1)
|
||||
#define bTrunc(b,n) ((btrunc)((b), (n)))
|
||||
#define bReplaceAll(b,find,repl,pos) ((bfindreplace)((b),(find),(repl),(pos)))
|
||||
#define bAssign(a, b) ((bassign)((a), (b)))
|
||||
#define bSubs(b, pos, len, a, c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c)))
|
||||
#define bStrchr(b, c) ((bstrchr)((b), (c)))
|
||||
#define bStrchrFast(b, c) ((bstrchr)((b), (c)))
|
||||
#define bCatCstr(b, s) ((bcatcstr)((b), (s)))
|
||||
#define bCatBlk(b, s, len) ((bcatblk)((b),(s),(len)))
|
||||
#define bCatStatic(b, s) bCatBlk ((b), ("" s ""), sizeof (s) - 1)
|
||||
#define bTrunc(b, n) ((btrunc)((b), (n)))
|
||||
#define bReplaceAll(b, find, repl, pos) ((bfindreplace)((b),(find),(repl),(pos)))
|
||||
#define bUppercase(b) ((btoupper)(b))
|
||||
#define bLowercase(b) ((btolower)(b))
|
||||
#define bCaselessCmp(a,b) ((bstricmp)((a), (b)))
|
||||
#define bCaselessNCmp(a,b,n) ((bstrnicmp)((a), (b), (n)))
|
||||
#define bCaselessCmp(a, b) ((bstricmp)((a), (b)))
|
||||
#define bCaselessNCmp(a, b, n) ((bstrnicmp)((a), (b), (n)))
|
||||
#define bBase64Decode(b) (bBase64DecodeEx ((b), NULL))
|
||||
#define bUuDecode(b) (bUuDecodeEx ((b), NULL))
|
||||
|
||||
/* Unusual functions */
|
||||
extern struct bStream * bsFromBstr (const_bstring b);
|
||||
extern bstring bTail (bstring b, int n);
|
||||
extern bstring bHead (bstring b, int n);
|
||||
extern int bSetCstrChar (bstring a, int pos, char c);
|
||||
extern int bSetChar (bstring b, int pos, char c);
|
||||
extern int bFill (bstring a, char c, int len);
|
||||
extern int bReplicate (bstring b, int n);
|
||||
extern int bReverse (bstring b);
|
||||
extern int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill);
|
||||
extern bstring bStrfTime (const char * fmt, const struct tm * timeptr);
|
||||
extern struct bStream * bsFromBstr(const_bstring b);
|
||||
extern bstring bTail(bstring b, int n);
|
||||
extern bstring bHead(bstring b, int n);
|
||||
extern int bSetCstrChar(bstring a, int pos, char c);
|
||||
extern int bSetChar(bstring b, int pos, char c);
|
||||
extern int bFill(bstring a, char c, int len);
|
||||
extern int bReplicate(bstring b, int n);
|
||||
extern int bReverse(bstring b);
|
||||
extern int bInsertChrs(bstring b, int pos, int len, unsigned char c, unsigned char fill);
|
||||
extern bstring bStrfTime(const char * fmt, const struct tm * timeptr);
|
||||
#define bAscTime(t) (bStrfTime ("%c\n", (t)))
|
||||
#define bCTime(t) ((t) ? bAscTime (localtime (t)) : NULL)
|
||||
|
||||
/* Spacing formatting */
|
||||
extern int bJustifyLeft (bstring b, int space);
|
||||
extern int bJustifyRight (bstring b, int width, int space);
|
||||
extern int bJustifyMargin (bstring b, int width, int space);
|
||||
extern int bJustifyCenter (bstring b, int width, int space);
|
||||
extern int bJustifyLeft(bstring b, int space);
|
||||
extern int bJustifyRight(bstring b, int width, int space);
|
||||
extern int bJustifyMargin(bstring b, int width, int space);
|
||||
extern int bJustifyCenter(bstring b, int width, int space);
|
||||
|
||||
/* Esoteric standards specific functions */
|
||||
extern char * bStr2NetStr (const_bstring b);
|
||||
extern bstring bNetStr2Bstr (const char * buf);
|
||||
extern bstring bBase64Encode (const_bstring b);
|
||||
extern bstring bBase64DecodeEx (const_bstring b, int * boolTruncError);
|
||||
extern struct bStream * bsUuDecode (struct bStream * sInp, int * badlines);
|
||||
extern bstring bUuDecodeEx (const_bstring src, int * badlines);
|
||||
extern bstring bUuEncode (const_bstring src);
|
||||
extern bstring bYEncode (const_bstring src);
|
||||
extern bstring bYDecode (const_bstring src);
|
||||
extern char * bStr2NetStr(const_bstring b);
|
||||
extern bstring bNetStr2Bstr(const char * buf);
|
||||
extern bstring bBase64Encode(const_bstring b);
|
||||
extern bstring bBase64DecodeEx(const_bstring b, int * boolTruncError);
|
||||
extern struct bStream * bsUuDecode(struct bStream * sInp, int * badlines);
|
||||
extern bstring bUuDecodeEx(const_bstring src, int * badlines);
|
||||
extern bstring bUuEncode(const_bstring src);
|
||||
extern bstring bYEncode(const_bstring src);
|
||||
extern bstring bYDecode(const_bstring src);
|
||||
|
||||
/* Writable stream */
|
||||
typedef int (* bNwrite) (const void * buf, size_t elsize, size_t nelem, void * parm);
|
||||
|
||||
struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm);
|
||||
int bwsWriteBstr (struct bwriteStream * stream, const_bstring b);
|
||||
int bwsWriteBlk (struct bwriteStream * stream, void * blk, int len);
|
||||
int bwsWriteFlush (struct bwriteStream * stream);
|
||||
int bwsIsEOF (const struct bwriteStream * stream);
|
||||
int bwsBuffLength (struct bwriteStream * stream, int sz);
|
||||
void * bwsClose (struct bwriteStream * stream);
|
||||
struct bwriteStream * bwsOpen(bNwrite writeFn, void * parm);
|
||||
int bwsWriteBstr(struct bwriteStream * stream, const_bstring b);
|
||||
int bwsWriteBlk(struct bwriteStream * stream, void * blk, int len);
|
||||
int bwsWriteFlush(struct bwriteStream * stream);
|
||||
int bwsIsEOF(const struct bwriteStream * stream);
|
||||
int bwsBuffLength(struct bwriteStream * stream, int sz);
|
||||
void * bwsClose(struct bwriteStream * stream);
|
||||
|
||||
/* Security functions */
|
||||
#define bSecureDestroy(b) { \
|
||||
bstring bstr__tmp = (b); \
|
||||
if (bstr__tmp && bstr__tmp->mlen > 0 && bstr__tmp->data) { \
|
||||
(void) memset (bstr__tmp->data, 0, (size_t) bstr__tmp->mlen); \
|
||||
bdestroy (bstr__tmp); \
|
||||
} \
|
||||
#define bSecureDestroy(b) { \
|
||||
bstring bstr__tmp = (b); \
|
||||
if (bstr__tmp && bstr__tmp->mlen > 0 && bstr__tmp->data) { \
|
||||
(void) memset (bstr__tmp->data, 0, (size_t) bstr__tmp->mlen); \
|
||||
bdestroy (bstr__tmp); \
|
||||
} \
|
||||
}
|
||||
#define bSecureWriteProtect(t) { \
|
||||
if ((t).mlen >= 0) { \
|
||||
if ((t).mlen > (t).slen)) { \
|
||||
(void) memset ((t).data + (t).slen, 0, (size_t) (t).mlen - (t).slen); \
|
||||
} \
|
||||
(t).mlen = -1; \
|
||||
} \
|
||||
#define bSecureWriteProtect(t) { \
|
||||
if ((t).mlen >= 0) { \
|
||||
if ((t).mlen > (t).slen)) { \
|
||||
(void) memset ((t).data + (t).slen, 0, (size_t) (t).mlen - (t).slen); \
|
||||
} \
|
||||
(t).mlen = -1; \
|
||||
} \
|
||||
}
|
||||
extern bstring bSecureInput (int maxlen, int termchar,
|
||||
bNgetc vgetchar, void * vgcCtx);
|
||||
extern bstring bSecureInput(int maxlen, int termchar,
|
||||
bNgetc vgetchar, void * vgcCtx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,14 @@
|
||||
/*
|
||||
* This source file is part of the bstring string library. This code was
|
||||
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
|
||||
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
|
||||
* written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
|
||||
* BSD open source license or GPL v2.0. Refer to the accompanying documentation
|
||||
* for details on usage and license.
|
||||
*/
|
||||
|
||||
/*
|
||||
* bstrlib.h
|
||||
*
|
||||
* This file is the header file for the core module for implementing the
|
||||
* This file is the header file for the core module for implementing the
|
||||
* bstring functions.
|
||||
*/
|
||||
|
||||
@ -24,8 +24,8 @@ extern "C" {
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP)
|
||||
# if defined (__TURBOC__) && !defined (__BORLANDC__)
|
||||
#if !defined(BSTRLIB_VSNP_OK) && !defined(BSTRLIB_NOVSNP)
|
||||
# if defined(__TURBOC__) && !defined(__BORLANDC__)
|
||||
# define BSTRLIB_NOVSNP
|
||||
# endif
|
||||
#endif
|
||||
@ -39,121 +39,122 @@ typedef const struct tagbstring * const_bstring;
|
||||
|
||||
/* Copy functions */
|
||||
#define cstr2bstr bfromcstr
|
||||
extern bstring bfromcstr (const char * str);
|
||||
extern bstring bfromcstralloc (int mlen, const char * str);
|
||||
extern bstring blk2bstr (const void * blk, int len);
|
||||
extern char * bstr2cstr (const_bstring s, char z);
|
||||
extern int bcstrfree (char * s);
|
||||
extern bstring bstrcpy (const_bstring b1);
|
||||
extern int bassign (bstring a, const_bstring b);
|
||||
extern int bassignmidstr (bstring a, const_bstring b, int left, int len);
|
||||
extern int bassigncstr (bstring a, const char * str);
|
||||
extern int bassignblk (bstring a, const void * s, int len);
|
||||
extern bstring bfromcstr(const char * str);
|
||||
extern bstring bfromcstralloc(int mlen, const char * str);
|
||||
extern bstring blk2bstr(const void * blk, int len);
|
||||
extern char * bstr2cstr(const_bstring s, char z);
|
||||
extern int bcstrfree(char * s);
|
||||
extern bstring bstrcpy(const_bstring b1);
|
||||
extern int bassign(bstring a, const_bstring b);
|
||||
extern int bassignmidstr(bstring a, const_bstring b, int left, int len);
|
||||
extern int bassigncstr(bstring a, const char * str);
|
||||
extern int bassignblk(bstring a, const void * s, int len);
|
||||
|
||||
/* Destroy function */
|
||||
extern int bdestroy (bstring b);
|
||||
extern int bdestroy(bstring b);
|
||||
|
||||
/* Space allocation hinting functions */
|
||||
extern int balloc (bstring s, int len);
|
||||
extern int ballocmin (bstring b, int len);
|
||||
extern int balloc(bstring s, int len);
|
||||
extern int ballocmin(bstring b, int len);
|
||||
|
||||
/* Substring extraction */
|
||||
extern bstring bmidstr (const_bstring b, int left, int len);
|
||||
extern bstring bmidstr(const_bstring b, int left, int len);
|
||||
|
||||
/* Various standard manipulations */
|
||||
extern int bconcat (bstring b0, const_bstring b1);
|
||||
extern int bconchar (bstring b0, char c);
|
||||
extern int bcatcstr (bstring b, const char * s);
|
||||
extern int bcatblk (bstring b, const void * s, int len);
|
||||
extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill);
|
||||
extern int binsertch (bstring s1, int pos, int len, unsigned char fill);
|
||||
extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill);
|
||||
extern int bdelete (bstring s1, int pos, int len);
|
||||
extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill);
|
||||
extern int btrunc (bstring b, int n);
|
||||
extern int bconcat(bstring b0, const_bstring b1);
|
||||
extern int bconchar(bstring b0, char c);
|
||||
extern int bcatcstr(bstring b, const char * s);
|
||||
extern int bcatblk(bstring b, const void * s, int len);
|
||||
extern int binsert(bstring s1, int pos, const_bstring s2, unsigned char fill);
|
||||
extern int binsertch(bstring s1, int pos, int len, unsigned char fill);
|
||||
extern int breplace(bstring b1, int pos, int len, const_bstring b2, unsigned char fill);
|
||||
extern int bdelete(bstring s1, int pos, int len);
|
||||
extern int bsetstr(bstring b0, int pos, const_bstring b1, unsigned char fill);
|
||||
extern int btrunc(bstring b, int n);
|
||||
|
||||
/* Scan/search functions */
|
||||
extern int bstricmp (const_bstring b0, const_bstring b1);
|
||||
extern int bstrnicmp (const_bstring b0, const_bstring b1, int n);
|
||||
extern int biseqcaseless (const_bstring b0, const_bstring b1);
|
||||
extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len);
|
||||
extern int biseq (const_bstring b0, const_bstring b1);
|
||||
extern int bisstemeqblk (const_bstring b0, const void * blk, int len);
|
||||
extern int biseqcstr (const_bstring b, const char * s);
|
||||
extern int biseqcstrcaseless (const_bstring b, const char * s);
|
||||
extern int bstrcmp (const_bstring b0, const_bstring b1);
|
||||
extern int bstrncmp (const_bstring b0, const_bstring b1, int n);
|
||||
extern int binstr (const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrr (const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2);
|
||||
extern int bstrchrp (const_bstring b, int c, int pos);
|
||||
extern int bstrrchrp (const_bstring b, int c, int pos);
|
||||
#define bstrchr(b,c) bstrchrp ((b), (c), 0)
|
||||
#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1)
|
||||
extern int binchr (const_bstring b0, int pos, const_bstring b1);
|
||||
extern int binchrr (const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bninchr (const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bninchrr (const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos);
|
||||
extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos);
|
||||
extern int bstricmp(const_bstring b0, const_bstring b1);
|
||||
extern int bstrnicmp(const_bstring b0, const_bstring b1, int n);
|
||||
extern int biseqcaseless(const_bstring b0, const_bstring b1);
|
||||
extern int bisstemeqcaselessblk(const_bstring b0, const void * blk, int len);
|
||||
extern int biseq(const_bstring b0, const_bstring b1);
|
||||
extern int bisstemeqblk(const_bstring b0, const void * blk, int len);
|
||||
extern int biseqcstr(const_bstring b, const char * s);
|
||||
extern int biseqcstrcaseless(const_bstring b, const char * s);
|
||||
extern int bstrcmp(const_bstring b0, const_bstring b1);
|
||||
extern int bstrncmp(const_bstring b0, const_bstring b1, int n);
|
||||
extern int binstr(const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrr(const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrcaseless(const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrrcaseless(const_bstring s1, int pos, const_bstring s2);
|
||||
extern int bstrchrp(const_bstring b, int c, int pos);
|
||||
extern int bstrrchrp(const_bstring b, int c, int pos);
|
||||
#define bstrchr(b, c) bstrchrp ((b), (c), 0)
|
||||
#define bstrrchr(b, c) bstrrchrp ((b), (c), blength(b)-1)
|
||||
extern int binchr(const_bstring b0, int pos, const_bstring b1);
|
||||
extern int binchrr(const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bninchr(const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bninchrr(const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bfindreplace(bstring b, const_bstring find, const_bstring repl, int pos);
|
||||
extern int bfindreplacecaseless(bstring b, const_bstring find, const_bstring repl, int pos);
|
||||
|
||||
/* List of string container functions */
|
||||
struct bstrList {
|
||||
struct bstrList
|
||||
{
|
||||
int qty, mlen;
|
||||
bstring * entry;
|
||||
};
|
||||
extern struct bstrList * bstrListCreate (void);
|
||||
extern int bstrListDestroy (struct bstrList * sl);
|
||||
extern int bstrListAlloc (struct bstrList * sl, int msz);
|
||||
extern int bstrListAllocMin (struct bstrList * sl, int msz);
|
||||
extern struct bstrList * bstrListCreate(void);
|
||||
extern int bstrListDestroy(struct bstrList * sl);
|
||||
extern int bstrListAlloc(struct bstrList * sl, int msz);
|
||||
extern int bstrListAllocMin(struct bstrList * sl, int msz);
|
||||
|
||||
/* String split and join functions */
|
||||
extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar);
|
||||
extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr);
|
||||
extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr);
|
||||
extern bstring bjoin (const struct bstrList * bl, const_bstring sep);
|
||||
extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
|
||||
int (* cb) (void * parm, int ofs, int len), void * parm);
|
||||
extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
|
||||
int (* cb) (void * parm, int ofs, int len), void * parm);
|
||||
extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
|
||||
int (* cb) (void * parm, int ofs, int len), void * parm);
|
||||
extern struct bstrList * bsplit(const_bstring str, unsigned char splitChar);
|
||||
extern struct bstrList * bsplits(const_bstring str, const_bstring splitStr);
|
||||
extern struct bstrList * bsplitstr(const_bstring str, const_bstring splitStr);
|
||||
extern bstring bjoin(const struct bstrList * bl, const_bstring sep);
|
||||
extern int bsplitcb(const_bstring str, unsigned char splitChar, int pos,
|
||||
int (* cb)(void * parm, int ofs, int len), void * parm);
|
||||
extern int bsplitscb(const_bstring str, const_bstring splitStr, int pos,
|
||||
int (* cb)(void * parm, int ofs, int len), void * parm);
|
||||
extern int bsplitstrcb(const_bstring str, const_bstring splitStr, int pos,
|
||||
int (* cb)(void * parm, int ofs, int len), void * parm);
|
||||
|
||||
/* Miscellaneous functions */
|
||||
extern int bpattern (bstring b, int len);
|
||||
extern int btoupper (bstring b);
|
||||
extern int btolower (bstring b);
|
||||
extern int bltrimws (bstring b);
|
||||
extern int brtrimws (bstring b);
|
||||
extern int btrimws (bstring b);
|
||||
extern int bpattern(bstring b, int len);
|
||||
extern int btoupper(bstring b);
|
||||
extern int btolower(bstring b);
|
||||
extern int bltrimws(bstring b);
|
||||
extern int brtrimws(bstring b);
|
||||
extern int btrimws(bstring b);
|
||||
|
||||
/* <*>printf format functions */
|
||||
#if !defined (BSTRLIB_NOVSNP)
|
||||
extern bstring bformat (const char * fmt, ...);
|
||||
extern int bformata (bstring b, const char * fmt, ...);
|
||||
extern int bassignformat (bstring b, const char * fmt, ...);
|
||||
extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist);
|
||||
#if !defined(BSTRLIB_NOVSNP)
|
||||
extern bstring bformat(const char * fmt, ...);
|
||||
extern int bformata(bstring b, const char * fmt, ...);
|
||||
extern int bassignformat(bstring b, const char * fmt, ...);
|
||||
extern int bvcformata(bstring b, int count, const char * fmt, va_list arglist);
|
||||
|
||||
#define bvformata(ret, b, fmt, lastarg) { \
|
||||
bstring bstrtmp_b = (b); \
|
||||
const char * bstrtmp_fmt = (fmt); \
|
||||
int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
|
||||
for (;;) { \
|
||||
va_list bstrtmp_arglist; \
|
||||
va_start (bstrtmp_arglist, lastarg); \
|
||||
bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
|
||||
va_end (bstrtmp_arglist); \
|
||||
if (bstrtmp_r >= 0) { /* Everything went ok */ \
|
||||
bstrtmp_r = BSTR_OK; \
|
||||
break; \
|
||||
} else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
|
||||
bstrtmp_r = BSTR_ERR; \
|
||||
break; \
|
||||
} \
|
||||
bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
|
||||
} \
|
||||
ret = bstrtmp_r; \
|
||||
for (;;) { \
|
||||
va_list bstrtmp_arglist; \
|
||||
va_start (bstrtmp_arglist, lastarg); \
|
||||
bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
|
||||
va_end (bstrtmp_arglist); \
|
||||
if (bstrtmp_r >= 0) { /* Everything went ok */ \
|
||||
bstrtmp_r = BSTR_OK; \
|
||||
break; \
|
||||
} else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
|
||||
bstrtmp_r = BSTR_ERR; \
|
||||
break; \
|
||||
} \
|
||||
bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
|
||||
} \
|
||||
ret = bstrtmp_r; \
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -162,34 +163,35 @@ typedef int (*bNgetc) (void *parm);
|
||||
typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm);
|
||||
|
||||
/* Input functions */
|
||||
extern bstring bgets (bNgetc getcPtr, void * parm, char terminator);
|
||||
extern bstring bread (bNread readPtr, void * parm);
|
||||
extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator);
|
||||
extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator);
|
||||
extern int breada (bstring b, bNread readPtr, void * parm);
|
||||
extern bstring bgets(bNgetc getcPtr, void * parm, char terminator);
|
||||
extern bstring bread(bNread readPtr, void * parm);
|
||||
extern int bgetsa(bstring b, bNgetc getcPtr, void * parm, char terminator);
|
||||
extern int bassigngets(bstring b, bNgetc getcPtr, void * parm, char terminator);
|
||||
extern int breada(bstring b, bNread readPtr, void * parm);
|
||||
|
||||
/* Stream functions */
|
||||
extern struct bStream * bsopen (bNread readPtr, void * parm);
|
||||
extern void * bsclose (struct bStream * s);
|
||||
extern int bsbufflength (struct bStream * s, int sz);
|
||||
extern int bsreadln (bstring b, struct bStream * s, char terminator);
|
||||
extern int bsreadlns (bstring r, struct bStream * s, const_bstring term);
|
||||
extern int bsread (bstring b, struct bStream * s, int n);
|
||||
extern int bsreadlna (bstring b, struct bStream * s, char terminator);
|
||||
extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term);
|
||||
extern int bsreada (bstring b, struct bStream * s, int n);
|
||||
extern int bsunread (struct bStream * s, const_bstring b);
|
||||
extern int bspeek (bstring r, const struct bStream * s);
|
||||
extern int bssplitscb (struct bStream * s, const_bstring splitStr,
|
||||
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
|
||||
extern int bssplitstrcb (struct bStream * s, const_bstring splitStr,
|
||||
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
|
||||
extern int bseof (const struct bStream * s);
|
||||
extern struct bStream * bsopen(bNread readPtr, void * parm);
|
||||
extern void * bsclose(struct bStream * s);
|
||||
extern int bsbufflength(struct bStream * s, int sz);
|
||||
extern int bsreadln(bstring b, struct bStream * s, char terminator);
|
||||
extern int bsreadlns(bstring r, struct bStream * s, const_bstring term);
|
||||
extern int bsread(bstring b, struct bStream * s, int n);
|
||||
extern int bsreadlna(bstring b, struct bStream * s, char terminator);
|
||||
extern int bsreadlnsa(bstring r, struct bStream * s, const_bstring term);
|
||||
extern int bsreada(bstring b, struct bStream * s, int n);
|
||||
extern int bsunread(struct bStream * s, const_bstring b);
|
||||
extern int bspeek(bstring r, const struct bStream * s);
|
||||
extern int bssplitscb(struct bStream * s, const_bstring splitStr,
|
||||
int (* cb)(void * parm, int ofs, const_bstring entry), void * parm);
|
||||
extern int bssplitstrcb(struct bStream * s, const_bstring splitStr,
|
||||
int (* cb)(void * parm, int ofs, const_bstring entry), void * parm);
|
||||
extern int bseof(const struct bStream * s);
|
||||
|
||||
struct tagbstring {
|
||||
int mlen;
|
||||
int slen;
|
||||
unsigned char * data;
|
||||
struct tagbstring
|
||||
{
|
||||
int mlen;
|
||||
int slen;
|
||||
unsigned char * data;
|
||||
};
|
||||
|
||||
/* Accessor macros */
|
||||
@ -203,7 +205,7 @@ struct tagbstring {
|
||||
#define bchar(b, p) bchare ((b), (p), '\0')
|
||||
|
||||
/* Static constant string initialization macro */
|
||||
#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")}
|
||||
#define bsStaticMlen(q, m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")}
|
||||
#if defined(_MSC_VER)
|
||||
/* There are many versions of MSVC which emit __LINE__ as a non-constant. */
|
||||
# define bsStatic(q) bsStaticMlen(q,-32)
|
||||
@ -217,18 +219,18 @@ struct tagbstring {
|
||||
|
||||
/* Reference building macros */
|
||||
#define cstr2tbstr btfromcstr
|
||||
#define btfromcstr(t,s) { \
|
||||
#define btfromcstr(t, s) { \
|
||||
(t).data = (unsigned char *) (s); \
|
||||
(t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \
|
||||
(t).mlen = -1; \
|
||||
}
|
||||
#define blk2tbstr(t,s,l) { \
|
||||
#define blk2tbstr(t, s, l) { \
|
||||
(t).data = (unsigned char *) (s); \
|
||||
(t).slen = l; \
|
||||
(t).mlen = -1; \
|
||||
}
|
||||
#define btfromblk(t,s,l) blk2tbstr(t,s,l)
|
||||
#define bmid2tbstr(t,b,p,l) { \
|
||||
#define btfromblk(t, s, l) blk2tbstr(t,s,l)
|
||||
#define bmid2tbstr(t, b, p, l) { \
|
||||
const_bstring bstrtmp_s = (b); \
|
||||
if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \
|
||||
int bstrtmp_left = (p); \
|
||||
@ -252,7 +254,7 @@ struct tagbstring {
|
||||
} \
|
||||
(t).mlen = -__LINE__; \
|
||||
}
|
||||
#define btfromblkltrimws(t,s,l) { \
|
||||
#define btfromblkltrimws(t, s, l) { \
|
||||
int bstrtmp_idx = 0, bstrtmp_len = (l); \
|
||||
unsigned char * bstrtmp_s = (s); \
|
||||
if (bstrtmp_s && bstrtmp_len >= 0) { \
|
||||
@ -264,7 +266,7 @@ struct tagbstring {
|
||||
(t).slen = bstrtmp_len - bstrtmp_idx; \
|
||||
(t).mlen = -__LINE__; \
|
||||
}
|
||||
#define btfromblkrtrimws(t,s,l) { \
|
||||
#define btfromblkrtrimws(t, s, l) { \
|
||||
int bstrtmp_len = (l) - 1; \
|
||||
unsigned char * bstrtmp_s = (s); \
|
||||
if (bstrtmp_s && bstrtmp_len >= 0) { \
|
||||
@ -276,7 +278,7 @@ struct tagbstring {
|
||||
(t).slen = bstrtmp_len + 1; \
|
||||
(t).mlen = -__LINE__; \
|
||||
}
|
||||
#define btfromblktrimws(t,s,l) { \
|
||||
#define btfromblktrimws(t, s, l) { \
|
||||
int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \
|
||||
unsigned char * bstrtmp_s = (s); \
|
||||
if (bstrtmp_s && bstrtmp_len >= 0) { \
|
||||
|
1284
src/decode.cpp
1284
src/decode.cpp
File diff suppressed because it is too large
Load Diff
@ -14,141 +14,135 @@ class Operand;
|
||||
namespace HLSLcc
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
namespace ControlFlow
|
||||
{
|
||||
class BasicBlock;
|
||||
|
||||
class ControlFlowGraph
|
||||
{
|
||||
friend class BasicBlock;
|
||||
public:
|
||||
ControlFlowGraph()
|
||||
: m_BlockMap()
|
||||
, m_BlockStorage()
|
||||
{}
|
||||
namespace ControlFlow
|
||||
{
|
||||
class BasicBlock;
|
||||
|
||||
typedef std::vector<shared_ptr<BasicBlock> > BasicBlockStorage;
|
||||
class ControlFlowGraph
|
||||
{
|
||||
friend class BasicBlock;
|
||||
public:
|
||||
ControlFlowGraph()
|
||||
: m_BlockMap()
|
||||
, m_BlockStorage()
|
||||
{}
|
||||
|
||||
const BasicBlock &Build(const Instruction *firstInstruction);
|
||||
typedef std::vector<shared_ptr<BasicBlock> > BasicBlockStorage;
|
||||
|
||||
// Only works for instructions that start the basic block
|
||||
const BasicBlock *GetBasicBlockForInstruction(const Instruction *instruction) const;
|
||||
const BasicBlock &Build(const Instruction *firstInstruction);
|
||||
|
||||
// non-const version for BasicBlock
|
||||
BasicBlock *GetBasicBlockForInstruction(const Instruction *instruction);
|
||||
// Only works for instructions that start the basic block
|
||||
const BasicBlock *GetBasicBlockForInstruction(const Instruction *instruction) const;
|
||||
|
||||
const BasicBlockStorage &AllBlocks() const { return m_BlockStorage; }
|
||||
private:
|
||||
// non-const version for BasicBlock
|
||||
BasicBlock *GetBasicBlockForInstruction(const Instruction *instruction);
|
||||
|
||||
// Map for storing the created basic blocks. Map key is the pointer to the first instruction in the block
|
||||
typedef std::map<const Instruction *, BasicBlock *> BasicBlockMap;
|
||||
const BasicBlockStorage &AllBlocks() const { return m_BlockStorage; }
|
||||
private:
|
||||
|
||||
BasicBlockMap m_BlockMap;
|
||||
// Map for storing the created basic blocks. Map key is the pointer to the first instruction in the block
|
||||
typedef std::map<const Instruction *, BasicBlock *> BasicBlockMap;
|
||||
|
||||
// auto_ptr -type storage for multiple BasicBlocks. BlockMap above only has pointers into these
|
||||
BasicBlockStorage m_BlockStorage;
|
||||
};
|
||||
BasicBlockMap m_BlockMap;
|
||||
|
||||
// auto_ptr -type storage for multiple BasicBlocks. BlockMap above only has pointers into these
|
||||
BasicBlockStorage m_BlockStorage;
|
||||
};
|
||||
|
||||
|
||||
class BasicBlock
|
||||
{
|
||||
friend class ControlFlowGraph;
|
||||
public:
|
||||
// A set of register indices, one per each vec4 component per register
|
||||
typedef std::set<uint32_t> RegisterSet;
|
||||
// The connections (either incoming or outgoing) from this block. The instruction is the same one as the key in ControlFlowGraph to that basic block
|
||||
typedef std::set<const Instruction *> ConnectionSet;
|
||||
class BasicBlock
|
||||
{
|
||||
friend class ControlFlowGraph;
|
||||
public:
|
||||
// A set of register indices, one per each vec4 component per register
|
||||
typedef std::set<uint32_t> RegisterSet;
|
||||
// The connections (either incoming or outgoing) from this block. The instruction is the same one as the key in ControlFlowGraph to that basic block
|
||||
typedef std::set<const Instruction *> ConnectionSet;
|
||||
|
||||
struct Definition
|
||||
{
|
||||
Definition(const Instruction *i = NULL, const Operand *o = NULL)
|
||||
: m_Instruction(i)
|
||||
, m_Operand(o)
|
||||
{}
|
||||
struct Definition
|
||||
{
|
||||
Definition(const Instruction *i = NULL, const Operand *o = NULL)
|
||||
: m_Instruction(i)
|
||||
, m_Operand(o)
|
||||
{}
|
||||
|
||||
Definition(const Definition &a)
|
||||
: m_Instruction(a.m_Instruction)
|
||||
, m_Operand(a.m_Operand)
|
||||
{}
|
||||
Definition(const Definition &a)
|
||||
: m_Instruction(a.m_Instruction)
|
||||
, m_Operand(a.m_Operand)
|
||||
{}
|
||||
|
||||
bool operator==(const Definition &a) const
|
||||
{
|
||||
if (a.m_Instruction != m_Instruction)
|
||||
return false;
|
||||
return a.m_Operand == m_Operand;
|
||||
}
|
||||
bool operator==(const Definition &a) const
|
||||
{
|
||||
if (a.m_Instruction != m_Instruction)
|
||||
return false;
|
||||
return a.m_Operand == m_Operand;
|
||||
}
|
||||
|
||||
bool operator!=(const Definition &a) const
|
||||
{
|
||||
if (a.m_Instruction == m_Instruction)
|
||||
return false;
|
||||
return a.m_Operand != m_Operand;
|
||||
}
|
||||
bool operator!=(const Definition &a) const
|
||||
{
|
||||
if (a.m_Instruction == m_Instruction)
|
||||
return false;
|
||||
return a.m_Operand != m_Operand;
|
||||
}
|
||||
|
||||
bool operator<(const Definition &a) const
|
||||
{
|
||||
if (m_Instruction != a.m_Instruction)
|
||||
return m_Instruction < a.m_Instruction;
|
||||
return m_Operand < a.m_Operand;
|
||||
}
|
||||
bool operator<(const Definition &a) const
|
||||
{
|
||||
if (m_Instruction != a.m_Instruction)
|
||||
return m_Instruction < a.m_Instruction;
|
||||
return m_Operand < a.m_Operand;
|
||||
}
|
||||
|
||||
const Instruction *m_Instruction;
|
||||
const Operand *m_Operand;
|
||||
};
|
||||
const Instruction *m_Instruction;
|
||||
const Operand *m_Operand;
|
||||
};
|
||||
|
||||
typedef std::set<Definition> ReachableDefinitionsPerVariable; // A set of possibly visible definitions for one component of one vec4 variable
|
||||
typedef std::map<uint32_t, ReachableDefinitionsPerVariable> ReachableVariables; // A VisibleDefinitionSet for each variable*component.
|
||||
typedef std::set<Definition> ReachableDefinitionsPerVariable; // A set of possibly visible definitions for one component of one vec4 variable
|
||||
typedef std::map<uint32_t, ReachableDefinitionsPerVariable> ReachableVariables; // A VisibleDefinitionSet for each variable*component.
|
||||
|
||||
const Instruction *First() const { return m_First; }
|
||||
const Instruction *Last() const { return m_Last; }
|
||||
const Instruction *First() const { return m_First; }
|
||||
const Instruction *Last() const { return m_Last; }
|
||||
|
||||
const RegisterSet &UEVar() const { return m_UEVar; }
|
||||
const RegisterSet &VarKill() const { return m_VarKill; }
|
||||
const RegisterSet &UEVar() const { return m_UEVar; }
|
||||
const RegisterSet &VarKill() const { return m_VarKill; }
|
||||
|
||||
const ConnectionSet &Preceding() const { return m_Preceding; }
|
||||
const ConnectionSet &Succeeding() const { return m_Succeeding; }
|
||||
const ConnectionSet &Preceding() const { return m_Preceding; }
|
||||
const ConnectionSet &Succeeding() const { return m_Succeeding; }
|
||||
|
||||
const ReachableVariables &DEDef() const { return m_DEDef; }
|
||||
const ReachableVariables &Reachable() const { return m_Reachable; }
|
||||
const ReachableVariables &DEDef() const { return m_DEDef; }
|
||||
const ReachableVariables &Reachable() const { return m_Reachable; }
|
||||
|
||||
// Helper function: Do union of 2 ReachableVariables, store result in a.
|
||||
static void RVarUnion(ReachableVariables &a, const ReachableVariables &b);
|
||||
// Helper function: Do union of 2 ReachableVariables, store result in a.
|
||||
static void RVarUnion(ReachableVariables &a, const ReachableVariables &b);
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
// Generate a basic block. Private constructor, can only be constructed from ControlFlowGraph::Build()
|
||||
BasicBlock(const Instruction *psFirst, ControlFlowGraph &graph, const Instruction *psPrecedingBlockHead);
|
||||
// Generate a basic block. Private constructor, can only be constructed from ControlFlowGraph::Build()
|
||||
BasicBlock(const Instruction *psFirst, ControlFlowGraph &graph, const Instruction *psPrecedingBlockHead);
|
||||
|
||||
// Walk through the instructions and build UEVar and VarKill sets, create succeeding nodes if they don't exist already.
|
||||
void Build();
|
||||
// Walk through the instructions and build UEVar and VarKill sets, create succeeding nodes if they don't exist already.
|
||||
void Build();
|
||||
|
||||
bool RebuildReachable(); // Rebuild m_Reachable from preceding blocks and this one. Returns true if current value changed.
|
||||
bool RebuildReachable(); // Rebuild m_Reachable from preceding blocks and this one. Returns true if current value changed.
|
||||
|
||||
|
||||
BasicBlock * AddChildBasicBlock(const Instruction *psFirst);
|
||||
BasicBlock * AddChildBasicBlock(const Instruction *psFirst);
|
||||
|
||||
private:
|
||||
ControlFlowGraph &m_Graph; // The graph object containing this block
|
||||
private:
|
||||
ControlFlowGraph &m_Graph; // The graph object containing this block
|
||||
|
||||
const Instruction *m_First; // The first instruction in the basic block
|
||||
const Instruction *m_Last; // The last instruction in the basic block. Either OPCODE_RET or a branch/jump/loop instruction
|
||||
const Instruction *m_First; // The first instruction in the basic block
|
||||
const Instruction *m_Last; // The last instruction in the basic block. Either OPCODE_RET or a branch/jump/loop instruction
|
||||
|
||||
RegisterSet m_UEVar; // Upwards-exposed variables (temps that need definition from upstream and are used in this basic block)
|
||||
RegisterSet m_VarKill; // Set of variables that are defined in this block.
|
||||
RegisterSet m_UEVar; // Upwards-exposed variables (temps that need definition from upstream and are used in this basic block)
|
||||
RegisterSet m_VarKill; // Set of variables that are defined in this block.
|
||||
|
||||
ConnectionSet m_Preceding; // Set of blocks that immediately precede this block in the CFG
|
||||
ConnectionSet m_Succeeding; // Set of blocks that follow this block in the CFG
|
||||
|
||||
ReachableVariables m_DEDef; // Downward-exposed definitions from this basic block. Always only one item per set.
|
||||
|
||||
ReachableVariables m_Reachable; // The set of variable definitions that are visible at the end of this block.
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
ConnectionSet m_Preceding; // Set of blocks that immediately precede this block in the CFG
|
||||
ConnectionSet m_Succeeding; // Set of blocks that follow this block in the CFG
|
||||
|
||||
ReachableVariables m_DEDef; // Downward-exposed definitions from this basic block. Always only one item per set.
|
||||
|
||||
ReachableVariables m_Reachable; // The set of variable definitions that are visible at the end of this block.
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -4,28 +4,27 @@ struct Instruction;
|
||||
|
||||
namespace HLSLcc
|
||||
{
|
||||
namespace ControlFlow
|
||||
{
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
// For a given flow-control instruction, find the corresponding jump location:
|
||||
// If the input is OPCODE_IF, then find the next same-level ELSE or ENDIF +1
|
||||
// For ELSE, find same level ENDIF + 1
|
||||
// For BREAK/BREAKC, find next ENDLOOP or ENDSWITCH + 1
|
||||
// For SWITCH, find next same-level CASE/DEFAULT (skip multiple consecutive case/default labels) or ENDSWITCH + 1
|
||||
// For ENDLOOP, find previous same-level LOOP + 1
|
||||
// For CASE/DEFAULT, find next same-level CASE/DEFAULT or ENDSWITCH + 1, skip multiple consecutive case/default labels
|
||||
// For CONTINUE/C the previous LOOP + 1
|
||||
// Note that LOOP/ENDSWITCH itself is nothing but a label but it still starts a new basic block.
|
||||
// Note that CASE labels fall through.
|
||||
// Always returns the beginning of the next block, so skip multiple CASE/DEFAULT labels etc.
|
||||
// If sawEndSwitch != null, will bet set to true if the label skipping saw past ENDSWITCH
|
||||
// If needConnectToParent != null, will be set to true if sawEndSwitch == true and there are one or more case labels directly before it.
|
||||
static const Instruction * GetJumpPoint(const Instruction *psStart, bool *sawEndSwitch = 0, bool *needConnectToParent = 0);
|
||||
namespace ControlFlow
|
||||
{
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
// For a given flow-control instruction, find the corresponding jump location:
|
||||
// If the input is OPCODE_IF, then find the next same-level ELSE or ENDIF +1
|
||||
// For ELSE, find same level ENDIF + 1
|
||||
// For BREAK/BREAKC, find next ENDLOOP or ENDSWITCH + 1
|
||||
// For SWITCH, find next same-level CASE/DEFAULT (skip multiple consecutive case/default labels) or ENDSWITCH + 1
|
||||
// For ENDLOOP, find previous same-level LOOP + 1
|
||||
// For CASE/DEFAULT, find next same-level CASE/DEFAULT or ENDSWITCH + 1, skip multiple consecutive case/default labels
|
||||
// For CONTINUE/C the previous LOOP + 1
|
||||
// Note that LOOP/ENDSWITCH itself is nothing but a label but it still starts a new basic block.
|
||||
// Note that CASE labels fall through.
|
||||
// Always returns the beginning of the next block, so skip multiple CASE/DEFAULT labels etc.
|
||||
// If sawEndSwitch != null, will bet set to true if the label skipping saw past ENDSWITCH
|
||||
// If needConnectToParent != null, will be set to true if sawEndSwitch == true and there are one or more case labels directly before it.
|
||||
static const Instruction * GetJumpPoint(const Instruction *psStart, bool *sawEndSwitch = 0, bool *needConnectToParent = 0);
|
||||
|
||||
static const Instruction *GetNextNonLabelInstruction(const Instruction *psStart, bool *sawEndSwitch = 0);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
static const Instruction *GetNextNonLabelInstruction(const Instruction *psStart, bool *sawEndSwitch = 0);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ struct Instruction;
|
||||
|
||||
namespace HLSLcc
|
||||
{
|
||||
namespace DataTypeAnalysis
|
||||
{
|
||||
void SetDataTypes(HLSLCrossCompilerContext* psContext, std::vector<Instruction> &instructions, uint32_t ui32TempCount, std::vector<SHADER_VARIABLE_TYPE> &results);
|
||||
};
|
||||
};
|
||||
namespace DataTypeAnalysis
|
||||
{
|
||||
void SetDataTypes(HLSLCrossCompilerContext* psContext, std::vector<Instruction> &instructions, uint32_t ui32TempCount, std::vector<SHADER_VARIABLE_TYPE> &results);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
@ -6,11 +5,12 @@
|
||||
#include "internal_includes/tokens.h"
|
||||
#include "internal_includes/Operand.h"
|
||||
|
||||
typedef struct ICBVec4_TAG {
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
uint32_t c;
|
||||
uint32_t d;
|
||||
typedef struct ICBVec4_TAG
|
||||
{
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
uint32_t c;
|
||||
uint32_t d;
|
||||
} ICBVec4;
|
||||
|
||||
#define ACCESS_FLAG_READ 0x1
|
||||
@ -18,85 +18,86 @@ typedef struct ICBVec4_TAG {
|
||||
|
||||
struct Declaration
|
||||
{
|
||||
Declaration()
|
||||
:
|
||||
eOpcode(OPCODE_INVALID),
|
||||
ui32NumOperands(0),
|
||||
ui32BufferStride(0)
|
||||
{}
|
||||
Declaration()
|
||||
:
|
||||
eOpcode(OPCODE_INVALID),
|
||||
ui32NumOperands(0),
|
||||
ui32BufferStride(0)
|
||||
{}
|
||||
|
||||
OPCODE_TYPE eOpcode;
|
||||
OPCODE_TYPE eOpcode;
|
||||
|
||||
uint32_t ui32NumOperands;
|
||||
uint32_t ui32NumOperands;
|
||||
|
||||
Operand asOperands[2];
|
||||
Operand asOperands[2];
|
||||
|
||||
std::vector<ICBVec4> asImmediateConstBuffer;
|
||||
//The declaration can set one of these
|
||||
//values depending on the opcode.
|
||||
union {
|
||||
uint32_t ui32GlobalFlags;
|
||||
uint32_t ui32NumTemps;
|
||||
RESOURCE_DIMENSION eResourceDimension;
|
||||
INTERPOLATION_MODE eInterpolation;
|
||||
PRIMITIVE_TOPOLOGY eOutputPrimitiveTopology;
|
||||
PRIMITIVE eInputPrimitive;
|
||||
uint32_t ui32MaxOutputVertexCount;
|
||||
TESSELLATOR_DOMAIN eTessDomain;
|
||||
TESSELLATOR_PARTITIONING eTessPartitioning;
|
||||
TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim;
|
||||
uint32_t aui32WorkGroupSize[3];
|
||||
uint32_t ui32HullPhaseInstanceCount;
|
||||
float fMaxTessFactor;
|
||||
uint32_t ui32IndexRange;
|
||||
uint32_t ui32GSInstanceCount;
|
||||
SB_SAMPLER_MODE eSamplerMode; // For sampler declarations, the sampler mode.
|
||||
std::vector<ICBVec4> asImmediateConstBuffer;
|
||||
//The declaration can set one of these
|
||||
//values depending on the opcode.
|
||||
union
|
||||
{
|
||||
uint32_t ui32GlobalFlags;
|
||||
uint32_t ui32NumTemps;
|
||||
RESOURCE_DIMENSION eResourceDimension;
|
||||
INTERPOLATION_MODE eInterpolation;
|
||||
PRIMITIVE_TOPOLOGY eOutputPrimitiveTopology;
|
||||
PRIMITIVE eInputPrimitive;
|
||||
uint32_t ui32MaxOutputVertexCount;
|
||||
TESSELLATOR_DOMAIN eTessDomain;
|
||||
TESSELLATOR_PARTITIONING eTessPartitioning;
|
||||
TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim;
|
||||
uint32_t aui32WorkGroupSize[3];
|
||||
uint32_t ui32HullPhaseInstanceCount;
|
||||
float fMaxTessFactor;
|
||||
uint32_t ui32IndexRange;
|
||||
uint32_t ui32GSInstanceCount;
|
||||
SB_SAMPLER_MODE eSamplerMode; // For sampler declarations, the sampler mode.
|
||||
|
||||
struct Interface_TAG
|
||||
{
|
||||
uint32_t ui32InterfaceID;
|
||||
uint32_t ui32NumFuncTables;
|
||||
uint32_t ui32ArraySize;
|
||||
} iface;
|
||||
} value;
|
||||
struct Interface_TAG
|
||||
{
|
||||
uint32_t ui32InterfaceID;
|
||||
uint32_t ui32NumFuncTables;
|
||||
uint32_t ui32ArraySize;
|
||||
} iface;
|
||||
} value;
|
||||
|
||||
uint32_t ui32BufferStride;
|
||||
uint32_t ui32BufferStride;
|
||||
|
||||
struct UAV_TAG
|
||||
{
|
||||
UAV_TAG() :
|
||||
ui32GloballyCoherentAccess(0),
|
||||
bCounter(0),
|
||||
Type(RETURN_TYPE_UNORM),
|
||||
ui32NumComponents(0),
|
||||
ui32AccessFlags(0)
|
||||
{
|
||||
}
|
||||
uint32_t ui32GloballyCoherentAccess;
|
||||
uint8_t bCounter;
|
||||
RESOURCE_RETURN_TYPE Type;
|
||||
uint32_t ui32NumComponents;
|
||||
uint32_t ui32AccessFlags;
|
||||
} sUAV;
|
||||
struct UAV_TAG
|
||||
{
|
||||
UAV_TAG() :
|
||||
ui32GloballyCoherentAccess(0),
|
||||
bCounter(0),
|
||||
Type(RETURN_TYPE_UNORM),
|
||||
ui32NumComponents(0),
|
||||
ui32AccessFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
struct TGSM_TAG
|
||||
{
|
||||
uint32_t ui32Stride;
|
||||
uint32_t ui32Count;
|
||||
} sTGSM;
|
||||
uint32_t ui32GloballyCoherentAccess;
|
||||
uint8_t bCounter;
|
||||
RESOURCE_RETURN_TYPE Type;
|
||||
uint32_t ui32NumComponents;
|
||||
uint32_t ui32AccessFlags;
|
||||
} sUAV;
|
||||
|
||||
struct IndexableTemp_TAG
|
||||
{
|
||||
uint32_t ui32RegIndex;
|
||||
uint32_t ui32RegCount;
|
||||
uint32_t ui32RegComponentSize;
|
||||
} sIdxTemp;
|
||||
struct TGSM_TAG
|
||||
{
|
||||
uint32_t ui32Stride;
|
||||
uint32_t ui32Count;
|
||||
} sTGSM;
|
||||
|
||||
uint32_t ui32TableLength;
|
||||
struct IndexableTemp_TAG
|
||||
{
|
||||
uint32_t ui32RegIndex;
|
||||
uint32_t ui32RegCount;
|
||||
uint32_t ui32RegComponentSize;
|
||||
} sIdxTemp;
|
||||
|
||||
uint32_t ui32IsShadowTex;
|
||||
uint32_t ui32TableLength;
|
||||
|
||||
// Set indexed by sampler register number.
|
||||
std::set<uint32_t> samplersUsed;
|
||||
uint32_t ui32IsShadowTex;
|
||||
|
||||
// Set indexed by sampler register number.
|
||||
std::set<uint32_t> samplersUsed;
|
||||
};
|
||||
|
||||
|
@ -15,48 +15,52 @@ class HLSLccReflection;
|
||||
class HLSLCrossCompilerContext
|
||||
{
|
||||
public:
|
||||
HLSLCrossCompilerContext(HLSLccReflection &refl) : m_Reflection(refl) {}
|
||||
HLSLCrossCompilerContext(HLSLccReflection &refl) : m_Reflection(refl) {}
|
||||
|
||||
bstring glsl;
|
||||
bstring extensions;
|
||||
bstring beforeMain;
|
||||
bstring glsl;
|
||||
bstring extensions;
|
||||
bstring beforeMain;
|
||||
|
||||
bstring* currentGLSLString;//either glsl or earlyMain of current phase
|
||||
bstring* currentGLSLString;//either glsl or earlyMain of current phase
|
||||
|
||||
uint32_t currentPhase;
|
||||
uint32_t currentPhase;
|
||||
|
||||
int indent;
|
||||
unsigned int flags;
|
||||
int indent;
|
||||
unsigned int flags;
|
||||
|
||||
// Helper functions for checking flags
|
||||
// Returns true if VULKAN_BINDINGS flag is set
|
||||
bool IsVulkan() const;
|
||||
// Helper functions for checking flags
|
||||
// Returns true if VULKAN_BINDINGS flag is set
|
||||
bool IsVulkan() const;
|
||||
|
||||
Shader* psShader;
|
||||
GLSLCrossDependencyData* psDependencies;
|
||||
const char *inputPrefix; // Prefix for shader inputs
|
||||
const char *outputPrefix; // Prefix for shader outputs
|
||||
// Helper functions for checking flags
|
||||
// Returns true if HLSLCC_FLAG_NVN_TARGET flag is set
|
||||
bool IsSwitch() const;
|
||||
|
||||
void DoDataTypeAnalysis(ShaderPhase *psPhase);
|
||||
Shader* psShader;
|
||||
GLSLCrossDependencyData* psDependencies;
|
||||
const char *inputPrefix; // Prefix for shader inputs
|
||||
const char *outputPrefix; // Prefix for shader outputs
|
||||
|
||||
void ClearDependencyData();
|
||||
void DoDataTypeAnalysis(ShaderPhase *psPhase);
|
||||
|
||||
void AddIndentation();
|
||||
void ClearDependencyData();
|
||||
|
||||
// Currently active translator
|
||||
Translator *psTranslator;
|
||||
void AddIndentation();
|
||||
|
||||
HLSLccReflection &m_Reflection; // Callbacks for bindings and diagnostic info
|
||||
// Currently active translator
|
||||
Translator *psTranslator;
|
||||
|
||||
// Retrieve the name for which the input or output is declared as. Takes into account possible redirections.
|
||||
std::string GetDeclaredInputName(const Operand* psOperand, int *piRebase, int iIgnoreRedirect, uint32_t *puiIgnoreSwizzle) const;
|
||||
std::string GetDeclaredOutputName(const Operand* psOperand, int* stream, uint32_t *puiIgnoreSwizzle, int *piRebase, int iIgnoreRedirect) const;
|
||||
HLSLccReflection &m_Reflection; // Callbacks for bindings and diagnostic info
|
||||
|
||||
bool OutputNeedsDeclaring(const Operand* psOperand, const int count);
|
||||
// Retrieve the name for which the input or output is declared as. Takes into account possible redirections.
|
||||
std::string GetDeclaredInputName(const Operand* psOperand, int *piRebase, int iIgnoreRedirect, uint32_t *puiIgnoreSwizzle) const;
|
||||
std::string GetDeclaredOutputName(const Operand* psOperand, int* stream, uint32_t *puiIgnoreSwizzle, int *piRebase, int iIgnoreRedirect) const;
|
||||
|
||||
bool RequireExtension(const std::string &extName);
|
||||
bool EnableExtension(const std::string &extName);
|
||||
bool OutputNeedsDeclaring(const Operand* psOperand, const int count);
|
||||
|
||||
bool RequireExtension(const std::string &extName);
|
||||
bool EnableExtension(const std::string &extName);
|
||||
|
||||
private:
|
||||
std::set<std::string> m_EnabledExtensions;
|
||||
std::set<std::string> m_EnabledExtensions;
|
||||
};
|
||||
|
@ -13,117 +13,118 @@ struct ConstantBuffer;
|
||||
|
||||
namespace HLSLcc
|
||||
{
|
||||
uint32_t GetNumberBitsSet(uint32_t a);
|
||||
uint32_t GetNumberBitsSet(uint32_t a);
|
||||
|
||||
uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType);
|
||||
uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType);
|
||||
|
||||
SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags);
|
||||
SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags);
|
||||
|
||||
const char * GetConstructorForType(const HLSLCrossCompilerContext *psContext, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision = true);
|
||||
const char * GetConstructorForType(const HLSLCrossCompilerContext *psContext, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision = true);
|
||||
|
||||
const char * GetConstructorForTypeGLSL(const HLSLCrossCompilerContext *context, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision);
|
||||
const char * GetConstructorForTypeGLSL(const HLSLCrossCompilerContext *context, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision);
|
||||
|
||||
const char * GetConstructorForTypeMetal(const SHADER_VARIABLE_TYPE eType, const int components);
|
||||
const char * GetConstructorForTypeMetal(const SHADER_VARIABLE_TYPE eType, const int components);
|
||||
|
||||
std::string GetMatrixTypeName(const HLSLCrossCompilerContext *psContext, const SHADER_VARIABLE_TYPE eBaseType, const int columns, const int rows);
|
||||
std::string GetMatrixTypeName(const HLSLCrossCompilerContext *psContext, const SHADER_VARIABLE_TYPE eBaseType, const int columns, const int rows);
|
||||
|
||||
void AddSwizzleUsingElementCount(bstring dest, uint32_t count);
|
||||
void AddSwizzleUsingElementCount(bstring dest, uint32_t count);
|
||||
|
||||
int WriteMaskToComponentCount(uint32_t writeMask);
|
||||
int WriteMaskToComponentCount(uint32_t writeMask);
|
||||
|
||||
uint32_t BuildComponentMaskFromElementCount(int count);
|
||||
uint32_t BuildComponentMaskFromElementCount(int count);
|
||||
|
||||
// Returns true if we can do direct assignment between types (mostly for mediump<->highp floats etc)
|
||||
bool DoAssignmentDataTypesMatch(SHADER_VARIABLE_TYPE dest, SHADER_VARIABLE_TYPE src);
|
||||
// Returns true if we can do direct assignment between types (mostly for mediump<->highp floats etc)
|
||||
bool DoAssignmentDataTypesMatch(SHADER_VARIABLE_TYPE dest, SHADER_VARIABLE_TYPE src);
|
||||
|
||||
// Convert resource return type to SVT_ flags
|
||||
uint32_t ResourceReturnTypeToFlag(const RESOURCE_RETURN_TYPE eType);
|
||||
// Convert resource return type to SVT_ flags
|
||||
uint32_t ResourceReturnTypeToFlag(const RESOURCE_RETURN_TYPE eType);
|
||||
|
||||
SHADER_VARIABLE_TYPE ResourceReturnTypeToSVTType(const RESOURCE_RETURN_TYPE eType, const REFLECT_RESOURCE_PRECISION ePrec);
|
||||
SHADER_VARIABLE_TYPE ResourceReturnTypeToSVTType(const RESOURCE_RETURN_TYPE eType, const REFLECT_RESOURCE_PRECISION ePrec);
|
||||
|
||||
uint32_t ElemCountToAutoExpandFlag(uint32_t elemCount);
|
||||
uint32_t ElemCountToAutoExpandFlag(uint32_t elemCount);
|
||||
|
||||
bool IsOperationCommutative(int /* OPCODE_TYPE */ eOpCode);
|
||||
bool IsOperationCommutative(int /* OPCODE_TYPE */ eOpCode);
|
||||
|
||||
bool AreTempOperandsIdentical(const Operand * psA, const Operand * psB);
|
||||
bool AreTempOperandsIdentical(const Operand * psA, const Operand * psB);
|
||||
|
||||
int GetNumTextureDimensions(int /* RESOURCE_DIMENSION */ eResDim);
|
||||
int GetNumTextureDimensions(int /* RESOURCE_DIMENSION */ eResDim);
|
||||
|
||||
SHADER_VARIABLE_TYPE SelectHigherType(SHADER_VARIABLE_TYPE a, SHADER_VARIABLE_TYPE b);
|
||||
SHADER_VARIABLE_TYPE SelectHigherType(SHADER_VARIABLE_TYPE a, SHADER_VARIABLE_TYPE b);
|
||||
|
||||
// Returns true if the instruction adds 1 to the destination temp register
|
||||
bool IsAddOneInstruction(const Instruction *psInst);
|
||||
// Returns true if the instruction adds 1 to the destination temp register
|
||||
bool IsAddOneInstruction(const Instruction *psInst);
|
||||
|
||||
bool CanDoDirectCast(const HLSLCrossCompilerContext *context, SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest);
|
||||
bool CanDoDirectCast(const HLSLCrossCompilerContext *context, SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest);
|
||||
|
||||
bool IsUnityFlexibleInstancingBuffer(const ConstantBuffer* psCBuf);
|
||||
|
||||
// Helper function to print floats with full precision
|
||||
void PrintFloat(bstring b, float f);
|
||||
// Helper function to print floats with full precision
|
||||
void PrintFloat(bstring b, float f);
|
||||
|
||||
// Flags for ForeachOperand
|
||||
// Process suboperands
|
||||
bstring GetEarlyMain(HLSLCrossCompilerContext *psContext);
|
||||
bstring GetPostShaderCode(HLSLCrossCompilerContext *psContext);
|
||||
|
||||
// Flags for ForeachOperand
|
||||
// Process suboperands
|
||||
#define FEO_FLAG_SUBOPERAND 1
|
||||
// Process src operands
|
||||
// Process src operands
|
||||
#define FEO_FLAG_SRC_OPERAND 2
|
||||
// Process destination operands
|
||||
// Process destination operands
|
||||
#define FEO_FLAG_DEST_OPERAND 4
|
||||
// Convenience: Process all operands, both src and dest, and all suboperands
|
||||
// Convenience: Process all operands, both src and dest, and all suboperands
|
||||
#define FEO_FLAG_ALL (FEO_FLAG_SUBOPERAND | FEO_FLAG_SRC_OPERAND | FEO_FLAG_DEST_OPERAND)
|
||||
|
||||
// For_each for all operands within a range of instructions. Flags above.
|
||||
template<typename ItrType, typename F> void ForEachOperand(ItrType _begin, ItrType _end, int flags, F callback)
|
||||
{
|
||||
ItrType inst = _begin;
|
||||
while (inst != _end)
|
||||
{
|
||||
uint32_t i, k;
|
||||
// For_each for all operands within a range of instructions. Flags above.
|
||||
template<typename ItrType, typename F> void ForEachOperand(ItrType _begin, ItrType _end, int flags, F callback)
|
||||
{
|
||||
ItrType inst = _begin;
|
||||
while (inst != _end)
|
||||
{
|
||||
uint32_t i, k;
|
||||
|
||||
if ((flags & FEO_FLAG_DEST_OPERAND) || (flags & FEO_FLAG_SUBOPERAND))
|
||||
{
|
||||
for (i = 0; i < inst->ui32FirstSrc; i++)
|
||||
{
|
||||
if (flags & FEO_FLAG_SUBOPERAND)
|
||||
{
|
||||
for (k = 0; k < MAX_SUB_OPERANDS; k++)
|
||||
{
|
||||
if (inst->asOperands[i].m_SubOperands[k].get())
|
||||
{
|
||||
callback(inst, inst->asOperands[i].m_SubOperands[k].get(), FEO_FLAG_SUBOPERAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags & FEO_FLAG_DEST_OPERAND)
|
||||
{
|
||||
callback(inst, &inst->asOperands[i], FEO_FLAG_DEST_OPERAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((flags & FEO_FLAG_DEST_OPERAND) || (flags & FEO_FLAG_SUBOPERAND))
|
||||
{
|
||||
for (i = 0; i < inst->ui32FirstSrc; i++)
|
||||
{
|
||||
if (flags & FEO_FLAG_SUBOPERAND)
|
||||
{
|
||||
for (k = 0; k < MAX_SUB_OPERANDS; k++)
|
||||
{
|
||||
if (inst->asOperands[i].m_SubOperands[k].get())
|
||||
{
|
||||
callback(inst, inst->asOperands[i].m_SubOperands[k].get(), FEO_FLAG_SUBOPERAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags & FEO_FLAG_DEST_OPERAND)
|
||||
{
|
||||
callback(inst, &inst->asOperands[i], FEO_FLAG_DEST_OPERAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FEO_FLAG_SRC_OPERAND) || (flags & FEO_FLAG_SUBOPERAND))
|
||||
{
|
||||
for (i = inst->ui32FirstSrc; i < inst->ui32NumOperands; i++)
|
||||
{
|
||||
if (flags & FEO_FLAG_SUBOPERAND)
|
||||
{
|
||||
for (k = 0; k < MAX_SUB_OPERANDS; k++)
|
||||
{
|
||||
if (inst->asOperands[i].m_SubOperands[k].get())
|
||||
{
|
||||
callback(inst, inst->asOperands[i].m_SubOperands[k].get(), FEO_FLAG_SUBOPERAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags & FEO_FLAG_SRC_OPERAND)
|
||||
{
|
||||
callback(inst, &inst->asOperands[i], FEO_FLAG_SRC_OPERAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((flags & FEO_FLAG_SRC_OPERAND) || (flags & FEO_FLAG_SUBOPERAND))
|
||||
{
|
||||
for (i = inst->ui32FirstSrc; i < inst->ui32NumOperands; i++)
|
||||
{
|
||||
if (flags & FEO_FLAG_SUBOPERAND)
|
||||
{
|
||||
for (k = 0; k < MAX_SUB_OPERANDS; k++)
|
||||
{
|
||||
if (inst->asOperands[i].m_SubOperands[k].get())
|
||||
{
|
||||
callback(inst, inst->asOperands[i].m_SubOperands[k].get(), FEO_FLAG_SUBOPERAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags & FEO_FLAG_SRC_OPERAND)
|
||||
{
|
||||
callback(inst, &inst->asOperands[i], FEO_FLAG_SRC_OPERAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
inst++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,134 +21,134 @@
|
||||
|
||||
struct Instruction
|
||||
{
|
||||
Instruction()
|
||||
: eOpcode(OPCODE_NOP)
|
||||
, eBooleanTestType(INSTRUCTION_TEST_ZERO)
|
||||
, ui32NumOperands(0)
|
||||
, ui32FirstSrc(0)
|
||||
, m_Uses()
|
||||
, m_SkipTranslation(false)
|
||||
, m_InductorRegister(0)
|
||||
, bSaturate(0)
|
||||
, m_IsStaticBranch(false)
|
||||
, m_StaticBranchCondition(NULL)
|
||||
{
|
||||
m_LoopInductors[0] = m_LoopInductors[1] = m_LoopInductors[2] = m_LoopInductors[3] = 0;
|
||||
}
|
||||
Instruction()
|
||||
: eOpcode(OPCODE_NOP)
|
||||
, eBooleanTestType(INSTRUCTION_TEST_ZERO)
|
||||
, ui32NumOperands(0)
|
||||
, ui32FirstSrc(0)
|
||||
, m_Uses()
|
||||
, m_SkipTranslation(false)
|
||||
, m_InductorRegister(0)
|
||||
, bSaturate(0)
|
||||
, m_IsStaticBranch(false)
|
||||
, m_StaticBranchCondition(NULL)
|
||||
{
|
||||
m_LoopInductors[0] = m_LoopInductors[1] = m_LoopInductors[2] = m_LoopInductors[3] = 0;
|
||||
}
|
||||
|
||||
// For creating unit tests only. Create an instruction with temps (unless reg is 0xffffffff in which case use OPERAND_TYPE_INPUT/OUTPUT)
|
||||
Instruction(uint64_t _id, OPCODE_TYPE opcode, uint32_t reg1 = 0, uint32_t reg1Mask = 0, uint32_t reg2 = 0, uint32_t reg2Mask = 0, uint32_t reg3 = 0, uint32_t reg3Mask = 0, uint32_t reg4 = 0, uint32_t reg4Mask = 0)
|
||||
{
|
||||
id = _id;
|
||||
eOpcode = opcode;
|
||||
eBooleanTestType = INSTRUCTION_TEST_ZERO;
|
||||
// For creating unit tests only. Create an instruction with temps (unless reg is 0xffffffff in which case use OPERAND_TYPE_INPUT/OUTPUT)
|
||||
Instruction(uint64_t _id, OPCODE_TYPE opcode, uint32_t reg1 = 0, uint32_t reg1Mask = 0, uint32_t reg2 = 0, uint32_t reg2Mask = 0, uint32_t reg3 = 0, uint32_t reg3Mask = 0, uint32_t reg4 = 0, uint32_t reg4Mask = 0)
|
||||
{
|
||||
id = _id;
|
||||
eOpcode = opcode;
|
||||
eBooleanTestType = INSTRUCTION_TEST_ZERO;
|
||||
ui32FirstSrc = 0;
|
||||
ui32NumOperands = 0;
|
||||
m_LoopInductors[0] = m_LoopInductors[1] = m_LoopInductors[2] = m_LoopInductors[3] = 0;
|
||||
m_SkipTranslation = false;
|
||||
m_InductorRegister = 0;
|
||||
ui32NumOperands = 0;
|
||||
m_LoopInductors[0] = m_LoopInductors[1] = m_LoopInductors[2] = m_LoopInductors[3] = 0;
|
||||
m_SkipTranslation = false;
|
||||
m_InductorRegister = 0;
|
||||
|
||||
if (reg1Mask == 0)
|
||||
return;
|
||||
if (reg1Mask == 0)
|
||||
return;
|
||||
|
||||
ui32NumOperands++;
|
||||
asOperands[0].eType = reg1 == 0xffffffff ? OPERAND_TYPE_OUTPUT : OPERAND_TYPE_TEMP;
|
||||
asOperands[0].ui32RegisterNumber = reg1 == 0xffffffff ? 0 : reg1;
|
||||
asOperands[0].ui32CompMask = reg1Mask;
|
||||
asOperands[0].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
ui32NumOperands++;
|
||||
asOperands[0].eType = reg1 == 0xffffffff ? OPERAND_TYPE_OUTPUT : OPERAND_TYPE_TEMP;
|
||||
asOperands[0].ui32RegisterNumber = reg1 == 0xffffffff ? 0 : reg1;
|
||||
asOperands[0].ui32CompMask = reg1Mask;
|
||||
asOperands[0].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
|
||||
if (reg2Mask == 0)
|
||||
return;
|
||||
if (reg2Mask == 0)
|
||||
return;
|
||||
|
||||
ui32FirstSrc = 1;
|
||||
ui32NumOperands++;
|
||||
ui32FirstSrc = 1;
|
||||
ui32NumOperands++;
|
||||
|
||||
asOperands[1].eType = reg2 == 0xffffffff ? OPERAND_TYPE_INPUT : OPERAND_TYPE_TEMP;
|
||||
asOperands[1].ui32RegisterNumber = reg2 == 0xffffffff ? 0 : reg2;
|
||||
asOperands[1].ui32CompMask = reg2Mask;
|
||||
asOperands[1].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
asOperands[1].eType = reg2 == 0xffffffff ? OPERAND_TYPE_INPUT : OPERAND_TYPE_TEMP;
|
||||
asOperands[1].ui32RegisterNumber = reg2 == 0xffffffff ? 0 : reg2;
|
||||
asOperands[1].ui32CompMask = reg2Mask;
|
||||
asOperands[1].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
|
||||
if (reg3Mask == 0)
|
||||
return;
|
||||
ui32NumOperands++;
|
||||
if (reg3Mask == 0)
|
||||
return;
|
||||
ui32NumOperands++;
|
||||
|
||||
asOperands[2].eType = reg3 == 0xffffffff ? OPERAND_TYPE_INPUT : OPERAND_TYPE_TEMP;
|
||||
asOperands[2].ui32RegisterNumber = reg3 == 0xffffffff ? 0 : reg3;
|
||||
asOperands[2].ui32CompMask = reg3Mask;
|
||||
asOperands[2].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
asOperands[2].eType = reg3 == 0xffffffff ? OPERAND_TYPE_INPUT : OPERAND_TYPE_TEMP;
|
||||
asOperands[2].ui32RegisterNumber = reg3 == 0xffffffff ? 0 : reg3;
|
||||
asOperands[2].ui32CompMask = reg3Mask;
|
||||
asOperands[2].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
|
||||
if (reg4Mask == 0)
|
||||
return;
|
||||
ui32NumOperands++;
|
||||
if (reg4Mask == 0)
|
||||
return;
|
||||
ui32NumOperands++;
|
||||
|
||||
asOperands[3].eType = reg4 == 0xffffffff ? OPERAND_TYPE_INPUT : OPERAND_TYPE_TEMP;
|
||||
asOperands[3].ui32RegisterNumber = reg4 == 0xffffffff ? 0 : reg4;
|
||||
asOperands[3].ui32CompMask = reg4Mask;
|
||||
asOperands[3].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
}
|
||||
asOperands[3].eType = reg4 == 0xffffffff ? OPERAND_TYPE_INPUT : OPERAND_TYPE_TEMP;
|
||||
asOperands[3].ui32RegisterNumber = reg4 == 0xffffffff ? 0 : reg4;
|
||||
asOperands[3].ui32CompMask = reg4Mask;
|
||||
asOperands[3].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
}
|
||||
|
||||
// Returns true if this instruction is a conditional branch
|
||||
bool IsConditionalBranchInstruction() const
|
||||
{
|
||||
switch (eOpcode)
|
||||
{
|
||||
case OPCODE_IF:
|
||||
case OPCODE_BREAKC:
|
||||
case OPCODE_CONTINUEC:
|
||||
case OPCODE_RETC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Returns true if this instruction is a conditional branch
|
||||
bool IsConditionalBranchInstruction() const
|
||||
{
|
||||
switch (eOpcode)
|
||||
{
|
||||
case OPCODE_IF:
|
||||
case OPCODE_BREAKC:
|
||||
case OPCODE_CONTINUEC:
|
||||
case OPCODE_RETC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPartialPrecisionSamplerInstruction(const ShaderInfo &info, OPERAND_MIN_PRECISION *pType) const;
|
||||
bool IsPartialPrecisionSamplerInstruction(const ShaderInfo &info, OPERAND_MIN_PRECISION *pType) const;
|
||||
|
||||
// Flags for ChangeOperandTempRegister
|
||||
// Flags for ChangeOperandTempRegister
|
||||
#define UD_CHANGE_SUBOPERANDS 1
|
||||
#define UD_CHANGE_MAIN_OPERAND 2
|
||||
#define UD_CHANGE_ALL 3
|
||||
|
||||
void ChangeOperandTempRegister(Operand *psOperand, uint32_t oldReg, uint32_t newReg, uint32_t compMask, uint32_t flags, uint32_t rebase);
|
||||
void ChangeOperandTempRegister(Operand *psOperand, uint32_t oldReg, uint32_t newReg, uint32_t compMask, uint32_t flags, uint32_t rebase);
|
||||
|
||||
|
||||
OPCODE_TYPE eOpcode;
|
||||
INSTRUCTION_TEST_BOOLEAN eBooleanTestType;
|
||||
uint32_t ui32SyncFlags;
|
||||
uint32_t ui32NumOperands;
|
||||
uint32_t ui32FirstSrc;
|
||||
Operand asOperands[6];
|
||||
uint32_t bSaturate;
|
||||
uint32_t ui32FuncIndexWithinInterface;
|
||||
RESINFO_RETURN_TYPE eResInfoReturnType;
|
||||
OPCODE_TYPE eOpcode;
|
||||
INSTRUCTION_TEST_BOOLEAN eBooleanTestType;
|
||||
uint32_t ui32SyncFlags;
|
||||
uint32_t ui32NumOperands;
|
||||
uint32_t ui32FirstSrc;
|
||||
Operand asOperands[6];
|
||||
uint32_t bSaturate;
|
||||
uint32_t ui32FuncIndexWithinInterface;
|
||||
RESINFO_RETURN_TYPE eResInfoReturnType;
|
||||
|
||||
int bAddressOffset;
|
||||
int8_t iUAddrOffset;
|
||||
int8_t iVAddrOffset;
|
||||
int8_t iWAddrOffset;
|
||||
RESOURCE_RETURN_TYPE xType, yType, zType, wType;
|
||||
RESOURCE_DIMENSION eResDim;
|
||||
int8_t iCausedSplit; // Nonzero if has caused a temp split. Later used by sampler datatype tweaking
|
||||
int bAddressOffset;
|
||||
int8_t iUAddrOffset;
|
||||
int8_t iVAddrOffset;
|
||||
int8_t iWAddrOffset;
|
||||
RESOURCE_RETURN_TYPE xType, yType, zType, wType;
|
||||
RESOURCE_DIMENSION eResDim;
|
||||
int8_t iCausedSplit; // Nonzero if has caused a temp split. Later used by sampler datatype tweaking
|
||||
|
||||
bool m_IsStaticBranch; // If true, this instruction is a static branch
|
||||
const Instruction *m_StaticBranchCondition; // If this is a static branch, this instruction points to the condition instruction. Can also be NULL if the operand itself is the condition
|
||||
std::string m_StaticBranchName; // The name of the static branch variable, with the condition encoded in it.
|
||||
bool m_IsStaticBranch; // If true, this instruction is a static branch
|
||||
const Instruction *m_StaticBranchCondition; // If this is a static branch, this instruction points to the condition instruction. Can also be NULL if the operand itself is the condition
|
||||
std::string m_StaticBranchName; // The name of the static branch variable, with the condition encoded in it.
|
||||
|
||||
struct Use
|
||||
{
|
||||
Use() : m_Inst(0), m_Op(0) {}
|
||||
Use(const Use &a) : m_Inst(a.m_Inst), m_Op(a.m_Op) {}
|
||||
Use(Instruction *inst, Operand *op) : m_Inst(inst), m_Op(op) {}
|
||||
struct Use
|
||||
{
|
||||
Use() : m_Inst(0), m_Op(0) {}
|
||||
Use(const Use &a) : m_Inst(a.m_Inst), m_Op(a.m_Op) {}
|
||||
Use(Instruction *inst, Operand *op) : m_Inst(inst), m_Op(op) {}
|
||||
|
||||
Instruction *m_Inst; // The instruction that references the result of this instruction
|
||||
Operand *m_Op; // The operand within the instruction above. Note: can also be suboperand.
|
||||
};
|
||||
Instruction *m_Inst; // The instruction that references the result of this instruction
|
||||
Operand *m_Op; // The operand within the instruction above. Note: can also be suboperand.
|
||||
};
|
||||
|
||||
std::vector<Use> m_Uses; // Array of use sites for the result(s) of this instruction, if any of the results is a temp reg.
|
||||
std::vector<Use> m_Uses; // Array of use sites for the result(s) of this instruction, if any of the results is a temp reg.
|
||||
|
||||
Instruction *m_LoopInductors[4]; // If OPCODE_LOOP and is suitable for transforming into for-loop, contains pointers to for initializer, end condition, breakc, and increment.
|
||||
bool m_SkipTranslation; // If true, don't emit this instruction (currently used by the for loop translation)
|
||||
uint32_t m_InductorRegister; // If non-zero, the inductor variable can be declared in the for statement, and this register number has been allocated for it
|
||||
Instruction *m_LoopInductors[4]; // If OPCODE_LOOP and is suitable for transforming into for-loop, contains pointers to for initializer, end condition, breakc, and increment.
|
||||
bool m_SkipTranslation; // If true, don't emit this instruction (currently used by the for loop translation)
|
||||
uint32_t m_InductorRegister; // If non-zero, the inductor variable can be declared in the for statement, and this register number has been allocated for it
|
||||
|
||||
uint64_t id;
|
||||
uint64_t id;
|
||||
};
|
||||
|
@ -1,9 +1,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
class ShaderPhase;
|
||||
class HLSLCrossCompilerContext;
|
||||
namespace HLSLcc
|
||||
{
|
||||
void DoLoopTransform(HLSLCrossCompilerContext *psContext, ShaderPhase &phase);
|
||||
};
|
||||
void DoLoopTransform(HLSLCrossCompilerContext *psContext, ShaderPhase &phase);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
enum{ MAX_SUB_OPERANDS = 3 };
|
||||
enum { MAX_SUB_OPERANDS = 3 };
|
||||
class Operand;
|
||||
class HLSLCrossCompilerContext;
|
||||
struct Instruction;
|
||||
@ -17,130 +17,129 @@ struct Instruction;
|
||||
class Operand
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr<Operand> SubOperandPtr;
|
||||
typedef std::shared_ptr<Operand> SubOperandPtr;
|
||||
|
||||
Operand()
|
||||
:
|
||||
iExtended(),
|
||||
eType(),
|
||||
eModifier(),
|
||||
eMinPrecision(),
|
||||
iIndexDims(),
|
||||
iWriteMask(),
|
||||
iGSInput(),
|
||||
iPSInOut(),
|
||||
iWriteMaskEnabled(),
|
||||
iArrayElements(),
|
||||
iNumComponents(),
|
||||
eSelMode(),
|
||||
ui32CompMask(),
|
||||
ui32Swizzle(),
|
||||
aui32Swizzle(),
|
||||
aui32ArraySizes(),
|
||||
ui32RegisterNumber(),
|
||||
afImmediates(),
|
||||
adImmediates(),
|
||||
eSpecialName(),
|
||||
specialName(),
|
||||
eIndexRep(),
|
||||
m_SubOperands(),
|
||||
aeDataType(),
|
||||
m_Rebase(0),
|
||||
m_Size(0),
|
||||
m_Defines(),
|
||||
m_ForLoopInductorName(0)
|
||||
Operand()
|
||||
:
|
||||
iExtended(),
|
||||
eType(),
|
||||
eModifier(),
|
||||
eMinPrecision(),
|
||||
iIndexDims(),
|
||||
iWriteMask(),
|
||||
iGSInput(),
|
||||
iPSInOut(),
|
||||
iWriteMaskEnabled(),
|
||||
iArrayElements(),
|
||||
iNumComponents(),
|
||||
eSelMode(),
|
||||
ui32CompMask(),
|
||||
ui32Swizzle(),
|
||||
aui32Swizzle(),
|
||||
aui32ArraySizes(),
|
||||
ui32RegisterNumber(),
|
||||
afImmediates(),
|
||||
adImmediates(),
|
||||
eSpecialName(),
|
||||
specialName(),
|
||||
eIndexRep(),
|
||||
m_SubOperands(),
|
||||
aeDataType(),
|
||||
m_Rebase(0),
|
||||
m_Size(0),
|
||||
m_Defines(),
|
||||
m_ForLoopInductorName(0)
|
||||
#ifdef _DEBUG
|
||||
, id(0)
|
||||
, id(0)
|
||||
#endif
|
||||
{}
|
||||
{}
|
||||
|
||||
// Retrieve the mask of all the components this operand accesses (either reads from or writes to).
|
||||
// Note that destination writemask does affect the effective access mask.
|
||||
uint32_t GetAccessMask() const;
|
||||
|
||||
// Returns the index of the highest accessed component, based on component mask
|
||||
int GetMaxComponent() const;
|
||||
// Retrieve the mask of all the components this operand accesses (either reads from or writes to).
|
||||
// Note that destination writemask does affect the effective access mask.
|
||||
uint32_t GetAccessMask() const;
|
||||
|
||||
bool IsSwizzleReplicated() const;
|
||||
// Returns the index of the highest accessed component, based on component mask
|
||||
int GetMaxComponent() const;
|
||||
|
||||
// Get the number of elements returned by operand, taking additional component mask into account
|
||||
//e.g.
|
||||
//.z = 1
|
||||
//.x = 1
|
||||
//.yw = 2
|
||||
uint32_t GetNumSwizzleElements(uint32_t ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL) const;
|
||||
bool IsSwizzleReplicated() const;
|
||||
|
||||
// When this operand is used as an input declaration, how many components does it have?
|
||||
int GetNumInputElements(const HLSLCrossCompilerContext *psContext) const;
|
||||
// Get the number of elements returned by operand, taking additional component mask into account
|
||||
//e.g.
|
||||
//.z = 1
|
||||
//.x = 1
|
||||
//.yw = 2
|
||||
uint32_t GetNumSwizzleElements(uint32_t ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL) const;
|
||||
|
||||
// Retrieve the operand data type.
|
||||
SHADER_VARIABLE_TYPE GetDataType(HLSLCrossCompilerContext* psContext, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates = SVT_INT) const;
|
||||
// When this operand is used as an input declaration, how many components does it have?
|
||||
int GetNumInputElements(const HLSLCrossCompilerContext *psContext) const;
|
||||
|
||||
// Returns 0 if the register used by the operand is per-vertex, or 1 if per-patch
|
||||
int GetRegisterSpace(const HLSLCrossCompilerContext *psContext) const;
|
||||
// Same as above but with explicit shader type and phase
|
||||
int GetRegisterSpace(SHADER_TYPE eShaderType, SHADER_PHASE_TYPE eShaderPhaseType) const;
|
||||
// Retrieve the operand data type.
|
||||
SHADER_VARIABLE_TYPE GetDataType(HLSLCrossCompilerContext* psContext, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates = SVT_INT) const;
|
||||
|
||||
// Returns 0 if the register used by the operand is per-vertex, or 1 if per-patch
|
||||
int GetRegisterSpace(const HLSLCrossCompilerContext *psContext) const;
|
||||
// Same as above but with explicit shader type and phase
|
||||
int GetRegisterSpace(SHADER_TYPE eShaderType, SHADER_PHASE_TYPE eShaderPhaseType) const;
|
||||
|
||||
// Find the operand that contains the dynamic index for this operand (array in constant buffer).
|
||||
// When isAoS is true, we'll try to find the original index var to avoid additional calculations.
|
||||
// needsIndexCalcRevert output will tell if we need to divide the value to get the correct index.
|
||||
Operand* GetDynamicIndexOperand(HLSLCrossCompilerContext *psContext, const ShaderVarType* psVar, bool isAoS, bool *needsIndexCalcRevert) const;
|
||||
|
||||
// Maps REFLECT_RESOURCE_PRECISION into OPERAND_MIN_PRECISION as much as possible
|
||||
static OPERAND_MIN_PRECISION ResourcePrecisionToOperandPrecision(REFLECT_RESOURCE_PRECISION ePrec);
|
||||
// Maps REFLECT_RESOURCE_PRECISION into OPERAND_MIN_PRECISION as much as possible
|
||||
static OPERAND_MIN_PRECISION ResourcePrecisionToOperandPrecision(REFLECT_RESOURCE_PRECISION ePrec);
|
||||
|
||||
int iExtended;
|
||||
OPERAND_TYPE eType;
|
||||
OPERAND_MODIFIER eModifier;
|
||||
OPERAND_MIN_PRECISION eMinPrecision;
|
||||
int iIndexDims;
|
||||
int iWriteMask;
|
||||
int iGSInput;
|
||||
int iPSInOut;
|
||||
int iWriteMaskEnabled;
|
||||
int iArrayElements;
|
||||
int iNumComponents;
|
||||
int iExtended;
|
||||
OPERAND_TYPE eType;
|
||||
OPERAND_MODIFIER eModifier;
|
||||
OPERAND_MIN_PRECISION eMinPrecision;
|
||||
int iIndexDims;
|
||||
int iWriteMask;
|
||||
int iGSInput;
|
||||
int iPSInOut;
|
||||
int iWriteMaskEnabled;
|
||||
int iArrayElements;
|
||||
int iNumComponents;
|
||||
|
||||
OPERAND_4_COMPONENT_SELECTION_MODE eSelMode;
|
||||
uint32_t ui32CompMask;
|
||||
uint32_t ui32Swizzle;
|
||||
uint32_t aui32Swizzle[4];
|
||||
OPERAND_4_COMPONENT_SELECTION_MODE eSelMode;
|
||||
uint32_t ui32CompMask;
|
||||
uint32_t ui32Swizzle;
|
||||
uint32_t aui32Swizzle[4];
|
||||
|
||||
uint32_t aui32ArraySizes[3];
|
||||
uint32_t ui32RegisterNumber;
|
||||
//If eType is OPERAND_TYPE_IMMEDIATE32
|
||||
float afImmediates[4];
|
||||
//If eType is OPERAND_TYPE_IMMEDIATE64
|
||||
double adImmediates[4];
|
||||
uint32_t aui32ArraySizes[3];
|
||||
uint32_t ui32RegisterNumber;
|
||||
//If eType is OPERAND_TYPE_IMMEDIATE32
|
||||
float afImmediates[4];
|
||||
//If eType is OPERAND_TYPE_IMMEDIATE64
|
||||
double adImmediates[4];
|
||||
|
||||
SPECIAL_NAME eSpecialName;
|
||||
std::string specialName;
|
||||
SPECIAL_NAME eSpecialName;
|
||||
std::string specialName;
|
||||
|
||||
OPERAND_INDEX_REPRESENTATION eIndexRep[3];
|
||||
OPERAND_INDEX_REPRESENTATION eIndexRep[3];
|
||||
|
||||
SubOperandPtr m_SubOperands[MAX_SUB_OPERANDS];
|
||||
SubOperandPtr m_SubOperands[MAX_SUB_OPERANDS];
|
||||
|
||||
//One type for each component.
|
||||
SHADER_VARIABLE_TYPE aeDataType[4];
|
||||
//One type for each component.
|
||||
SHADER_VARIABLE_TYPE aeDataType[4];
|
||||
|
||||
uint32_t m_Rebase; // Rebase value, for constant array accesses.
|
||||
uint32_t m_Size; // Component count, only for constant array access.
|
||||
uint32_t m_Rebase; // Rebase value, for constant array accesses.
|
||||
uint32_t m_Size; // Component count, only for constant array access.
|
||||
|
||||
struct Define
|
||||
{
|
||||
Define() : m_Inst(0), m_Op(0) {}
|
||||
Define(const Define &a) : m_Inst(a.m_Inst), m_Op(a.m_Op) {}
|
||||
Define(Instruction *inst, Operand *op) : m_Inst(inst), m_Op(op) {}
|
||||
struct Define
|
||||
{
|
||||
Define() : m_Inst(0), m_Op(0) {}
|
||||
Define(const Define &a) : m_Inst(a.m_Inst), m_Op(a.m_Op) {}
|
||||
Define(Instruction *inst, Operand *op) : m_Inst(inst), m_Op(op) {}
|
||||
|
||||
Instruction *m_Inst; // Instruction that writes to the temp
|
||||
Operand *m_Op; // The (destination) operand within that instruction.
|
||||
};
|
||||
Instruction *m_Inst; // Instruction that writes to the temp
|
||||
Operand *m_Op; // The (destination) operand within that instruction.
|
||||
};
|
||||
|
||||
std::vector<Define> m_Defines; // Array of instructions whose results this operand can use. (only if eType == OPERAND_TYPE_TEMP)
|
||||
uint32_t m_ForLoopInductorName; // If non-zero, this (eType==OPERAND_TYPE_TEMP) is an inductor variable used in for loop, and it has a special number as given here (overrides ui32RegisterNumber)
|
||||
std::vector<Define> m_Defines; // Array of instructions whose results this operand can use. (only if eType == OPERAND_TYPE_TEMP)
|
||||
uint32_t m_ForLoopInductorName; // If non-zero, this (eType==OPERAND_TYPE_TEMP) is an inductor variable used in for loop, and it has a special number as given here (overrides ui32RegisterNumber)
|
||||
|
||||
#ifdef _DEBUG
|
||||
uint64_t id;
|
||||
uint64_t id;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
@ -16,251 +15,252 @@
|
||||
|
||||
struct ConstantArrayChunk
|
||||
{
|
||||
ConstantArrayChunk() : m_Size(0), m_AccessMask(0) {}
|
||||
ConstantArrayChunk(uint32_t sz, uint32_t mask, Operand *firstUse)
|
||||
: m_Size(sz), m_AccessMask(mask)
|
||||
{
|
||||
m_UseSites.push_back(firstUse);
|
||||
}
|
||||
ConstantArrayChunk() : m_Size(0), m_AccessMask(0) {}
|
||||
ConstantArrayChunk(uint32_t sz, uint32_t mask, Operand *firstUse)
|
||||
: m_Size(sz), m_AccessMask(mask)
|
||||
{
|
||||
m_UseSites.push_back(firstUse);
|
||||
}
|
||||
|
||||
uint32_t m_Size;
|
||||
uint32_t m_AccessMask;
|
||||
uint32_t m_Rebase;
|
||||
uint32_t m_ComponentCount;
|
||||
uint32_t m_Size;
|
||||
uint32_t m_AccessMask;
|
||||
uint32_t m_Rebase;
|
||||
uint32_t m_ComponentCount;
|
||||
|
||||
std::vector<Operand *> m_UseSites;
|
||||
std::vector<Operand *> m_UseSites;
|
||||
};
|
||||
typedef std::multimap<uint32_t, ConstantArrayChunk> ChunkMap;
|
||||
|
||||
struct ConstantArrayInfo
|
||||
{
|
||||
ConstantArrayInfo() : m_OrigDeclaration(0), m_Chunks() {}
|
||||
ConstantArrayInfo() : m_OrigDeclaration(0), m_Chunks() {}
|
||||
|
||||
Declaration *m_OrigDeclaration; // Pointer to the original declaration of the const array
|
||||
ChunkMap m_Chunks; // map of <starting offset, chunk info>, same start offset might have multiple entries for different access masks
|
||||
Declaration *m_OrigDeclaration; // Pointer to the original declaration of the const array
|
||||
ChunkMap m_Chunks; // map of <starting offset, chunk info>, same start offset might have multiple entries for different access masks
|
||||
};
|
||||
|
||||
class ShaderPhase
|
||||
{
|
||||
public:
|
||||
ShaderPhase()
|
||||
:
|
||||
ePhase(MAIN_PHASE),
|
||||
ui32InstanceCount(0),
|
||||
postShaderCode(),
|
||||
hasPostShaderCode(0),
|
||||
earlyMain(),
|
||||
ui32OrigTemps(0),
|
||||
ui32TotalTemps(0),
|
||||
psTempDeclaration(NULL),
|
||||
pui32SplitInfo(),
|
||||
peTempTypes(),
|
||||
acInputNeedsRedirect(),
|
||||
acOutputNeedsRedirect(),
|
||||
acPatchConstantsNeedsRedirect(),
|
||||
m_CFG(),
|
||||
m_CFGInitialized(false),
|
||||
m_NextFreeTempRegister(1),
|
||||
m_NextTexCoordTemp(0)
|
||||
{}
|
||||
ShaderPhase()
|
||||
:
|
||||
ePhase(MAIN_PHASE),
|
||||
ui32InstanceCount(0),
|
||||
postShaderCode(),
|
||||
hasPostShaderCode(0),
|
||||
earlyMain(),
|
||||
ui32OrigTemps(0),
|
||||
ui32TotalTemps(0),
|
||||
psTempDeclaration(NULL),
|
||||
pui32SplitInfo(),
|
||||
peTempTypes(),
|
||||
acInputNeedsRedirect(),
|
||||
acOutputNeedsRedirect(),
|
||||
acPatchConstantsNeedsRedirect(),
|
||||
m_CFG(),
|
||||
m_CFGInitialized(false),
|
||||
m_NextFreeTempRegister(1),
|
||||
m_NextTexCoordTemp(0)
|
||||
{}
|
||||
|
||||
void ResolveUAVProperties();
|
||||
void ResolveUAVProperties();
|
||||
|
||||
void UnvectorizeImmMoves(); // Transform MOV tX.xyz, (0, 1, 2) into MOV tX.x, 0; MOV tX.y, 1; MOV tX.z, 2 to make datatype analysis easier
|
||||
void UnvectorizeImmMoves(); // Transform MOV tX.xyz, (0, 1, 2) into MOV tX.x, 0; MOV tX.y, 1; MOV tX.z, 2 to make datatype analysis easier
|
||||
|
||||
void PruneConstArrays(); // Walk through everything that accesses a const array to see if we could make it smaller
|
||||
void PruneConstArrays(); // Walk through everything that accesses a const array to see if we could make it smaller
|
||||
|
||||
void ExpandSWAPCs(); // Expand all SWAPC opcodes into a bunch of MOVCs. Must be done first!
|
||||
void ExpandSWAPCs(); // Expand all SWAPC opcodes into a bunch of MOVCs. Must be done first!
|
||||
|
||||
ConstantArrayInfo m_ConstantArrayInfo;
|
||||
ConstantArrayInfo m_ConstantArrayInfo;
|
||||
|
||||
std::vector<Declaration> psDecl;
|
||||
std::vector<Instruction> psInst;
|
||||
std::vector<Declaration> psDecl;
|
||||
std::vector<Instruction> psInst;
|
||||
|
||||
SHADER_PHASE_TYPE ePhase;
|
||||
uint32_t ui32InstanceCount; // In case of hull shaders, how many instances this phase needs to have. Defaults to 1.
|
||||
bstring postShaderCode;//End of main or before emit()
|
||||
int hasPostShaderCode;
|
||||
SHADER_PHASE_TYPE ePhase;
|
||||
uint32_t ui32InstanceCount; // In case of hull shaders, how many instances this phase needs to have. Defaults to 1.
|
||||
bstring postShaderCode;//End of main or before emit()
|
||||
int hasPostShaderCode;
|
||||
|
||||
bstring earlyMain;//Code to be inserted at the start of phase
|
||||
bstring earlyMain;//Code to be inserted at the start of phase
|
||||
|
||||
uint32_t ui32OrigTemps; // The number of temporaries this phase originally declared
|
||||
uint32_t ui32TotalTemps; // The number of temporaries this phase has now
|
||||
Declaration *psTempDeclaration; // Shortcut to the OPCODE_DCL_TEMPS opcode
|
||||
uint32_t ui32OrigTemps; // The number of temporaries this phase originally declared
|
||||
uint32_t ui32TotalTemps; // The number of temporaries this phase has now
|
||||
Declaration *psTempDeclaration; // Shortcut to the OPCODE_DCL_TEMPS opcode
|
||||
|
||||
// The split table is a table containing the index of the original register this register was split out from, or 0xffffffff
|
||||
// Format: lowest 16 bits: original register. bits 16-23: rebase (eg value of 1 means .yzw was changed to .xyz): bits 24-31: component count
|
||||
std::vector<uint32_t> pui32SplitInfo;
|
||||
std::vector<SHADER_VARIABLE_TYPE> peTempTypes;
|
||||
// The split table is a table containing the index of the original register this register was split out from, or 0xffffffff
|
||||
// Format: lowest 16 bits: original register. bits 16-23: rebase (eg value of 1 means .yzw was changed to .xyz): bits 24-31: component count
|
||||
std::vector<uint32_t> pui32SplitInfo;
|
||||
std::vector<SHADER_VARIABLE_TYPE> peTempTypes;
|
||||
|
||||
// These are needed in cases we have 2 vec2 texcoords combined into one vec4 and they are accessed together.
|
||||
std::vector<unsigned char> acInputNeedsRedirect; // If 0xff, requires re-routing all reads via a combined vec4. If 0xfe, the same but the vec4 has already been declared.
|
||||
std::vector<unsigned char> acOutputNeedsRedirect; // Same for outputs
|
||||
std::vector<unsigned char> acPatchConstantsNeedsRedirect; // Same for patch constants
|
||||
// These are needed in cases we have 2 vec2 texcoords combined into one vec4 and they are accessed together.
|
||||
std::vector<unsigned char> acInputNeedsRedirect; // If 0xff, requires re-routing all reads via a combined vec4. If 0xfe, the same but the vec4 has already been declared.
|
||||
std::vector<unsigned char> acOutputNeedsRedirect; // Same for outputs
|
||||
std::vector<unsigned char> acPatchConstantsNeedsRedirect; // Same for patch constants
|
||||
|
||||
// Get the Control Flow Graph for this phase, build it if necessary.
|
||||
HLSLcc::ControlFlow::ControlFlowGraph &GetCFG();
|
||||
// Get the Control Flow Graph for this phase, build it if necessary.
|
||||
HLSLcc::ControlFlow::ControlFlowGraph &GetCFG();
|
||||
|
||||
uint32_t m_NextFreeTempRegister; // A counter for creating new temporaries for for-loops.
|
||||
uint32_t m_NextTexCoordTemp; // A counter for creating tex coord temps for driver issue workarounds
|
||||
uint32_t m_NextFreeTempRegister; // A counter for creating new temporaries for for-loops.
|
||||
uint32_t m_NextTexCoordTemp; // A counter for creating tex coord temps for driver issue workarounds
|
||||
|
||||
// Instructions that are static branches (branches based on constant buffer values only)
|
||||
std::vector<Instruction *> m_StaticBranchInstructions;
|
||||
// Instructions that are static branches (branches based on constant buffer values only)
|
||||
std::vector<Instruction *> m_StaticBranchInstructions;
|
||||
|
||||
private:
|
||||
bool m_CFGInitialized;
|
||||
HLSLcc::ControlFlow::ControlFlowGraph m_CFG;
|
||||
bool m_CFGInitialized;
|
||||
HLSLcc::ControlFlow::ControlFlowGraph m_CFG;
|
||||
};
|
||||
|
||||
class Shader
|
||||
{
|
||||
public:
|
||||
|
||||
Shader()
|
||||
:
|
||||
ui32MajorVersion(0),
|
||||
ui32MinorVersion(0),
|
||||
eShaderType(INVALID_SHADER),
|
||||
eTargetLanguage(LANG_DEFAULT),
|
||||
extensions(0),
|
||||
fp64(0),
|
||||
ui32ShaderLength(0),
|
||||
aui32FuncTableToFuncPointer(),
|
||||
aui32FuncBodyToFuncTable(),
|
||||
funcTable(),
|
||||
funcPointer(),
|
||||
ui32NextClassFuncName(),
|
||||
pui32FirstToken(NULL),
|
||||
asPhases(),
|
||||
sInfo(),
|
||||
abScalarInput(),
|
||||
abScalarOutput(),
|
||||
aIndexedInput(),
|
||||
aIndexedOutput(),
|
||||
aIndexedInputParents(),
|
||||
aeResourceDims(),
|
||||
acInputDeclared(),
|
||||
acOutputDeclared(),
|
||||
aiOpcodeUsed(NUM_OPCODES, 0),
|
||||
ui32CurrentVertexOutputStream(0),
|
||||
textureSamplers(),
|
||||
aui32StructuredBufferBindingPoints(MAX_RESOURCE_BINDINGS, 0),
|
||||
ui32CurrentStructuredBufferIndex(),
|
||||
m_DummySamplerDeclared(false)
|
||||
{
|
||||
}
|
||||
Shader()
|
||||
:
|
||||
ui32MajorVersion(0),
|
||||
ui32MinorVersion(0),
|
||||
eShaderType(INVALID_SHADER),
|
||||
eTargetLanguage(LANG_DEFAULT),
|
||||
extensions(0),
|
||||
fp64(0),
|
||||
ui32ShaderLength(0),
|
||||
aui32FuncTableToFuncPointer(),
|
||||
aui32FuncBodyToFuncTable(),
|
||||
funcTable(),
|
||||
funcPointer(),
|
||||
ui32NextClassFuncName(),
|
||||
pui32FirstToken(NULL),
|
||||
asPhases(),
|
||||
sInfo(),
|
||||
abScalarInput(),
|
||||
abScalarOutput(),
|
||||
aIndexedInput(),
|
||||
aIndexedOutput(),
|
||||
aIndexedInputParents(),
|
||||
aeResourceDims(),
|
||||
acInputDeclared(),
|
||||
acOutputDeclared(),
|
||||
aiOpcodeUsed(NUM_OPCODES, 0),
|
||||
ui32CurrentVertexOutputStream(0),
|
||||
textureSamplers(),
|
||||
aui32StructuredBufferBindingPoints(MAX_RESOURCE_BINDINGS, 0),
|
||||
ui32CurrentStructuredBufferIndex(),
|
||||
m_DummySamplerDeclared(false)
|
||||
{
|
||||
}
|
||||
|
||||
// Retrieve the number of components the temp register has.
|
||||
uint32_t GetTempComponentCount(SHADER_VARIABLE_TYPE eType, uint32_t ui32Reg) const;
|
||||
// Retrieve the number of components the temp register has.
|
||||
uint32_t GetTempComponentCount(SHADER_VARIABLE_TYPE eType, uint32_t ui32Reg) const;
|
||||
|
||||
//Hull shaders have multiple phases.
|
||||
//Each phase has its own temps.
|
||||
//Convert from per-phase temps to global temps.
|
||||
void ConsolidateHullTempVars();
|
||||
//Hull shaders have multiple phases.
|
||||
//Each phase has its own temps.
|
||||
//Convert from per-phase temps to global temps.
|
||||
void ConsolidateHullTempVars();
|
||||
|
||||
// Go through all declarations and remove UAV occupied binding points from the aui32StructuredBufferBindingPoints list
|
||||
void ResolveStructuredBufferBindingSlots(ShaderPhase *psPhase);
|
||||
// Go through all declarations and remove UAV occupied binding points from the aui32StructuredBufferBindingPoints list
|
||||
void ResolveStructuredBufferBindingSlots(ShaderPhase *psPhase);
|
||||
|
||||
// HLSL has separate register spaces for UAV and structured buffers. GLSL has shared register space for all buffers.
|
||||
// The aim here is to preserve the UAV buffer bindings as they are and use remaining binding points for structured buffers.
|
||||
// In this step make aui32StructuredBufferBindingPoints contain increasingly ordered uints starting from zero.
|
||||
void PrepareStructuredBufferBindingSlots();
|
||||
// HLSL has separate register spaces for UAV and structured buffers. GLSL has shared register space for all buffers.
|
||||
// The aim here is to preserve the UAV buffer bindings as they are and use remaining binding points for structured buffers.
|
||||
// In this step make aui32StructuredBufferBindingPoints contain increasingly ordered uints starting from zero.
|
||||
void PrepareStructuredBufferBindingSlots();
|
||||
|
||||
// Detect temp registers per data type that are actually used.
|
||||
void PruneTempRegisters();
|
||||
// Detect temp registers per data type that are actually used.
|
||||
void PruneTempRegisters();
|
||||
|
||||
// Check if inputs and outputs are accessed across semantic boundaries
|
||||
// as in, 2x texcoord vec2's are packed together as vec4 but still accessed together.
|
||||
void AnalyzeIOOverlap();
|
||||
// Check if inputs and outputs are accessed across semantic boundaries
|
||||
// as in, 2x texcoord vec2's are packed together as vec4 but still accessed together.
|
||||
void AnalyzeIOOverlap();
|
||||
|
||||
// Change all references to vertex position to always be highp, having them be mediump causes problems on Metal and Vivante GPUs.
|
||||
void ForcePositionToHighp();
|
||||
|
||||
void FindUnusedGlobals(uint32_t flags); // Finds the DCL_CONSTANT_BUFFER with name "$Globals" and searches through all usages for each member of it and mark if they're actually ever used.
|
||||
// Change all references to vertex position to always be highp, having them be mediump causes problems on Metal and Vivante GPUs.
|
||||
void ForcePositionToHighp();
|
||||
|
||||
void ExpandSWAPCs();
|
||||
void FindUnusedGlobals(uint32_t flags); // Finds the DCL_CONSTANT_BUFFER with name "$Globals" and searches through all usages for each member of it and mark if they're actually ever used.
|
||||
|
||||
uint32_t ui32MajorVersion;
|
||||
uint32_t ui32MinorVersion;
|
||||
SHADER_TYPE eShaderType;
|
||||
void ExpandSWAPCs();
|
||||
|
||||
GLLang eTargetLanguage;
|
||||
const struct GlExtensions *extensions;
|
||||
uint32_t ui32MajorVersion;
|
||||
uint32_t ui32MinorVersion;
|
||||
SHADER_TYPE eShaderType;
|
||||
|
||||
int fp64;
|
||||
GLLang eTargetLanguage;
|
||||
const struct GlExtensions *extensions;
|
||||
|
||||
//DWORDs in program code, including version and length tokens.
|
||||
uint32_t ui32ShaderLength;
|
||||
int fp64;
|
||||
|
||||
//DWORDs in program code, including version and length tokens.
|
||||
uint32_t ui32ShaderLength;
|
||||
|
||||
|
||||
//Instruction* functions;//non-main subroutines
|
||||
HLSLcc::growing_vector<uint32_t> aui32FuncTableToFuncPointer; // dynamic alloc?
|
||||
HLSLcc::growing_vector<uint32_t> aui32FuncBodyToFuncTable;
|
||||
//Instruction* functions;//non-main subroutines
|
||||
HLSLcc::growing_vector<uint32_t> aui32FuncTableToFuncPointer; // dynamic alloc?
|
||||
HLSLcc::growing_vector<uint32_t> aui32FuncBodyToFuncTable;
|
||||
|
||||
struct FuncTableEntry{
|
||||
HLSLcc::growing_vector<uint32_t> aui32FuncBodies;
|
||||
};
|
||||
HLSLcc::growing_vector<FuncTableEntry> funcTable;
|
||||
struct FuncTableEntry
|
||||
{
|
||||
HLSLcc::growing_vector<uint32_t> aui32FuncBodies;
|
||||
};
|
||||
HLSLcc::growing_vector<FuncTableEntry> funcTable;
|
||||
|
||||
struct FuncPointerEntry {
|
||||
HLSLcc::growing_vector<uint32_t> aui32FuncTables;
|
||||
uint32_t ui32NumBodiesPerTable;
|
||||
};
|
||||
struct FuncPointerEntry
|
||||
{
|
||||
HLSLcc::growing_vector<uint32_t> aui32FuncTables;
|
||||
uint32_t ui32NumBodiesPerTable;
|
||||
};
|
||||
|
||||
HLSLcc::growing_vector<FuncPointerEntry> funcPointer;
|
||||
HLSLcc::growing_vector<FuncPointerEntry> funcPointer;
|
||||
|
||||
HLSLcc::growing_vector<uint32_t> ui32NextClassFuncName;
|
||||
HLSLcc::growing_vector<uint32_t> ui32NextClassFuncName;
|
||||
|
||||
const uint32_t* pui32FirstToken;//Reference for calculating current position in token stream.
|
||||
const uint32_t* pui32FirstToken;//Reference for calculating current position in token stream.
|
||||
|
||||
std::vector<ShaderPhase> asPhases;
|
||||
|
||||
ShaderInfo sInfo;
|
||||
std::vector<ShaderPhase> asPhases;
|
||||
|
||||
// There are 2 input/output register spaces in DX bytecode: one for per-patch data and one for per-vertex.
|
||||
// Which one is used depends on the context:
|
||||
// per-vertex space is used in vertex/pixel/geom shaders always
|
||||
// hull shader control point phase uses per-vertex by default, other phases are per-patch by default (can access per-vertex with OPERAND_TYPE_I/O_CONTROL_POINT)
|
||||
// domain shader is per-patch by default, can access per-vertex with OPERAND_TYPE_I/O_CONTROL_POINT
|
||||
ShaderInfo sInfo;
|
||||
|
||||
// Below, the [2] is accessed with 0 == per-vertex, 1 == per-patch
|
||||
// Note that these ints are component masks
|
||||
HLSLcc::growing_vector<int> abScalarInput[2];
|
||||
HLSLcc::growing_vector<int> abScalarOutput[2];
|
||||
// There are 2 input/output register spaces in DX bytecode: one for per-patch data and one for per-vertex.
|
||||
// Which one is used depends on the context:
|
||||
// per-vertex space is used in vertex/pixel/geom shaders always
|
||||
// hull shader control point phase uses per-vertex by default, other phases are per-patch by default (can access per-vertex with OPERAND_TYPE_I/O_CONTROL_POINT)
|
||||
// domain shader is per-patch by default, can access per-vertex with OPERAND_TYPE_I/O_CONTROL_POINT
|
||||
|
||||
HLSLcc::growing_vector<int> aIndexedInput[2];
|
||||
HLSLcc::growing_vector<bool> aIndexedOutput[2];
|
||||
// Below, the [2] is accessed with 0 == per-vertex, 1 == per-patch
|
||||
// Note that these ints are component masks
|
||||
HLSLcc::growing_vector<int> abScalarInput[2];
|
||||
HLSLcc::growing_vector<int> abScalarOutput[2];
|
||||
|
||||
HLSLcc::growing_vector<int> aIndexedInputParents[2];
|
||||
HLSLcc::growing_vector<int> aIndexedInput[2];
|
||||
HLSLcc::growing_vector<bool> aIndexedOutput[2];
|
||||
|
||||
HLSLcc::growing_vector<RESOURCE_DIMENSION> aeResourceDims;
|
||||
HLSLcc::growing_vector<int> aIndexedInputParents[2];
|
||||
|
||||
HLSLcc::growing_vector<char> acInputDeclared[2];
|
||||
HLSLcc::growing_vector<char> acOutputDeclared[2];
|
||||
HLSLcc::growing_vector<RESOURCE_DIMENSION> aeResourceDims;
|
||||
|
||||
std::vector<int> aiOpcodeUsed; // Initialized to NUM_OPCODES elements above.
|
||||
HLSLcc::growing_vector<char> acInputDeclared[2];
|
||||
HLSLcc::growing_vector<char> acOutputDeclared[2];
|
||||
|
||||
uint32_t ui32CurrentVertexOutputStream;
|
||||
std::vector<int> aiOpcodeUsed; // Initialized to NUM_OPCODES elements above.
|
||||
|
||||
TextureSamplerPairs textureSamplers;
|
||||
uint32_t ui32CurrentVertexOutputStream;
|
||||
|
||||
std::vector<uint32_t> aui32StructuredBufferBindingPoints;
|
||||
uint32_t ui32CurrentStructuredBufferIndex;
|
||||
TextureSamplerPairs textureSamplers;
|
||||
|
||||
std::vector<char> psIntTempSizes; // Array for whether this temp register needs declaration as int temp
|
||||
std::vector<char> psInt16TempSizes; // min16ints
|
||||
std::vector<char> psInt12TempSizes; // min12ints
|
||||
std::vector<char> psUIntTempSizes; // Same for uints
|
||||
std::vector<char> psUInt16TempSizes; // ... and for uint16's
|
||||
std::vector<char> psFloatTempSizes; // ...and for floats
|
||||
std::vector<char> psFloat16TempSizes; // ...and for min16floats
|
||||
std::vector<char> psFloat10TempSizes; // ...and for min10floats
|
||||
std::vector<char> psDoubleTempSizes; // ...and for doubles
|
||||
std::vector<char> psBoolTempSizes; // ... and for bools
|
||||
std::vector<uint32_t> aui32StructuredBufferBindingPoints;
|
||||
uint32_t ui32CurrentStructuredBufferIndex;
|
||||
|
||||
bool m_DummySamplerDeclared; // If true, the shader doesn't declare any samplers but uses texelFetch and we have added a dummy sampler for Vulkan for that.
|
||||
std::vector<char> psIntTempSizes; // Array for whether this temp register needs declaration as int temp
|
||||
std::vector<char> psInt16TempSizes; // min16ints
|
||||
std::vector<char> psInt12TempSizes; // min12ints
|
||||
std::vector<char> psUIntTempSizes; // Same for uints
|
||||
std::vector<char> psUInt16TempSizes; // ... and for uint16's
|
||||
std::vector<char> psFloatTempSizes; // ...and for floats
|
||||
std::vector<char> psFloat16TempSizes; // ...and for min16floats
|
||||
std::vector<char> psFloat10TempSizes; // ...and for min10floats
|
||||
std::vector<char> psDoubleTempSizes; // ...and for doubles
|
||||
std::vector<char> psBoolTempSizes; // ... and for bools
|
||||
|
||||
bool m_DummySamplerDeclared; // If true, the shader doesn't declare any samplers but uses texelFetch and we have added a dummy sampler for Vulkan for that.
|
||||
|
||||
private:
|
||||
void DoIOOverlapOperand(ShaderPhase *psPhase, Operand *psOperand);
|
||||
|
||||
void DoIOOverlapOperand(ShaderPhase *psPhase, Operand *psOperand);
|
||||
};
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#pragma once
|
||||
#include "HLSLCrossCompilerContext.h"
|
||||
#include "Shader.h"
|
||||
@ -8,28 +7,26 @@ struct Declaration;
|
||||
class Translator
|
||||
{
|
||||
protected:
|
||||
HLSLCrossCompilerContext *psContext;
|
||||
HLSLCrossCompilerContext *psContext;
|
||||
public:
|
||||
explicit Translator(HLSLCrossCompilerContext *ctx) : psContext(ctx) {}
|
||||
virtual ~Translator() {}
|
||||
explicit Translator(HLSLCrossCompilerContext *ctx) : psContext(ctx) {}
|
||||
virtual ~Translator() {}
|
||||
|
||||
virtual bool Translate() = 0;
|
||||
virtual bool Translate() = 0;
|
||||
|
||||
virtual void TranslateDeclaration(const Declaration *psDecl) = 0;
|
||||
virtual void TranslateDeclaration(const Declaration *psDecl) = 0;
|
||||
|
||||
// Translate system value type to name, return true if succeeded and no further translation is necessary
|
||||
virtual bool TranslateSystemValue(const Operand *psOperand, const ShaderInfo::InOutSignature *sig, std::string &result, uint32_t *pui32IgnoreSwizzle, bool isIndexed, bool isInput, bool *outSkipPrefix = NULL, int *iIgnoreRedirect = NULL) = 0;
|
||||
// Translate system value type to name, return true if succeeded and no further translation is necessary
|
||||
virtual bool TranslateSystemValue(const Operand *psOperand, const ShaderInfo::InOutSignature *sig, std::string &result, uint32_t *pui32IgnoreSwizzle, bool isIndexed, bool isInput, bool *outSkipPrefix = NULL, int *iIgnoreRedirect = NULL) = 0;
|
||||
|
||||
// In GLSL, the input and output names cannot clash.
|
||||
// Also, the output name of previous stage must match the input name of the next stage.
|
||||
// So, do gymnastics depending on which shader we're running on and which other shaders exist in this program.
|
||||
//
|
||||
virtual void SetIOPrefixes() = 0;
|
||||
// In GLSL, the input and output names cannot clash.
|
||||
// Also, the output name of previous stage must match the input name of the next stage.
|
||||
// So, do gymnastics depending on which shader we're running on and which other shaders exist in this program.
|
||||
//
|
||||
virtual void SetIOPrefixes() = 0;
|
||||
|
||||
void SetExtensions(const struct GlExtensions *ext)
|
||||
{
|
||||
psContext->psShader->extensions = ext;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
void SetExtensions(const struct GlExtensions *ext)
|
||||
{
|
||||
psContext->psShader->extensions = ext;
|
||||
}
|
||||
};
|
||||
|
@ -20,102 +20,100 @@ class Operand;
|
||||
class ShaderInfo;
|
||||
namespace HLSLcc
|
||||
{
|
||||
namespace ControlFlow
|
||||
{
|
||||
class ControlFlowGraph;
|
||||
};
|
||||
};
|
||||
namespace ControlFlow
|
||||
{
|
||||
class ControlFlowGraph;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Def-Use chain per temp component
|
||||
struct DefineUseChainEntry
|
||||
{
|
||||
DefineUseChainEntry()
|
||||
: psInst(0)
|
||||
, psOp(0)
|
||||
, usages()
|
||||
, writeMask(0)
|
||||
, index(0)
|
||||
, isStandalone(0)
|
||||
{
|
||||
memset(psSiblings, 0, 4 * sizeof(DefineUseChainEntry *));
|
||||
}
|
||||
DefineUseChainEntry()
|
||||
: psInst(0)
|
||||
, psOp(0)
|
||||
, usages()
|
||||
, writeMask(0)
|
||||
, index(0)
|
||||
, isStandalone(0)
|
||||
{
|
||||
memset(psSiblings, 0, 4 * sizeof(DefineUseChainEntry *));
|
||||
}
|
||||
|
||||
Instruction *psInst; // The declaration (write to this temp component)
|
||||
Operand *psOp; // The operand within this instruction for the write target
|
||||
UsageSet usages; // List of usages that are dependent on this write
|
||||
uint32_t writeMask; // Access mask; which all components were written to in the same op
|
||||
uint32_t index; // For which component was this definition created for?
|
||||
uint32_t isStandalone; // A shortcut for analysis: if nonzero, all siblings of all usages for both this and all this siblings
|
||||
struct DefineUseChainEntry *psSiblings[4]; // In case of vectorized op, contains pointer to this define's corresponding entries for the other components.
|
||||
Instruction *psInst; // The declaration (write to this temp component)
|
||||
Operand *psOp; // The operand within this instruction for the write target
|
||||
UsageSet usages; // List of usages that are dependent on this write
|
||||
uint32_t writeMask; // Access mask; which all components were written to in the same op
|
||||
uint32_t index; // For which component was this definition created for?
|
||||
uint32_t isStandalone; // A shortcut for analysis: if nonzero, all siblings of all usages for both this and all this siblings
|
||||
struct DefineUseChainEntry *psSiblings[4]; // In case of vectorized op, contains pointer to this define's corresponding entries for the other components.
|
||||
|
||||
#if _DEBUG
|
||||
bool operator==(const DefineUseChainEntry &a) const
|
||||
{
|
||||
if (psInst != a.psInst)
|
||||
return false;
|
||||
if (psOp != a.psOp)
|
||||
return false;
|
||||
if (writeMask != a.writeMask)
|
||||
return false;
|
||||
if (index != a.index)
|
||||
return false;
|
||||
if (isStandalone != a.isStandalone)
|
||||
return false;
|
||||
bool operator==(const DefineUseChainEntry &a) const
|
||||
{
|
||||
if (psInst != a.psInst)
|
||||
return false;
|
||||
if (psOp != a.psOp)
|
||||
return false;
|
||||
if (writeMask != a.writeMask)
|
||||
return false;
|
||||
if (index != a.index)
|
||||
return false;
|
||||
if (isStandalone != a.isStandalone)
|
||||
return false;
|
||||
|
||||
// Just check that each one has the same amount of usages
|
||||
if (usages.size() != a.usages.size())
|
||||
return false;
|
||||
// Just check that each one has the same amount of usages
|
||||
if (usages.size() != a.usages.size())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
typedef std::list<DefineUseChainEntry> DefineUseChain;
|
||||
|
||||
struct UseDefineChainEntry
|
||||
{
|
||||
UseDefineChainEntry()
|
||||
: psInst(0)
|
||||
, psOp(0)
|
||||
, defines()
|
||||
, accessMask(0)
|
||||
, index(0)
|
||||
{
|
||||
memset(psSiblings, 0, 4 * sizeof(UseDefineChainEntry *));
|
||||
}
|
||||
UseDefineChainEntry()
|
||||
: psInst(0)
|
||||
, psOp(0)
|
||||
, defines()
|
||||
, accessMask(0)
|
||||
, index(0)
|
||||
{
|
||||
memset(psSiblings, 0, 4 * sizeof(UseDefineChainEntry *));
|
||||
}
|
||||
|
||||
Instruction *psInst; // The use (read from this temp component)
|
||||
Operand *psOp; // The operand within this instruction for the read
|
||||
DefineSet defines; // List of writes that are visible to this read
|
||||
uint32_t accessMask; // Which all components were read together with this one
|
||||
uint32_t index; // For which component was this usage created for?
|
||||
struct UseDefineChainEntry *psSiblings[4]; // In case of vectorized op, contains pointer to this usage's corresponding entries for the other components.
|
||||
Instruction *psInst; // The use (read from this temp component)
|
||||
Operand *psOp; // The operand within this instruction for the read
|
||||
DefineSet defines; // List of writes that are visible to this read
|
||||
uint32_t accessMask; // Which all components were read together with this one
|
||||
uint32_t index; // For which component was this usage created for?
|
||||
struct UseDefineChainEntry *psSiblings[4]; // In case of vectorized op, contains pointer to this usage's corresponding entries for the other components.
|
||||
|
||||
#if _DEBUG
|
||||
bool operator==(const UseDefineChainEntry &a) const
|
||||
{
|
||||
if (psInst != a.psInst)
|
||||
return false;
|
||||
if (psOp != a.psOp)
|
||||
return false;
|
||||
if (accessMask != a.accessMask)
|
||||
return false;
|
||||
if (index != a.index)
|
||||
return false;
|
||||
bool operator==(const UseDefineChainEntry &a) const
|
||||
{
|
||||
if (psInst != a.psInst)
|
||||
return false;
|
||||
if (psOp != a.psOp)
|
||||
return false;
|
||||
if (accessMask != a.accessMask)
|
||||
return false;
|
||||
if (index != a.index)
|
||||
return false;
|
||||
|
||||
// Just check that each one has the same amount of usages
|
||||
if (defines.size() != a.defines.size())
|
||||
return false;
|
||||
// Just check that each one has the same amount of usages
|
||||
if (defines.size() != a.defines.size())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
typedef std::list<UseDefineChainEntry> UseDefineChain;
|
||||
@ -138,4 +136,3 @@ void CalculateStandaloneDefinitions(DefineUseChains &psDUChains, uint32_t ui32Nu
|
||||
|
||||
// Write the uses and defines back to Instruction and Operand member lists.
|
||||
void WriteBackUsesAndDefines(DefineUseChains &psDUChains);
|
||||
|
||||
|
@ -6,14 +6,15 @@
|
||||
#define ASSERT(expr) CustomAssert(expr)
|
||||
static void CustomAssert(int expression)
|
||||
{
|
||||
if(!expression)
|
||||
if (!expression)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#define UNUSED(EXPR_) \
|
||||
do { if (false) (void)(EXPR_); } while(0)
|
||||
do { if (false) (void)(EXPR_); } while(0)
|
||||
#define ASSERT(expr) UNUSED(expr)
|
||||
#endif
|
||||
|
||||
|
@ -7,55 +7,55 @@
|
||||
|
||||
static int InOutSupported(const GLLang eLang)
|
||||
{
|
||||
if(eLang == LANG_ES_100 || eLang == LANG_120)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
if (eLang == LANG_ES_100 || eLang == LANG_120)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int WriteToFragData(const GLLang eLang)
|
||||
{
|
||||
if(eLang == LANG_ES_100 || eLang == LANG_120)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang == LANG_ES_100 || eLang == LANG_120)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ShaderBitEncodingSupported(const GLLang eLang)
|
||||
{
|
||||
if( eLang != LANG_ES_300 &&
|
||||
eLang != LANG_ES_310 &&
|
||||
eLang < LANG_330)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
if (eLang != LANG_ES_300 &&
|
||||
eLang != LANG_ES_310 &&
|
||||
eLang < LANG_330)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int HaveOverloadedTextureFuncs(const GLLang eLang)
|
||||
{
|
||||
if(eLang == LANG_ES_100 || eLang == LANG_120)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
if (eLang == LANG_ES_100 || eLang == LANG_120)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Only enable for ES. Vulkan and Switch.
|
||||
//Not present in 120, ignored in other desktop languages. Specifically enabled on Vulkan.
|
||||
static int HavePrecisionQualifiers(const HLSLCrossCompilerContext *psContext)
|
||||
{
|
||||
if ((psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0 || (psContext->flags & HLSLCC_FLAG_NVN_TARGET) != 0)
|
||||
return 1;
|
||||
if ((psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0 || (psContext->flags & HLSLCC_FLAG_NVN_TARGET) != 0)
|
||||
return 1;
|
||||
|
||||
const GLLang eLang = psContext->psShader->eTargetLanguage;
|
||||
if(eLang >= LANG_ES_100 && eLang <= LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
const GLLang eLang = psContext->psShader->eTargetLanguage;
|
||||
if (eLang >= LANG_ES_100 && eLang <= LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int EmitLowp(const HLSLCrossCompilerContext *psContext)
|
||||
@ -66,25 +66,25 @@ static int EmitLowp(const HLSLCrossCompilerContext *psContext)
|
||||
|
||||
static int HaveCubemapArray(const GLLang eLang)
|
||||
{
|
||||
if (eLang >= LANG_400 && eLang <= LANG_GL_LAST)
|
||||
return 1;
|
||||
return 0;
|
||||
if (eLang >= LANG_400 && eLang <= LANG_GL_LAST)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool IsESLanguage(const GLLang eLang)
|
||||
{
|
||||
return (eLang >= LANG_ES_FIRST && eLang <= LANG_ES_LAST);
|
||||
return (eLang >= LANG_ES_FIRST && eLang <= LANG_ES_LAST);
|
||||
}
|
||||
|
||||
static bool IsDesktopGLLanguage(const GLLang eLang)
|
||||
{
|
||||
return (eLang >= LANG_GL_FIRST && eLang <= LANG_GL_LAST);
|
||||
return (eLang >= LANG_GL_FIRST && eLang <= LANG_GL_LAST);
|
||||
}
|
||||
|
||||
//Only on vertex inputs and pixel outputs.
|
||||
static int HaveLimitedInOutLocationQualifier(const GLLang eLang, const struct GlExtensions *extensions)
|
||||
{
|
||||
if(eLang >= LANG_330 || eLang == LANG_ES_300 || eLang == LANG_ES_310 || (extensions && ((struct GlExtensions*)extensions)->ARB_explicit_attrib_location))
|
||||
if (eLang >= LANG_330 || eLang == LANG_ES_300 || eLang == LANG_ES_310 || (extensions && ((struct GlExtensions*)extensions)->ARB_explicit_attrib_location))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -93,7 +93,7 @@ static int HaveLimitedInOutLocationQualifier(const GLLang eLang, const struct Gl
|
||||
|
||||
static int HaveInOutLocationQualifier(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_410 || eLang == LANG_ES_310)
|
||||
if (eLang >= LANG_410 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -102,13 +102,13 @@ static int HaveInOutLocationQualifier(const GLLang eLang)
|
||||
|
||||
//layout(binding = X) uniform {uniformA; uniformB;}
|
||||
//layout(location = X) uniform uniform_name;
|
||||
static int HaveUniformBindingsAndLocations(const GLLang eLang,const struct GlExtensions *extensions, unsigned int flags)
|
||||
static int HaveUniformBindingsAndLocations(const GLLang eLang, const struct GlExtensions *extensions, unsigned int flags)
|
||||
{
|
||||
if (flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)
|
||||
return 0;
|
||||
if (flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)
|
||||
return 0;
|
||||
|
||||
if (eLang >= LANG_430 || eLang == LANG_ES_310 ||
|
||||
(extensions && ((struct GlExtensions*)extensions)->ARB_explicit_uniform_location && ((struct GlExtensions*)extensions)->ARB_shading_language_420pack))
|
||||
if (eLang >= LANG_430 || eLang == LANG_ES_310 ||
|
||||
(extensions && ((struct GlExtensions*)extensions)->ARB_explicit_uniform_location && ((struct GlExtensions*)extensions)->ARB_shading_language_420pack))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -117,7 +117,7 @@ static int HaveUniformBindingsAndLocations(const GLLang eLang,const struct GlExt
|
||||
|
||||
static int DualSourceBlendSupported(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_330)
|
||||
if (eLang >= LANG_330)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -126,7 +126,7 @@ static int DualSourceBlendSupported(const GLLang eLang)
|
||||
|
||||
static int SubroutinesSupported(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_400)
|
||||
if (eLang >= LANG_400)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -138,7 +138,7 @@ static int SubroutinesSupported(const GLLang eLang)
|
||||
//HLSL bytecode only tells us the interpolation in pixel shader.
|
||||
static int PixelInterpDependency(const GLLang eLang)
|
||||
{
|
||||
if(eLang < LANG_430)
|
||||
if (eLang < LANG_430)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -147,166 +147,165 @@ static int PixelInterpDependency(const GLLang eLang)
|
||||
|
||||
static int HaveUnsignedTypes(const GLLang eLang)
|
||||
{
|
||||
switch(eLang)
|
||||
{
|
||||
case LANG_ES_100:
|
||||
case LANG_120:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
switch (eLang)
|
||||
{
|
||||
case LANG_ES_100:
|
||||
case LANG_120:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int HaveBitEncodingOps(const GLLang eLang)
|
||||
{
|
||||
switch(eLang)
|
||||
{
|
||||
case LANG_ES_100:
|
||||
case LANG_120:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
switch (eLang)
|
||||
{
|
||||
case LANG_ES_100:
|
||||
case LANG_120:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int HaveNativeBitwiseOps(const GLLang eLang)
|
||||
{
|
||||
switch(eLang)
|
||||
{
|
||||
case LANG_ES_100:
|
||||
case LANG_120:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
switch (eLang)
|
||||
{
|
||||
case LANG_ES_100:
|
||||
case LANG_120:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int HaveDynamicIndexing(HLSLCrossCompilerContext *psContext, const Operand* psOperand = NULL)
|
||||
{
|
||||
// WebGL only allows dynamic indexing with constant expressions, loop indices or a combination.
|
||||
// The only exception is for uniform access in vertex shaders, which can be indexed using any expression.
|
||||
// WebGL only allows dynamic indexing with constant expressions, loop indices or a combination.
|
||||
// The only exception is for uniform access in vertex shaders, which can be indexed using any expression.
|
||||
|
||||
switch(psContext->psShader->eTargetLanguage)
|
||||
{
|
||||
case LANG_ES_100:
|
||||
case LANG_120:
|
||||
if (psOperand != NULL)
|
||||
{
|
||||
if (psOperand->m_ForLoopInductorName)
|
||||
return 1;
|
||||
switch (psContext->psShader->eTargetLanguage)
|
||||
{
|
||||
case LANG_ES_100:
|
||||
case LANG_120:
|
||||
if (psOperand != NULL)
|
||||
{
|
||||
if (psOperand->m_ForLoopInductorName)
|
||||
return 1;
|
||||
|
||||
if (psContext->psShader->eShaderType == VERTEX_SHADER && psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER)
|
||||
return 1;
|
||||
}
|
||||
if (psContext->psShader->eShaderType == VERTEX_SHADER && psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int HaveGather(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_400 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_400 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveGatherNonConstOffset(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_420 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_420 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int HaveQueryLod(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_400)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_400)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveQueryLevels(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_430)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_430)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveFragmentCoordConventions(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_150)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_150)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveGeometryShaderARB(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_150)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_150)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveAtomicCounter(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_420 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_420 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveAtomicMem(const GLLang eLang)
|
||||
{
|
||||
if (eLang >= LANG_430 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_430 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveImageAtomics(const GLLang eLang)
|
||||
{
|
||||
if (eLang >= LANG_420)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_420)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveCompute(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_430 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_430 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HaveImageLoadStore(const GLLang eLang)
|
||||
{
|
||||
if(eLang >= LANG_420 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (eLang >= LANG_420 || eLang == LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -13,9 +13,9 @@ typedef struct
|
||||
uint32_t* pui32Interfaces;
|
||||
uint32_t* pui32Inputs11;
|
||||
uint32_t* pui32Outputs11;
|
||||
uint32_t* pui32OutputsWithStreams;
|
||||
uint32_t* pui32PatchConstants;
|
||||
uint32_t* pui32PatchConstants11;
|
||||
uint32_t* pui32OutputsWithStreams;
|
||||
uint32_t* pui32PatchConstants;
|
||||
uint32_t* pui32PatchConstants11;
|
||||
} ReflectionChunks;
|
||||
|
||||
void LoadShaderInfo(const uint32_t ui32MajorVersion,
|
||||
@ -24,4 +24,3 @@ void LoadShaderInfo(const uint32_t ui32MajorVersion,
|
||||
ShaderInfo* psInfo, uint32_t decodeFlags);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -8,121 +8,122 @@ class HLSLCrossCompilerContext;
|
||||
class ToGLSL : public Translator
|
||||
{
|
||||
protected:
|
||||
GLLang language;
|
||||
GLLang language;
|
||||
bool m_NeedUnityInstancingArraySizeDecl;
|
||||
|
||||
public:
|
||||
explicit ToGLSL(HLSLCrossCompilerContext *ctx) : Translator(ctx), language(LANG_DEFAULT), m_NeedUnityInstancingArraySizeDecl(false), m_NumDeclaredWhileTrueLoops(0) {}
|
||||
// Sets the target language according to given input. if LANG_DEFAULT, does autodetect and returns the selected language
|
||||
GLLang SetLanguage(GLLang suggestedLanguage);
|
||||
explicit ToGLSL(HLSLCrossCompilerContext *ctx) : Translator(ctx), language(LANG_DEFAULT), m_NeedUnityInstancingArraySizeDecl(false), m_NumDeclaredWhileTrueLoops(0) {}
|
||||
// Sets the target language according to given input. if LANG_DEFAULT, does autodetect and returns the selected language
|
||||
GLLang SetLanguage(GLLang suggestedLanguage);
|
||||
|
||||
virtual bool Translate();
|
||||
virtual void TranslateDeclaration(const Declaration* psDecl);
|
||||
virtual bool TranslateSystemValue(const Operand *psOperand, const ShaderInfo::InOutSignature *sig, std::string &result, uint32_t *pui32IgnoreSwizzle, bool isIndexed, bool isInput, bool *outSkipPrefix = NULL, int *iIgnoreRedirect = NULL);
|
||||
virtual void SetIOPrefixes();
|
||||
virtual bool Translate();
|
||||
virtual void TranslateDeclaration(const Declaration* psDecl);
|
||||
virtual bool TranslateSystemValue(const Operand *psOperand, const ShaderInfo::InOutSignature *sig, std::string &result, uint32_t *pui32IgnoreSwizzle, bool isIndexed, bool isInput, bool *outSkipPrefix = NULL, int *iIgnoreRedirect = NULL);
|
||||
virtual void SetIOPrefixes();
|
||||
|
||||
private:
|
||||
// Vulkan-only: detect which branches only depend on uniforms and immediate values and can be turned into specialization constants.
|
||||
void IdentifyStaticBranches(ShaderPhase *psPhase);
|
||||
// May return false when we detect too complex stuff (matrices, arrays etc)
|
||||
bool BuildStaticBranchNameForInstruction(Instruction &inst);
|
||||
// Vulkan-only: detect which branches only depend on uniforms and immediate values and can be turned into specialization constants.
|
||||
void IdentifyStaticBranches(ShaderPhase *psPhase);
|
||||
// May return false when we detect too complex stuff (matrices, arrays etc)
|
||||
bool BuildStaticBranchNameForInstruction(Instruction &inst);
|
||||
|
||||
void DeclareSpecializationConstants(ShaderPhase &phase);
|
||||
void DeclareSpecializationConstants(ShaderPhase &phase);
|
||||
|
||||
void TranslateOperand(bstring glsl, const Operand *psOp, uint32_t flags, uint32_t ui32ComponentMask = OPERAND_4_COMPONENT_MASK_ALL);
|
||||
void TranslateOperand(const Operand *psOp, uint32_t flags, uint32_t ui32ComponentMask = OPERAND_4_COMPONENT_MASK_ALL);
|
||||
void TranslateInstruction(Instruction* psInst, bool isEmbedded = false);
|
||||
void TranslateOperand(bstring glsl, const Operand *psOp, uint32_t flags, uint32_t ui32ComponentMask = OPERAND_4_COMPONENT_MASK_ALL);
|
||||
void TranslateOperand(const Operand *psOp, uint32_t flags, uint32_t ui32ComponentMask = OPERAND_4_COMPONENT_MASK_ALL);
|
||||
void TranslateInstruction(Instruction* psInst, bool isEmbedded = false);
|
||||
|
||||
void TranslateVariableNameWithMask(bstring glsl, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase);
|
||||
void TranslateVariableNameWithMask(const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase);
|
||||
void TranslateVariableNameWithMask(bstring glsl, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase);
|
||||
void TranslateVariableNameWithMask(const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase);
|
||||
|
||||
void TranslateOperandIndex(const Operand* psOperand, int index);
|
||||
void TranslateOperandIndexMAD(const Operand* psOperand, int index, uint32_t multiply, uint32_t add);
|
||||
void TranslateOperandIndex(const Operand* psOperand, int index);
|
||||
void TranslateOperandIndexMAD(const Operand* psOperand, int index, uint32_t multiply, uint32_t add);
|
||||
|
||||
void AddOpAssignToDestWithMask(const Operand* psDest,
|
||||
SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, const char *szAssignmentOp, int *pNeedsParenthesis, uint32_t ui32CompMask);
|
||||
void AddAssignToDest(const Operand* psDest,
|
||||
SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, int* pNeedsParenthesis);
|
||||
void AddAssignPrologue(int numParenthesis, bool isEmbedded = false);
|
||||
void AddOpAssignToDestWithMask(const Operand* psDest,
|
||||
SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, const char *szAssignmentOp, int *pNeedsParenthesis, uint32_t ui32CompMask);
|
||||
void AddAssignToDest(const Operand* psDest,
|
||||
SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, int* pNeedsParenthesis);
|
||||
void AddAssignPrologue(int numParenthesis, bool isEmbedded = false);
|
||||
|
||||
|
||||
void AddBuiltinOutput(const Declaration* psDecl, int arrayElements, const char* builtinName);
|
||||
void AddBuiltinInput(const Declaration* psDecl, const char* builtinName);
|
||||
void HandleOutputRedirect(const Declaration *psDecl, const char *Precision);
|
||||
void HandleInputRedirect(const Declaration *psDecl, const char *Precision);
|
||||
void AddBuiltinOutput(const Declaration* psDecl, int arrayElements, const char* builtinName);
|
||||
void AddBuiltinInput(const Declaration* psDecl, const char* builtinName);
|
||||
void HandleOutputRedirect(const Declaration *psDecl, const char *Precision);
|
||||
void HandleInputRedirect(const Declaration *psDecl, const char *Precision);
|
||||
|
||||
void AddUserOutput(const Declaration* psDecl);
|
||||
void DeclareStructConstants(const uint32_t ui32BindingPoint, const ConstantBuffer* psCBuf, const Operand* psOperand, bstring glsl);
|
||||
void AddUserOutput(const Declaration* psDecl);
|
||||
void DeclareStructConstants(const uint32_t ui32BindingPoint, const ConstantBuffer* psCBuf, const Operand* psOperand, bstring glsl);
|
||||
void DeclareConstBufferShaderVariable(const char* varName, const struct ShaderVarType* psType, const struct ConstantBuffer* psCBuf, int unsizedArray, bool addUniformPrefix = false);
|
||||
void PreDeclareStructType(const std::string &name, const struct ShaderVarType* psType);
|
||||
void DeclareUBOConstants(const uint32_t ui32BindingPoint, const ConstantBuffer* psCBuf, bstring glsl);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CMP_EQ,
|
||||
CMP_LT,
|
||||
CMP_GE,
|
||||
CMP_NE,
|
||||
} ComparisonType;
|
||||
|
||||
void AddComparison(Instruction* psInst, ComparisonType eType,
|
||||
uint32_t typeFlag);
|
||||
typedef enum
|
||||
{
|
||||
CMP_EQ,
|
||||
CMP_LT,
|
||||
CMP_GE,
|
||||
CMP_NE,
|
||||
} ComparisonType;
|
||||
|
||||
void AddMOVBinaryOp(const Operand *pDest, Operand *pSrc, bool isEmbedded = false);
|
||||
void AddMOVCBinaryOp(const Operand *pDest, const Operand *src0, Operand *src1, Operand *src2);
|
||||
void CallBinaryOp(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType, bool isEmbedded = false);
|
||||
void CallTernaryOp(const char* op1, const char* op2, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, uint32_t dataType);
|
||||
void CallHelper3(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2Int(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2UInt(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper1(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int paramsShouldFollowWriteMask);
|
||||
void CallHelper1Int(
|
||||
const char* name,
|
||||
Instruction* psInst,
|
||||
const int dest,
|
||||
const int src0,
|
||||
int paramsShouldFollowWriteMask);
|
||||
void TranslateTexelFetch(
|
||||
Instruction* psInst,
|
||||
const ResourceBinding* psBinding,
|
||||
bstring glsl);
|
||||
void TranslateTexCoord(
|
||||
const RESOURCE_DIMENSION eResDim,
|
||||
Operand* psTexCoordOperand);
|
||||
void GetResInfoData(Instruction* psInst, int index, int destElem);
|
||||
void TranslateTextureSample(Instruction* psInst,
|
||||
uint32_t ui32Flags);
|
||||
void TranslateDynamicComponentSelection(const ShaderVarType* psVarType,
|
||||
const Operand* psByteAddr, uint32_t offset, uint32_t mask);
|
||||
void TranslateShaderStorageStore(Instruction* psInst);
|
||||
void TranslateShaderStorageLoad(Instruction* psInst);
|
||||
void TranslateAtomicMemOp(Instruction* psInst);
|
||||
void TranslateConditional(
|
||||
Instruction* psInst,
|
||||
bstring glsl);
|
||||
void AddComparison(Instruction* psInst, ComparisonType eType,
|
||||
uint32_t typeFlag);
|
||||
|
||||
// Add an extra function to the m_FunctionDefinitions list, unless it's already there.
|
||||
bool DeclareExtraFunction(const std::string &name, bstring body);
|
||||
void UseExtraFunctionDependency(const std::string &name);
|
||||
void AddMOVBinaryOp(const Operand *pDest, Operand *pSrc, bool isEmbedded = false);
|
||||
void AddMOVCBinaryOp(const Operand *pDest, const Operand *src0, Operand *src1, Operand *src2);
|
||||
void CallBinaryOp(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType, bool isEmbedded = false);
|
||||
void CallTernaryOp(const char* op1, const char* op2, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, uint32_t dataType);
|
||||
void CallHelper3(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2Int(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2UInt(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper1(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int paramsShouldFollowWriteMask);
|
||||
void CallHelper1Int(
|
||||
const char* name,
|
||||
Instruction* psInst,
|
||||
const int dest,
|
||||
const int src0,
|
||||
int paramsShouldFollowWriteMask);
|
||||
void TranslateTexelFetch(
|
||||
Instruction* psInst,
|
||||
const ResourceBinding* psBinding,
|
||||
bstring glsl);
|
||||
void TranslateTexCoord(
|
||||
const RESOURCE_DIMENSION eResDim,
|
||||
Operand* psTexCoordOperand);
|
||||
void GetResInfoData(Instruction* psInst, int index, int destElem);
|
||||
void TranslateTextureSample(Instruction* psInst,
|
||||
uint32_t ui32Flags);
|
||||
void TranslateDynamicComponentSelection(const ShaderVarType* psVarType,
|
||||
const Operand* psByteAddr, uint32_t offset, uint32_t mask);
|
||||
void TranslateShaderStorageStore(Instruction* psInst);
|
||||
void TranslateShaderStorageLoad(Instruction* psInst);
|
||||
void TranslateAtomicMemOp(Instruction* psInst);
|
||||
void TranslateConditional(
|
||||
Instruction* psInst,
|
||||
bstring glsl);
|
||||
|
||||
void DeclareDynamicIndexWrapper(const struct ShaderVarType* psType);
|
||||
void DeclareDynamicIndexWrapper(const char* psName, SHADER_VARIABLE_CLASS eClass, SHADER_VARIABLE_TYPE eType, uint32_t ui32Rows, uint32_t ui32Columns, uint32_t ui32Elements);
|
||||
// Add an extra function to the m_FunctionDefinitions list, unless it's already there.
|
||||
bool DeclareExtraFunction(const std::string &name, bstring body);
|
||||
void UseExtraFunctionDependency(const std::string &name);
|
||||
|
||||
bool RenderTargetDeclared(uint32_t input);
|
||||
void DeclareDynamicIndexWrapper(const struct ShaderVarType* psType);
|
||||
void DeclareDynamicIndexWrapper(const char* psName, SHADER_VARIABLE_CLASS eClass, SHADER_VARIABLE_TYPE eType, uint32_t ui32Rows, uint32_t ui32Columns, uint32_t ui32Elements);
|
||||
|
||||
std::string GetVulkanDummySamplerName();
|
||||
bool RenderTargetDeclared(uint32_t input);
|
||||
|
||||
// A <function name, body text> map of extra helper functions we'll need.
|
||||
FunctionDefinitions m_FunctionDefinitions;
|
||||
std::string GetVulkanDummySamplerName();
|
||||
|
||||
std::set<uint32_t> m_DeclaredRenderTarget;
|
||||
int m_NumDeclaredWhileTrueLoops;
|
||||
// A <function name, body text> map of extra helper functions we'll need.
|
||||
FunctionDefinitions m_FunctionDefinitions;
|
||||
std::vector<std::string> m_FunctionDefinitionsOrder;
|
||||
|
||||
std::set<uint32_t> m_DeclaredRenderTarget;
|
||||
int m_NumDeclaredWhileTrueLoops;
|
||||
};
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#pragma once
|
||||
#include "internal_includes/Translator.h"
|
||||
#include <map>
|
||||
@ -6,174 +5,172 @@
|
||||
|
||||
struct SamplerDesc
|
||||
{
|
||||
std::string name;
|
||||
uint32_t reg, slot;
|
||||
std::string name;
|
||||
uint32_t reg, slot;
|
||||
};
|
||||
struct TextureSamplerDesc
|
||||
{
|
||||
std::string name;
|
||||
int textureBind, samplerBind;
|
||||
HLSLCC_TEX_DIMENSION dim;
|
||||
bool isMultisampled;
|
||||
bool isDepthSampler;
|
||||
bool uav;
|
||||
std::string name;
|
||||
int textureBind, samplerBind;
|
||||
HLSLCC_TEX_DIMENSION dim;
|
||||
bool isMultisampled;
|
||||
bool isDepthSampler;
|
||||
bool uav;
|
||||
};
|
||||
|
||||
class ToMetal : public Translator
|
||||
{
|
||||
protected:
|
||||
GLLang language;
|
||||
GLLang language;
|
||||
public:
|
||||
explicit ToMetal(HLSLCrossCompilerContext *ctx)
|
||||
explicit ToMetal(HLSLCrossCompilerContext *ctx)
|
||||
: Translator(ctx)
|
||||
, m_ShadowSamplerDeclared(false)
|
||||
, m_NeedFBOutputRemapDecl(false)
|
||||
, m_NeedFBInputRemapDecl(false)
|
||||
{}
|
||||
|
||||
virtual bool Translate();
|
||||
virtual void TranslateDeclaration(const Declaration *psDecl);
|
||||
virtual bool TranslateSystemValue(const Operand *psOperand, const ShaderInfo::InOutSignature *sig, std::string &result, uint32_t *pui32IgnoreSwizzle, bool isIndexed, bool isInput, bool *outSkipPrefix = NULL, int *iIgnoreRedirect = NULL);
|
||||
std::string TranslateOperand(const Operand *psOp, uint32_t flags, uint32_t ui32ComponentMask = OPERAND_4_COMPONENT_MASK_ALL);
|
||||
virtual bool Translate();
|
||||
virtual void TranslateDeclaration(const Declaration *psDecl);
|
||||
virtual bool TranslateSystemValue(const Operand *psOperand, const ShaderInfo::InOutSignature *sig, std::string &result, uint32_t *pui32IgnoreSwizzle, bool isIndexed, bool isInput, bool *outSkipPrefix = NULL, int *iIgnoreRedirect = NULL);
|
||||
std::string TranslateOperand(const Operand *psOp, uint32_t flags, uint32_t ui32ComponentMask = OPERAND_4_COMPONENT_MASK_ALL);
|
||||
|
||||
virtual void SetIOPrefixes();
|
||||
virtual void SetIOPrefixes();
|
||||
|
||||
private:
|
||||
void TranslateInstruction(Instruction* psInst);
|
||||
void TranslateInstruction(Instruction* psInst);
|
||||
|
||||
void DeclareBuiltinInput(const Declaration *psDecl);
|
||||
void DeclareBuiltinOutput(const Declaration *psDecl);
|
||||
void DeclareClipPlanes(const Declaration* decl, unsigned declCount);
|
||||
void GenerateTexturesReflection(HLSLccReflection* refl);
|
||||
void DeclareBuiltinInput(const Declaration *psDecl);
|
||||
void DeclareBuiltinOutput(const Declaration *psDecl);
|
||||
void DeclareClipPlanes(const Declaration* decl, unsigned declCount);
|
||||
void GenerateTexturesReflection(HLSLccReflection* refl);
|
||||
|
||||
// Retrieve the name of the output struct for this shader
|
||||
std::string GetOutputStructName() const;
|
||||
std::string GetInputStructName() const;
|
||||
std::string GetCBName(const std::string& cbName) const;
|
||||
// Retrieve the name of the output struct for this shader
|
||||
std::string GetOutputStructName() const;
|
||||
std::string GetInputStructName() const;
|
||||
std::string GetCBName(const std::string& cbName) const;
|
||||
|
||||
void DeclareHullShaderPassthrough();
|
||||
void HandleInputRedirect(const Declaration *psDecl, const std::string &typeName);
|
||||
void HandleOutputRedirect(const Declaration *psDecl, const std::string &typeName);
|
||||
void DeclareHullShaderPassthrough();
|
||||
void HandleInputRedirect(const Declaration *psDecl, const std::string &typeName);
|
||||
void HandleOutputRedirect(const Declaration *psDecl, const std::string &typeName);
|
||||
|
||||
void DeclareConstantBuffer(const ConstantBuffer *psCBuf, uint32_t ui32BindingPoint);
|
||||
void DeclareStructType(const std::string &name, const std::vector<ShaderVar> &contents, bool withinCB = false, uint32_t cumulativeOffset = 0, bool stripUnused = false);
|
||||
void DeclareStructType(const std::string &name, const std::vector<ShaderVarType> &contents, bool withinCB = false, uint32_t cumulativeOffset = 0);
|
||||
void DeclareStructVariable(const std::string &parentName, const ShaderVar &var, bool withinCB = false, uint32_t cumulativeOffset = 0);
|
||||
void DeclareStructVariable(const std::string &parentName, const ShaderVarType &var, bool withinCB = false, uint32_t cumulativeOffset = 0);
|
||||
void DeclareBufferVariable(const Declaration *psDecl, bool isRaw, bool isUAV);
|
||||
void DeclareConstantBuffer(const ConstantBuffer *psCBuf, uint32_t ui32BindingPoint);
|
||||
void DeclareStructType(const std::string &name, const std::vector<ShaderVar> &contents, bool withinCB = false, uint32_t cumulativeOffset = 0, bool stripUnused = false);
|
||||
void DeclareStructType(const std::string &name, const std::vector<ShaderVarType> &contents, bool withinCB = false, uint32_t cumulativeOffset = 0);
|
||||
void DeclareStructVariable(const std::string &parentName, const ShaderVar &var, bool withinCB = false, uint32_t cumulativeOffset = 0, bool isUsed = true);
|
||||
void DeclareStructVariable(const std::string &parentName, const ShaderVarType &var, bool withinCB = false, uint32_t cumulativeOffset = 0, bool isUsed = true);
|
||||
void DeclareBufferVariable(const Declaration *psDecl, bool isRaw, bool isUAV);
|
||||
|
||||
void DeclareResource(const Declaration *psDecl);
|
||||
void TranslateResourceTexture(const Declaration* psDecl, uint32_t samplerCanDoShadowCmp, HLSLCC_TEX_DIMENSION texDim);
|
||||
void DeclareResource(const Declaration *psDecl);
|
||||
void TranslateResourceTexture(const Declaration* psDecl, uint32_t samplerCanDoShadowCmp, HLSLCC_TEX_DIMENSION texDim);
|
||||
|
||||
void DeclareOutput(const Declaration *decl);
|
||||
void DeclareOutput(const Declaration *decl);
|
||||
|
||||
void PrintStructDeclarations(StructDefinitions &defs, const char *name = "");
|
||||
void PrintStructDeclarations(StructDefinitions &defs, const char *name = "");
|
||||
|
||||
std::string ResourceName(ResourceGroup group, const uint32_t ui32RegisterNumber);
|
||||
std::string ResourceName(ResourceGroup group, const uint32_t ui32RegisterNumber);
|
||||
|
||||
// ToMetalOperand.cpp
|
||||
std::string TranslateOperandSwizzle(const Operand* psOperand, uint32_t ui32ComponentMask, int iRebase, bool includeDot = true);
|
||||
std::string TranslateOperandIndex(const Operand* psOperand, int index);
|
||||
std::string TranslateVariableName(const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase);
|
||||
// ToMetalOperand.cpp
|
||||
std::string TranslateOperandSwizzle(const Operand* psOperand, uint32_t ui32ComponentMask, int iRebase, bool includeDot = true);
|
||||
std::string TranslateOperandIndex(const Operand* psOperand, int index);
|
||||
std::string TranslateVariableName(const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase);
|
||||
|
||||
// ToMetalInstruction.cpp
|
||||
// ToMetalInstruction.cpp
|
||||
|
||||
void AddOpAssignToDestWithMask(const Operand* psDest,
|
||||
SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, const char *szAssignmentOp, int *pNeedsParenthesis, uint32_t ui32CompMask);
|
||||
void AddAssignToDest(const Operand* psDest,
|
||||
SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, int* pNeedsParenthesis);
|
||||
void AddAssignPrologue(int numParenthesis);
|
||||
void AddOpAssignToDestWithMask(const Operand* psDest,
|
||||
SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, const char *szAssignmentOp, int *pNeedsParenthesis, uint32_t ui32CompMask);
|
||||
void AddAssignToDest(const Operand* psDest,
|
||||
SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, int* pNeedsParenthesis);
|
||||
void AddAssignPrologue(int numParenthesis);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CMP_EQ,
|
||||
CMP_LT,
|
||||
CMP_GE,
|
||||
CMP_NE,
|
||||
} ComparisonType;
|
||||
typedef enum
|
||||
{
|
||||
CMP_EQ,
|
||||
CMP_LT,
|
||||
CMP_GE,
|
||||
CMP_NE,
|
||||
} ComparisonType;
|
||||
|
||||
void AddComparison(Instruction* psInst, ComparisonType eType,
|
||||
uint32_t typeFlag);
|
||||
void AddComparison(Instruction* psInst, ComparisonType eType,
|
||||
uint32_t typeFlag);
|
||||
|
||||
bool CanForceToHalfOperand(const Operand *psOperand);
|
||||
bool CanForceToHalfOperand(const Operand *psOperand);
|
||||
|
||||
void AddMOVBinaryOp(const Operand *pDest, Operand *pSrc);
|
||||
void AddMOVCBinaryOp(const Operand *pDest, const Operand *src0, Operand *src1, Operand *src2);
|
||||
void CallBinaryOp(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType);
|
||||
void CallTernaryOp(const char* op1, const char* op2, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, uint32_t dataType);
|
||||
void CallHelper3(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, int paramsShouldFollowWriteMask, uint32_t ui32Flags);
|
||||
void CallHelper3(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2Int(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2UInt(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper1(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int paramsShouldFollowWriteMask);
|
||||
void CallHelper1Int(
|
||||
const char* name,
|
||||
Instruction* psInst,
|
||||
const int dest,
|
||||
const int src0,
|
||||
int paramsShouldFollowWriteMask);
|
||||
void TranslateTexelFetch(
|
||||
Instruction* psInst,
|
||||
const ResourceBinding* psBinding,
|
||||
bstring glsl);
|
||||
void TranslateTexelFetchOffset(
|
||||
Instruction* psInst,
|
||||
const ResourceBinding* psBinding,
|
||||
bstring glsl);
|
||||
void TranslateTexCoord(
|
||||
const RESOURCE_DIMENSION eResDim,
|
||||
Operand* psTexCoordOperand);
|
||||
void GetResInfoData(Instruction* psInst, int index, int destElem);
|
||||
void TranslateTextureSample(Instruction* psInst,
|
||||
uint32_t ui32Flags);
|
||||
void TranslateDynamicComponentSelection(const ShaderVarType* psVarType,
|
||||
const Operand* psByteAddr, uint32_t offset, uint32_t mask);
|
||||
void TranslateShaderStorageStore(Instruction* psInst);
|
||||
void TranslateShaderStorageLoad(Instruction* psInst);
|
||||
void TranslateAtomicMemOp(Instruction* psInst);
|
||||
void TranslateConditional(
|
||||
Instruction* psInst,
|
||||
bstring glsl);
|
||||
void AddMOVBinaryOp(const Operand *pDest, Operand *pSrc);
|
||||
void AddMOVCBinaryOp(const Operand *pDest, const Operand *src0, Operand *src1, Operand *src2);
|
||||
void CallBinaryOp(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType);
|
||||
void CallTernaryOp(const char* op1, const char* op2, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, uint32_t dataType);
|
||||
void CallHelper3(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, int paramsShouldFollowWriteMask, uint32_t ui32Flags);
|
||||
void CallHelper3(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int src2, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2Int(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper2UInt(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int src1, int paramsShouldFollowWriteMask);
|
||||
void CallHelper1(const char* name, Instruction* psInst,
|
||||
int dest, int src0, int paramsShouldFollowWriteMask);
|
||||
void CallHelper1Int(
|
||||
const char* name,
|
||||
Instruction* psInst,
|
||||
const int dest,
|
||||
const int src0,
|
||||
int paramsShouldFollowWriteMask);
|
||||
void TranslateTexelFetch(
|
||||
Instruction* psInst,
|
||||
const ResourceBinding* psBinding,
|
||||
bstring glsl);
|
||||
void TranslateTexelFetchOffset(
|
||||
Instruction* psInst,
|
||||
const ResourceBinding* psBinding,
|
||||
bstring glsl);
|
||||
void TranslateTexCoord(
|
||||
const RESOURCE_DIMENSION eResDim,
|
||||
Operand* psTexCoordOperand);
|
||||
void GetResInfoData(Instruction* psInst, int index, int destElem);
|
||||
void TranslateTextureSample(Instruction* psInst,
|
||||
uint32_t ui32Flags);
|
||||
void TranslateDynamicComponentSelection(const ShaderVarType* psVarType,
|
||||
const Operand* psByteAddr, uint32_t offset, uint32_t mask);
|
||||
void TranslateShaderStorageStore(Instruction* psInst);
|
||||
void TranslateShaderStorageLoad(Instruction* psInst);
|
||||
void TranslateAtomicMemOp(Instruction* psInst);
|
||||
void TranslateConditional(
|
||||
Instruction* psInst,
|
||||
bstring glsl);
|
||||
|
||||
// The map is keyed by struct name. The special name "" (empty string) is reserved for entry point function parameters
|
||||
StructDefinitions m_StructDefinitions;
|
||||
// The map is keyed by struct name. The special name "" (empty string) is reserved for entry point function parameters
|
||||
StructDefinitions m_StructDefinitions;
|
||||
|
||||
// A <function name, body text> map of extra helper functions we'll need.
|
||||
FunctionDefinitions m_FunctionDefinitions;
|
||||
// A <function name, body text> map of extra helper functions we'll need.
|
||||
FunctionDefinitions m_FunctionDefinitions;
|
||||
|
||||
BindingSlotAllocator m_TextureSlots, m_SamplerSlots;
|
||||
BindingSlotAllocator m_BufferSlots;
|
||||
BindingSlotAllocator m_TextureSlots, m_SamplerSlots;
|
||||
BindingSlotAllocator m_BufferSlots;
|
||||
|
||||
std::vector<SamplerDesc> m_Samplers;
|
||||
std::vector<TextureSamplerDesc> m_Textures;
|
||||
std::vector<SamplerDesc> m_Samplers;
|
||||
std::vector<TextureSamplerDesc> m_Textures;
|
||||
|
||||
std::string m_ExtraGlobalDefinitions;
|
||||
std::string m_ExtraGlobalDefinitions;
|
||||
|
||||
// Flags for whether we need to add the declaration for the FB IO remaps
|
||||
bool m_NeedFBInputRemapDecl;
|
||||
bool m_NeedFBOutputRemapDecl;
|
||||
|
||||
bool m_ShadowSamplerDeclared;
|
||||
|
||||
void EnsureShadowSamplerDeclared();
|
||||
bool m_ShadowSamplerDeclared;
|
||||
|
||||
// Add an extra function to the m_FunctionDefinitions list, unless it's already there.
|
||||
void DeclareExtraFunction(const std::string &name, const std::string &body);
|
||||
void EnsureShadowSamplerDeclared();
|
||||
|
||||
// Move all lowp -> mediump
|
||||
void ClampPartialPrecisions();
|
||||
|
||||
// Reseve UAV slots in advance to match the original HLSL bindings -> correct bindings in SetRandomWriteTarget()
|
||||
void ReserveUAVBindingSlots(ShaderPhase *phase);
|
||||
// Add an extra function to the m_FunctionDefinitions list, unless it's already there.
|
||||
void DeclareExtraFunction(const std::string &name, const std::string &body);
|
||||
|
||||
// Move all lowp -> mediump
|
||||
void ClampPartialPrecisions();
|
||||
|
||||
// Reseve UAV slots in advance to match the original HLSL bindings -> correct bindings in SetRandomWriteTarget()
|
||||
void ReserveUAVBindingSlots(ShaderPhase *phase);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "internal_includes/Declaration.h"
|
||||
#include "internal_includes/Declaration.h"
|
||||
|
@ -5,17 +5,17 @@
|
||||
|
||||
enum SHADER_PHASE_TYPE
|
||||
{
|
||||
SHADER_PHASE_INVALID = -1,
|
||||
MAIN_PHASE = 0,
|
||||
HS_GLOBAL_DECL_PHASE = 1,
|
||||
HS_CTRL_POINT_PHASE = 2,
|
||||
HS_FORK_PHASE = 3,
|
||||
HS_JOIN_PHASE = 4
|
||||
SHADER_PHASE_INVALID = -1,
|
||||
MAIN_PHASE = 0,
|
||||
HS_GLOBAL_DECL_PHASE = 1,
|
||||
HS_CTRL_POINT_PHASE = 2,
|
||||
HS_FORK_PHASE = 3,
|
||||
HS_JOIN_PHASE = 4
|
||||
};
|
||||
|
||||
static SHADER_TYPE DecodeShaderType(uint32_t ui32Token)
|
||||
{
|
||||
return (SHADER_TYPE)((ui32Token & 0xffff0000) >> 16);
|
||||
return (SHADER_TYPE)((ui32Token & 0xffff0000) >> 16);
|
||||
}
|
||||
|
||||
static uint32_t DecodeProgramMajorVersion(uint32_t ui32Token)
|
||||
@ -51,25 +51,24 @@ static EXTENDED_OPCODE_TYPE DecodeExtendedOpcodeType(uint32_t ui32Token)
|
||||
return (EXTENDED_OPCODE_TYPE)(ui32Token & 0x0000003f);
|
||||
}
|
||||
|
||||
|
||||
static RESOURCE_RETURN_TYPE DecodeResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token)
|
||||
{
|
||||
return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4))&0xF);
|
||||
return (RESOURCE_RETURN_TYPE)((ui32Token >> (ui32Coord * 4)) & 0xF);
|
||||
}
|
||||
|
||||
static RESOURCE_RETURN_TYPE DecodeExtendedResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token)
|
||||
{
|
||||
return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4 + 6))&0xF);
|
||||
return (RESOURCE_RETURN_TYPE)((ui32Token >> (ui32Coord * 4 + 6)) & 0xF);
|
||||
}
|
||||
|
||||
enum OPCODE_TYPE
|
||||
{
|
||||
//For DX9
|
||||
OPCODE_POW = -6,
|
||||
OPCODE_DP2ADD = -5,
|
||||
OPCODE_LRP = -4,
|
||||
OPCODE_ENDREP = -3,
|
||||
OPCODE_REP = -2,
|
||||
OPCODE_POW = -6,
|
||||
OPCODE_DP2ADD = -5,
|
||||
OPCODE_LRP = -4,
|
||||
OPCODE_ENDREP = -3,
|
||||
OPCODE_REP = -2,
|
||||
OPCODE_SPECIAL_DCL_IMMCONST = -1,
|
||||
|
||||
OPCODE_ADD,
|
||||
@ -183,7 +182,7 @@ enum OPCODE_TYPE
|
||||
// -----------------------------------------------
|
||||
|
||||
OPCODE_RESERVED_10,
|
||||
|
||||
|
||||
// ---------- DX 10.1 op codes---------------------
|
||||
|
||||
OPCODE_LOD,
|
||||
@ -234,7 +233,7 @@ enum OPCODE_TYPE
|
||||
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,
|
||||
@ -278,9 +277,9 @@ enum OPCODE_TYPE
|
||||
OPCODE_IMM_ATOMIC_IMAX,
|
||||
OPCODE_IMM_ATOMIC_IMIN,
|
||||
OPCODE_IMM_ATOMIC_UMAX,
|
||||
OPCODE_IMM_ATOMIC_UMIN,
|
||||
OPCODE_IMM_ATOMIC_UMIN,
|
||||
OPCODE_SYNC,
|
||||
|
||||
|
||||
OPCODE_DADD,
|
||||
OPCODE_DMAX,
|
||||
OPCODE_DMIN,
|
||||
@ -297,7 +296,7 @@ enum OPCODE_TYPE
|
||||
OPCODE_EVAL_SNAPPED,
|
||||
OPCODE_EVAL_SAMPLE_INDEX,
|
||||
OPCODE_EVAL_CENTROID,
|
||||
|
||||
|
||||
OPCODE_DCL_GS_INSTANCE_COUNT,
|
||||
|
||||
OPCODE_ABORT,
|
||||
@ -343,14 +342,14 @@ typedef enum
|
||||
|
||||
static OPERAND_INDEX_DIMENSION DecodeOperandIndexDimension(uint32_t ui32Token)
|
||||
{
|
||||
return (OPERAND_INDEX_DIMENSION)((ui32Token & 0x00300000) >> 20);
|
||||
return (OPERAND_INDEX_DIMENSION)((ui32Token & 0x00300000) >> 20);
|
||||
}
|
||||
|
||||
typedef enum OPERAND_TYPE
|
||||
{
|
||||
OPERAND_TYPE_SPECIAL_LOOPCOUNTER = -10,
|
||||
OPERAND_TYPE_SPECIAL_IMMCONSTINT = -9,
|
||||
OPERAND_TYPE_SPECIAL_TEXCOORD = -8,
|
||||
OPERAND_TYPE_SPECIAL_IMMCONSTINT = -9,
|
||||
OPERAND_TYPE_SPECIAL_TEXCOORD = -8,
|
||||
OPERAND_TYPE_SPECIAL_POSITION = -7,
|
||||
OPERAND_TYPE_SPECIAL_FOG = -6,
|
||||
OPERAND_TYPE_SPECIAL_POINTSIZE = -5,
|
||||
@ -363,25 +362,25 @@ typedef enum OPERAND_TYPE
|
||||
OPERAND_TYPE_OUTPUT = 2, // General Output Register File
|
||||
OPERAND_TYPE_INDEXABLE_TEMP = 3, // Temporary Register File (indexable)
|
||||
OPERAND_TYPE_IMMEDIATE32 = 4, // 32bit/component immediate value(s)
|
||||
// If for example, operand token bits
|
||||
// [01:00]==OPERAND_4_COMPONENT,
|
||||
// this means that the operand type:
|
||||
// OPERAND_TYPE_IMMEDIATE32
|
||||
// results in 4 additional 32bit
|
||||
// DWORDS present for the operand.
|
||||
// If for example, operand token bits
|
||||
// [01:00]==OPERAND_4_COMPONENT,
|
||||
// this means that the operand type:
|
||||
// OPERAND_TYPE_IMMEDIATE32
|
||||
// results in 4 additional 32bit
|
||||
// DWORDS present for the operand.
|
||||
OPERAND_TYPE_IMMEDIATE64 = 5, // 64bit/comp.imm.val(s)HI:LO
|
||||
OPERAND_TYPE_SAMPLER = 6, // Reference to sampler state
|
||||
OPERAND_TYPE_RESOURCE = 7, // Reference to memory resource (e.g. texture)
|
||||
OPERAND_TYPE_CONSTANT_BUFFER= 8, // Reference to constant buffer
|
||||
OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER= 9, // Reference to immediate constant buffer
|
||||
OPERAND_TYPE_CONSTANT_BUFFER = 8, // Reference to constant buffer
|
||||
OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER = 9, // Reference to immediate constant buffer
|
||||
OPERAND_TYPE_LABEL = 10, // Label
|
||||
OPERAND_TYPE_INPUT_PRIMITIVEID = 11, // Input primitive ID
|
||||
OPERAND_TYPE_OUTPUT_DEPTH = 12, // Output Depth
|
||||
OPERAND_TYPE_NULL = 13, // Null register, used to discard results of operations
|
||||
// Below Are operands new in DX 10.1
|
||||
// Below Are operands new in DX 10.1
|
||||
OPERAND_TYPE_RASTERIZER = 14, // DX10.1 Rasterizer register, used to denote the depth/stencil and render target resources
|
||||
OPERAND_TYPE_OUTPUT_COVERAGE_MASK = 15, // DX10.1 PS output MSAA coverage mask (scalar)
|
||||
// Below Are operands new in DX 11
|
||||
// Below Are operands new in DX 11
|
||||
OPERAND_TYPE_STREAM = 16, // Reference to GS stream output resource
|
||||
OPERAND_TYPE_FUNCTION_BODY = 17, // Reference to a function definition
|
||||
OPERAND_TYPE_FUNCTION_TABLE = 18, // Reference to a set of functions used by a class
|
||||
@ -411,30 +410,30 @@ typedef enum OPERAND_TYPE
|
||||
|
||||
static OPERAND_TYPE DecodeOperandType(uint32_t ui32Token)
|
||||
{
|
||||
return (OPERAND_TYPE)((ui32Token & 0x000ff000) >> 12);
|
||||
return (OPERAND_TYPE)((ui32Token & 0x000ff000) >> 12);
|
||||
}
|
||||
|
||||
static SPECIAL_NAME DecodeOperandSpecialName(uint32_t ui32Token)
|
||||
{
|
||||
return (SPECIAL_NAME)(ui32Token & 0x0000ffff);
|
||||
return (SPECIAL_NAME)(ui32Token & 0x0000ffff);
|
||||
}
|
||||
|
||||
typedef enum OPERAND_INDEX_REPRESENTATION
|
||||
{
|
||||
OPERAND_INDEX_IMMEDIATE32 = 0, // Extra DWORD
|
||||
OPERAND_INDEX_IMMEDIATE64 = 1, // 2 Extra DWORDs
|
||||
// (HI32:LO32)
|
||||
// (HI32:LO32)
|
||||
OPERAND_INDEX_RELATIVE = 2, // Extra operand
|
||||
OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE = 3, // Extra DWORD followed by
|
||||
// extra operand
|
||||
// extra operand
|
||||
OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE = 4, // 2 Extra DWORDS
|
||||
// (HI32:LO32) followed
|
||||
// by extra operand
|
||||
// (HI32:LO32) followed
|
||||
// by extra operand
|
||||
} OPERAND_INDEX_REPRESENTATION;
|
||||
|
||||
static OPERAND_INDEX_REPRESENTATION DecodeOperandIndexRepresentation(uint32_t ui32Dimension, uint32_t ui32Token)
|
||||
{
|
||||
return (OPERAND_INDEX_REPRESENTATION)((ui32Token & (0x3<<(22+3*((ui32Dimension)&3)))) >> (22+3*((ui32Dimension)&3)));
|
||||
return (OPERAND_INDEX_REPRESENTATION)((ui32Token & (0x3 << (22 + 3 * ((ui32Dimension) & 3)))) >> (22 + 3 * ((ui32Dimension) & 3)));
|
||||
}
|
||||
|
||||
typedef enum OPERAND_NUM_COMPONENTS
|
||||
@ -447,7 +446,7 @@ typedef enum OPERAND_NUM_COMPONENTS
|
||||
|
||||
static OPERAND_NUM_COMPONENTS DecodeOperandNumComponents(uint32_t ui32Token)
|
||||
{
|
||||
return (OPERAND_NUM_COMPONENTS)(ui32Token & 0x00000003);
|
||||
return (OPERAND_NUM_COMPONENTS)(ui32Token & 0x00000003);
|
||||
}
|
||||
|
||||
typedef enum OPERAND_4_COMPONENT_SELECTION_MODE
|
||||
@ -459,7 +458,7 @@ typedef enum OPERAND_4_COMPONENT_SELECTION_MODE
|
||||
|
||||
static OPERAND_4_COMPONENT_SELECTION_MODE DecodeOperand4CompSelMode(uint32_t ui32Token)
|
||||
{
|
||||
return (OPERAND_4_COMPONENT_SELECTION_MODE)((ui32Token & 0x0000000c) >> 2);
|
||||
return (OPERAND_4_COMPONENT_SELECTION_MODE)((ui32Token & 0x0000000c) >> 2);
|
||||
}
|
||||
|
||||
#define OPERAND_4_COMPONENT_MASK_X 0x00000001
|
||||
@ -474,17 +473,17 @@ static OPERAND_4_COMPONENT_SELECTION_MODE DecodeOperand4CompSelMode(uint32_t ui3
|
||||
|
||||
static uint32_t DecodeOperand4CompMask(uint32_t ui32Token)
|
||||
{
|
||||
return (uint32_t)((ui32Token & 0x000000f0) >> 4);
|
||||
return (uint32_t)((ui32Token & 0x000000f0) >> 4);
|
||||
}
|
||||
|
||||
static uint32_t DecodeOperand4CompSwizzle(uint32_t ui32Token)
|
||||
{
|
||||
return (uint32_t)((ui32Token & 0x00000ff0) >> 4);
|
||||
return (uint32_t)((ui32Token & 0x00000ff0) >> 4);
|
||||
}
|
||||
|
||||
static uint32_t DecodeOperand4CompSel1(uint32_t ui32Token)
|
||||
{
|
||||
return (uint32_t)((ui32Token & 0x00000030) >> 4);
|
||||
return (uint32_t)((ui32Token & 0x00000030) >> 4);
|
||||
}
|
||||
|
||||
#define OPERAND_4_COMPONENT_X 0
|
||||
@ -492,7 +491,7 @@ static uint32_t DecodeOperand4CompSel1(uint32_t ui32Token)
|
||||
#define OPERAND_4_COMPONENT_Z 2
|
||||
#define OPERAND_4_COMPONENT_W 3
|
||||
|
||||
static const uint32_t NO_SWIZZLE = (( (OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_W << 6))/*<<4*/);
|
||||
static const uint32_t NO_SWIZZLE = (((OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_Y << 2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_W << 6)) /*<<4*/);
|
||||
|
||||
static const uint32_t XXXX_SWIZZLE = (((OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_X << 2) | (OPERAND_4_COMPONENT_X << 4) | (OPERAND_4_COMPONENT_X << 6)));
|
||||
static const uint32_t YYYY_SWIZZLE = (((OPERAND_4_COMPONENT_Y) | (OPERAND_4_COMPONENT_Y << 2) | (OPERAND_4_COMPONENT_Y << 4) | (OPERAND_4_COMPONENT_Y << 6)));
|
||||
@ -501,7 +500,7 @@ static const uint32_t WWWW_SWIZZLE = (((OPERAND_4_COMPONENT_W) | (OPERAND_4_COMP
|
||||
|
||||
static uint32_t DecodeOperand4CompSwizzleSource(uint32_t ui32Token, uint32_t comp)
|
||||
{
|
||||
return (uint32_t)(((ui32Token)>>(4+2*((comp)&3)))&3);
|
||||
return (uint32_t)(((ui32Token) >> (4 + 2 * ((comp) & 3))) & 3);
|
||||
}
|
||||
|
||||
typedef enum RESOURCE_DIMENSION
|
||||
@ -523,12 +522,12 @@ typedef enum RESOURCE_DIMENSION
|
||||
|
||||
static RESOURCE_DIMENSION DecodeResourceDimension(uint32_t ui32Token)
|
||||
{
|
||||
return (RESOURCE_DIMENSION)((ui32Token & 0x0000f800) >> 11);
|
||||
return (RESOURCE_DIMENSION)((ui32Token & 0x0000f800) >> 11);
|
||||
}
|
||||
|
||||
static RESOURCE_DIMENSION DecodeExtendedResourceDimension(uint32_t ui32Token)
|
||||
{
|
||||
return (RESOURCE_DIMENSION)((ui32Token & 0x000007C0) >> 6);
|
||||
return (RESOURCE_DIMENSION)((ui32Token & 0x000007C0) >> 6);
|
||||
}
|
||||
|
||||
typedef enum INSTRUCTION_TEST_BOOLEAN
|
||||
@ -539,7 +538,7 @@ typedef enum INSTRUCTION_TEST_BOOLEAN
|
||||
|
||||
static INSTRUCTION_TEST_BOOLEAN DecodeInstrTestBool(uint32_t ui32Token)
|
||||
{
|
||||
return (INSTRUCTION_TEST_BOOLEAN)((ui32Token & 0x00040000) >> 18);
|
||||
return (INSTRUCTION_TEST_BOOLEAN)((ui32Token & 0x00040000) >> 18);
|
||||
}
|
||||
|
||||
static uint32_t DecodeIsOperandExtended(uint32_t ui32Token)
|
||||
@ -555,7 +554,7 @@ typedef enum EXTENDED_OPERAND_TYPE
|
||||
|
||||
static EXTENDED_OPERAND_TYPE DecodeExtendedOperandType(uint32_t ui32Token)
|
||||
{
|
||||
return (EXTENDED_OPERAND_TYPE)(ui32Token & 0x0000003f);
|
||||
return (EXTENDED_OPERAND_TYPE)(ui32Token & 0x0000003f);
|
||||
}
|
||||
|
||||
typedef enum OPERAND_MODIFIER
|
||||
@ -568,29 +567,28 @@ typedef enum OPERAND_MODIFIER
|
||||
|
||||
static OPERAND_MODIFIER DecodeExtendedOperandModifier(uint32_t ui32Token)
|
||||
{
|
||||
return (OPERAND_MODIFIER)((ui32Token & 0x00003fc0) >> 6);
|
||||
return (OPERAND_MODIFIER)((ui32Token & 0x00003fc0) >> 6);
|
||||
}
|
||||
|
||||
static const uint32_t GLOBAL_FLAG_REFACTORING_ALLOWED = (1<<11);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = (1<<12);
|
||||
static const uint32_t GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL = (1<<13);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS = (1<<14);
|
||||
static const uint32_t GLOBAL_FLAG_SKIP_OPTIMIZATION = (1<<15);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION = (1<<16);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS = (1<<17);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS = (1<<18);
|
||||
static const uint32_t GLOBAL_FLAG_REFACTORING_ALLOWED = (1 << 11);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = (1 << 12);
|
||||
static const uint32_t GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL = (1 << 13);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS = (1 << 14);
|
||||
static const uint32_t GLOBAL_FLAG_SKIP_OPTIMIZATION = (1 << 15);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION = (1 << 16);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS = (1 << 17);
|
||||
static const uint32_t GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS = (1 << 18);
|
||||
|
||||
static uint32_t DecodeGlobalFlags(uint32_t ui32Token)
|
||||
{
|
||||
return (uint32_t)(ui32Token & 0x00fff800);
|
||||
return (uint32_t)(ui32Token & 0x00fff800);
|
||||
}
|
||||
|
||||
static INTERPOLATION_MODE DecodeInterpolationMode(uint32_t ui32Token)
|
||||
{
|
||||
return (INTERPOLATION_MODE)((ui32Token & 0x00007800) >> 11);
|
||||
return (INTERPOLATION_MODE)((ui32Token & 0x00007800) >> 11);
|
||||
}
|
||||
|
||||
|
||||
typedef enum PRIMITIVE_TOPOLOGY
|
||||
{
|
||||
PRIMITIVE_TOPOLOGY_UNDEFINED = 0,
|
||||
@ -609,7 +607,7 @@ typedef enum PRIMITIVE_TOPOLOGY
|
||||
|
||||
static PRIMITIVE_TOPOLOGY DecodeGSOutputPrimitiveTopology(uint32_t ui32Token)
|
||||
{
|
||||
return (PRIMITIVE_TOPOLOGY)((ui32Token & 0x0001f800) >> 11);
|
||||
return (PRIMITIVE_TOPOLOGY)((ui32Token & 0x0001f800) >> 11);
|
||||
}
|
||||
|
||||
typedef enum PRIMITIVE
|
||||
@ -657,22 +655,22 @@ typedef enum PRIMITIVE
|
||||
|
||||
static PRIMITIVE DecodeGSInputPrimitive(uint32_t ui32Token)
|
||||
{
|
||||
return (PRIMITIVE)((ui32Token & 0x0001f800) >> 11);
|
||||
return (PRIMITIVE)((ui32Token & 0x0001f800) >> 11);
|
||||
}
|
||||
|
||||
static TESSELLATOR_PARTITIONING DecodeTessPartitioning(uint32_t ui32Token)
|
||||
{
|
||||
return (TESSELLATOR_PARTITIONING)((ui32Token & 0x00003800) >> 11);
|
||||
return (TESSELLATOR_PARTITIONING)((ui32Token & 0x00003800) >> 11);
|
||||
}
|
||||
|
||||
static TESSELLATOR_DOMAIN DecodeTessDomain(uint32_t ui32Token)
|
||||
{
|
||||
return (TESSELLATOR_DOMAIN)((ui32Token & 0x00001800) >> 11);
|
||||
return (TESSELLATOR_DOMAIN)((ui32Token & 0x00001800) >> 11);
|
||||
}
|
||||
|
||||
static TESSELLATOR_OUTPUT_PRIMITIVE DecodeTessOutPrim(uint32_t ui32Token)
|
||||
{
|
||||
return (TESSELLATOR_OUTPUT_PRIMITIVE)((ui32Token & 0x00003800) >> 11);
|
||||
return (TESSELLATOR_OUTPUT_PRIMITIVE)((ui32Token & 0x00003800) >> 11);
|
||||
}
|
||||
|
||||
static const uint32_t SYNC_THREADS_IN_GROUP = 0x00000800;
|
||||
@ -682,19 +680,19 @@ static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL = 0x00004000;
|
||||
|
||||
static uint32_t DecodeSyncFlags(uint32_t ui32Token)
|
||||
{
|
||||
return ui32Token & 0x00007800;
|
||||
return ui32Token & 0x00007800;
|
||||
}
|
||||
|
||||
// The number of types that implement this interface
|
||||
static uint32_t DecodeInterfaceTableLength(uint32_t ui32Token)
|
||||
{
|
||||
return (uint32_t)((ui32Token & 0x0000ffff) >> 0);
|
||||
return (uint32_t)((ui32Token & 0x0000ffff) >> 0);
|
||||
}
|
||||
|
||||
// The number of interfaces that are defined in this array.
|
||||
static uint32_t DecodeInterfaceArrayLength(uint32_t ui32Token)
|
||||
{
|
||||
return (uint32_t)((ui32Token & 0xffff0000) >> 16);
|
||||
return (uint32_t)((ui32Token & 0xffff0000) >> 16);
|
||||
}
|
||||
|
||||
typedef enum CUSTOMDATA_CLASS
|
||||
@ -708,7 +706,7 @@ typedef enum CUSTOMDATA_CLASS
|
||||
|
||||
static CUSTOMDATA_CLASS DecodeCustomDataClass(uint32_t ui32Token)
|
||||
{
|
||||
return (CUSTOMDATA_CLASS)((ui32Token & 0xfffff800) >> 11);
|
||||
return (CUSTOMDATA_CLASS)((ui32Token & 0xfffff800) >> 11);
|
||||
}
|
||||
|
||||
static uint32_t DecodeInstructionSaturate(uint32_t ui32Token)
|
||||
@ -718,8 +716,8 @@ static uint32_t DecodeInstructionSaturate(uint32_t ui32Token)
|
||||
|
||||
typedef enum OPERAND_MIN_PRECISION
|
||||
{
|
||||
OPERAND_MIN_PRECISION_DEFAULT = 0, // Default precision
|
||||
// for the shader model
|
||||
OPERAND_MIN_PRECISION_DEFAULT = 0, // Default precision
|
||||
// for the shader model
|
||||
OPERAND_MIN_PRECISION_FLOAT_16 = 1, // Min 16 bit/component float
|
||||
OPERAND_MIN_PRECISION_FLOAT_2_8 = 2, // Min 10(2.8)bit/comp. float
|
||||
OPERAND_MIN_PRECISION_SINT_16 = 4, // Min 16 bit/comp. signed integer
|
||||
@ -733,7 +731,7 @@ static uint32_t DecodeOperandMinPrecision(uint32_t ui32Token)
|
||||
|
||||
static uint32_t DecodeOutputControlPointCount(uint32_t ui32Token)
|
||||
{
|
||||
return ((ui32Token & 0x0001f800) >> 11);
|
||||
return ((ui32Token & 0x0001f800) >> 11);
|
||||
}
|
||||
|
||||
typedef enum IMMEDIATE_ADDRESS_OFFSET_COORD
|
||||
@ -749,7 +747,7 @@ typedef enum IMMEDIATE_ADDRESS_OFFSET_COORD
|
||||
|
||||
static uint32_t DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_COORD eCoord, uint32_t ui32Token)
|
||||
{
|
||||
return ((((ui32Token)&IMMEDIATE_ADDRESS_OFFSET_MASK(eCoord))>>(IMMEDIATE_ADDRESS_OFFSET_SHIFT(eCoord))));
|
||||
return ((((ui32Token) & IMMEDIATE_ADDRESS_OFFSET_MASK(eCoord)) >> (IMMEDIATE_ADDRESS_OFFSET_SHIFT(eCoord))));
|
||||
}
|
||||
|
||||
// UAV access scope flags
|
||||
@ -759,7 +757,6 @@ static uint32_t DecodeAccessCoherencyFlags(uint32_t ui32Token)
|
||||
return ui32Token & 0x00010000;
|
||||
}
|
||||
|
||||
|
||||
typedef enum RESINFO_RETURN_TYPE
|
||||
{
|
||||
RESINFO_INSTRUCTION_RETURN_FLOAT = 0,
|
||||
@ -774,15 +771,14 @@ static RESINFO_RETURN_TYPE DecodeResInfoReturnType(uint32_t ui32Token)
|
||||
|
||||
typedef enum SB_SAMPLER_MODE
|
||||
{
|
||||
D3D10_SB_SAMPLER_MODE_DEFAULT = 0,
|
||||
D3D10_SB_SAMPLER_MODE_COMPARISON = 1,
|
||||
D3D10_SB_SAMPLER_MODE_MONO = 2,
|
||||
D3D10_SB_SAMPLER_MODE_DEFAULT = 0,
|
||||
D3D10_SB_SAMPLER_MODE_COMPARISON = 1,
|
||||
D3D10_SB_SAMPLER_MODE_MONO = 2,
|
||||
} SB_SAMPLER_MODE;
|
||||
|
||||
static SB_SAMPLER_MODE DecodeSamplerMode(uint32_t ui32Token)
|
||||
{
|
||||
return (SB_SAMPLER_MODE)((ui32Token & 0x00001800) >> 11);
|
||||
return (SB_SAMPLER_MODE)((ui32Token & 0x00001800) >> 11);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
497
src/reflect.cpp
497
src/reflect.cpp
@ -1,4 +1,3 @@
|
||||
|
||||
#include "internal_includes/reflect.h"
|
||||
#include "internal_includes/debug.h"
|
||||
#include "internal_includes/decode.h"
|
||||
@ -18,11 +17,11 @@ static void FormatVariableName(std::string & Name)
|
||||
|
||||
/* Leave $ThisPointer, $Element and $Globals as-is.
|
||||
Otherwise remove $ character ($ is not a valid character for GLSL variable names). */
|
||||
if(Name[0] == '$')
|
||||
if (Name[0] == '$')
|
||||
{
|
||||
if(strcmp(Name.c_str(), "$Element") !=0 &&
|
||||
strcmp(Name.c_str(), "$Globals") != 0 &&
|
||||
strcmp(Name.c_str(), "$ThisPointer") != 0)
|
||||
if (strcmp(Name.c_str(), "$Element") != 0 &&
|
||||
strcmp(Name.c_str(), "$Globals") != 0 &&
|
||||
strcmp(Name.c_str(), "$ThisPointer") != 0)
|
||||
{
|
||||
Name[0] = '_';
|
||||
}
|
||||
@ -31,25 +30,25 @@ static void FormatVariableName(std::string & Name)
|
||||
|
||||
static std::string ReadStringFromTokenStream(const uint32_t* tokens)
|
||||
{
|
||||
char* charTokens = (char*) tokens;
|
||||
return std::string(charTokens);
|
||||
char* charTokens = (char*)tokens;
|
||||
return std::string(charTokens);
|
||||
}
|
||||
|
||||
static int MaskToRebaseOffset(const uint32_t mask)
|
||||
{
|
||||
int res = 0;
|
||||
uint32_t m = mask;
|
||||
while ((m & 1) == 0)
|
||||
{
|
||||
res++;
|
||||
m = m >> 1;
|
||||
}
|
||||
return res;
|
||||
int res = 0;
|
||||
uint32_t m = mask;
|
||||
while ((m & 1) == 0)
|
||||
{
|
||||
res++;
|
||||
m = m >> 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void ReadInputSignatures(const uint32_t* pui32Tokens,
|
||||
ShaderInfo* psShaderInfo,
|
||||
const int extended)
|
||||
ShaderInfo* psShaderInfo,
|
||||
const int extended)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
@ -57,44 +56,44 @@ static void ReadInputSignatures(const uint32_t* pui32Tokens,
|
||||
const uint32_t ui32ElementCount = *pui32Tokens++;
|
||||
/* const uint32_t ui32Key = * */ pui32Tokens++;
|
||||
|
||||
psShaderInfo->psInputSignatures.clear();
|
||||
psShaderInfo->psInputSignatures.resize(ui32ElementCount);
|
||||
psShaderInfo->psInputSignatures.clear();
|
||||
psShaderInfo->psInputSignatures.resize(ui32ElementCount);
|
||||
|
||||
for(i=0; i<ui32ElementCount; ++i)
|
||||
for (i = 0; i < ui32ElementCount; ++i)
|
||||
{
|
||||
uint32_t ui32ComponentMasks;
|
||||
ShaderInfo::InOutSignature* psCurrentSignature = &psShaderInfo->psInputSignatures[i];
|
||||
uint32_t ui32SemanticNameOffset;
|
||||
|
||||
psCurrentSignature->ui32Stream = 0;
|
||||
psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT;
|
||||
psCurrentSignature->ui32Stream = 0;
|
||||
psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT;
|
||||
|
||||
if(extended)
|
||||
psCurrentSignature->ui32Stream = *pui32Tokens++;
|
||||
if (extended)
|
||||
psCurrentSignature->ui32Stream = *pui32Tokens++;
|
||||
|
||||
ui32SemanticNameOffset = *pui32Tokens++;
|
||||
ui32SemanticNameOffset = *pui32Tokens++;
|
||||
psCurrentSignature->ui32SemanticIndex = *pui32Tokens++;
|
||||
psCurrentSignature->eSystemValueType = (SPECIAL_NAME) *pui32Tokens++;
|
||||
psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++;
|
||||
psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++;
|
||||
psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE)*pui32Tokens++;
|
||||
psCurrentSignature->ui32Register = *pui32Tokens++;
|
||||
|
||||
|
||||
ui32ComponentMasks = *pui32Tokens++;
|
||||
psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F;
|
||||
//Shows which components are read
|
||||
psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8;
|
||||
psCurrentSignature->iRebase = MaskToRebaseOffset(psCurrentSignature->ui32Mask);
|
||||
psCurrentSignature->iRebase = MaskToRebaseOffset(psCurrentSignature->ui32Mask);
|
||||
|
||||
if(extended)
|
||||
psCurrentSignature->eMinPrec = (MIN_PRECISION) *pui32Tokens++;
|
||||
if (extended)
|
||||
psCurrentSignature->eMinPrec = (MIN_PRECISION)*pui32Tokens++;
|
||||
|
||||
psCurrentSignature->semanticName = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken+ui32SemanticNameOffset));
|
||||
psCurrentSignature->semanticName = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset));
|
||||
}
|
||||
}
|
||||
|
||||
static void ReadOutputSignatures(const uint32_t* pui32Tokens,
|
||||
ShaderInfo* psShaderInfo,
|
||||
const int minPrec,
|
||||
const int streams)
|
||||
ShaderInfo* psShaderInfo,
|
||||
const int minPrec,
|
||||
const int streams)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
@ -102,50 +101,50 @@ static void ReadOutputSignatures(const uint32_t* pui32Tokens,
|
||||
const uint32_t ui32ElementCount = *pui32Tokens++;
|
||||
/*const uint32_t ui32Key = * */ pui32Tokens++;
|
||||
|
||||
psShaderInfo->psOutputSignatures.clear();
|
||||
psShaderInfo->psOutputSignatures.resize(ui32ElementCount);
|
||||
psShaderInfo->psOutputSignatures.clear();
|
||||
psShaderInfo->psOutputSignatures.resize(ui32ElementCount);
|
||||
|
||||
for(i=0; i<ui32ElementCount; ++i)
|
||||
for (i = 0; i < ui32ElementCount; ++i)
|
||||
{
|
||||
uint32_t ui32ComponentMasks;
|
||||
ShaderInfo::InOutSignature* psCurrentSignature = &psShaderInfo->psOutputSignatures[i];
|
||||
uint32_t ui32SemanticNameOffset;
|
||||
|
||||
psCurrentSignature->ui32Stream = 0;
|
||||
psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT;
|
||||
psCurrentSignature->ui32Stream = 0;
|
||||
psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT;
|
||||
|
||||
if(streams)
|
||||
psCurrentSignature->ui32Stream = *pui32Tokens++;
|
||||
if (streams)
|
||||
psCurrentSignature->ui32Stream = *pui32Tokens++;
|
||||
|
||||
ui32SemanticNameOffset = *pui32Tokens++;
|
||||
ui32SemanticNameOffset = *pui32Tokens++;
|
||||
psCurrentSignature->ui32SemanticIndex = *pui32Tokens++;
|
||||
psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++;
|
||||
psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++;
|
||||
psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE)*pui32Tokens++;
|
||||
psCurrentSignature->ui32Register = *pui32Tokens++;
|
||||
|
||||
// Massage some special inputs/outputs to match the types of GLSL counterparts
|
||||
if (psCurrentSignature->eSystemValueType == NAME_RENDER_TARGET_ARRAY_INDEX)
|
||||
{
|
||||
psCurrentSignature->eComponentType = INOUT_COMPONENT_SINT32;
|
||||
}
|
||||
// Massage some special inputs/outputs to match the types of GLSL counterparts
|
||||
if (psCurrentSignature->eSystemValueType == NAME_RENDER_TARGET_ARRAY_INDEX)
|
||||
{
|
||||
psCurrentSignature->eComponentType = INOUT_COMPONENT_SINT32;
|
||||
}
|
||||
|
||||
ui32ComponentMasks = *pui32Tokens++;
|
||||
psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F;
|
||||
//Shows which components are NEVER written.
|
||||
psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8;
|
||||
psCurrentSignature->iRebase = MaskToRebaseOffset(psCurrentSignature->ui32Mask);
|
||||
psCurrentSignature->iRebase = MaskToRebaseOffset(psCurrentSignature->ui32Mask);
|
||||
|
||||
if(minPrec)
|
||||
psCurrentSignature->eMinPrec = (MIN_PRECISION)*pui32Tokens++;
|
||||
if (minPrec)
|
||||
psCurrentSignature->eMinPrec = (MIN_PRECISION)*pui32Tokens++;
|
||||
|
||||
psCurrentSignature->semanticName = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset));
|
||||
psCurrentSignature->semanticName = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset));
|
||||
}
|
||||
}
|
||||
|
||||
static void ReadPatchConstantSignatures(const uint32_t* pui32Tokens,
|
||||
ShaderInfo* psShaderInfo,
|
||||
const int minPrec,
|
||||
const int streams)
|
||||
ShaderInfo* psShaderInfo,
|
||||
const int minPrec,
|
||||
const int streams)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
@ -153,94 +152,101 @@ static void ReadPatchConstantSignatures(const uint32_t* pui32Tokens,
|
||||
const uint32_t ui32ElementCount = *pui32Tokens++;
|
||||
/*const uint32_t ui32Key = * */ pui32Tokens++;
|
||||
|
||||
psShaderInfo->psPatchConstantSignatures.clear();
|
||||
psShaderInfo->psPatchConstantSignatures.resize(ui32ElementCount);
|
||||
psShaderInfo->psPatchConstantSignatures.clear();
|
||||
psShaderInfo->psPatchConstantSignatures.resize(ui32ElementCount);
|
||||
|
||||
for(i=0; i<ui32ElementCount; ++i)
|
||||
for (i = 0; i < ui32ElementCount; ++i)
|
||||
{
|
||||
uint32_t ui32ComponentMasks;
|
||||
ShaderInfo::InOutSignature* psCurrentSignature = &psShaderInfo->psPatchConstantSignatures[i];
|
||||
ShaderInfo::InOutSignature* psCurrentSignature = &psShaderInfo->psPatchConstantSignatures[i];
|
||||
uint32_t ui32SemanticNameOffset;
|
||||
|
||||
psCurrentSignature->ui32Stream = 0;
|
||||
psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT;
|
||||
psCurrentSignature->ui32Stream = 0;
|
||||
psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT;
|
||||
|
||||
if(streams)
|
||||
psCurrentSignature->ui32Stream = *pui32Tokens++;
|
||||
if (streams)
|
||||
psCurrentSignature->ui32Stream = *pui32Tokens++;
|
||||
|
||||
ui32SemanticNameOffset = *pui32Tokens++;
|
||||
ui32SemanticNameOffset = *pui32Tokens++;
|
||||
psCurrentSignature->ui32SemanticIndex = *pui32Tokens++;
|
||||
psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++;
|
||||
psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++;
|
||||
psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE)*pui32Tokens++;
|
||||
psCurrentSignature->ui32Register = *pui32Tokens++;
|
||||
|
||||
// Massage some special inputs/outputs to match the types of GLSL counterparts
|
||||
if (psCurrentSignature->eSystemValueType == NAME_RENDER_TARGET_ARRAY_INDEX)
|
||||
{
|
||||
psCurrentSignature->eComponentType = INOUT_COMPONENT_SINT32;
|
||||
}
|
||||
// Massage some special inputs/outputs to match the types of GLSL counterparts
|
||||
if (psCurrentSignature->eSystemValueType == NAME_RENDER_TARGET_ARRAY_INDEX)
|
||||
{
|
||||
psCurrentSignature->eComponentType = INOUT_COMPONENT_SINT32;
|
||||
}
|
||||
|
||||
ui32ComponentMasks = *pui32Tokens++;
|
||||
psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F;
|
||||
//Shows which components are NEVER written.
|
||||
psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8;
|
||||
psCurrentSignature->iRebase = MaskToRebaseOffset(psCurrentSignature->ui32Mask);
|
||||
psCurrentSignature->iRebase = MaskToRebaseOffset(psCurrentSignature->ui32Mask);
|
||||
|
||||
if(minPrec)
|
||||
psCurrentSignature->eMinPrec = (MIN_PRECISION)*pui32Tokens++;
|
||||
if (minPrec)
|
||||
psCurrentSignature->eMinPrec = (MIN_PRECISION)*pui32Tokens++;
|
||||
|
||||
psCurrentSignature->semanticName = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset));
|
||||
psCurrentSignature->semanticName = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset));
|
||||
}
|
||||
}
|
||||
|
||||
static const uint32_t* ReadResourceBinding(const uint32_t* pui32FirstResourceToken, const uint32_t* pui32Tokens, ResourceBinding* psBinding, uint32_t decodeFlags)
|
||||
static const uint32_t* ReadResourceBinding(ShaderInfo* psShaderInfo, const uint32_t* pui32FirstResourceToken, const uint32_t* pui32Tokens, ResourceBinding* psBinding, uint32_t decodeFlags)
|
||||
{
|
||||
uint32_t ui32NameOffset = *pui32Tokens++;
|
||||
|
||||
psBinding->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstResourceToken+ui32NameOffset));
|
||||
psBinding->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstResourceToken + ui32NameOffset));
|
||||
FormatVariableName(psBinding->name);
|
||||
|
||||
psBinding->eType = (ResourceType)*pui32Tokens++;
|
||||
psBinding->eType = (ResourceType) * pui32Tokens++;
|
||||
psBinding->ui32ReturnType = (RESOURCE_RETURN_TYPE)*pui32Tokens++;
|
||||
psBinding->eDimension = (REFLECT_RESOURCE_DIMENSION)*pui32Tokens++;
|
||||
psBinding->ui32NumSamples = *pui32Tokens++;
|
||||
psBinding->ui32NumSamples = *pui32Tokens++; // fxc generates 2^32 - 1 for non MS images
|
||||
psBinding->ui32BindPoint = *pui32Tokens++;
|
||||
psBinding->ui32BindCount = *pui32Tokens++;
|
||||
psBinding->ui32Flags = *pui32Tokens++;
|
||||
psBinding->ePrecision = REFLECT_RESOURCE_PRECISION_UNKNOWN;
|
||||
if (((psShaderInfo->ui32MajorVersion >= 5) && (psShaderInfo->ui32MinorVersion >= 1)) ||
|
||||
(psShaderInfo->ui32MajorVersion > 5))
|
||||
{
|
||||
psBinding->ui32Space = *pui32Tokens++;
|
||||
psBinding->ui32RangeID = *pui32Tokens++;
|
||||
}
|
||||
|
||||
if (decodeFlags & HLSLCC_FLAG_SAMPLER_PRECISION_ENCODED_IN_NAME)
|
||||
{
|
||||
if (psBinding->name.rfind("_highp") == psBinding->name.length() - 6)
|
||||
{
|
||||
psBinding->ePrecision = REFLECT_RESOURCE_PRECISION_HIGHP;
|
||||
psBinding->name.resize(psBinding->name.length() - 6);
|
||||
}
|
||||
else if (psBinding->name.rfind("_mediump") == psBinding->name.length() - 8)
|
||||
{
|
||||
psBinding->ePrecision = REFLECT_RESOURCE_PRECISION_MEDIUMP;
|
||||
psBinding->name.resize(psBinding->name.length() - 8);
|
||||
}
|
||||
else if (psBinding->name.rfind("_lowp") == psBinding->name.length() - 5)
|
||||
{
|
||||
psBinding->ePrecision = REFLECT_RESOURCE_PRECISION_LOWP;
|
||||
psBinding->name.resize(psBinding->name.length() - 5);
|
||||
}
|
||||
}
|
||||
psBinding->ePrecision = REFLECT_RESOURCE_PRECISION_UNKNOWN;
|
||||
|
||||
if (decodeFlags & HLSLCC_FLAG_SAMPLER_PRECISION_ENCODED_IN_NAME)
|
||||
{
|
||||
if (psBinding->name.rfind("_highp") == psBinding->name.length() - 6)
|
||||
{
|
||||
psBinding->ePrecision = REFLECT_RESOURCE_PRECISION_HIGHP;
|
||||
psBinding->name.resize(psBinding->name.length() - 6);
|
||||
}
|
||||
else if (psBinding->name.rfind("_mediump") == psBinding->name.length() - 8)
|
||||
{
|
||||
psBinding->ePrecision = REFLECT_RESOURCE_PRECISION_MEDIUMP;
|
||||
psBinding->name.resize(psBinding->name.length() - 8);
|
||||
}
|
||||
else if (psBinding->name.rfind("_lowp") == psBinding->name.length() - 5)
|
||||
{
|
||||
psBinding->ePrecision = REFLECT_RESOURCE_PRECISION_LOWP;
|
||||
psBinding->name.resize(psBinding->name.length() - 5);
|
||||
}
|
||||
}
|
||||
|
||||
return pui32Tokens;
|
||||
}
|
||||
|
||||
//Read D3D11_SHADER_TYPE_DESC
|
||||
static void ReadShaderVariableType(const uint32_t ui32MajorVersion,
|
||||
const uint32_t* pui32FirstConstBufToken,
|
||||
const uint32_t* pui32tokens, ShaderVarType* varType)
|
||||
const uint32_t* pui32FirstConstBufToken,
|
||||
const uint32_t* pui32tokens, ShaderVarType* varType)
|
||||
{
|
||||
const uint16_t* pui16Tokens = (const uint16_t*) pui32tokens;
|
||||
const uint16_t* pui16Tokens = (const uint16_t*)pui32tokens;
|
||||
uint16_t ui32MemberCount;
|
||||
uint32_t ui32MemberOffset;
|
||||
const uint32_t* pui32MemberTokens;
|
||||
uint32_t i;
|
||||
const uint32_t* pui32MemberTokens;
|
||||
uint32_t i;
|
||||
|
||||
varType->Class = (SHADER_VARIABLE_CLASS)pui16Tokens[0];
|
||||
varType->Type = (SHADER_VARIABLE_TYPE)pui16Tokens[1];
|
||||
@ -249,41 +255,41 @@ static void ReadShaderVariableType(const uint32_t ui32MajorVersion,
|
||||
varType->Elements = pui16Tokens[4];
|
||||
|
||||
varType->MemberCount = ui32MemberCount = pui16Tokens[5];
|
||||
varType->Members.clear();
|
||||
varType->Members.clear();
|
||||
|
||||
if(varType->ParentCount)
|
||||
{
|
||||
// Add empty brackets for array parents. Indices are filled in later in the printing codes.
|
||||
if (varType->Parent->Elements > 1)
|
||||
varType->fullName = varType->Parent->fullName + "[]." + varType->name;
|
||||
else
|
||||
varType->fullName = varType->Parent->fullName + "." + varType->name;
|
||||
}
|
||||
if (varType->ParentCount)
|
||||
{
|
||||
// Add empty brackets for array parents. Indices are filled in later in the printing codes.
|
||||
if (varType->Parent->Elements > 1)
|
||||
varType->fullName = varType->Parent->fullName + "[]." + varType->name;
|
||||
else
|
||||
varType->fullName = varType->Parent->fullName + "." + varType->name;
|
||||
}
|
||||
|
||||
if(ui32MemberCount)
|
||||
{
|
||||
varType->Members.resize(ui32MemberCount);
|
||||
if (ui32MemberCount)
|
||||
{
|
||||
varType->Members.resize(ui32MemberCount);
|
||||
|
||||
ui32MemberOffset = pui32tokens[3];
|
||||
|
||||
pui32MemberTokens = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32MemberOffset);
|
||||
ui32MemberOffset = pui32tokens[3];
|
||||
|
||||
for(i=0; i< ui32MemberCount; ++i)
|
||||
{
|
||||
uint32_t ui32NameOffset = *pui32MemberTokens++;
|
||||
uint32_t ui32MemberTypeOffset = *pui32MemberTokens++;
|
||||
|
||||
varType->Members[i].Parent = varType;
|
||||
varType->Members[i].ParentCount = varType->ParentCount + 1;
|
||||
pui32MemberTokens = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32MemberOffset);
|
||||
|
||||
varType->Members[i].Offset = *pui32MemberTokens++;
|
||||
for (i = 0; i < ui32MemberCount; ++i)
|
||||
{
|
||||
uint32_t ui32NameOffset = *pui32MemberTokens++;
|
||||
uint32_t ui32MemberTypeOffset = *pui32MemberTokens++;
|
||||
|
||||
varType->Members[i].name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset));
|
||||
varType->Members[i].Parent = varType;
|
||||
varType->Members[i].ParentCount = varType->ParentCount + 1;
|
||||
|
||||
ReadShaderVariableType(ui32MajorVersion, pui32FirstConstBufToken,
|
||||
(const uint32_t*)((const char*)pui32FirstConstBufToken+ui32MemberTypeOffset), &varType->Members[i]);
|
||||
}
|
||||
}
|
||||
varType->Members[i].Offset = *pui32MemberTokens++;
|
||||
|
||||
varType->Members[i].name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset));
|
||||
|
||||
ReadShaderVariableType(ui32MajorVersion, pui32FirstConstBufToken,
|
||||
(const uint32_t*)((const char*)pui32FirstConstBufToken + ui32MemberTypeOffset), &varType->Members[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo,
|
||||
@ -293,15 +299,15 @@ static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo,
|
||||
uint32_t ui32NameOffset = *pui32Tokens++;
|
||||
uint32_t ui32VarCount = *pui32Tokens++;
|
||||
uint32_t ui32VarOffset = *pui32Tokens++;
|
||||
const uint32_t* pui32VarToken = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32VarOffset);
|
||||
const uint32_t* pui32VarToken = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32VarOffset);
|
||||
|
||||
psBuffer->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset));
|
||||
psBuffer->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset));
|
||||
FormatVariableName(psBuffer->name);
|
||||
|
||||
psBuffer->asVars.clear();
|
||||
psBuffer->asVars.resize(ui32VarCount);
|
||||
psBuffer->asVars.clear();
|
||||
psBuffer->asVars.resize(ui32VarCount);
|
||||
|
||||
for(i=0; i<ui32VarCount; ++i)
|
||||
for (i = 0; i < ui32VarCount; ++i)
|
||||
{
|
||||
//D3D11_SHADER_VARIABLE_DESC
|
||||
ShaderVar * const psVar = &psBuffer->asVars[i];
|
||||
@ -311,66 +317,66 @@ static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo,
|
||||
|
||||
ui32NameOffset = *pui32VarToken++;
|
||||
|
||||
psVar->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset));
|
||||
psVar->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset));
|
||||
FormatVariableName(psVar->name);
|
||||
|
||||
psVar->ui32StartOffset = *pui32VarToken++;
|
||||
psVar->ui32Size = *pui32VarToken++;
|
||||
|
||||
|
||||
//skip ui32Flags
|
||||
pui32VarToken++;
|
||||
|
||||
|
||||
ui32TypeOffset = *pui32VarToken++;
|
||||
|
||||
psVar->sType.name = psVar->name;
|
||||
psVar->sType.fullName = psVar->name;
|
||||
psVar->sType.Parent = 0;
|
||||
psVar->sType.ParentCount = 0;
|
||||
psVar->sType.Offset = 0;
|
||||
psVar->sType.m_IsUsed = false;
|
||||
psVar->sType.name = psVar->name;
|
||||
psVar->sType.fullName = psVar->name;
|
||||
psVar->sType.Parent = 0;
|
||||
psVar->sType.ParentCount = 0;
|
||||
psVar->sType.Offset = 0;
|
||||
psVar->sType.m_IsUsed = false;
|
||||
|
||||
ReadShaderVariableType(psShaderInfo->ui32MajorVersion, pui32FirstConstBufToken,
|
||||
(const uint32_t*)((const char*)pui32FirstConstBufToken+ui32TypeOffset), &psVar->sType);
|
||||
ReadShaderVariableType(psShaderInfo->ui32MajorVersion, pui32FirstConstBufToken,
|
||||
(const uint32_t*)((const char*)pui32FirstConstBufToken + ui32TypeOffset), &psVar->sType);
|
||||
|
||||
ui32DefaultValueOffset = *pui32VarToken++;
|
||||
|
||||
|
||||
if (psShaderInfo->ui32MajorVersion >= 5)
|
||||
{
|
||||
/*uint32_t StartTexture = * */pui32VarToken++;
|
||||
/*uint32_t TextureSize = * */pui32VarToken++;
|
||||
/*uint32_t StartSampler = * */pui32VarToken++;
|
||||
/*uint32_t SamplerSize = * */pui32VarToken++;
|
||||
}
|
||||
|
||||
psVar->haveDefaultValue = 0;
|
||||
|
||||
if(ui32DefaultValueOffset)
|
||||
if (psShaderInfo->ui32MajorVersion >= 5)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
const uint32_t ui32NumDefaultValues = psVar->ui32Size / 4;
|
||||
const uint32_t* pui32DefaultValToken = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32DefaultValueOffset);
|
||||
/*uint32_t StartTexture = * */ pui32VarToken++;
|
||||
/*uint32_t TextureSize = * */ pui32VarToken++;
|
||||
/*uint32_t StartSampler = * */ pui32VarToken++;
|
||||
/*uint32_t SamplerSize = * */ pui32VarToken++;
|
||||
}
|
||||
|
||||
//Always a sequence of 4-bytes at the moment.
|
||||
//bool const becomes 0 or 0xFFFFFFFF int, int & float are 4-bytes.
|
||||
ASSERT(psVar->ui32Size%4 == 0);
|
||||
psVar->haveDefaultValue = 0;
|
||||
|
||||
psVar->haveDefaultValue = 1;
|
||||
if (ui32DefaultValueOffset)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
const uint32_t ui32NumDefaultValues = psVar->ui32Size / 4;
|
||||
const uint32_t* pui32DefaultValToken = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32DefaultValueOffset);
|
||||
|
||||
psVar->pui32DefaultValues.clear();
|
||||
psVar->pui32DefaultValues.resize(psVar->ui32Size / 4);
|
||||
//Always a sequence of 4-bytes at the moment.
|
||||
//bool const becomes 0 or 0xFFFFFFFF int, int & float are 4-bytes.
|
||||
ASSERT(psVar->ui32Size % 4 == 0);
|
||||
|
||||
for(i=0; i<ui32NumDefaultValues;++i)
|
||||
{
|
||||
psVar->pui32DefaultValues[i] = pui32DefaultValToken[i];
|
||||
}
|
||||
psVar->haveDefaultValue = 1;
|
||||
|
||||
psVar->pui32DefaultValues.clear();
|
||||
psVar->pui32DefaultValues.resize(psVar->ui32Size / 4);
|
||||
|
||||
for (i = 0; i < ui32NumDefaultValues; ++i)
|
||||
{
|
||||
psVar->pui32DefaultValues[i] = pui32DefaultValToken[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
psBuffer->ui32TotalSizeInBytes = *pui32Tokens++;
|
||||
|
||||
|
||||
//skip ui32Flags
|
||||
pui32Tokens++;
|
||||
//skip ui32BufferType
|
||||
@ -381,8 +387,8 @@ static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo,
|
||||
}
|
||||
|
||||
static void ReadResources(const uint32_t* pui32Tokens,//in
|
||||
ShaderInfo* psShaderInfo, //out
|
||||
uint32_t decodeFlags)
|
||||
ShaderInfo* psShaderInfo, //out
|
||||
uint32_t decodeFlags)
|
||||
{
|
||||
ResourceBinding* psResBindings;
|
||||
ConstantBuffer* psConstantBuffers;
|
||||
@ -391,7 +397,7 @@ static void ReadResources(const uint32_t* pui32Tokens,//in
|
||||
const uint32_t* pui32FirstToken = pui32Tokens;
|
||||
uint32_t i;
|
||||
|
||||
const uint32_t ui32NumConstantBuffers = *pui32Tokens++;
|
||||
const uint32_t ui32NumConstantBuffers = *pui32Tokens++;
|
||||
const uint32_t ui32ConstantBufferOffset = *pui32Tokens++;
|
||||
|
||||
uint32_t ui32NumResourceBindings = *pui32Tokens++;
|
||||
@ -402,63 +408,63 @@ static void ReadResources(const uint32_t* pui32Tokens,//in
|
||||
//Resources
|
||||
pui32ResourceBindings = (const uint32_t*)((const char*)pui32FirstToken + ui32ResourceBindingOffset);
|
||||
|
||||
psShaderInfo->psResourceBindings.clear();
|
||||
psShaderInfo->psResourceBindings.resize(ui32NumResourceBindings);
|
||||
psResBindings = ui32NumResourceBindings == 0 ? NULL : &psShaderInfo->psResourceBindings[0];
|
||||
psShaderInfo->psResourceBindings.clear();
|
||||
psShaderInfo->psResourceBindings.resize(ui32NumResourceBindings);
|
||||
psResBindings = ui32NumResourceBindings == 0 ? NULL : &psShaderInfo->psResourceBindings[0];
|
||||
|
||||
for(i=0; i < ui32NumResourceBindings; ++i)
|
||||
for (i = 0; i < ui32NumResourceBindings; ++i)
|
||||
{
|
||||
pui32ResourceBindings = ReadResourceBinding(pui32FirstToken, pui32ResourceBindings, psResBindings+i, decodeFlags);
|
||||
ASSERT(psResBindings[i].ui32BindPoint < MAX_RESOURCE_BINDINGS);
|
||||
}
|
||||
pui32ResourceBindings = ReadResourceBinding(psShaderInfo, pui32FirstToken, pui32ResourceBindings, psResBindings + i, decodeFlags);
|
||||
ASSERT(psResBindings[i].ui32BindPoint < MAX_RESOURCE_BINDINGS);
|
||||
}
|
||||
|
||||
//Constant buffers
|
||||
pui32ConstantBuffers = (const uint32_t*)((const char*)pui32FirstToken + ui32ConstantBufferOffset);
|
||||
|
||||
psShaderInfo->psConstantBuffers.clear();
|
||||
psShaderInfo->psConstantBuffers.resize(ui32NumConstantBuffers);
|
||||
psConstantBuffers = ui32NumConstantBuffers == 0 ? NULL : &psShaderInfo->psConstantBuffers[0];
|
||||
psShaderInfo->psConstantBuffers.clear();
|
||||
psShaderInfo->psConstantBuffers.resize(ui32NumConstantBuffers);
|
||||
psConstantBuffers = ui32NumConstantBuffers == 0 ? NULL : &psShaderInfo->psConstantBuffers[0];
|
||||
|
||||
for(i=0; i < ui32NumConstantBuffers; ++i)
|
||||
for (i = 0; i < ui32NumConstantBuffers; ++i)
|
||||
{
|
||||
pui32ConstantBuffers = ReadConstantBuffer(psShaderInfo, pui32FirstToken, pui32ConstantBuffers, psConstantBuffers+i);
|
||||
pui32ConstantBuffers = ReadConstantBuffer(psShaderInfo, pui32FirstToken, pui32ConstantBuffers, psConstantBuffers + i);
|
||||
}
|
||||
|
||||
|
||||
//Map resource bindings to constant buffers
|
||||
if(psShaderInfo->psConstantBuffers.size())
|
||||
{
|
||||
for(i=0; i < ui32NumResourceBindings; ++i)
|
||||
{
|
||||
ResourceGroup eRGroup;
|
||||
uint32_t cbufIndex = 0;
|
||||
//Map resource bindings to constant buffers
|
||||
if (psShaderInfo->psConstantBuffers.size())
|
||||
{
|
||||
for (i = 0; i < ui32NumResourceBindings; ++i)
|
||||
{
|
||||
ResourceGroup eRGroup;
|
||||
uint32_t cbufIndex = 0;
|
||||
|
||||
eRGroup = ShaderInfo::ResourceTypeToResourceGroup(psResBindings[i].eType);
|
||||
eRGroup = ShaderInfo::ResourceTypeToResourceGroup(psResBindings[i].eType);
|
||||
|
||||
//Find the constant buffer whose name matches the resource at the given resource binding point
|
||||
for(cbufIndex=0; cbufIndex < psShaderInfo->psConstantBuffers.size(); cbufIndex++)
|
||||
{
|
||||
if(psConstantBuffers[cbufIndex].name == psResBindings[i].name)
|
||||
{
|
||||
psShaderInfo->aui32ResourceMap[eRGroup][psResBindings[i].ui32BindPoint] = cbufIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Find the constant buffer whose name matches the resource at the given resource binding point
|
||||
for (cbufIndex = 0; cbufIndex < psShaderInfo->psConstantBuffers.size(); cbufIndex++)
|
||||
{
|
||||
if (psConstantBuffers[cbufIndex].name == psResBindings[i].name)
|
||||
{
|
||||
psShaderInfo->aui32ResourceMap[eRGroup][psResBindings[i].ui32BindPoint] = cbufIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const uint16_t* ReadClassType(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassType* psClassType)
|
||||
{
|
||||
const uint32_t* pui32Tokens = (const uint32_t*)pui16Tokens;
|
||||
uint32_t ui32NameOffset = *pui32Tokens;
|
||||
pui16Tokens+= 2;
|
||||
pui16Tokens += 2;
|
||||
|
||||
psClassType->ui16ID = *pui16Tokens++;
|
||||
psClassType->ui16ConstBufStride = *pui16Tokens++;
|
||||
psClassType->ui16Texture = *pui16Tokens++;
|
||||
psClassType->ui16Sampler = *pui16Tokens++;
|
||||
|
||||
psClassType->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32NameOffset));
|
||||
psClassType->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32NameOffset));
|
||||
|
||||
return pui16Tokens;
|
||||
}
|
||||
@ -474,14 +480,13 @@ static const uint16_t* ReadClassInstance(const uint32_t* pui32FirstInterfaceToke
|
||||
psClassInstance->ui16Texture = *pui16Tokens++;
|
||||
psClassInstance->ui16Sampler = *pui16Tokens++;
|
||||
|
||||
psClassInstance->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32NameOffset));
|
||||
psClassInstance->name = ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32NameOffset));
|
||||
|
||||
return pui16Tokens;
|
||||
}
|
||||
|
||||
|
||||
static void ReadInterfaces(const uint32_t* pui32Tokens,
|
||||
ShaderInfo* psShaderInfo)
|
||||
ShaderInfo* psShaderInfo)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t ui32StartSlot;
|
||||
@ -503,64 +508,63 @@ static void ReadInterfaces(const uint32_t* pui32Tokens,
|
||||
ClassType* psClassTypes;
|
||||
ClassInstance* psClassInstances;
|
||||
|
||||
psShaderInfo->psClassTypes.clear();
|
||||
psShaderInfo->psClassTypes.resize(ui32ClassTypeCount);
|
||||
psClassTypes = &psShaderInfo->psClassTypes[0];
|
||||
psShaderInfo->psClassTypes.clear();
|
||||
psShaderInfo->psClassTypes.resize(ui32ClassTypeCount);
|
||||
psClassTypes = &psShaderInfo->psClassTypes[0];
|
||||
|
||||
for(i=0; i<ui32ClassTypeCount; ++i)
|
||||
for (i = 0; i < ui32ClassTypeCount; ++i)
|
||||
{
|
||||
pui16ClassTypes = ReadClassType(pui32FirstInterfaceToken, pui16ClassTypes, psClassTypes+i);
|
||||
pui16ClassTypes = ReadClassType(pui32FirstInterfaceToken, pui16ClassTypes, psClassTypes + i);
|
||||
psClassTypes[i].ui16ID = (uint16_t)i;
|
||||
}
|
||||
|
||||
psShaderInfo->psClassInstances.clear();
|
||||
psShaderInfo->psClassInstances.resize(ui32ClassInstanceCount);
|
||||
psClassInstances = &psShaderInfo->psClassInstances[0];
|
||||
psShaderInfo->psClassInstances.clear();
|
||||
psShaderInfo->psClassInstances.resize(ui32ClassInstanceCount);
|
||||
psClassInstances = &psShaderInfo->psClassInstances[0];
|
||||
|
||||
for(i=0; i<ui32ClassInstanceCount; ++i)
|
||||
for (i = 0; i < ui32ClassInstanceCount; ++i)
|
||||
{
|
||||
pui16ClassInstances = ReadClassInstance(pui32FirstInterfaceToken, pui16ClassInstances, psClassInstances+i);
|
||||
pui16ClassInstances = ReadClassInstance(pui32FirstInterfaceToken, pui16ClassInstances, psClassInstances + i);
|
||||
}
|
||||
|
||||
//Slots map function table to $ThisPointer cbuffer variable index
|
||||
ui32StartSlot = 0;
|
||||
for(i=0; i<ui32InterfaceSlotRecordCount;++i)
|
||||
for (i = 0; i < ui32InterfaceSlotRecordCount; ++i)
|
||||
{
|
||||
uint32_t k;
|
||||
|
||||
|
||||
const uint32_t ui32SlotSpan = *pui32InterfaceSlotTokens++;
|
||||
const uint32_t ui32Count = *pui32InterfaceSlotTokens++;
|
||||
const uint32_t ui32TypeIDOffset = *pui32InterfaceSlotTokens++;
|
||||
const uint32_t ui32TableIDOffset = *pui32InterfaceSlotTokens++;
|
||||
|
||||
const uint16_t* pui16TypeID = (const uint16_t*)((const char*)pui32FirstInterfaceToken+ui32TypeIDOffset);
|
||||
const uint32_t* pui32TableID = (const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32TableIDOffset);
|
||||
const uint16_t* pui16TypeID = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32TypeIDOffset);
|
||||
const uint32_t* pui32TableID = (const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32TableIDOffset);
|
||||
|
||||
for(k=0; k < ui32Count; ++k)
|
||||
for (k = 0; k < ui32Count; ++k)
|
||||
{
|
||||
psShaderInfo->aui32TableIDToTypeID[*pui32TableID++] = *pui16TypeID++;
|
||||
}
|
||||
|
||||
ui32StartSlot += ui32SlotSpan;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LoadShaderInfo(const uint32_t ui32MajorVersion,
|
||||
const uint32_t ui32MinorVersion,
|
||||
const ReflectionChunks* psChunks,
|
||||
ShaderInfo* psInfo,
|
||||
uint32_t decodeFlags)
|
||||
uint32_t decodeFlags)
|
||||
{
|
||||
const uint32_t* pui32Inputs = psChunks->pui32Inputs;
|
||||
const uint32_t* pui32Inputs11 = psChunks->pui32Inputs11;
|
||||
const uint32_t* pui32Inputs11 = psChunks->pui32Inputs11;
|
||||
const uint32_t* pui32Resources = psChunks->pui32Resources;
|
||||
const uint32_t* pui32Interfaces = psChunks->pui32Interfaces;
|
||||
const uint32_t* pui32Outputs = psChunks->pui32Outputs;
|
||||
const uint32_t* pui32Outputs11 = psChunks->pui32Outputs11;
|
||||
const uint32_t* pui32OutputsWithStreams = psChunks->pui32OutputsWithStreams;
|
||||
const uint32_t* pui32PatchConstants = psChunks->pui32PatchConstants;
|
||||
const uint32_t* pui32PatchConstants11 = psChunks->pui32PatchConstants11;
|
||||
const uint32_t* pui32Outputs11 = psChunks->pui32Outputs11;
|
||||
const uint32_t* pui32OutputsWithStreams = psChunks->pui32OutputsWithStreams;
|
||||
const uint32_t* pui32PatchConstants = psChunks->pui32PatchConstants;
|
||||
const uint32_t* pui32PatchConstants11 = psChunks->pui32PatchConstants11;
|
||||
|
||||
psInfo->eTessOutPrim = TESSELLATOR_OUTPUT_UNDEFINED;
|
||||
psInfo->eTessPartitioning = TESSELLATOR_PARTITIONING_UNDEFINED;
|
||||
@ -573,34 +577,33 @@ void LoadShaderInfo(const uint32_t ui32MajorVersion,
|
||||
psInfo->ui32MinorVersion = ui32MinorVersion;
|
||||
|
||||
|
||||
if(pui32Inputs)
|
||||
if (pui32Inputs)
|
||||
ReadInputSignatures(pui32Inputs, psInfo, 0);
|
||||
if(pui32Inputs11)
|
||||
if (pui32Inputs11)
|
||||
ReadInputSignatures(pui32Inputs11, psInfo, 1);
|
||||
if(pui32Resources)
|
||||
if (pui32Resources)
|
||||
ReadResources(pui32Resources, psInfo, decodeFlags);
|
||||
if(pui32Interfaces)
|
||||
if (pui32Interfaces)
|
||||
ReadInterfaces(pui32Interfaces, psInfo);
|
||||
if(pui32Outputs)
|
||||
if (pui32Outputs)
|
||||
ReadOutputSignatures(pui32Outputs, psInfo, 0, 0);
|
||||
if(pui32Outputs11)
|
||||
if (pui32Outputs11)
|
||||
ReadOutputSignatures(pui32Outputs11, psInfo, 1, 1);
|
||||
if(pui32OutputsWithStreams)
|
||||
ReadOutputSignatures(pui32OutputsWithStreams, psInfo, 0, 1);
|
||||
if(pui32PatchConstants)
|
||||
ReadPatchConstantSignatures(pui32PatchConstants, psInfo, 0, 0);
|
||||
if (pui32PatchConstants11)
|
||||
ReadPatchConstantSignatures(pui32PatchConstants11, psInfo, 1, 1);
|
||||
if (pui32OutputsWithStreams)
|
||||
ReadOutputSignatures(pui32OutputsWithStreams, psInfo, 0, 1);
|
||||
if (pui32PatchConstants)
|
||||
ReadPatchConstantSignatures(pui32PatchConstants, psInfo, 0, 0);
|
||||
if (pui32PatchConstants11)
|
||||
ReadPatchConstantSignatures(pui32PatchConstants11, psInfo, 1, 1);
|
||||
|
||||
{
|
||||
uint32_t i;
|
||||
for(i=0; i<psInfo->psConstantBuffers.size();++i)
|
||||
for (i = 0; i < psInfo->psConstantBuffers.size(); ++i)
|
||||
{
|
||||
if (psInfo->psConstantBuffers[i].name == "$ThisPointer")
|
||||
if (psInfo->psConstantBuffers[i].name == "$ThisPointer")
|
||||
{
|
||||
psInfo->psThisPointerConstBuffer = &psInfo->psConstantBuffers[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1731
src/toGLSL.cpp
1731
src/toGLSL.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1417
src/toMetal.cpp
1417
src/toMetal.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user