Skip to content

Commit 1d91e68

Browse files
authored
Merge pull request #29 from Unity-Technologies/upstream
Pulled changes from internal unity repo at changeset 42ec4a54d7ca
2 parents e2d66dc + ab352e4 commit 1d91e68

17 files changed

+807
-523
lines changed

include/ShaderInfo.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,8 @@ class ShaderInfo
451451

452452
static ResourceGroup ResourceTypeToResourceGroup(ResourceType);
453453

454+
static uint32_t GetCBVarSize(const ShaderVarType* psType, bool matrixAsVectors, bool wholeArraySize = false);
455+
454456
static int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset,
455457
const uint32_t (&pui32Swizzle)[4],
456458
const ConstantBuffer* psCBuf,
@@ -460,7 +462,7 @@ class ShaderInfo
460462
int32_t* pi32Rebase,
461463
uint32_t flags);
462464

463-
static std::string GetShaderVarIndexedFullName(const ShaderVarType* psShaderVar, std::vector<uint32_t> &indices);
465+
static std::string GetShaderVarIndexedFullName(const ShaderVarType* psShaderVar, std::vector<uint32_t> &indices, const std::string dynamicIndex, bool revertDynamicIndexCalc, bool matrixAsVectors);
464466

465467
// Apply shader precision information to resource bindings
466468
void AddSamplerPrecisions(HLSLccSamplerPrecisionInfo &info);

include/hlslcc.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,15 +444,21 @@ static const unsigned int HLSLCC_FLAG_VULKAN_BINDINGS = 0x40000;
444444
// If set, metal output will use linear sampler for shadow compares, otherwise point sampler.
445445
static const unsigned int HLSLCC_FLAG_METAL_SHADOW_SAMPLER_LINEAR = 0x80000;
446446

447-
// If set, emits for NVN, the Nvidia-provided graphics API for Nintendo Switch.
448-
static const unsigned int HLSLCC_FLAG_NVN_TARGET = 0x100000;
447+
// If set, avoid emit atomic counter (ARB_shader_atomic_counters) and use atomic functions provided by ARB_shader_storage_buffer_object instead.
448+
static const unsigned int HLSLCC_FLAG_AVOID_SHADER_ATOMIC_COUNTERS = 0x100000;
449449

450450
// If set, and generating Vulkan shaders, attempts to detect static branching and transforms them into specialization constants
451451
static const unsigned int HLSLCC_FLAG_VULKAN_SPECIALIZATION_CONSTANTS = 0x200000;
452452

453453
// If set, this shader uses the GLSL extension EXT_shader_framebuffer_fetch
454454
static const unsigned int HLSLCC_FLAG_SHADER_FRAMEBUFFER_FETCH = 0x400000;
455455

456+
// Build for Switch.
457+
static const unsigned int HLSLCC_FLAG_NVN_TARGET = 0x800000;
458+
459+
// If set, generate an instance name for constant buffers. GLSL specs 4.5 disallows uniform variables from different constant buffers sharing the same name
460+
// as long as they are part of the same final linked program. Uniform buffer instance names solve this cross-shader symbol conflict issue.
461+
static const unsigned int HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT_WITH_INSTANCE_NAME = 0x1000000;
456462

