HLSLcc/include/hlslcc.h
2020-09-23 14:10:02 -07:00

817 lines
30 KiB
C++

#ifndef HLSLCC_H_
#define HLSLCC_H_
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#if defined(_WIN32) && defined(HLSLCC_DYNLIB)
#define HLSLCC_APIENTRY __stdcall
#if defined(libHLSLcc_EXPORTS)
#define HLSLCC_API __declspec(dllexport)
#else
#define HLSLCC_API __declspec(dllimport)
#endif
#else
#define HLSLCC_APIENTRY
#define HLSLCC_API
#endif
#include <stdint.h>
#include <string.h>
typedef enum
{
LANG_DEFAULT,// Depends on the HLSL shader model.
LANG_ES_100, LANG_ES_FIRST = LANG_ES_100,
LANG_ES_300,
LANG_ES_310, LANG_ES_LAST = LANG_ES_310,
LANG_120, LANG_GL_FIRST = LANG_120,
LANG_130,
LANG_140,
LANG_150,
LANG_330,
LANG_400,
LANG_410,
LANG_420,
LANG_430,
LANG_440, LANG_GL_LAST = LANG_440,
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;
} GlExtensions;
#include "ShaderInfo.h"
#include "UnityInstancingFlexibleArraySize.h"
typedef std::vector<std::string> TextureSamplerPairs;
typedef enum INTERPOLATION_MODE
{
INTERPOLATION_UNDEFINED = 0,
INTERPOLATION_CONSTANT = 1,
INTERPOLATION_LINEAR = 2,
INTERPOLATION_LINEAR_CENTROID = 3,
INTERPOLATION_LINEAR_NOPERSPECTIVE = 4,
INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID = 5,
INTERPOLATION_LINEAR_SAMPLE = 6,
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_GEOMETRY_SHADER 0x8
#define PS_FLAG_PIXEL_SHADER 0x10
#define TO_FLAG_NONE 0x0
#define TO_FLAG_INTEGER 0x1
#define TO_FLAG_NAME_ONLY 0x2
#define TO_FLAG_DECLARATION_NAME 0x4
#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment.
#define TO_FLAG_UNSIGNED_INTEGER 0x10
#define TO_FLAG_DOUBLE 0x20
// --- TO_AUTO_BITCAST_TO_FLOAT ---
//If the operand is an integer temp variable then this flag
//indicates that the temp has a valid floating point encoding
//and that the current expression expects the operand to be floating point
//and therefore intBitsToFloat must be applied to that variable.
#define TO_AUTO_BITCAST_TO_FLOAT 0x40
#define TO_AUTO_BITCAST_TO_INT 0x80
#define TO_AUTO_BITCAST_TO_UINT 0x100
// AUTO_EXPAND flags automatically expand the operand to at least (i/u)vecX
// to match HLSL functionality.
#define TO_AUTO_EXPAND_TO_VEC2 0x200
#define TO_AUTO_EXPAND_TO_VEC3 0x400
#define TO_AUTO_EXPAND_TO_VEC4 0x800
#define TO_FLAG_BOOL 0x1000
// These flags are only used for Metal:
// Force downscaling of the operand to match
// the other operand (Metal doesn't like mixing halfs with floats)
#define TO_FLAG_FORCE_HALF 0x2000
typedef enum
{
INVALID_SHADER = -1,
PIXEL_SHADER,
VERTEX_SHADER,
GEOMETRY_SHADER,
HULL_SHADER,
DOMAIN_SHADER,
COMPUTE_SHADER,
} SHADER_TYPE;
// 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
} 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;
// We store struct definition contents inside a vector of strings
struct StructDefinition
{
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?
};
typedef std::map<std::string, StructDefinition> StructDefinitions;
// Map of extra function definitions we need to add before the shader body but after the declarations.
typedef std::map<std::string, std::string> FunctionDefinitions;
// A helper class for allocating binding slots
// (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;
public:
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
};
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));
// 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 PeekFirstFreeSlot() const
{
return m_FreeSlots.back();
}
uint32_t SaveTotalShaderStageAllocationsCount()
{
m_ShaderStageAllocations = m_Allocations.size();
return m_ShaderStageAllocations;
}
private:
std::vector<uint32_t> m_FreeSlots;
};
//The shader stages (Vertex, Pixel et al) do not depend on each other
//in HLSL. GLSL is a different story. HLSLCrossCompiler requires
//that hull shaders must be compiled before domain shaders, and
//the pixel shader must be compiled before all of the others.
//During compilation the GLSLCrossDependencyData struct will
//carry over any information needed about a different shader stage
//in order to construct valid GLSL shader combinations.
//Using GLSLCrossDependencyData is optional. However some shader
//combinations may show link failures, or runtime errors.
class GLSLCrossDependencyData
{
public:
struct GLSLBufferBindPointInfo
{
uint32_t slot;
bool known;
};
// A container for a single Vulkan resource binding (<set, binding> pair)
struct VulkanResourceBinding
{
uint32_t set;
uint32_t binding;
};
enum GLSLBufferType
{
BufferType_ReadWrite,
BufferType_Constant,
BufferType_SSBO,
BufferType_Texture,
BufferType_UBO,
BufferType_Count,
BufferType_Generic = BufferType_ReadWrite
};
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;
static const int MAX_NAMESPACES = 6; // Max namespaces: vert input, hull input, domain input, geom input, ps input, (ps output)
VaryingLocations varyingLocationsMap[MAX_NAMESPACES];
uint32_t nextAvailableVaryingLocation[MAX_NAMESPACES];
typedef std::map<std::string, VulkanResourceBinding> VulkanResourceBindings;
VulkanResourceBindings m_VulkanResourceBindings;
uint32_t m_NextAvailableVulkanResourceBinding[8]; // one per set.
typedef std::map<std::string, uint32_t> GLSLResouceBindings;
public:
GLSLResouceBindings m_GLSLResourceBindings;
uint32_t m_NextAvailableGLSLResourceBinding[BufferType_Count]; // UAV, Constant and Buffers have seperate binding ranges
uint32_t m_StructuredBufferBindPoints[MAX_RESOURCE_BINDINGS]; // for the old style bindings
inline int GetVaryingNamespace(SHADER_TYPE eShaderType, bool isInput)
{
switch (eShaderType)
{
case VERTEX_SHADER:
return isInput ? 0 : 1;
case HULL_SHADER:
return isInput ? 1 : 2;
case DOMAIN_SHADER:
return isInput ? 2 : 3;
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 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;
}
}
public:
GLSLCrossDependencyData()
: eTessPartitioning(),
eTessOutPrim(),
fMaxTessFactor(64.0),
numPatchesInThreadGroup(0),
hasControlPoint(false),
hasPatchConstant(false),
ui32ProgramStages(0),
m_ExtBlendModes()
{
memset(nextAvailableVaryingLocation, 0, sizeof(nextAvailableVaryingLocation));
memset(m_NextAvailableVulkanResourceBinding, 0, sizeof(m_NextAvailableVulkanResourceBinding));
memset(m_NextAvailableGLSLResourceBinding, 0, sizeof(m_NextAvailableGLSLResourceBinding));
}
// 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, bool keepLocation, uint32_t maxSemanticIndex)
{
int nspace = GetVaryingNamespace(eShaderType, isInput);
VaryingLocations::iterator itr = varyingLocationsMap[nspace].find(name);
if (itr != varyingLocationsMap[nspace].end())
return itr->second;
if (keepLocation)
{
// Try to generate consistent varying locations based on the semantic indices in the hlsl source, i.e "TEXCOORD11" gets assigned to layout(location = 11)
// Inspect last 2 characters in name
size_t len = name.length();
if (len > 1)
{
if (isdigit(name[len - 1]))
{
uint32_t index = 0;
if (isdigit(name[len - 2]))
index = atoi(&name[len - 2]); // 2-digits index
else
index = atoi(&name[len - 1]); // 1-digit index
if (index < 32) // Some platforms only allow 32 varying locations
{
// Check that index is not already used
bool canUseIndex = true;
for (VaryingLocations::iterator it = varyingLocationsMap[nspace].begin(); it != varyingLocationsMap[nspace].end(); ++it)
{
if (it->second == index)
{
canUseIndex = false;
break;
}
}
if (canUseIndex)
{
varyingLocationsMap[nspace].insert(std::make_pair(name, index));
return index;
}
}
}
}
// fallback: pick an unused index (max of already allocated AND of semanticIndices found by SignatureAnalysis
uint32_t maxIndexAlreadyAssigned = 0;
for (VaryingLocations::iterator it = varyingLocationsMap[nspace].begin(); it != varyingLocationsMap[nspace].end(); ++it)
maxIndexAlreadyAssigned = std::max(maxIndexAlreadyAssigned, it->second);
uint32_t fallbackIndex = std::max(maxIndexAlreadyAssigned + 1, maxSemanticIndex + 1);
varyingLocationsMap[nspace].insert(std::make_pair(name, fallbackIndex));
return fallbackIndex;
}
else
{
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 VulkanResourceBinding 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 = { Set, Binding };
m_VulkanResourceBindings.insert(std::make_pair(name, newBind));
if (allocRoomForCounter)
{
VulkanResourceBinding counterBind = { Set, Binding + 1 };
m_VulkanResourceBindings.insert(std::make_pair(name + "_counter", counterBind));
}
return newBind;
}
VulkanResourceBindings::iterator itr = m_VulkanResourceBindings.find(name);
if (itr != m_VulkanResourceBindings.end())
return itr->second;
// Allocate a new one
VulkanResourceBinding newBind = { preferredSet, m_NextAvailableVulkanResourceBinding[preferredSet] };
m_NextAvailableVulkanResourceBinding[preferredSet]++;
m_VulkanResourceBindings.insert(std::make_pair(name, newBind));
if (allocRoomForCounter)
{
VulkanResourceBinding counterBind = { preferredSet, m_NextAvailableVulkanResourceBinding[preferredSet] };
m_NextAvailableVulkanResourceBinding[preferredSet]++;
m_VulkanResourceBindings.insert(std::make_pair(name + "_counter", counterBind));
}
return newBind;
}
// GLSL Bind point handling logic
// Handles both 'old style' fill around fixed UAV and new style partitioned offsets with fixed UAV locations
// 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 m_structuredBufferBindPoints contain increasingly ordered uints starting from zero.
// This is only used when we are doing old style binding setup
void SetupGLSLResourceBindingSlotsIndices()
{
for (uint32_t i = 0; i < MAX_RESOURCE_BINDINGS; i++)
{
m_StructuredBufferBindPoints[i] = i;
}
}
void RemoveBindPointFromAvailableList(uint32_t bindPoint)
{
for (uint32_t i = 0; i < MAX_RESOURCE_BINDINGS - 1 && m_StructuredBufferBindPoints[i] <= bindPoint; i++)
{
if (m_StructuredBufferBindPoints[i] == bindPoint) // Remove uav binding point from the list by copying array remainder here
{
memcpy(&m_StructuredBufferBindPoints[i], &m_StructuredBufferBindPoints[i + 1], (MAX_RESOURCE_BINDINGS - 1 - i) * sizeof(uint32_t));
break;
}
}
}
void ReserveNamedBindPoint(const std::string &name, uint32_t bindPoint, GLSLBufferType type)
{
m_GLSLResourceBindings.insert(std::make_pair(name, bindPoint));
RemoveBindPointFromAvailableList(bindPoint);
}
bool ShouldUseBufferSpecificBinding(GLSLBufferType bufferType)
{
return bufferType == BufferType_Constant || bufferType == BufferType_Texture || bufferType == BufferType_UBO;
}
uint32_t GetGLSLBufferBindPointIndex(GLSLBufferType bufferType)
{
uint32_t binding = -1;
if (ShouldUseBufferSpecificBinding(bufferType))
{
binding = m_NextAvailableGLSLResourceBinding[bufferType];
}
else
{
binding = m_StructuredBufferBindPoints[m_NextAvailableGLSLResourceBinding[BufferType_Generic]];
}
return binding;
}
void UpdateResourceBindingIndex(GLSLBufferType bufferType)
{
if (ShouldUseBufferSpecificBinding(bufferType))
{
m_NextAvailableGLSLResourceBinding[bufferType]++;
}
else
{
m_NextAvailableGLSLResourceBinding[BufferType_Generic]++;
}
}
inline GLSLBufferBindPointInfo GetGLSLResourceBinding(const std::string &name, GLSLBufferType bufferType)
{
GLSLResouceBindings::iterator itr = m_GLSLResourceBindings.find(name);
if (itr != m_GLSLResourceBindings.end())
{
return GLSLBufferBindPointInfo{ itr->second, true };
}
uint32_t binding = GetGLSLBufferBindPointIndex(bufferType);
UpdateResourceBindingIndex(bufferType);
m_GLSLResourceBindings.insert(std::make_pair(name, binding));
return GLSLBufferBindPointInfo{ binding, false };
}
//dcl_tessellator_partitioning and dcl_tessellator_output_primitive appear in hull shader for D3D,
//but they appear on inputs inside domain shaders for GL.
//Hull shader must be compiled before domain so the
//ensure correct partitioning and primitive type information
//can be saved when compiling hull and passed to domain compilation.
TESSELLATOR_PARTITIONING eTessPartitioning;
TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim;
float fMaxTessFactor;
int numPatchesInThreadGroup;
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;
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];
}
inline void SetInterpolationMode(uint32_t regNo, INTERPOLATION_MODE mode)
{
if (regNo >= pixelInterpolation.size())
pixelInterpolation.resize((regNo + 1) * 2, INTERPOLATION_UNDEFINED);
pixelInterpolation[regNo] = mode;
}
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;
};
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;
}
MemberDefinitions m_SharedFunctionMembers;
std::vector<std::string> m_SharedDependencies;
BindingSlotAllocator m_SharedTextureSlots, m_SharedSamplerSlots;
BindingSlotAllocator m_SharedBufferSlots;
inline void ClearCrossDependencyData()
{
pixelInterpolation.clear();
for (int i = 0; i < MAX_NAMESPACES; i++)
{
varyingLocationsMap[i].clear();
nextAvailableVaryingLocation[i] = 0;
}
m_SharedFunctionMembers.clear();
m_SharedDependencies.clear();
}
bool IsHullShaderInputAlreadyDeclared(const std::string& name)
{
bool isKnown = false;
for (size_t idx = 0, end = m_hullShaderInputs.size(); idx < end; ++idx)
{
if (m_hullShaderInputs[idx] == name)
{
isKnown = true;
break;
}
}
return isKnown;
}
void RecordHullShaderInput(const std::string& name)
{
m_hullShaderInputs.push_back(name);
}
std::vector<std::string> m_hullShaderInputs;
};
struct GLSLShader
{
int shaderType; //One of the GL enums.
std::string sourceCode;
ShaderInfo reflection;
GLLang GLSLLanguage;
TextureSamplerPairs textureSamplers; // HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS fills this out
};
// Interface for retrieving reflection and diagnostics data
class HLSLccReflection
{
public:
HLSLccReflection() {}
virtual ~HLSLccReflection() {}
// 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) {}
// 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, 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) {}
// these are for now metal only (but can be trivially added for other backends if needed)
// they are useful mostly for diagnostics as interim values are actually hidden from user
virtual void OnVertexProgramOutput(const std::string& name, const std::string& semantic, int semanticIndex) {}
virtual void OnBuiltinOutput(SPECIAL_NAME name) {}
virtual void OnFragmentOutputDeclaration(int numComponents, int outputIndex) {}
enum AccessType
{
ReadAccess = 1 << 0,
WriteAccess = 1 << 1
};
virtual void OnStorageImage(int bindIndex, unsigned int access) {}
};
/*HLSL constant buffers are treated as default-block unform arrays by default. This is done
to support versions of GLSL which lack ARB_uniform_buffer_object functionality.
Setting this flag causes each one to have its own uniform block.
Note: Currently the nth const buffer will be named UnformBufferN. This is likey to change to the original HLSL name in the future.*/
static const unsigned int HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT = 0x1;
static const unsigned int HLSLCC_FLAG_ORIGIN_UPPER_LEFT = 0x2;
static const unsigned int HLSLCC_FLAG_PIXEL_CENTER_INTEGER = 0x4;
static const unsigned int HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO = 0x8;
//GS enabled?
//Affects vertex shader (i.e. need to compile vertex shader again to use with/without GS).
//This flag is needed in order for the interfaces between stages to match when GS is in use.
//PS inputs VtxGeoOutput
//GS outputs VtxGeoOutput
//Vs outputs VtxOutput if GS enabled. VtxGeoOutput otherwise.
static const unsigned int HLSLCC_FLAG_GS_ENABLED = 0x10;
static const unsigned int HLSLCC_FLAG_TESS_ENABLED = 0x20;
//Either use this flag or glBindFragDataLocationIndexed.
//When set the first pixel shader output is the first input to blend
//equation, the others go to the second input.
static const unsigned int HLSLCC_FLAG_DUAL_SOURCE_BLENDING = 0x40;
//If set, shader inputs and outputs are declared with their semantic name.
static const unsigned int HLSLCC_FLAG_INOUT_SEMANTIC_NAMES = 0x80;
//If set, shader inputs and outputs are declared with their semantic name appended.
static const unsigned int HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES = 0x100;
//If set, combines texture/sampler pairs used together into samplers named "texturename_X_samplername".
static const unsigned int HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS = 0x200;
//If set, attribute and uniform explicit location qualifiers are disabled (even if the language version supports that)
static const unsigned int HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS = 0x400;
//If set, global uniforms are not stored in a struct.
static const unsigned int HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT = 0x800;
//If set, image declarations will always have binding and format qualifiers.
static const unsigned int HLSLCC_FLAG_GLES31_IMAGE_QUALIFIERS = 0x1000;
// If set, treats sampler names ending with _highp, _mediump, and _lowp as sampler precision qualifiers
// Also removes that prefix from generated output
static const unsigned int HLSLCC_FLAG_SAMPLER_PRECISION_ENCODED_IN_NAME = 0x2000;
// If set, adds location qualifiers to intra-shader varyings.
static const unsigned int HLSLCC_FLAG_SEPARABLE_SHADER_OBJECTS = 0x4000; // NOTE: obsolete flag (behavior enabled by this flag began default in 83a16a1829cf)
// If set, wraps all uniform buffer declarations in a preprocessor macro #ifdef HLSLCC_ENABLE_UNIFORM_BUFFERS
// so that if that macro is undefined, all UBO declarations will become normal uniforms
static const unsigned int HLSLCC_FLAG_WRAP_UBO = 0x8000;
// If set, skips all members of the $Globals constant buffer struct that are not referenced in the shader code
static const unsigned int HLSLCC_FLAG_REMOVE_UNUSED_GLOBALS = 0x10000;
#define HLSLCC_TRANSLATE_MATRIX_FORMAT_STRING "hlslcc_mtx%dx%d"
// If set, translates all matrix declarations into vec4 arrays (as the DX bytecode treats them), and prefixes the name with 'hlslcc_mtx<rows>x<cols>'
static const unsigned int HLSLCC_FLAG_TRANSLATE_MATRICES = 0x20000;
// If set, emits Vulkan-style (set, binding) bindings, also captures that info from any declaration named "<Name>_hlslcc_set_X_bind_Y"
// Unless bindings are given explicitly, they are allocated into set 0 (map stored in GLSLCrossDependencyData)
static const unsigned int HLSLCC_FLAG_VULKAN_BINDINGS = 0x40000;
// If set, metal output will use linear sampler for shadow compares, otherwise point sampler.
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;
// Unused 0x200000;
// If set, this shader uses the GLSL extension EXT_shader_framebuffer_fetch
static const unsigned int HLSLCC_FLAG_SHADER_FRAMEBUFFER_FETCH = 0x400000;
// Build for Switch.
static const unsigned int HLSLCC_FLAG_NVN_TARGET = 0x800000;
// If set, generate an instance name for constant buffers. GLSL specs 4.5 disallows uniform variables from different constant buffers sharing the same name
// as long as they are part of the same final linked program. Uniform buffer instance names solve this cross-shader symbol conflict issue.
static const unsigned int HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT_WITH_INSTANCE_NAME = 0x1000000;
// Massage shader steps into Metal compute kernel from vertex/hull shaders + post-tessellation vertex shader from domain shader
static const unsigned int HLSLCC_FLAG_METAL_TESSELLATION = 0x2000000;
// Disable fastmath
static const unsigned int HLSLCC_FLAG_DISABLE_FASTMATH = 0x4000000;
//If set, uniform explicit location qualifiers are enabled (even if the language version doesn't support that)
static const unsigned int HLSLCC_FLAG_FORCE_EXPLICIT_LOCATIONS = 0x8000000;
// If set, each line of the generated source will be preceded by a comment specifying which DirectX bytecode instruction it maps to
static const unsigned int HLSLCC_FLAG_INCLUDE_INSTRUCTIONS_COMMENTS = 0x10000000;
// If set, try to generate consistent varying locations based on the semantic indices in the hlsl source, i.e "TEXCOORD11" gets assigned to layout(location = 11)
static const unsigned int HLSLCC_FLAG_KEEP_VARYING_LOCATIONS = 0x20000000;
// Code generation might vary for mobile targets, or using lower sampler precision than full by default
static const unsigned int HLSLCC_FLAG_MOBILE_TARGET = 0x40000000;
#ifdef __cplusplus
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
);
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);
#ifdef __cplusplus
}
#endif
#endif