44#include < string>
55#include < vector>
66#include < map>
7+ #include < algorithm>
78
89#if defined (_WIN32) && defined(HLSLCC_DYNLIB)
910 #define HLSLCC_APIENTRY __stdcall
@@ -48,6 +49,7 @@ typedef struct GlExtensions {
4849} GlExtensions;
4950
5051#include " ShaderInfo.h"
52+ #include " UnityInstancingFlexibleArraySize.h"
5153
5254typedef std::vector<std::string> TextureSamplerPairs;
5355
@@ -123,6 +125,88 @@ typedef enum
123125// Using a texture or uniform name like this will cause conflicts
124126#define HLSLCC_TEMP_PREFIX " u_xlat"
125127
128+ typedef std::vector<std::pair<std::string, std::string>> MemberDefinitions;
129+
130+ // We store struct definition contents inside a vector of strings
131+ struct StructDefinition
132+ {
133+ StructDefinition () : m_Members(), m_Dependencies(), m_IsPrinted(false ) {}
134+
135+ MemberDefinitions m_Members; // A vector of strings with the struct members
136+ std::vector<std::string> m_Dependencies; // A vector of struct names this struct depends on.
137+ bool m_IsPrinted; // Has this struct been printed out yet?
138+ };
139+
140+ typedef std::map<std::string, StructDefinition> StructDefinitions;
141+
142+ // Map of extra function definitions we need to add before the shader body but after the declarations.
143+ typedef std::map<std::string, std::string> FunctionDefinitions;
144+
145+ // A helper class for allocating binding slots
146+ // (because both UAVs and textures use the same slots in Metal, also constant buffers and other buffers etc)
147+ class BindingSlotAllocator
148+ {
149+ typedef std::map<uint32_t , uint32_t > SlotMap;
150+ SlotMap m_Allocations;
151+ uint32_t m_ShaderStageAllocations;
152+ public:
153+ BindingSlotAllocator () : m_Allocations(), m_ShaderStageAllocations(0 )
154+ {
155+ for (int i = MAX_RESOURCE_BINDINGS-1 ; i >= 0 ; i --)
156+ m_FreeSlots.push_back (i);
157+ }
158+
159+ enum BindType
160+ {
161+ ConstantBuffer = 0 ,
162+ RWBuffer,
163+ Texture,
164+ UAV
165+ };
166+
167+ uint32_t GetBindingSlot (uint32_t regNo, BindType type)
168+ {
169+ // The key is regNumber with the bindtype stored to highest 16 bits
170+ uint32_t key = (m_ShaderStageAllocations + regNo) | (uint32_t (type) << 16 );
171+ SlotMap::iterator itr = m_Allocations.find (key);
172+ if (itr == m_Allocations.end ())
173+ {
174+ uint32_t slot = m_FreeSlots.back ();
175+ m_FreeSlots.pop_back ();
176+ m_Allocations.insert (std::make_pair (key, slot));
177+ return slot;
178+ }
179+ return itr->second ;
180+ }
181+
182+ // Func for reserving binding slots with the original reg number.
183+ // Used for fragment shader UAVs (SetRandomWriteTarget etc).
184+ void ReserveBindingSlot (uint32_t regNo, BindType type)
185+ {
186+ uint32_t key = regNo | (uint32_t (type) << 16 );
187+ m_Allocations.insert (std::make_pair (key, regNo));
188+
189+ // Remove regNo from free slots
190+ for (int i = m_FreeSlots.size () - 1 ; i >= 0 ; i--)
191+ {
192+ if (m_FreeSlots[i] == regNo)
193+ {
194+ m_FreeSlots.erase (m_FreeSlots.begin () + i);
195+ return ;
196+ }
197+ }
198+ }
199+
200+ uint32_t SaveTotalShaderStageAllocationsCount ()
201+ {
202+ m_ShaderStageAllocations = m_Allocations.size ();
203+ return m_ShaderStageAllocations;
204+ }
205+
206+ private:
207+ std::vector<uint32_t > m_FreeSlots;
208+ };
209+
126210// The shader stages (Vertex, Pixel et al) do not depend on each other
127211// in HLSL. GLSL is a different story. HLSLCrossCompiler requires
128212// that hull shaders must be compiled before domain shaders, and
@@ -207,6 +291,10 @@ class GLSLCrossDependencyData
207291 GLSLCrossDependencyData ()
208292 : eTessPartitioning(),
209293 eTessOutPrim (),
294+ fMaxTessFactor(64.0 ),
295+ numPatchesInThreadGroup(0 ),
296+ hasControlPoint(false ),
297+ hasPatchConstant(false ),
210298 ui32ProgramStages(0 ),
211299 m_ExtBlendModes(),
212300 m_NextSpecID(0 )
@@ -290,6 +378,10 @@ class GLSLCrossDependencyData
290378 // can be saved when compiling hull and passed to domain compilation.
291379 TESSELLATOR_PARTITIONING eTessPartitioning;
292380 TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim;
381+ float fMaxTessFactor ;
382+ int numPatchesInThreadGroup;
383+ bool hasControlPoint;
384+ bool hasPatchConstant;
293385
294386 // Bitfield for the shader stages this program is going to include (see PS_FLAG_*).
295387 // Needed so we can construct proper shader input and output names
@@ -313,6 +405,28 @@ class GLSLCrossDependencyData
313405 pixelInterpolation[regNo] = mode;
314406 }
315407
408+ struct CompareFirst
409+ {
410+ CompareFirst (std::string val) : m_Val (val) {}
411+ bool operator ()(const std::pair<std::string, std::string>& elem) const
412+ {
413+ return m_Val == elem.first ;
414+ }
415+ private:
416+ std::string m_Val;
417+ };
418+
419+ inline bool IsMemberDeclared (const std::string &name)
420+ {
421+ if (std::find_if (m_SharedFunctionMembers.begin (), m_SharedFunctionMembers.end (), CompareFirst (name)) != m_SharedFunctionMembers.end ())
422+ return true ;
423+ return false ;
424+ }
425+
426+ MemberDefinitions m_SharedFunctionMembers;
427+ BindingSlotAllocator m_SharedTextureSlots, m_SharedSamplerSlots;
428+ BindingSlotAllocator m_SharedBufferSlots;
429+
316430 inline void ClearCrossDependencyData ()
317431 {
318432 pixelInterpolation.clear ();
@@ -321,8 +435,9 @@ class GLSLCrossDependencyData
321435 varyingLocationsMap[i].clear ();
322436 nextAvailableVaryingLocation[i] = 0 ;
323437 }
324- m_NextSpecID = 0 ;
438+ m_NextSpecID = kArraySizeConstantID + 1 ;
325439 m_SpecConstantMap.clear ();
440+ m_SharedFunctionMembers.clear ();
326441 }
327442
328443 // Retrieve or allocate a layout slot for Vulkan specialization constant
@@ -368,9 +483,11 @@ class HLSLccReflection
368483 virtual bool OnConstant (const std::string &name, int bindIndex, SHADER_VARIABLE_TYPE cType, int rows, int cols, bool isMatrix, int arraySize) { return true ; }
369484
370485 virtual void OnConstantBufferBinding (const std::string &name, int bindIndex) {}
371- virtual void OnTextureBinding (const std::string &name, int bindIndex, int samplerIndex, HLSLCC_TEX_DIMENSION dim, bool isUAV) {}
486+ virtual void OnTextureBinding (const std::string &name, int bindIndex, int samplerIndex, bool multisampled, HLSLCC_TEX_DIMENSION dim, bool isUAV) {}
372487 virtual void OnBufferBinding (const std::string &name, int bindIndex, bool isUAV) {}
373488 virtual void OnThreadGroupSize (unsigned int xSize, unsigned int ySize, unsigned int zSize) {}
489+ virtual void OnTessellationInfo (uint32_t tessPartitionMode, uint32_t tessOutputWindingOrder, uint32_t tessMaxFactor, uint32_t tessNumPatchesInThreadGroup) {}
490+ virtual void OnTessellationKernelInfo (uint32_t patchKernelBufferCount) {}
374491};
375492
376493
@@ -460,6 +577,12 @@ static const unsigned int HLSLCC_FLAG_NVN_TARGET = 0x800000;
460577// as long as they are part of the same final linked program. Uniform buffer instance names solve this cross-shader symbol conflict issue.
461578static const unsigned int HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT_WITH_INSTANCE_NAME = 0x1000000 ;
462579
580+ // Massage shader steps into Metal compute kernel from vertex/hull shaders + post-tessellation vertex shader from domain shader
581+ static const unsigned int HLSLCC_FLAG_METAL_TESSELLATION = 0x2000000 ;
582+
583+ // Disable fastmath
584+ static const unsigned int HLSLCC_FLAG_DISABLE_FASTMATH = 0x4000000 ;
585+
463586#ifdef __cplusplus
464587extern " C" {
465588#endif
0 commit comments