457463
#ifdef __cplusplus
458464
extern "C" {

src/DataTypeAnalysis.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,6 @@ void HLSLcc::DataTypeAnalysis::SetDataTypes(HLSLCrossCompilerContext* psContext,
315315
MarkOperandAs(&psInst->asOperands[2], SVT_INT_AMBIGUOUS, aeTempVecType);
316316
break;
317317

318-
case OPCODE_AND:
319-
MarkOperandAs(&psInst->asOperands[0], SVT_INT_AMBIGUOUS, aeTempVecType);
320-
MarkOperandAs(&psInst->asOperands[1], SVT_BOOL, aeTempVecType);
321-
MarkOperandAs(&psInst->asOperands[2], SVT_BOOL, aeTempVecType);
322-
break;
323-
324-
325318
case OPCODE_IF:
326319
case OPCODE_BREAKC:
327320
case OPCODE_CALLC:
@@ -344,12 +337,18 @@ void HLSLcc::DataTypeAnalysis::SetDataTypes(HLSLCrossCompilerContext* psContext,
344337
MarkOperandAs(&psInst->asOperands[2], SVT_UINT, aeTempVecType);
345338
break;
346339

340+
case OPCODE_AND:
341+
case OPCODE_OR:
342+
MarkOperandAs(&psInst->asOperands[0], SVT_INT_AMBIGUOUS, aeTempVecType);
343+
MarkOperandAs(&psInst->asOperands[1], SVT_BOOL, aeTempVecType);
344+
MarkOperandAs(&psInst->asOperands[2], SVT_BOOL, aeTempVecType);
345+
break;
346+
347347
// Integer ops that don't care of signedness
348348
case OPCODE_IADD:
349349
case OPCODE_INEG:
350350
case OPCODE_ISHL:
351351
case OPCODE_NOT:
352-
case OPCODE_OR:
353352
case OPCODE_XOR:
354353
case OPCODE_BUFINFO:
355354
case OPCODE_COUNTBITS:
@@ -673,7 +672,9 @@ void HLSLcc::DataTypeAnalysis::SetDataTypes(HLSLCrossCompilerContext* psContext,
673672
}
674673
}
675674

676-
if (foundImmediate && dataType == SVT_VOID)
675+
// Use at minimum int type when any operand is immediate.
676+
// Allowing bool could lead into bugs like case 883080
677+
if (foundImmediate && (dataType == SVT_VOID || dataType == SVT_BOOL))
677678
dataType = SVT_INT;
678679

679680
if (dataType != SVT_VOID)

src/HLSLCrossCompilerContext.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ void HLSLCrossCompilerContext::RequireExtension(const std::string &extName)
101101
return;
102102

103103
m_EnabledExtensions.insert(extName);
104+
bformata(extensions, "#ifdef %s\n", extName.c_str());
104105
bformata(extensions, "#extension %s : require\n", extName.c_str());
106+
bcatcstr(extensions, "#endif\n");
105107
}
106108

107109
std::string HLSLCrossCompilerContext::GetDeclaredInputName(const Operand* psOperand, int *piRebase, int iIgnoreRedirect, uint32_t *puiIgnoreSwizzle) const

src/HLSLccToolkit.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,13 @@ namespace HLSLcc
457457
return false;
458458
}
459459

460+
#ifndef fpcheck
460461
#ifdef _MSC_VER
461462
#define fpcheck(x) (_isnan(x) || !_finite(x))
462463
#else
463464
#define fpcheck(x) (std::isnan(x) || std::isinf(x))
464465
#endif
466+
#endif // #ifndef fpcheck
465467

466468
// Helper function to print floats with full precision
467469
void PrintFloat(bstring b, float f)

src/Operand.cpp

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -476,12 +476,11 @@ SHADER_VARIABLE_TYPE Operand::GetDataType(HLSLCrossCompilerContext* psContext, S
476476
const ShaderVarType* psVarType = NULL;
477477
int32_t rebase = -1;
478478
bool isArray;
479-
int foundVar;
480479
psContext->psShader->sInfo.GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, aui32ArraySizes[0], &psCBuf);
481480
if (psCBuf)
482481
{
483-
foundVar = ShaderInfo::GetShaderVarFromOffset(aui32ArraySizes[1], aui32Swizzle, psCBuf, &psVarType, &isArray, NULL, &rebase, psContext->flags);
484-
if (foundVar && m_SubOperands[1].get() == NULL) // TODO: why this suboperand thing?
482+
int foundVar = ShaderInfo::GetShaderVarFromOffset(aui32ArraySizes[1], aui32Swizzle, psCBuf, &psVarType, &isArray, NULL, &rebase, psContext->flags);
483+
if (foundVar)
485484
{
486485
return psVarType->Type;
487486
}
@@ -584,4 +583,67 @@ int Operand::GetNumInputElements(const HLSLCrossCompilerContext *psContext) cons
584583

585584
// TODO: Are there ever any cases where the mask has 'holes'?
586585
return HLSLcc::GetNumberBitsSet(psSig->ui32Mask);
586+
}
587+
588+
Operand* Operand::GetDynamicIndexOperand(HLSLCrossCompilerContext *psContext, const ShaderVarType* psVar, bool isAoS, bool *needsIndexCalcRevert) const
589+
{
590+
Operand *psDynIndexOp = m_SubOperands[0].get();
591+
if (psDynIndexOp == NULL)
592+
psDynIndexOp = m_SubOperands[1].get();
593+
594+
*needsIndexCalcRevert = false;
595+
if (psDynIndexOp != NULL && isAoS)
596+
{
597+
// if dynamically indexing array of structs, try using the original index var before the float4 address calc
598+
bool indexVarFound = false;
599+
*needsIndexCalcRevert = true;
600+
Instruction *psDynIndexOrigin = psDynIndexOp->m_Defines[0].m_Inst;
601+
Operand *asOps = psDynIndexOrigin->asOperands;
602+
Operand *psOriginOp = NULL;
603+
604+
// DXBC always addresses as float4, find the address calculation
605+
606+
// Special case where struct is float4 size, no extra calc is done
607+
if (ShaderInfo::GetCBVarSize(psVar->Parent, true) <= 16) // matrixAsVectors arg does not matter here as with matrices the size will go over the limit anyway
608+
{
609+
indexVarFound = true;
610+
*needsIndexCalcRevert = false;
611+
}
612+
else if (psDynIndexOrigin->eOpcode == OPCODE_IMUL)
613+
{
614+
// check which one of the src operands is the original index
615+
if ((asOps[2].eType == OPERAND_TYPE_TEMP || asOps[2].eType == OPERAND_TYPE_INPUT) && asOps[3].eType == OPERAND_TYPE_IMMEDIATE32)
616+
psOriginOp = &asOps[2];
617+
else if ((asOps[3].eType == OPERAND_TYPE_TEMP || asOps[3].eType == OPERAND_TYPE_INPUT) && asOps[2].eType == OPERAND_TYPE_IMMEDIATE32)
618+
psOriginOp = &asOps[3];
619+
}
620+
else if (psDynIndexOrigin->eOpcode == OPCODE_ISHL)
621+
{
622+
if (asOps[2].eType == OPERAND_TYPE_IMMEDIATE32)
623+
psOriginOp = &asOps[1];
624+
}
625+
626+
if (psOriginOp != NULL)
627+
{
628+
indexVarFound = true;
629+
630+
// Check if the mul dest is not the same temp as the src. Also check that the temp
631+
// does not have multiple uses (which could override the value)
632+
// -> we can use src straight and no index revert calc is needed
633+
if ((psOriginOp->eType == OPERAND_TYPE_INPUT)
634+
|| ((psOriginOp->ui32RegisterNumber != psDynIndexOp->ui32RegisterNumber || psOriginOp->GetDataType(psContext) != psDynIndexOp->GetDataType(psContext))
635+
&& psOriginOp->m_Defines[0].m_Inst->m_Uses.size() == 1))
636+
{
637+
psDynIndexOp = psOriginOp;
638+
*needsIndexCalcRevert = false;
639+
}
640+
}
641+
642+
// Atm we support only this very basic case of dynamic indexing array of structs.
643+
// Return error if something else is encountered.
644+
if (!indexVarFound)
645+
psContext->m_Reflection.OnDiagnostics("Unsupported dynamic indexing scheme on constant buffer vars.", 0, true);
646+
}
647+
648+
return psDynIndexOp;
587649
}

src/ShaderInfo.cpp

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -150,29 +150,37 @@ int ShaderInfo::GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType,
150150
return 0;
151151
}
152152

153-
static uint32_t GetCBVarSize(const ShaderVarType* psType, bool matrixAsVectors)
153+
uint32_t ShaderInfo::GetCBVarSize(const ShaderVarType* psType, bool matrixAsVectors, bool wholeArraySize)
154154
{
155-
// Struct size is calculated from the offset and size of its last member
155+
// Default is regular matrices, vectors and scalars
156+
uint32_t size = psType->Columns * psType->Rows * 4;
157+
158+
// Struct size is calculated from the offset and size of its last member.
159+
// Need to take into account that members could be arrays.
156160
if (psType->Class == SVC_STRUCT)
157161
{
158-
return psType->Members.back().Offset + GetCBVarSize(&psType->Members.back(), matrixAsVectors);
162+
size = psType->Members.back().Offset + GetCBVarSize(&psType->Members.back(), matrixAsVectors, true);
159163
}
160-
161164
// Matrices represented as vec4 arrays have special size calculation
162-
if (matrixAsVectors)
165+
else if (matrixAsVectors)
163166
{
164167
if (psType->Class == SVC_MATRIX_ROWS)
165168
{
166-
return psType->Rows * 16;
169+
size = psType->Rows * 16;
167170
}
168171
else if (psType->Class == SVC_MATRIX_COLUMNS)
169172
{
170-
return psType->Columns * 16;
173+
size = psType->Columns * 16;
171174
}
172175
}
173176

174-
// Regular matrices, vectors and scalars
175-
return psType->Columns * psType->Rows * 4;
177+
if (wholeArraySize && psType->Elements > 1)
178+
{
179+
uint32_t paddedSize = ((size + 15) / 16) * 16; // Arrays are padded to float4 size
180+
size = (psType->Elements - 1) * paddedSize + size; // Except the last element
181+
}
182+
183+
return size;
176184
}
177185

178186
static const ShaderVarType* IsOffsetInType(const ShaderVarType* psType,
@@ -184,10 +192,8 @@ static const ShaderVarType* IsOffsetInType(const ShaderVarType* psType,
184192
uint32_t flags)
185193
{
186194
uint32_t thisOffset = parentOffset + psType->Offset;
187-
uint32_t thisSize = GetCBVarSize(psType, (flags & HLSLCC_FLAG_TRANSLATE_MATRICES) != 0);
188-
uint32_t paddedSize = thisSize;
189-
if (thisSize % 16 > 0)
190-
paddedSize += (16 - (thisSize % 16));
195+
uint32_t thisSize = ShaderInfo::GetCBVarSize(psType, (flags & HLSLCC_FLAG_TRANSLATE_MATRICES) != 0);
196+
uint32_t paddedSize = ((thisSize + 15) / 16) * 16;
191197
uint32_t arraySize = thisSize;
192198

193199
// Array elements are padded to align on vec4 size, except for the last one
@@ -308,7 +314,7 @@ int ShaderInfo::GetShaderVarFromOffset(const uint32_t ui32Vec4Offset,
308314

309315
// Patches the fullName of the var with given array indices. Does not insert the indexing for the var itself if it is an array.
310316
// Searches for brackets and inserts indices one by one.
311-
std::string ShaderInfo::GetShaderVarIndexedFullName(const ShaderVarType* psShaderVar, std::vector<uint32_t> &indices)
317+
std::string ShaderInfo::GetShaderVarIndexedFullName(const ShaderVarType* psShaderVar, std::vector<uint32_t> &indices, const std::string dynamicIndex, bool revertDynamicIndexCalc, bool matrixAsVectors)
312318
{
313319
std::ostringstream oss;
314320
size_t prevpos = 0;
@@ -318,8 +324,29 @@ std::string ShaderInfo::GetShaderVarIndexedFullName(const ShaderVarType* psShade
318324
{
319325
pos++;
320326
oss << psShaderVar->fullName.substr(prevpos, pos - prevpos);
321-
if (i < indices.size())
327+
328+
// Add possibly given dynamic index for the root array.
329+
if (i == 0 && !dynamicIndex.empty())
330+
{
331+
oss << dynamicIndex;
332+
333+
// if we couldn't use original index temp, revert the float4 address calc here
334+
if (revertDynamicIndexCalc)
335+
{
336+
const ShaderVarType* psRootVar = psShaderVar;
337+
while (psRootVar->Parent != NULL)
338+
psRootVar = psRootVar->Parent;
339+
340+
uint32_t thisSize = (GetCBVarSize(psRootVar, matrixAsVectors) + 15) / 16; // size in float4
341+
oss << " / " << thisSize;
342+
}
343+
344+
if (!indices.empty() && indices[i] != 0)
345+
oss << " + " << indices[i];
346+
}
347+
else if (i < indices.size())
322348
oss << indices[i];
349+
323350
prevpos = pos;
324351
i++;
325352
pos = psShaderVar->fullName.find('[', prevpos);

src/internal_includes/Operand.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ class Operand
9292
// Same as above but with explicit shader type and phase
9393
int GetRegisterSpace(SHADER_TYPE eShaderType, SHADER_PHASE_TYPE eShaderPhaseType) const;
9494

95+
// Find the operand that contains the dynamic index for this operand (array in constant buffer).
96+
// When isAoS is true, we'll try to find the original index var to avoid additional calculations.
97+
// needsIndexCalcRevert output will tell if we need to divide the value to get the correct index.
98+
Operand* GetDynamicIndexOperand(HLSLCrossCompilerContext *psContext, const ShaderVarType* psVar, bool isAoS, bool *needsIndexCalcRevert) const;
99+
95100
// Maps REFLECT_RESOURCE_PRECISION into OPERAND_MIN_PRECISION as much as possible
96101
static OPERAND_MIN_PRECISION ResourcePrecisionToOperandPrecision(REFLECT_RESOURCE_PRECISION ePrec);
97102

src/internal_includes/toGLSLOperand.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ std::string ResourceName(HLSLCrossCompilerContext* psContext, ResourceGroup grou
2121
std::string TextureSamplerName(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare);
2222
void ConcatTextureSamplerName(bstring str, ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare);
2323

24+
std::string UniformBufferInstanceName(HLSLCrossCompilerContext* psContext, const std::string& name);
25+
2426
#endif

src/internal_includes/toMetal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ class ToMetal : public Translator
165165
void AddComparison(Instruction* psInst, ComparisonType eType,
166166
uint32_t typeFlag);
167167

168+
bool CanForceToHalfOperand(const Operand *psOperand);
169+
168170
void AddMOVBinaryOp(const Operand *pDest, Operand *pSrc);
169171
void AddMOVCBinaryOp(const Operand *pDest, const Operand *src0, Operand *src1, Operand *src2);
170172
void CallBinaryOp(const char* name, Instruction* psInst,

0 commit comments

Comments
 (0)