From b20c52398598a93da45f48ca99c884ce29a0a0b1 Mon Sep 17 00:00:00 2001 From: MrShoor Date: Tue, 30 Sep 2014 15:55:39 +0800 Subject: [PATCH 01/47] Fix MOVC translation with swizzle --- src/toGLSLInstruction.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index f988a7c..c1da2cc 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -371,7 +371,6 @@ static void AddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand * else { // TODO: We can actually do this in one op using mix(). - int srcElem = 0; for (destElem = 0; destElem < 4; ++destElem) { int numParenthesis = 0; @@ -381,7 +380,7 @@ static void AddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand * AddIndentation(psContext); AddOpAssignToDestWithMask(psContext, pDest, eDestType, 1, "=", &numParenthesis, 1 << destElem); bcatcstr(glsl, "("); - TranslateOperandWithMask(psContext, src0, TO_AUTO_BITCAST_TO_INT, 1 << srcElem); + TranslateOperandWithMask(psContext, src0, TO_AUTO_BITCAST_TO_INT, 1 << destElem); if (psContext->psShader->ui32MajorVersion < 4) { //cmp opcode uses >= 0 @@ -392,13 +391,11 @@ static void AddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand * bcatcstr(glsl, " != 0) ? "); } - TranslateOperandWithMask(psContext, src1, SVTTypeToFlag(eDestType), 1 << srcElem); + TranslateOperandWithMask(psContext, src1, SVTTypeToFlag(eDestType), 1 << destElem); bcatcstr(glsl, " : "); - TranslateOperandWithMask(psContext, src2, SVTTypeToFlag(eDestType), 1 << srcElem); + TranslateOperandWithMask(psContext, src2, SVTTypeToFlag(eDestType), 1 << destElem); AddAssignPrologue(psContext, numParenthesis); - - srcElem++; } } } From 9f8339319809cb18baf4645725010abaa1d32df7 Mon Sep 17 00:00:00 2001 From: MrShoor Date: Wed, 8 Apr 2015 11:13:16 -0700 Subject: [PATCH 02/47] Fix incorrect behavior GLSL compiler for ATI cards: this case will cast to 0.0: intBitsToFloat(int(0xBECCCCCDu)); this case will cast to -0.4: uint q = 0xBECCCCCDu; intBitsToFloat(int(q)); this case will cast to 0.0 again: const uint q = 0xBECCCCCDu; intBitsToFloat(int(q)); --- src/toGLSLOperand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 0f00f2d..9f92861 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -811,7 +811,7 @@ static void printImmediate32(HLSLCrossCompilerContext *psContext, uint32_t value case SVT_INT: // Need special handling for anything >= uint 0x3fffffff if (value > 0x3ffffffe) - bformata(glsl, "int(0x%Xu)", value); + bformata(glsl, "int(0x%X)", value); else bformata(glsl, "0x%X", value); break; From 8160436e2e3c82928757372ed33f2fc10efccf13 Mon Sep 17 00:00:00 2001 From: MrShoor Date: Wed, 8 Apr 2015 14:32:58 -0700 Subject: [PATCH 03/47] Fix incorrect swizzling for ftoi instruction. For example instruction: ftoi r0.yz, r0.yyzy Will translate into: Temp[0].yz = intBitsToFloat(ivec4(Temp[0].yyzy).xy); Instead correct translate: Temp[0].yz = intBitsToFloat(ivec4(Temp[0].yyzy).yz); --- src/toGLSLInstruction.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index c1da2cc..cc74e13 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -2683,15 +2683,16 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn AddIndentation(psContext); - AddAssignToDest(psContext, &psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount, &numParenthesis); + AddAssignToDest(psContext, &psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount, &numParenthesis); bcatcstr(glsl, GetConstructorForType(psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount == dstCount ? dstCount : 4)); bcatcstr(glsl, "("); // 1 TranslateOperand(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT); bcatcstr(glsl, ")"); // 1 // Add destination writemask if the component counts do not match if (srcCount != dstCount) - AddSwizzleUsingElementCount(psContext, dstCount); + TranslateOperandSwizzleWithMask(psContext, &psInst->asOperands[0], OPERAND_4_COMPONENT_MASK_ALL); AddAssignPrologue(psContext, numParenthesis); + //*/ break; } From d79f7445323e2f796ad684b4968b8f6d003cc01c Mon Sep 17 00:00:00 2001 From: MrShoor Date: Fri, 30 Oct 2015 15:28:30 -0700 Subject: [PATCH 04/47] Fix translation LT instruction: lt r2.zw, l(0.000000, 0.000000, 0.500000, 0.500000), |v4.xxxy| was: Temp[2].zw = uintBitsToFloat(uvec2(lessThan(vec4(intBitsToFloat(0x0), intBitsToFloat(0x0), intBitsToFloat(0x3F000000), intBitsToFloat(0x3F000000)), abs(Input4.xxxy))) * 0xFFFFFFFFu); should be: Temp[2].zw = uintBitsToFloat(uvec2(lessThan(vec4(intBitsToFloat(0x0), intBitsToFloat(0x0), intBitsToFloat(0x3F000000), intBitsToFloat(0x3F000000)), abs(Input4.xxxy)).zw) * 0xFFFFFFFFu); --- src/toGLSLInstruction.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index cc74e13..2720970 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -217,7 +217,9 @@ static void AddComparision(HLSLCrossCompilerContext* psContext, Instruction* psI TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); bcatcstr(glsl, ", "); TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); - bcatcstr(glsl, "))"); + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + bcatcstr(glsl, ")"); if (!floatResult) { bcatcstr(glsl, " * 0xFFFFFFFFu"); From 8ada4954d8c63d48841bb64b249505689e317e8d Mon Sep 17 00:00:00 2001 From: David Jewsbury Date: Sat, 9 Apr 2016 11:23:12 +0900 Subject: [PATCH 05/47] Added a little more flexibility when writing the "layout" qualifiers for resources - new flag "HLSLCC_FLAG_PREFER_BINDINGS" that causes the compiler to use bindings (rather than locations) for all resources - another flag, "HLSLCC_FLAG_ASSIGN_DESCRIPTOR_SET" uses the set qualifier to distinguish between resource bindings and constant buffer bindings - this is intended to be used when compiling HLSL -> SPIR-V (via GLSL). --- include/hlslcc.h | 7 +++ src/internal_includes/languages.h | 7 +++ src/toGLSLDeclaration.c | 96 ++++++++++++++++++++++++++----- 3 files changed, 95 insertions(+), 15 deletions(-) diff --git a/include/hlslcc.h b/include/hlslcc.h index ca2ffec..e1d6e83 100644 --- a/include/hlslcc.h +++ b/include/hlslcc.h @@ -444,6 +444,13 @@ 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, always write binding qualifiers for resources, rather than location qualifiers +static const unsigned int HLSLCC_FLAG_PREFER_BINDINGS = 0x1000; + +//If set, bindings for different types of resources assigned to different descriptor sets +//(eg, in HLSL we can assign a resource to "register(t8)" or "register(b8)" -- they both become binding 8, but in different sets) +static const unsigned int HLSLCC_FLAG_ASSIGN_DESCRIPTOR_SET = 0x2000; + #ifdef __cplusplus extern "C" { #endif diff --git a/src/internal_includes/languages.h b/src/internal_includes/languages.h index 1f8dbd2..7f78778 100644 --- a/src/internal_includes/languages.h +++ b/src/internal_includes/languages.h @@ -86,6 +86,13 @@ static int HaveUniformBindingsAndLocations(const GLLang eLang,const struct GlExt return 0; } +static int HaveBindingQualifier(const GLLang eLang, const struct GlExtensions *extensions, unsigned int flags) +{ + return + (eLang >= LANG_420) + || (extensions && ((GlExtensions*)extensions)->ARB_shading_language_420pack); +} + static int DualSourceBlendSupported(const GLLang eLang) { if(eLang >= LANG_330) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 234d355..f869faa 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1126,6 +1126,80 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec } } +typedef enum { + BINDABLE_UBO, + BINDABLE_RESOURCE, + BINDABLE_UNORDERED_ACCESS +} BINDABLE_TYPE; + +static void WriteUniformLayout( + HLSLCrossCompilerContext* psContext, + BINDABLE_TYPE type, + uint32_t ui32BindingPoint, + bstring glsl) +{ + // Write the "layout(...)" decoration that should preceed uniform objects + // We have 3 qualifiers we're going to consider: + // "location" + // "binding" + // "set" + // + // This implementation was intended to support a path from HLSL to SPIR-V (via GLSL). + // Since HLSL 5 has no "descriptor set" concept, we're going to assign one based on + // the resource type. + // For example, in HLSL we can assign a resource to "register(t8)" or "register(b8)" + // 8 is the binding point, but we need to use different descriptor sets to separate + // the texture resources from the buffer resources (etc) + // + // Note that to maintain backwards compatibility, we follow these rules: + // * when HLSLCC_FLAG_PREFER_BINDINGS is set, we always write a binding, and never a location + // * otherwise, we write bindings for UBO and unordered access buffers, but write a location for resources + // The second case is the previous behaviour of this library. + + unsigned preferBindings = (psContext->flags & HLSLCC_FLAG_PREFER_BINDINGS) == HLSLCC_FLAG_PREFER_BINDINGS; + preferBindings |= (type == BINDABLE_UBO) || (type == BINDABLE_UNORDERED_ACCESS); + + if (preferBindings && HaveBindingQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + { + const unsigned assignSet = (psContext->flags & HLSLCC_FLAG_ASSIGN_DESCRIPTOR_SET) == HLSLCC_FLAG_ASSIGN_DESCRIPTOR_SET; + if (!assignSet) + { + // when not assigning a set, we need to shift the binding point to after all constant buffers + // (to avoid overlapping) + if (type == BINDABLE_RESOURCE) + ui32BindingPoint += psContext->psShader->sInfo.ui32NumConstantBuffers; + } + + bformata(glsl, "layout(binding = %d", ui32BindingPoint); + + // note, we could set the location, also, if HaveUniformBindingsAndLocations...? + if (assignSet) + { + unsigned setIndex = 0; + switch (type) + { + default: + case BINDABLE_UBO: setIndex = 0; break; + case BINDABLE_RESOURCE: setIndex = 1; break; + case BINDABLE_UNORDERED_ACCESS: setIndex = 2; break; + } + bformata(glsl, ", set = %d", setIndex); + } + + bcatcstr(glsl, ") "); + return; + } + + // If we haven't selected to write a binding, let's write a location. This maintains backward compatibility + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + { + if (type == BINDABLE_RESOURCE) + ui32BindingPoint += psContext->psShader->sInfo.ui32NumConstantBuffers; + + bformata(glsl, "layout(location = %d) ", ui32BindingPoint); + } +} + void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* psCBuf, bstring glsl) @@ -1145,9 +1219,7 @@ void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui3 } /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - bformata(glsl, "layout(binding = %d) ", ui32BindingPoint); - + WriteUniformLayout(psContext, BINDABLE_UBO, ui32BindingPoint, glsl); bformata(glsl, "uniform %s {\n ", Name); for(i=0; i < psCBuf->ui32NumVars; ++i) @@ -1193,8 +1265,7 @@ void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t u &psCBuf->asVars[0].sType); /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - bformata(glsl, "layout(binding = %d) ", ui32BindingPoint); + WriteUniformLayout(psContext, BINDABLE_UNORDERED_ACCESS, ui32BindingPoint, glsl); if(ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) { @@ -1997,16 +2068,11 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } case OPCODE_DCL_RESOURCE: { - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - { - // Explicit layout bindings are not currently compatible with combined texture samplers. The layout below assumes there is exactly one GLSL sampler - // for each HLSL texture declaration, but when combining textures+samplers, there can be multiple OGL samplers for each HLSL texture declaration. - if((psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) != HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) - { - //Constant buffer locations start at 0. Resource locations start at ui32NumConstantBuffers. - bformata(glsl, "layout(location = %d) ", - psContext->psShader->sInfo.ui32NumConstantBuffers + psDecl->asOperands[0].ui32RegisterNumber); - } + // Explicit layout bindings are not currently compatible with combined texture samplers. The layout below assumes there is exactly one GLSL sampler + // for each HLSL texture declaration, but when combining textures+samplers, there can be multiple OGL samplers for each HLSL texture declaration. + if ((psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) != HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) + { + WriteUniformLayout(psContext, BINDABLE_RESOURCE, psDecl->asOperands[0].ui32RegisterNumber, glsl); } switch(psDecl->value.eResourceDimension) From 853f47fb229e2252f0fd1da8a12893063dc713aa Mon Sep 17 00:00:00 2001 From: David Jewsbury Date: Sat, 9 Apr 2016 11:49:43 +0900 Subject: [PATCH 06/47] Explicitly specifying matrix dimensions - in order to support float3x4/float4x3 type matrices --- src/toGLSLDeclaration.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index f869faa..38d4f3d 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -101,7 +101,14 @@ void DeclareConstBufferShaderVariable(bstring glsl, const char* Name, const stru { case SVT_FLOAT: { - bformata(glsl, "\tmat4 %s", Name); + if (psType->Class == SVC_MATRIX_COLUMNS) + { + bformata(glsl, "\tmat%ix%i %s", psType->Columns, psType->Rows, Name); + } + else + { + bformata(glsl, "\tmat%ix%i %s", psType->Rows, psType->Columns, Name); + } break; } default: From 5cbc6c8bfa2847ac0bc02dc20f41552b76df29a9 Mon Sep 17 00:00:00 2001 From: David Jewsbury Date: Wed, 13 Apr 2016 18:08:15 +0900 Subject: [PATCH 07/47] Added support for a few unsigned integer instruction that were missing --- src/decode.c | 6 ++++- src/internal_includes/structs.h | 1 + src/toGLSLInstruction.c | 40 +++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/decode.c b/src/decode.c index c292673..5c1900a 100644 --- a/src/decode.c +++ b/src/decode.c @@ -1023,8 +1023,10 @@ const uint32_t* DeocdeInstruction(const uint32_t* pui32Token, Instruction* psIns //Intentional fall-through } case OPCODE_IMIN: + case OPCODE_UMIN: case OPCODE_MIN: case OPCODE_IMAX: + case OPCODE_UMAX: case OPCODE_MAX: case OPCODE_MUL: case OPCODE_DIV: @@ -1078,6 +1080,7 @@ const uint32_t* DeocdeInstruction(const uint32_t* pui32Token, Instruction* psIns case OPCODE_MAD: case OPCODE_MOVC: case OPCODE_IMAD: + case OPCODE_UMAD: case OPCODE_UDIV: case OPCODE_LOD: case OPCODE_SAMPLE: @@ -1098,10 +1101,11 @@ const uint32_t* DeocdeInstruction(const uint32_t* pui32Token, Instruction* psIns case OPCODE_DMOVC: case OPCODE_DFMA: case OPCODE_IMUL: + case OPCODE_UMUL: { psInst->ui32NumOperands = 4; - if(eOpcode == OPCODE_IMUL) + if(eOpcode == OPCODE_IMUL || eOpcode == OPCODE_UMUL) { psInst->ui32FirstSrc = 2; } diff --git a/src/internal_includes/structs.h b/src/internal_includes/structs.h index 241c851..9a5c9e0 100644 --- a/src/internal_includes/structs.h +++ b/src/internal_includes/structs.h @@ -157,6 +157,7 @@ enum {MAX_TEMP_VEC4 = 512}; enum {MAX_GROUPSHARED = 8}; +#pragma warning(disable:4091) // warning C4091: 'static ': ignored on left of '' when no variable is declared static enum {MAX_DX9_IMMCONST = 256}; static const uint32_t MAIN_PHASE = 0; diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 2720970..5d0c75f 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -2764,6 +2764,16 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn CallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, ui32Flags); break; } + case OPCODE_UMAD: + { + uint32_t ui32Flags = TO_FLAG_UNSIGNED_INTEGER; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UMAD\n"); +#endif + CallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, ui32Flags); + break; + } case OPCODE_DADD: { #ifdef _DEBUG @@ -2856,6 +2866,18 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn CallBinaryOp(psContext, "*", psInst, 1, 2, 3, eType); break; } + case OPCODE_UMUL: + { + SHADER_VARIABLE_TYPE eType = SVT_UINT; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UMUL\n"); +#endif + ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_NULL); + + CallBinaryOp(psContext, "*", psInst, 1, 2, 3, eType); + break; + } case OPCODE_UDIV: { #ifdef _DEBUG @@ -3140,6 +3162,15 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn CallHelper2Int(psContext, "max", psInst, 0, 1, 2, 1); break; } + case OPCODE_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UMAX\n"); +#endif + CallHelper2UInt(psContext, "max", psInst, 0, 1, 2, 1); + break; + } case OPCODE_MAX: { #ifdef _DEBUG @@ -3158,6 +3189,15 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn CallHelper2Int(psContext, "min", psInst, 0, 1, 2, 1); break; } + case OPCODE_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UMIN\n"); +#endif + CallHelper2UInt(psContext, "min", psInst, 0, 1, 2, 1); + break; + } case OPCODE_MIN: { #ifdef _DEBUG From eb520e41f4dfa0f43002bb0e77b0a1168c3bf3a6 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Fri, 15 Apr 2016 16:34:16 +0900 Subject: [PATCH 08/47] Removed a line that write "subroutine void SubroutineType();" into all shaders with higher GLSL version numbers - it's not clear to me what the intention of this line is - however, it causes a compile error when attempting to compile the result to SPIR-V (which doesn't support subroutines) --- src/toGLSL.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/toGLSL.c b/src/toGLSL.c index fad6707..75df23b 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -207,11 +207,13 @@ void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) } bcatcstr(glsl, "\n"); } - - if (SubroutinesSupported(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "subroutine void SubroutineType();\n"); - } + + // DavidJ -- Removed this line. It causes a compile error with the SPIR-V compiler (which doesn't support subroutines) + // It's not clear to me what the intention of this line is. + // if (SubroutinesSupported(psContext->psShader->eTargetLanguage)) + // { + // bcatcstr(glsl, "subroutine void SubroutineType();\n"); + // } if (psContext->psShader->ui32MajorVersion <= 3) { From 8420fdd7ec4b8c2229445d72917478ee12322f18 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 18 Apr 2016 12:53:46 +0900 Subject: [PATCH 09/47] INEG instruction can now handle format conversions and swizzling properly - new CallUnaryOp, which duplicates the behaviour of CallBinaryOp function (but for unary operations) - this allows the INEG instruction (which is translated as X = 0 - A) to deal with complex swizzling operations, as well as casting (when the register types are not integers) --- src/toGLSLInstruction.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 5d0c75f..a16f43c 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -450,6 +450,24 @@ static int IsOperationCommutative(OPCODE_TYPE eOpCode) }; } +static void CallUnaryOp(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, SHADER_VARIABLE_TYPE eDataType) +{ + bstring glsl = *psContext->currentGLSLString; + uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + uint32_t destMask = GetOperandWriteMask(&psInst->asOperands[dest]); + int needsParenthesis = 0; + + AddIndentation(psContext); + + AddAssignToDest(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, &needsParenthesis); + + bformata(glsl, " %s ", name); + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], SVTTypeToFlag(eDataType), destMask); + AddAssignPrologue(psContext, needsParenthesis); +} + static void CallBinaryOp(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType) { @@ -4407,11 +4425,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn bcatcstr(glsl, "//INEG\n"); #endif //dest = 0 - src0 - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION | TO_FLAG_INTEGER); - bcatcstr(glsl, " = 0 - "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE | TO_FLAG_INTEGER); - bcatcstr(glsl, ";\n"); + CallUnaryOp(psContext, "0 - ", psInst, 0, 1, SVT_INT); break; } case OPCODE_DERIV_RTX_COARSE: From 9345ac31f5a98eef26682cfd00e7fb43fe850e87 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 18 Apr 2016 14:57:25 +0900 Subject: [PATCH 10/47] RESINFO instruction now translates to imageSize when appropriate - previously, textureSize was always used for RESINFO, regardless of the type of the object we were querying - UAV declarations are translated into "image" types, and so size queries should use the corresponding function, "imageSize" - this only works when targetting GLSL 4.3 (which is the standard that adds imageSize) - when targetting early languages, using RESINFO with a UAV will result in uncompilable code --- src/internal_includes/languages.h | 9 ++++++ src/internal_includes/structs.h | 1 + src/toGLSLDeclaration.c | 3 ++ src/toGLSLInstruction.c | 46 +++++++++++++++++++++++-------- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/internal_includes/languages.h b/src/internal_includes/languages.h index 7f78778..d487984 100644 --- a/src/internal_includes/languages.h +++ b/src/internal_includes/languages.h @@ -111,6 +111,15 @@ static int SubroutinesSupported(const GLLang eLang) return 0; } +static int HasImageSizeFunction(const GLLang eLang) +{ + if(eLang >= LANG_430) + { + return 1; + } + return 0; +} + //Before 430, flat/smooth/centroid/noperspective must match //between fragment and its previous stage. //HLSL bytecode only tells us the interpolation in pixel shader. diff --git a/src/internal_includes/structs.h b/src/internal_includes/structs.h index 9a5c9e0..eff56bc 100644 --- a/src/internal_includes/structs.h +++ b/src/internal_includes/structs.h @@ -223,6 +223,7 @@ typedef struct Shader_TAG int aIndexedInputParents[MAX_SHADER_VEC4_INPUT]; RESOURCE_DIMENSION aeResourceDims[MAX_TEXTURES]; + RESOURCE_DIMENSION aeUAVResourceDims[MAX_TEXTURES]; int aiInputDeclaredSize[MAX_SHADER_VEC4_INPUT]; diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 38d4f3d..68690e2 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -2591,6 +2591,9 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); bcatcstr(glsl, ";\n"); + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_TEXTURES); + psShader->aeUAVResourceDims[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eResourceDimension; break; } case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index a16f43c..75fe158 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -923,7 +923,6 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in bstring glsl = *psContext->currentGLSLString; int numParenthesis = 0; const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; AddIndentation(psContext); AddOpAssignToDestWithMask(psContext, &psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, "=", &numParenthesis, 1 << destElem); @@ -931,6 +930,27 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in //[width, height, depth or array size, total-mip-count] if (index < 3) { + RESOURCE_DIMENSION eResDim; + const char* queryFunction = "textureSize"; + int includeLODParameter = 1; + + // "UAV" types in HLSL become "image" types in GLSL. + // In these cases, we must use "imageSize" rather than "textureSize" + // However, this function is only available in GLSL v4.3 or greater + // If are compiling to an earlier version of GLSL, and we hit this instruction, + // we will probably generate uncompilable GLSL code + if (HasImageSizeFunction(psContext->psShader->eTargetLanguage) + && psInst->asOperands[2].eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) { + ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); + eResDim = psContext->psShader->aeUAVResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + queryFunction = "imageSize"; + includeLODParameter = 0; + } else { + ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); + ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); + eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + } + int dim = GetNumTextureDimensions(psContext, eResDim); bcatcstr(glsl, "("); if (dim < (index + 1)) @@ -941,19 +961,21 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in { if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) { - bformata(glsl, "uvec%d(textureSize(", dim); + bformata(glsl, "uvec%d(%s(", dim, queryFunction); } else if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_RCPFLOAT) { - bformata(glsl, "vec%d(1.0) / vec%d(textureSize(", dim, dim); + bformata(glsl, "vec%d(1.0) / vec%d(%s(", dim, dim, queryFunction); } else { - bformata(glsl, "vec%d(textureSize(", dim); + bformata(glsl, "vec%d(%s(", dim, queryFunction); } TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + if (includeLODParameter) { + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + } bcatcstr(glsl, "))"); switch (index) @@ -974,6 +996,7 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in } else { + ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) bcatcstr(glsl, "uint("); else @@ -1006,6 +1029,7 @@ static void TranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruct uint32_t ui32NumOffsets = 0; + ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; const int iHaveOverloadedTexFuncs = HaveOverloadedTextureFuncs(psContext->psShader->eTargetLanguage); @@ -3228,6 +3252,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn case OPCODE_GATHER4: { //dest, coords, tex, sampler + ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; #ifdef _DEBUG @@ -3259,7 +3284,8 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn case OPCODE_GATHER4_PO_C: { //dest, coords, offset, tex, sampler, srcReferenceValue - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; + ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; #ifdef _DEBUG AddIndentation(psContext); @@ -4084,7 +4110,8 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); bcatcstr(glsl, ","); - TranslateTexCoord(psContext, + ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); + TranslateTexCoord(psContext, psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber], &psInst->asOperands[1]); bcatcstr(glsl, ")"); @@ -4549,9 +4576,6 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn } case OPCODE_RESINFO: { - - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); uint32_t destElem; #ifdef _DEBUG From 81a07e3d04a1e18d451962e726c6c98fa1f13427 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 18 Apr 2016 17:24:27 +0900 Subject: [PATCH 11/47] Support for "GL_KHR_vulkan_glsl" extension - this extension renames gl_VertexID -> gl_VertexIndex and gl_InstanceID -> gl_InstanceIndex - this is required when using the GLSL -> SPIR-V path --- include/hlslcc.h | 1 + offline/toGLSLStandalone.cpp | 1 + src/internal_includes/languages.h | 9 +++++++++ src/toGLSL.c | 1 + src/toGLSLDeclaration.c | 18 ++++++++++++++++-- 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/hlslcc.h b/include/hlslcc.h index e1d6e83..e7c99b1 100644 --- a/include/hlslcc.h +++ b/include/hlslcc.h @@ -39,6 +39,7 @@ typedef struct { uint32_t ARB_explicit_attrib_location : 1; uint32_t ARB_explicit_uniform_location : 1; uint32_t ARB_shading_language_420pack : 1; + uint32_t GL_KHR_vulkan_glsl : 1; }GlExtensions; enum {MAX_SHADER_VEC4_OUTPUT = 512}; diff --git a/offline/toGLSLStandalone.cpp b/offline/toGLSLStandalone.cpp index 0013971..bde667b 100644 --- a/offline/toGLSLStandalone.cpp +++ b/offline/toGLSLStandalone.cpp @@ -605,6 +605,7 @@ int Run(const char* srcPath, const char* destPath, GLLang language, int flags, c ext.ARB_explicit_attrib_location = 0; ext.ARB_explicit_uniform_location = 0; ext.ARB_shading_language_420pack = 0; + ext.GL_KHR_vulkan_glsl = 0; compiledOK = TranslateHLSLFromFile(srcPath, flags, language, &ext , dependencies, &result); crossCompileTime = ReadTimer(&timer); diff --git a/src/internal_includes/languages.h b/src/internal_includes/languages.h index d487984..4cc336f 100644 --- a/src/internal_includes/languages.h +++ b/src/internal_includes/languages.h @@ -120,6 +120,15 @@ static int HasImageSizeFunction(const GLLang eLang) return 0; } +static int UseSPIRVNames(const GLLang eLang,const struct GlExtensions *extensions) +{ + if(extensions && ((GlExtensions*)extensions)->GL_KHR_vulkan_glsl) + { + return 1; + } + return 0; +} + //Before 430, flat/smooth/centroid/noperspective must match //between fragment and its previous stage. //HLSL bytecode only tells us the interpolation in pixel shader. diff --git a/src/toGLSL.c b/src/toGLSL.c index 75df23b..32b1711 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -494,6 +494,7 @@ void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,cons bcatcstr(glsl,"#extension GL_ARB_explicit_uniform_location : require\n"); if(extensions->ARB_shading_language_420pack) bcatcstr(glsl,"#extension GL_ARB_shading_language_420pack : require\n"); + // extension GL_KHR_vulkan_glsl doesn't need to be declared } ClearDependencyData(psShader->eShaderType, psContext->psDependencies); diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 68690e2..b2de0b1 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1593,7 +1593,14 @@ void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration } case NAME_INSTANCE_ID: { - AddBuiltinInput(psContext, psDecl, "gl_InstanceID"); + if (UseSPIRVNames(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + AddBuiltinInput(psContext, psDecl, "gl_InstanceIndex"); + } + else + { + AddBuiltinInput(psContext, psDecl, "gl_InstanceID"); + } break; } case NAME_IS_FRONT_FACE: @@ -1614,7 +1621,14 @@ void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration } case NAME_VERTEX_ID: { - AddBuiltinInput(psContext, psDecl, "gl_VertexID"); + if (UseSPIRVNames(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + AddBuiltinInput(psContext, psDecl, "gl_VertexIndex"); + } + else + { + AddBuiltinInput(psContext, psDecl, "gl_VertexID"); + } break; } case NAME_PRIMITIVE_ID: From 5ffcb6bdcf9f4ce2b732b9166d10dd60f5b3fcc0 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 18 Apr 2016 17:26:43 +0900 Subject: [PATCH 12/47] Using "TranslateTexCoord" for all variations of "GATHER" instructions - this is required when doing a depth compare gather on an array of 2d textures (for example) - previously, this was implemented for some variations of the GATHER instruction - this change uses the same logic for all variations --- src/toGLSLInstruction.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 75fe158..5671ada 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -3325,6 +3325,8 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn case OPCODE_GATHER4_PO: { //dest, coords, offset, tex, sampler + ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; #ifdef _DEBUG AddIndentation(psContext); @@ -3341,11 +3343,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0)); bcatcstr(glsl, ", "); - //Texture coord cannot be vec4 - //Determining if it is a vec3 for vec2 yet to be done. - psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); bcatcstr(glsl, ", ivec2("); //ivec2 offset @@ -3364,6 +3362,8 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn case OPCODE_GATHER4_C: { //dest, coords, tex, sampler srcReferenceValue + ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; #ifdef _DEBUG AddIndentation(psContext); @@ -3380,11 +3380,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); bcatcstr(glsl, ", "); - //Texture coord cannot be vec4 - //Determining if it is a vec3 for vec2 yet to be done. - psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); bcatcstr(glsl, ", "); TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_NONE); From 2408f08e550c945148e7567f80a24e00f7fbb4dd Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 18 Apr 2016 17:54:54 +0900 Subject: [PATCH 13/47] Improved support for output variables from vertex shaders that have overlap on the same location - now, all output locations get a temporary "vec4" - we copy from those vec4 values to the actual output values in a fixup step at the end of the shader - previously there was an attempt at this behaviour with #defines - however, this required declaring one of the output variables as a vec4 (even if really wasn't) - this solution handles more cases and results in a shader interface that better matches the original HLSL code - there may be issues with types largers than a vec4 (such as a matrix) - currently this is only supported for vertex shader outputs... but it could be made more general and used for other shader types --- src/internal_includes/languages.h | 11 ++ src/toGLSLDeclaration.c | 248 ++++++++++++++++++------------ 2 files changed, 161 insertions(+), 98 deletions(-) diff --git a/src/internal_includes/languages.h b/src/internal_includes/languages.h index 4cc336f..b37f653 100644 --- a/src/internal_includes/languages.h +++ b/src/internal_includes/languages.h @@ -120,6 +120,17 @@ static int HasImageSizeFunction(const GLLang eLang) return 0; } +static int HasInterfaceComponentQualifier(const GLLang eLang) +{ + // Allows for the use of "component" layout qualifier attached + // to interface components. + if (eLang >= LANG_440) + { + return 1; + } + return 0; +} + static int UseSPIRVNames(const GLLang eLang,const struct GlExtensions *extensions) { if(extensions && ((GlExtensions*)extensions)->GL_KHR_vulkan_glsl) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index b2de0b1..2653499 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -811,79 +811,124 @@ void AddBuiltinOutput(HLSLCrossCompilerContext* psContext, const Declaration* ps } } +static int LSBBit(uint32_t value) +{ + // Returns the least significant bit set, zero based + // Lots of hardware has intructions built-in for this... But for portability, + // we're just going to use a general solution. This isn't used by a performance + // critical client. + // (see: http://stackoverflow.com/questions/757059/position-of-least-significant-bit-that-is-set) + const int MultiplyDeBruijnBitPosition[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + int32_t x = (int32_t)value; + return MultiplyDeBruijnBitPosition[((uint32_t)((x & -x) * 0x077CB531U)) >> 27]; +} + +static int MSBBit(uint32_t x) +{ + // Returns the most significant bit set, zero based + // Like LSBBit, just using a general method (even though there might be a hardware instruction) + int r = 0; + while (x >>= 1) r++; + return r; +} + +static void WriteOutputFixup(HLSLCrossCompilerContext* psContext, const Operand* psOperand, const char* OutputName) +{ + // Here, we copy from a temporary buffer (called OutputXX) to + // the actual output variable "OutputName". This allows us to deal with + // cases where multiple outputs exist on the same register "location" + psContext->havePostShaderCode[psContext->currentPhase] = 1; + + psContext->currentGLSLString = &psContext->postShaderCode[psContext->currentPhase]; + bstring glsl = *psContext->currentGLSLString; + + bcatcstr(glsl, OutputName); + AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(psOperand)); + bformata(glsl, " = Output%d", psOperand->ui32RegisterNumber); + TranslateOperandSwizzle(psContext, psOperand); + bcatcstr(glsl, ";\n"); + + psContext->currentGLSLString = &psContext->glsl; + glsl = *psContext->currentGLSLString; +} + void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) { bstring glsl = *psContext->currentGLSLString; Shader* psShader = psContext->psShader; - if(OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], 1)) - { - const Operand* psOperand = &psDecl->asOperands[0]; - const char* Precision = ""; - const char* type = "vec"; + const char* Precision = ""; + const char* type = "vec"; - InOutSignature* psSignature = NULL; + const Operand* psOperand = &psDecl->asOperands[0]; + InOutSignature* psSignature = NULL; - GetOutputSignatureFromRegister( - psContext->currentPhase, - psDecl->asOperands[0].ui32RegisterNumber, - psDecl->asOperands[0].ui32CompMask, - psShader->ui32CurrentVertexOutputStream, - &psShader->sInfo, - &psSignature); + GetOutputSignatureFromRegister( + psContext->currentPhase, + psDecl->asOperands[0].ui32RegisterNumber, + psDecl->asOperands[0].ui32CompMask, + psShader->ui32CurrentVertexOutputStream, + &psShader->sInfo, + &psSignature); + + switch(psSignature->eComponentType) + { + case INOUT_COMPONENT_UINT32: + { + type = "uvec"; + break; + } + case INOUT_COMPONENT_SINT32: + { + type = "ivec"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; + } + } - switch(psSignature->eComponentType) + if(HavePrecisionQualifers(psShader->eTargetLanguage)) + { + switch(psOperand->eMinPrecision) { - case INOUT_COMPONENT_UINT32: + case OPERAND_MIN_PRECISION_DEFAULT: { - type = "uvec"; + Precision = "highp"; break; } - case INOUT_COMPONENT_SINT32: + case OPERAND_MIN_PRECISION_FLOAT_16: { - type = "ivec"; + Precision = "mediump"; break; } - case INOUT_COMPONENT_FLOAT32: + case OPERAND_MIN_PRECISION_FLOAT_2_8: { + Precision = "lowp"; break; } - } - - if(HavePrecisionQualifers(psShader->eTargetLanguage)) - { - switch(psOperand->eMinPrecision) + case OPERAND_MIN_PRECISION_SINT_16: { - case OPERAND_MIN_PRECISION_DEFAULT: - { - Precision = "highp"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_2_8: - { - Precision = "lowp"; - break; - } - case OPERAND_MIN_PRECISION_SINT_16: - { - Precision = "mediump"; - //type = "ivec"; - break; - } - case OPERAND_MIN_PRECISION_UINT_16: - { - Precision = "mediump"; - //type = "uvec"; - break; - } + Precision = "mediump"; + //type = "ivec"; + break; + } + case OPERAND_MIN_PRECISION_UINT_16: + { + Precision = "mediump"; + //type = "uvec"; + break; } } + } + if(OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], 1)) + { switch(psShader->eShaderType) { case PIXEL_SHADER: @@ -960,7 +1005,13 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec } case VERTEX_SHADER: { - int iNumComponents = 4;//GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); + // int iNumComponents = 4;//GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); + ASSERT(psDecl->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + ASSERT(psDecl->asOperands[0].iWriteMaskEnabled && (psDecl->asOperands[0].iNumComponents == 4)); + int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) + int lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); + int iNumComponents = highestComponent - lowestComponent + 1; + const char* Interpolation = ""; int stream = 0; const char* OutputName = GetDeclaredOutputName(psContext, VERTEX_SHADER, psOperand, &stream); @@ -975,8 +1026,21 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) { - if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) + { + // note that we have to write the "component" qualifier for every variable that shares the + // same location (otherwise the glsl compiler will consider the variable to use all 4 components). + // Since we don't know if there will be future variables sharing this location, + // that means we have to write "component" for all variables... + if (HasInterfaceComponentQualifier(psContext->psShader->eTargetLanguage)) + { + bformata(glsl, "layout(location = %d, component = %d) ", psDecl->asOperands[0].ui32RegisterNumber, lowestComponent); + } + else + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + } } if(InOutSupported(psContext->psShader->eTargetLanguage)) @@ -987,8 +1051,14 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec { bformata(glsl, "%s varying %s %s%d %s;\n", Interpolation, Precision, type, iNumComponents, OutputName); } - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + // We're going to define a special temporary vec4 for this output index. + // The values in this temporary will be redirected to the true outputs in a post + // shader fixup section. + // Note that there may be issues if the types of the overlapping outputs are not the same + // (ie, some are float, some are int) + bformata(glsl, "%s4 Output%d;\n", type, psDecl->asOperands[0].ui32RegisterNumber); + WriteOutputFixup(psContext, psOperand, OutputName); break; } case GEOMETRY_SHADER: @@ -1077,58 +1147,40 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec if((psContext->flags & (HLSLCC_FLAG_INOUT_SEMANTIC_NAMES|HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES)) && (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT)) { - const Operand* psOperand = &psDecl->asOperands[0]; - InOutSignature* psSignature = NULL; - const char* type = "vec"; + const char* Interpolation = ""; int stream = 0; - const char* OutputName = GetDeclaredOutputName(psContext, psShader->eShaderType, psOperand, &stream); + const char* OutputName = GetDeclaredOutputName(psContext, VERTEX_SHADER, psOperand, &stream); + + if(psContext->psDependencies) + { + if(psShader->eShaderType == VERTEX_SHADER) + { + Interpolation = GetInterpolationString(psContext->psDependencies->aePixelInputInterpolation[psDecl->asOperands[0].ui32RegisterNumber]); + } + } - GetOutputSignatureFromRegister( - psContext->currentPhase, - psOperand->ui32RegisterNumber, - psOperand->ui32CompMask, - 0, - &psShader->sInfo, - &psSignature); + int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) + int lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); + int iNumComponents = highestComponent - lowestComponent + 1; if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) { if (!((psShader->eShaderType == VERTEX_SHADER) && (psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS))) - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - switch(psSignature->eComponentType) - { - case INOUT_COMPONENT_UINT32: - { - type = "uvec"; - break; - } - case INOUT_COMPONENT_SINT32: - { - type = "ivec"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } + { + if (HasInterfaceComponentQualifier(psContext->psShader->eTargetLanguage)) + { + bformata(glsl, "layout(location = %d, component = %d) ", psDecl->asOperands[0].ui32RegisterNumber, lowestComponent); + } + else + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + } } - bformata(glsl, "out %s4 %s;\n", type, OutputName); - - psContext->havePostShaderCode[psContext->currentPhase] = 1; - - psContext->currentGLSLString = &psContext->postShaderCode[psContext->currentPhase]; - glsl = *psContext->currentGLSLString; - bcatcstr(glsl, OutputName); - AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(psOperand)); - bformata(glsl, " = Output%d", psOperand->ui32RegisterNumber); - TranslateOperandSwizzle(psContext, psOperand); - bcatcstr(glsl, ";\n"); + bformata(glsl, "%s out %s %s%d %s;\n", Interpolation, Precision, type, iNumComponents, OutputName); - psContext->currentGLSLString = &psContext->glsl; - glsl = *psContext->currentGLSLString; + WriteOutputFixup(psContext, psOperand, OutputName); } } } From 3182d86cf8d04cf3c422527c93b5a9b4202a38e5 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 18 Apr 2016 19:39:34 +0900 Subject: [PATCH 14/47] Fix for RESINFO instruction when using complex swizzle patterns on the destination - previously, RESINFO instruction only supported some "mask" type swizzle pattern for the destination - this adds support for all swizzle patterns - added a new function that can calculate the order of the components referenced by a given swizzle pattern - that is, it converts the swizzle values into an array of 4 ints, where each int references either x, y, z or w --- src/internal_includes/toGLSLOperand.h | 1 + src/toGLSLInstruction.c | 26 +++++-- src/toGLSLOperand.c | 106 ++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 6 deletions(-) diff --git a/src/internal_includes/toGLSLOperand.h b/src/internal_includes/toGLSLOperand.h index 5116aef..b142d3d 100644 --- a/src/internal_includes/toGLSLOperand.h +++ b/src/internal_includes/toGLSLOperand.h @@ -37,6 +37,7 @@ void TranslateOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const uint32_t GetNumSwizzleElements(const Operand* psOperand); uint32_t GetNumSwizzleElementsWithMask(const Operand *psOperand, uint32_t ui32CompMask); +uint32_t GetOrderedSwizzleElements(const Operand *psOperand, uint32_t ui32CompMask, uint32_t result[4]); void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count); int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); uint32_t IsSwizzleReplicated(const Operand* psOperand); diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 5671ada..16fb3a2 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -4572,18 +4572,32 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn } case OPCODE_RESINFO: { - uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t destElem; + uint32_t destSwizzle[4]; + uint32_t destElemCount = GetOrderedSwizzleElements(&psInst->asOperands[0], OPERAND_4_COMPONENT_MASK_ALL, destSwizzle); + + uint32_t srcSwizzle[4]; + uint32_t srcElemCount = GetOrderedSwizzleElements(&psInst->asOperands[2], OPERAND_4_COMPONENT_MASK_ALL, srcSwizzle); + + uint32_t eleIndex; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//RESINFO\n"); #endif - for (destElem = 0; destElem < destElemCount; ++destElem) + for (eleIndex = 0; eleIndex < min(srcElemCount, destElemCount); ++eleIndex) { - const char* swizzle[] = { ".x", ".y", ".z", ".w" }; - - GetResInfoData(psContext, psInst, psInst->asOperands[2].aui32Swizzle[destElem], destElem); + // note -- This doesn't follow the normal pattern for dealing with + // swizzles. We need to take into account the swizzle values + // attached to both and input and output operands, and we need + // to support the different possible modes. The code uses a + // different pattern for other operations... We could refactor + // this path to better match the other code... But it could take + // some work, because single RESINFO instructions can generate multiple + // GLSL expressions. + GetResInfoData( + psContext, psInst, + srcSwizzle[eleIndex], + destSwizzle[eleIndex]); } break; diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 9f92861..6d5785a 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -319,6 +319,112 @@ uint32_t GetNumSwizzleElementsWithMask(const Operand *psOperand, uint32_t ui32Co return count; } +static uint32_t FindBitsInMask(uint32_t mask, uint32_t result[4]) +{ + uint32_t outputCount = 0; + for (unsigned c=0; c<4; ++c) + if (mask & (1<eType) + { + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: + return 1; // TODO: does mask make any sense here? + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: + case OPERAND_TYPE_INPUT_THREAD_ID: + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: + // Adjust component count and break to more processing + ((Operand *)psOperand)->iNumComponents = 3; + break; + case OPERAND_TYPE_IMMEDIATE32: + case OPERAND_TYPE_IMMEDIATE64: + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH: + { + // Translate numComponents into bitmask + // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 + uint32_t compMask = (1 << psOperand->iNumComponents) - 1; + + compMask &= ui32CompMask; + // Calculate bits left in compMask + return FindBitsInMask(compMask, result); + } + default: + { + break; + } + } + + if(psOperand->iWriteMaskEnabled && + psOperand->iNumComponents != 1) + { + //Component Mask + if(psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t compMask = psOperand->ui32CompMask; + if (compMask == 0) + compMask = OPERAND_4_COMPONENT_MASK_ALL; + compMask &= ui32CompMask; + count = FindBitsInMask(compMask, result); + } + else + //Component Swizzle + if(psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if(psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + for(i=0; i< 4; ++i) + { + if ((ui32CompMask & (1 << i)) == 0) + continue; + + ASSERT( psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X + || psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y + || psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z + || psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W); + result[count++] = psOperand->aui32Swizzle[i]; + } + } + } + else + if(psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (ui32CompMask & psOperand->aui32Swizzle[0]) + result[count++] = psOperand->aui32Swizzle[0]; + } + + //Component Select 1 + } + + if(!count) + { + // Translate numComponents into bitmask + // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 + uint32_t compMask = (1 << psOperand->iNumComponents) - 1; + + compMask &= ui32CompMask; + // Calculate bits left in compMask + return FindBitsInMask(compMask, result); + } + + return count; +} + void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count) { bstring glsl = *psContext->currentGLSLString; From 017bf7fc0f9faa0f3b07f5b4165289bc8841cf36 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 18 Apr 2016 19:51:59 +0900 Subject: [PATCH 15/47] Shader inputs are now correctly sized for the used components - previously all shader inputs would be 4 component vectors - this could cause shader linking errors now that vertex shaders can output fewer components - this change uses the "component" layout attribute and uses the correct sized vector types --- src/toGLSLDeclaration.c | 73 ++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 2653499..58c8921 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -70,6 +70,31 @@ const uint32_t GetTypeElementCount(GLVARTYPE eType) } } +static int LSBBit(uint32_t value) +{ + // Returns the least significant bit set, zero based + // Lots of hardware has intructions built-in for this... But for portability, + // we're just going to use a general solution. This isn't used by a performance + // critical client. + // (see: http://stackoverflow.com/questions/757059/position-of-least-significant-bit-that-is-set) + const int MultiplyDeBruijnBitPosition[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + int32_t x = (int32_t)value; + return MultiplyDeBruijnBitPosition[((uint32_t)((x & -x) * 0x077CB531U)) >> 27]; +} + +static int MSBBit(uint32_t x) +{ + // Returns the most significant bit set, zero based + // Like LSBBit, just using a general method (even though there might be a hardware instruction) + int r = 0; + while (x >>= 1) r++; + return r; +} + void AddToDx9ImmConstIndexableArray(HLSLCrossCompilerContext* psContext, const Operand* psOperand) { bstring* savedStringPtr = psContext->currentGLSLString; @@ -415,7 +440,7 @@ const char* GetInterpolationString(INTERPOLATION_MODE eMode) static void DeclareInput( HLSLCrossCompilerContext* psContext, const Declaration* psDecl, - const char* Interpolation, const char* StorageQualifier, const char* Precision, int iNumComponents, OPERAND_INDEX_DIMENSION eIndexDim, const char* InputName) + const char* Interpolation, const char* StorageQualifier, const char* Precision, OPERAND_INDEX_DIMENSION eIndexDim, const char* InputName) { Shader* psShader = psContext->psShader; bstring glsl = *psContext->currentGLSLString; @@ -461,12 +486,25 @@ static void DeclareInput( } } + int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) + int lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); + int iNumComponents = highestComponent - lowestComponent + 1; + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags) || (psShader->eShaderType == VERTEX_SHADER && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->flags))) { // Skip location if requested by the flags. if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + { + if (HasInterfaceComponentQualifier(psContext->psShader->eTargetLanguage)) + { + bformata(glsl, "layout(location = %d, component = %d) ", psDecl->asOperands[0].ui32RegisterNumber, lowestComponent); + } + else + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + } } switch(eIndexDim) @@ -811,31 +849,6 @@ void AddBuiltinOutput(HLSLCrossCompilerContext* psContext, const Declaration* ps } } -static int LSBBit(uint32_t value) -{ - // Returns the least significant bit set, zero based - // Lots of hardware has intructions built-in for this... But for portability, - // we're just going to use a general solution. This isn't used by a performance - // critical client. - // (see: http://stackoverflow.com/questions/757059/position-of-least-significant-bit-that-is-set) - const int MultiplyDeBruijnBitPosition[32] = - { - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 - }; - int32_t x = (int32_t)value; - return MultiplyDeBruijnBitPosition[((uint32_t)((x & -x) * 0x077CB531U)) >> 27]; -} - -static int MSBBit(uint32_t x) -{ - // Returns the most significant bit set, zero based - // Like LSBBit, just using a general method (even though there might be a hardware instruction) - int r = 0; - while (x >>= 1) r++; - return r; -} - static void WriteOutputFixup(HLSLCrossCompilerContext* psContext, const Operand* psOperand, const char* OutputName) { // Here, we copy from a temporary buffer (called OutputXX) to @@ -1851,7 +1864,6 @@ void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration Would generate a vec2 and a vec3. We discard the second one making .z invalid! */ - int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); const char* StorageQualifier = "attribute"; const char* InputName; const char* Precision = ""; @@ -1914,7 +1926,7 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } DeclareInput(psContext, psDecl, - "", StorageQualifier, Precision, iNumComponents, (OPERAND_INDEX_DIMENSION)psOperand->iIndexDims, InputName); + "", StorageQualifier, Precision, (OPERAND_INDEX_DIMENSION)psOperand->iIndexDims, InputName); break; } @@ -1941,7 +1953,6 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! case OPCODE_DCL_INPUT_PS: { const Operand* psOperand = &psDecl->asOperands[0]; - int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); const char* StorageQualifier = "varying"; const char* Precision = ""; const char* InputName = GetDeclaredInputName(psContext, PIXEL_SHADER, psOperand); @@ -2023,7 +2034,7 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } DeclareInput(psContext, psDecl, - Interpolation, StorageQualifier, Precision, iNumComponents, INDEX_1D, InputName); + Interpolation, StorageQualifier, Precision, INDEX_1D, InputName); break; } From cb719bdada59e62494a16b3c6bf141ac05a3495f Mon Sep 17 00:00:00 2001 From: MrShoor Date: Fri, 22 Apr 2016 11:57:15 -0700 Subject: [PATCH 16/47] typecast of gl_FrontFacing should match with type of destination Input code: uvec4 Input7 Input7.x = uint(gl_FrontFacing); cause: error C7011: implicit cast from "int" to "uint" at least at NVidia GF960 --- offline/toGLSLStandalone.cpp | 2 +- src/toGLSLDeclaration.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/offline/toGLSLStandalone.cpp b/offline/toGLSLStandalone.cpp index 0013971..f71a676 100644 --- a/offline/toGLSLStandalone.cpp +++ b/offline/toGLSLStandalone.cpp @@ -16,7 +16,7 @@ #include "timer.h" #if defined(_WIN32) -#define VALIDATE_OUTPUT +//#define VALIDATE_OUTPUT #endif #if defined(VALIDATE_OUTPUT) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 234d355..6e9570e 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1526,7 +1526,22 @@ void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration Suggests no implicit conversion for bool<->int. */ - AddBuiltinInput(psContext, psDecl, "int(gl_FrontFacing)"); + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, &psDecl->asOperands[0]); + switch (eType) + { + case SVT_INT: + AddBuiltinInput(psContext, psDecl, "int(gl_FrontFacing)"); + break; + case SVT_UINT: + AddBuiltinInput(psContext, psDecl, "uint(gl_FrontFacing)"); + break; + case SVT_BOOL: + AddBuiltinInput(psContext, psDecl, "bool(gl_FrontFacing)"); + break; + default: + AddBuiltinInput(psContext, psDecl, "float(gl_FrontFacing)"); + break; + } break; } case NAME_SAMPLE_INDEX: From fc0c9e66de30b23046820733abf9177fa5d0d841 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 25 Apr 2016 20:09:48 +0900 Subject: [PATCH 17/47] New callback to allow the client to construct the rules for selecting binding points and descriptor set indices - Clients can use the callback function, EvaluateBindingFn, to select any binding, descriptor set, or location for HLSL resources - clients get access to the type, HLSL binding register information and name with which to make an assignment - this is important for Vulkan, were we need to assign descriptor sets to resources - depreciated the previous flags, HLSLCC_FLAG_PREFER_BINDINGS & HLSLCC_FLAG_ASSIGN_DESCRIPTOR_SET, since this is much more powerful solution --- include/hlslcc.h | 33 ++++++++--- src/internal_includes/structs.h | 2 + src/toGLSL.c | 34 ++++++++---- src/toGLSLDeclaration.c | 97 ++++++++++++++++++++++----------- 4 files changed, 114 insertions(+), 52 deletions(-) diff --git a/include/hlslcc.h b/include/hlslcc.h index e7c99b1..ce6a1eb 100644 --- a/include/hlslcc.h +++ b/include/hlslcc.h @@ -323,6 +323,25 @@ typedef struct TextureSamplerInfo_TAG TextureSamplerPair aTextureSamplerPair[MAX_RESOURCE_BINDINGS]; } TextureSamplerInfo; +typedef enum GLSL_BINDING_FLAGS +{ + GLSL_BINDING_TYPE_PUSHCONSTANTS = 1<<0, +} GLSL_BINDING_FLAGS; + +typedef struct GLSLResourceBinding_TAG { + uint32_t _locationIndex; + uint32_t _bindingIndex; + uint32_t _setIndex; + uint32_t _flags; // GLSL_BINDING_FLAGS +} GLSLResourceBinding; + +typedef uint32_t (*EvaluateBindingFn)( + void* userData, + GLSLResourceBinding* dstBinding, + ResourceBinding* srcResBinding, + ConstantBuffer* srcCBBinding, + uint32_t bindPoint, uint32_t shaderStage); + typedef struct ShaderInfo_TAG { uint32_t ui32MajorVersion; @@ -445,13 +464,6 @@ 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, always write binding qualifiers for resources, rather than location qualifiers -static const unsigned int HLSLCC_FLAG_PREFER_BINDINGS = 0x1000; - -//If set, bindings for different types of resources assigned to different descriptor sets -//(eg, in HLSL we can assign a resource to "register(t8)" or "register(b8)" -- they both become binding 8, but in different sets) -static const unsigned int HLSLCC_FLAG_ASSIGN_DESCRIPTOR_SET = 0x2000; - #ifdef __cplusplus extern "C" { #endif @@ -466,14 +478,17 @@ HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFile(const char* filename, GLLang language, const GlExtensions *extensions, GLSLCrossDependencyData* dependencies, - GLSLShader* result - ); + EvaluateBindingFn evaluateBindingFn, + void* evaluateBindingData, + GLSLShader* result); HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader, unsigned int flags, GLLang language, const GlExtensions *extensions, GLSLCrossDependencyData* dependencies, + EvaluateBindingFn evaluateBindingFn, + void* evaluateBindingData, GLSLShader* result); HLSLCC_API void HLSLCC_APIENTRY FreeGLSLShader(GLSLShader*); diff --git a/src/internal_includes/structs.h b/src/internal_includes/structs.h index eff56bc..347c8de 100644 --- a/src/internal_includes/structs.h +++ b/src/internal_includes/structs.h @@ -259,6 +259,8 @@ typedef struct HLSLCrossCompilerContext_TAG unsigned int flags; Shader* psShader; GLSLCrossDependencyData* psDependencies; + EvaluateBindingFn pEvaluateBindingFn; + void* pEvaluateBindingData; } HLSLCrossCompilerContext; #endif diff --git a/src/toGLSL.c b/src/toGLSL.c index 32b1711..460cb11 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -323,20 +323,25 @@ void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) } /* For versions which do not support a vec1 (currently all versions) */ - bcatcstr(glsl,"struct vec1 {\n"); - bcatcstr(glsl,"\tfloat x;\n"); - bcatcstr(glsl,"};\n"); + // DavidJ -- Replacing this with a define. + // Using a struct was causing problems with code like: + // vec1 value; + // value = 0.5f; + // Here, the ".x" could be ommitted after "value" because + // both sides are determined to have the same components. + // That's fine with true vectors; but does not produce the + // correct result when using a "struct" to stand in for vec1. + // + // Note -- this is still not going to work correctly, because "value.x" + // isn't valid for scalar types in GLSL! + bcatcstr(glsl, "#define vec1 float\n"); if(HaveUVec(psContext->psShader->eTargetLanguage)) { - bcatcstr(glsl,"struct uvec1 {\n"); - bcatcstr(glsl,"\tuint x;\n"); - bcatcstr(glsl,"};\n"); + bcatcstr(glsl, "#define uvec1 uint\n"); } - bcatcstr(glsl,"struct ivec1 {\n"); - bcatcstr(glsl,"\tint x;\n"); - bcatcstr(glsl,"};\n"); + bcatcstr(glsl, "#define ivec1 int\n"); /* OpenGL 4.1 API spec: @@ -760,6 +765,8 @@ HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader, GLLang language, const GlExtensions *extensions, GLSLCrossDependencyData* dependencies, + EvaluateBindingFn evaluateBindingFn, + void* evaluateBindingData, GLSLShader* result) { uint32_t* tokens; @@ -785,6 +792,8 @@ HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader, sContext.psShader = psShader; sContext.flags = flags; sContext.psDependencies = dependencies; + sContext.pEvaluateBindingFn = evaluateBindingFn; + sContext.pEvaluateBindingData = evaluateBindingData; for(i=0; iflags & HLSLCC_FLAG_PREFER_BINDINGS) == HLSLCC_FLAG_PREFER_BINDINGS; - preferBindings |= (type == BINDABLE_UBO) || (type == BINDABLE_UNORDERED_ACCESS); + if (psContext->pEvaluateBindingFn) { + GLSLResourceBinding binding; + binding._locationIndex = ~0u; + binding._bindingIndex = ~0u; + binding._setIndex = ~0u; + binding._flags = 0; + uint32_t bindingAttempt = + (*psContext->pEvaluateBindingFn)( + psContext->pEvaluateBindingData, + &binding, + srcResBinding, srcCBBinding, + ui32BindingPoint, shaderStage); + if (bindingAttempt) { + bformata(glsl, "layout("); + int needComma = 0; + + if (binding._flags & GLSL_BINDING_TYPE_PUSHCONSTANTS) { + bformata(glsl, "push_constant"); + needComma = 1; + } + + if (binding._locationIndex != ~0u) { + if (needComma) bformata(glsl, ", "); + bformata(glsl, "location = %d", binding._locationIndex); + needComma = 1; + } + + if (binding._bindingIndex != ~0u) { + if (needComma) bformata(glsl, ", "); + bformata(glsl, "binding = %d", binding._bindingIndex); + needComma = 1; + } + + if (binding._setIndex != ~0u) { + if (needComma) bformata(glsl, ", "); + bformata(glsl, "set = %d", binding._setIndex); + needComma = 1; + } + + bformata(glsl, ") "); + return; + } + } + + ResourceGroup resGroup = RGROUP_CBUFFER; + if (srcResBinding) + resGroup = ResourceTypeToResourceGroup(srcResBinding->eType); + + unsigned preferBindings = (resGroup == RGROUP_CBUFFER) || (resGroup == RGROUP_UAV); if (preferBindings && HaveBindingQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) { - const unsigned assignSet = (psContext->flags & HLSLCC_FLAG_ASSIGN_DESCRIPTOR_SET) == HLSLCC_FLAG_ASSIGN_DESCRIPTOR_SET; + const unsigned assignSet = 0; if (!assignSet) { // when not assigning a set, we need to shift the binding point to after all constant buffers // (to avoid overlapping) - if (type == BINDABLE_RESOURCE) + if (resGroup == RGROUP_TEXTURE) ui32BindingPoint += psContext->psShader->sInfo.ui32NumConstantBuffers; } - bformata(glsl, "layout(binding = %d", ui32BindingPoint); - - // note, we could set the location, also, if HaveUniformBindingsAndLocations...? - if (assignSet) - { - unsigned setIndex = 0; - switch (type) - { - default: - case BINDABLE_UBO: setIndex = 0; break; - case BINDABLE_RESOURCE: setIndex = 1; break; - case BINDABLE_UNORDERED_ACCESS: setIndex = 2; break; - } - bformata(glsl, ", set = %d", setIndex); - } - - bcatcstr(glsl, ") "); + bformata(glsl, "layout(binding = %d)", ui32BindingPoint); return; } // If we haven't selected to write a binding, let's write a location. This maintains backward compatibility if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) { - if (type == BINDABLE_RESOURCE) + if (resGroup == RGROUP_TEXTURE) ui32BindingPoint += psContext->psShader->sInfo.ui32NumConstantBuffers; bformata(glsl, "layout(location = %d) ", ui32BindingPoint); @@ -1291,7 +1320,7 @@ void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui3 } /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - WriteUniformLayout(psContext, BINDABLE_UBO, ui32BindingPoint, glsl); + WriteUniformLayout(psContext, NULL, psCBuf, ui32BindingPoint, psContext->psShader->eShaderType, glsl); bformata(glsl, "uniform %s {\n ", Name); for(i=0; i < psCBuf->ui32NumVars; ++i) @@ -1337,7 +1366,7 @@ void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t u &psCBuf->asVars[0].sType); /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - WriteUniformLayout(psContext, BINDABLE_UNORDERED_ACCESS, ui32BindingPoint, glsl); + WriteUniformLayout(psContext, NULL, psCBuf, ui32BindingPoint, psContext->psShader->eShaderType, glsl); if(ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) { @@ -2156,7 +2185,9 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! // for each HLSL texture declaration, but when combining textures+samplers, there can be multiple OGL samplers for each HLSL texture declaration. if ((psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) != HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) { - WriteUniformLayout(psContext, BINDABLE_RESOURCE, psDecl->asOperands[0].ui32RegisterNumber, glsl); + ResourceBinding* psBinding = 0; + int found = GetResourceFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, glsl); } switch(psDecl->value.eResourceDimension) From fdf120198dcf7cd41c64a0217993abc0e4e6bbb2 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Wed, 27 Apr 2016 12:58:49 +0900 Subject: [PATCH 18/47] Added support for separated texture and sampler objects (as defined by GL_KHR_vulkan_glsl) - this is useful when compiling to Vulkan - when using the "Load" method in texture objects in HLSL, we need to use a dummy sampler in the generated GLSL - this appears to only be required in order to compile... the sampler may have no effect on the output - the dummy sampler is bound to s16 by default; but it can be rebound using the bind evaluation function --- src/decode.c | 2 + src/internal_includes/languages.h | 5 + src/toGLSL.c | 36 ++++++ src/toGLSLDeclaration.c | 195 +++++++++++++++++++++++++++++- src/toGLSLInstruction.c | 103 ++++++++-------- src/toGLSLOperand.c | 10 +- 6 files changed, 295 insertions(+), 56 deletions(-) diff --git a/src/decode.c b/src/decode.c index 5c1900a..46e5bbd 100644 --- a/src/decode.c +++ b/src/decode.c @@ -444,6 +444,8 @@ const uint32_t* DecodeDeclaration(Shader* psShader, const uint32_t* pui32Token, } case OPCODE_DCL_SAMPLER: { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token+ui32OperandOffset, &psDecl->asOperands[0]); break; } case OPCODE_DCL_INDEX_RANGE: diff --git a/src/internal_includes/languages.h b/src/internal_includes/languages.h index b37f653..ad3098a 100644 --- a/src/internal_includes/languages.h +++ b/src/internal_includes/languages.h @@ -93,6 +93,11 @@ static int HaveBindingQualifier(const GLLang eLang, const struct GlExtensions *e || (extensions && ((GlExtensions*)extensions)->ARB_shading_language_420pack); } +static int HaveSeparateTexturesAndSamplers(const GLLang eLang, const struct GlExtensions *extensions) +{ + return extensions && ((GlExtensions*)extensions)->GL_KHR_vulkan_glsl; +} + static int DualSourceBlendSupported(const GLLang eLang) { if(eLang >= LANG_330) diff --git a/src/toGLSL.c b/src/toGLSL.c index 460cb11..cbdc44b 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -77,6 +77,13 @@ void AddIndentation(HLSLCrossCompilerContext* psContext) } } +void WriteUniformLayout( + HLSLCrossCompilerContext* psContext, + ResourceBinding* srcResBinding, + ConstantBuffer* srcCBBinding, + unsigned ui32BindingPoint, unsigned shaderStage, + bstring glsl); + void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) { bstring glsl = *psContext->currentGLSLString; @@ -343,6 +350,35 @@ void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) bcatcstr(glsl, "#define ivec1 int\n"); + // In HLSL, we can use "Load" on a texture object and access it without a sampler. + // For GLSL, we have 2 options: + // * use a gtexture2d/gsampler2d and access with texelFetch + // * use a image2d and access with imageLoad + // + // If we use imageLoad, we don't need a sampler. This is a closer analogue to HLSL. + // If we use gtexture2d, we need to use a sampler. But we can also call other texture + // access functions (like texture, textureGather). + // + // It seems like "images" will be necessary if we need to perform atomic operations on + // the data (ie, like RWTextures in HLSL). + // But for HLSL "texture" objects, perhaps it's best to just stick with gtexture2d/gsampler2d + // objects for consistancy. But, we will need to declare a dummy sampler to use with texelFetch. + if (HaveSeparateTexturesAndSamplers(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) { + ResourceBinding resBinding; + strcpy(resBinding.Name, "DummySampler"); + resBinding.eType = RTYPE_SAMPLER; + resBinding.ui32BindPoint = 16; + resBinding.ui32BindCount = 1; + resBinding.ui32Flags = 0; + resBinding.eDimension = REFLECT_RESOURCE_DIMENSION_UNKNOWN; + resBinding.ui32ReturnType = 0; + resBinding.ui32NumSamples = 0; + WriteUniformLayout( + psContext, &resBinding, NULL, resBinding.ui32BindPoint, + psContext->psShader->eShaderType, glsl); + bcatcstr(glsl, "uniform sampler DummySampler;\n"); + } + /* OpenGL 4.1 API spec: To use any built-in input or output in the gl_PerVertex block in separable diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index bdcb12f..dfd03ac 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1198,7 +1198,7 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec } } -static void WriteUniformLayout( +void WriteUniformLayout( HLSLCrossCompilerContext* psContext, ResourceBinding* srcResBinding, ConstantBuffer* srcCBBinding, @@ -1600,6 +1600,169 @@ char* GetSamplerType(HLSLCrossCompilerContext* psContext, return "sampler2D"; } +char* GetTextureType(HLSLCrossCompilerContext* psContext, + const RESOURCE_DIMENSION eDimension, + const uint32_t ui32RegisterNumber) +{ + // This is used when GL_KHR_vulkan_glsl is enabled, and allows us to specify + // a texture object is in independant from any sampling function (much like the DirectX + // method of separating textures and samplers) + // Just following the pattern from GetSamplerType very closely + + ResourceBinding* psBinding = 0; + RESOURCE_RETURN_TYPE eType = RETURN_TYPE_UNORM; + int found; + found = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + if(found) + { + eType = (RESOURCE_RETURN_TYPE)psBinding->ui32ReturnType; + } + switch(eDimension) + { + case RESOURCE_DIMENSION_BUFFER: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itextureBuffer"; + case RETURN_TYPE_UINT: + return "utextureBuffer"; + default: + return "samplerBuffer"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE1D: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itexture1D"; + case RETURN_TYPE_UINT: + return "utexture1D"; + default: + return "texture1D"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2D: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itexture2D"; + case RETURN_TYPE_UINT: + return "utexture2D"; + default: + return "texture2D"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DMS: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itexture2DMS"; + case RETURN_TYPE_UINT: + return "utexture2DMS"; + default: + return "texture2DMS"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE3D: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itexture3D"; + case RETURN_TYPE_UINT: + return "utexture3D"; + default: + return "texture3D"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURECUBE: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itextureCube"; + case RETURN_TYPE_UINT: + return "utextureCube"; + default: + return "textureCube"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itexture1DArray"; + case RETURN_TYPE_UINT: + return "utexture1DArray"; + default: + return "texture1DArray"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itexture2DArray"; + case RETURN_TYPE_UINT: + return "utexture2DArray"; + default: + return "texture2DArray"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itexture2DMSArray"; + case RETURN_TYPE_UINT: + return "utexture2DMSArray"; + default: + return "texture2DMSArray"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "itextureCubeArray"; + case RETURN_TYPE_UINT: + return "utextureCubeArray"; + default: + return "textureCubeArray"; + } + break; + } + } + + return "texture2D"; +} + static void TranslateResourceTexture(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, uint32_t samplerCanDoShadowCmp) { bstring glsl = *psContext->currentGLSLString; @@ -1631,6 +1794,13 @@ static void TranslateResourceTexture(HLSLCrossCompilerContext* psContext, const ConcatTextureSamplerName(glsl, &psShader->sInfo, psDecl->asOperands[0].ui32RegisterNumber, psDecl->ui32SamplerUsed[i], 0); bcatcstr(glsl, ";\n"); } + } + else if (HaveSeparateTexturesAndSamplers(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + samplerTypeName = GetTextureType( + psContext, + psDecl->value.eResourceDimension, + psDecl->asOperands[0].ui32RegisterNumber); } if(samplerCanDoShadowCmp && psDecl->ui32IsShadowTex) @@ -2194,9 +2364,18 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! { case RESOURCE_DIMENSION_BUFFER: { - bformata(glsl, "uniform %s ", GetSamplerType(psContext, + const char* samplerTypeName = GetSamplerType( + psContext, RESOURCE_DIMENSION_BUFFER, - psDecl->asOperands[0].ui32RegisterNumber)); + psDecl->asOperands[0].ui32RegisterNumber); + if (HaveSeparateTexturesAndSamplers(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + samplerTypeName = GetTextureType( + psContext, + RESOURCE_DIMENSION_BUFFER, + psDecl->asOperands[0].ui32RegisterNumber); + } + bformata(glsl, "uniform %s ", samplerTypeName); TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); bcatcstr(glsl, ";\n"); break; @@ -2593,6 +2772,16 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } case OPCODE_DCL_SAMPLER: { + if ((psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) != HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) + { + ResourceBinding* psBinding = 0; + int found = GetResourceFromBindingPoint(RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, glsl); + + bformata(glsl, "uniform sampler "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bcatcstr(glsl, ";\n"); + } break; } case OPCODE_DCL_HS_MAX_TESSFACTOR: diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 16fb3a2..e83fa0d 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -676,6 +676,40 @@ static void CallHelper1Int(HLSLCrossCompilerContext* psContext, AddAssignPrologue(psContext, numParenthesis); } +char* GetSamplerType(HLSLCrossCompilerContext* psContext, + const RESOURCE_DIMENSION eDimension, + const uint32_t ui32RegisterNumber); + +static void WriteSamplerExpression(HLSLCrossCompilerContext* psContext, uint32_t textureRegisterNumber, uint32_t samplerRegisterNumber, const int bZCompare) +{ + bstring glsl = *psContext->currentGLSLString; + const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; + if (useCombinedTextureSamplers) { + if (samplerRegisterNumber != ~0) { + bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, textureRegisterNumber, samplerRegisterNumber, bZCompare)); + } else { + ResourceName(glsl, psContext, RGROUP_TEXTURE, textureRegisterNumber, bZCompare); + } + } else if (HaveSeparateTexturesAndSamplers(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) { + char* combinedSamplerType = GetSamplerType(psContext, psContext->psShader->aeResourceDims[textureRegisterNumber], textureRegisterNumber); + bcatcstr(glsl, combinedSamplerType); + bcatcstr(glsl, "("); + ResourceName(glsl, psContext, RGROUP_TEXTURE, textureRegisterNumber, bZCompare); + bcatcstr(glsl, ", "); + if (samplerRegisterNumber != ~0) { + ResourceName(glsl, psContext, RGROUP_SAMPLER, samplerRegisterNumber, bZCompare); + } else { + // These cases are generated by methods such as "Load" in HLSL. Load takes no + // sampler in HLSL, but GLSL requires some sampler object (see the description of "GL_KHR_vulkan_glsl") + // We must provide a dummy sampler to get valid GLSL output. + bcatcstr(glsl, "DummySampler"); + } + bcatcstr(glsl, ")"); + } else { + ResourceName(glsl, psContext, RGROUP_TEXTURE, textureRegisterNumber, bZCompare); + } +} + static void TranslateTexelFetch(HLSLCrossCompilerContext* psContext, Instruction* psInst, ResourceBinding* psBinding, @@ -692,7 +726,7 @@ static void TranslateTexelFetch(HLSLCrossCompilerContext* psContext, case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: case REFLECT_RESOURCE_DIMENSION_BUFFER: { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); if (psBinding->eDimension != REFLECT_RESOURCE_DIMENSION_BUFFER) @@ -703,7 +737,7 @@ static void TranslateTexelFetch(HLSLCrossCompilerContext* psContext, case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); bcatcstr(glsl, ", 0)"); @@ -712,7 +746,7 @@ static void TranslateTexelFetch(HLSLCrossCompilerContext* psContext, case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); bcatcstr(glsl, ", 0)"); @@ -721,7 +755,7 @@ static void TranslateTexelFetch(HLSLCrossCompilerContext* psContext, case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: // TODO does this make any sense at all? { ASSERT(psInst->eOpcode == OPCODE_LD_MS); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); bcatcstr(glsl, ", "); @@ -732,7 +766,7 @@ static void TranslateTexelFetch(HLSLCrossCompilerContext* psContext, case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: { ASSERT(psInst->eOpcode == OPCODE_LD_MS); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); bcatcstr(glsl, ", "); @@ -770,7 +804,7 @@ static void TranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, { case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); bformata(glsl, ", 0, %d)", psInst->iUAddrOffset); @@ -778,7 +812,7 @@ static void TranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, } case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); bformata(glsl, ", 0, ivec2(%d, %d))", @@ -788,7 +822,7 @@ static void TranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, } case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); bformata(glsl, ", 0, ivec3(%d, %d, %d))", @@ -799,7 +833,7 @@ static void TranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, } case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); bformata(glsl, ", 0, ivec2(%d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset); @@ -807,7 +841,7 @@ static void TranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, } case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0, 0); bcatcstr(glsl, ", "); TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); bformata(glsl, ", 0, int(%d))", psInst->iUAddrOffset); @@ -1034,8 +1068,6 @@ static void TranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruct const int iHaveOverloadedTexFuncs = HaveOverloadedTextureFuncs(psContext->psShader->eTargetLanguage); - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; - ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); if (psInst->bAddressOffset) @@ -1130,10 +1162,7 @@ static void TranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruct { bcatcstr(glsl, "texture("); } - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) ? 1 : 0); - else - bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) ? 1 : 0)); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) ? 1 : 0); bcatcstr(glsl, ","); TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); bcatcstr(glsl, ","); @@ -1177,10 +1206,7 @@ static void TranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruct { bformata(glsl, "%s%s(", funcName, offset); } - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 1); - else - bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); bformata(glsl, ", %s(", depthCmpCoordType); TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); bcatcstr(glsl, ","); @@ -1214,10 +1240,7 @@ static void TranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruct { bformata(glsl, "%s%s(", funcName, offset); } - if (!useCombinedTextureSamplers) - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE);//resource - else - bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0)); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0); bcatcstr(glsl, ", "); TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); @@ -3254,7 +3277,6 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn //dest, coords, tex, sampler ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//GATHER4\n"); @@ -3263,12 +3285,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn AddIndentation(psContext); // TODO FIXME integer samplers AddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); bcatcstr(glsl, "textureGather("); - - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); - else - bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0)); - + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0); bcatcstr(glsl, ", "); TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); bcatcstr(glsl, ")"); @@ -3286,7 +3303,6 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn //dest, coords, offset, tex, sampler, srcReferenceValue ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//GATHER4_PO_C\n"); @@ -3295,12 +3311,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn AddIndentation(psContext); // TODO FIXME integer samplers AddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); bcatcstr(glsl, "textureGatherOffset("); - - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, 1); - else - bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); - + WriteSamplerExpression(psContext, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 1); bcatcstr(glsl, ", "); TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); @@ -3327,7 +3338,6 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn //dest, coords, offset, tex, sampler ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//GATHER4_PO\n"); @@ -3336,12 +3346,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn AddIndentation(psContext); // TODO FIXME integer samplers AddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); bcatcstr(glsl, "textureGatherOffset("); - - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, 0); - else - bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0)); - + WriteSamplerExpression(psContext, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0); bcatcstr(glsl, ", "); TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); @@ -3364,7 +3369,6 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn //dest, coords, tex, sampler srcReferenceValue ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; #ifdef _DEBUG AddIndentation(psContext); bcatcstr(glsl, "//GATHER4_C\n"); @@ -3373,12 +3377,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn AddIndentation(psContext); // TODO FIXME integer samplers AddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); bcatcstr(glsl, "textureGather("); - - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 1); - else - bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); - + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); bcatcstr(glsl, ", "); TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 6d5785a..404f7d7 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -2,6 +2,7 @@ #include "internal_includes/toGLSLDeclaration.h" #include "bstrlib.h" #include "hlslcc.h" +#include "internal_includes/languages.h" #include "internal_includes/debug.h" #include @@ -1466,7 +1467,14 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c } case OPERAND_TYPE_SAMPLER: { - bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber); + if (HaveSeparateTexturesAndSamplers(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + ResourceName(glsl, psContext, RGROUP_SAMPLER, psOperand->ui32RegisterNumber, 0); + } + else + { + bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber); + } *pui32IgnoreSwizzle = 1; break; } From 92f4e700b242562da8eae50c37b8848914df2c9a Mon Sep 17 00:00:00 2001 From: djewsbury Date: Wed, 27 Apr 2016 17:42:49 +0900 Subject: [PATCH 19/47] UAV objects can now have binding and set information --- src/toGLSLDeclaration.c | 61 +++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index dfd03ac..f085ec9 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1203,6 +1203,7 @@ void WriteUniformLayout( ResourceBinding* srcResBinding, ConstantBuffer* srcCBBinding, unsigned ui32BindingPoint, unsigned shaderStage, + const char* extraLayoutQualifiers, bstring glsl) { // Write the "layout(...)" decoration that should preceed uniform objects @@ -1239,33 +1240,39 @@ void WriteUniformLayout( srcResBinding, srcCBBinding, ui32BindingPoint, shaderStage); if (bindingAttempt) { - bformata(glsl, "layout("); + bcatcstr(glsl, "layout("); int needComma = 0; if (binding._flags & GLSL_BINDING_TYPE_PUSHCONSTANTS) { - bformata(glsl, "push_constant"); + bcatcstr(glsl, "push_constant"); needComma = 1; } if (binding._locationIndex != ~0u) { - if (needComma) bformata(glsl, ", "); + if (needComma) bcatcstr(glsl, ", "); bformata(glsl, "location = %d", binding._locationIndex); needComma = 1; } if (binding._bindingIndex != ~0u) { - if (needComma) bformata(glsl, ", "); + if (needComma) bcatcstr(glsl, ", "); bformata(glsl, "binding = %d", binding._bindingIndex); needComma = 1; } if (binding._setIndex != ~0u) { - if (needComma) bformata(glsl, ", "); + if (needComma) bcatcstr(glsl, ", "); bformata(glsl, "set = %d", binding._setIndex); needComma = 1; } - bformata(glsl, ") "); + if (extraLayoutQualifiers != NULL && extraLayoutQualifiers[0]) { + if (needComma) bcatcstr(glsl, ", "); + bcatcstr(glsl, extraLayoutQualifiers); + needComma = 1; + } + + bcatcstr(glsl, ") "); return; } } @@ -1287,7 +1294,14 @@ void WriteUniformLayout( ui32BindingPoint += psContext->psShader->sInfo.ui32NumConstantBuffers; } - bformata(glsl, "layout(binding = %d)", ui32BindingPoint); + bformata(glsl, "layout(binding = %d", ui32BindingPoint); + + if (extraLayoutQualifiers != NULL && extraLayoutQualifiers[0]) { + bcatcstr(glsl, ", "); + bcatcstr(glsl, extraLayoutQualifiers); + } + bcatcstr(glsl, ") "); + return; } @@ -1297,7 +1311,13 @@ void WriteUniformLayout( if (resGroup == RGROUP_TEXTURE) ui32BindingPoint += psContext->psShader->sInfo.ui32NumConstantBuffers; - bformata(glsl, "layout(location = %d) ", ui32BindingPoint); + bformata(glsl, "layout(location = %d", ui32BindingPoint); + + if (extraLayoutQualifiers != NULL && extraLayoutQualifiers[0]) { + bcatcstr(glsl, ", "); + bcatcstr(glsl, extraLayoutQualifiers); + } + bcatcstr(glsl, ") "); } } @@ -1320,7 +1340,7 @@ void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui3 } /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - WriteUniformLayout(psContext, NULL, psCBuf, ui32BindingPoint, psContext->psShader->eShaderType, glsl); + WriteUniformLayout(psContext, NULL, psCBuf, ui32BindingPoint, psContext->psShader->eShaderType, NULL, glsl); bformata(glsl, "uniform %s {\n ", Name); for(i=0; i < psCBuf->ui32NumVars; ++i) @@ -1366,7 +1386,7 @@ void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t u &psCBuf->asVars[0].sType); /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - WriteUniformLayout(psContext, NULL, psCBuf, ui32BindingPoint, psContext->psShader->eShaderType, glsl); + WriteUniformLayout(psContext, NULL, psCBuf, ui32BindingPoint, psContext->psShader->eShaderType, NULL, glsl); if(ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) { @@ -2357,7 +2377,7 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! { ResourceBinding* psBinding = 0; int found = GetResourceFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, glsl); + WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, NULL, glsl); } switch(psDecl->value.eResourceDimension) @@ -2776,7 +2796,7 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! { ResourceBinding* psBinding = 0; int found = GetResourceFromBindingPoint(RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, glsl); + WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, NULL, glsl); bformata(glsl, "uniform sampler "); TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); @@ -2793,6 +2813,7 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! { // non-float images need either 'i' or 'u' prefix. char imageTypePrefix[2] = { 0, 0 }; + char* extraLayoutQualifiers = ""; if(psDecl->sUAV.ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) { bcatcstr(glsl, "coherent "); @@ -2812,20 +2833,20 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! switch(psDecl->sUAV.Type) { case RETURN_TYPE_FLOAT: - bcatcstr(glsl, "layout(rgba32f) "); + extraLayoutQualifiers = "rgba32f"; break; case RETURN_TYPE_UNORM: - bcatcstr(glsl, "layout(rgba8) "); + extraLayoutQualifiers = "rgba8"; break; case RETURN_TYPE_SNORM: - bcatcstr(glsl, "layout(rgba8_snorm) "); + extraLayoutQualifiers = "rgba8_snorm"; break; case RETURN_TYPE_UINT: - bcatcstr(glsl, "layout(rgba32ui) "); + extraLayoutQualifiers = "rgba32ui"; imageTypePrefix[0] = 'u'; break; case RETURN_TYPE_SINT: - bcatcstr(glsl, "layout(rgba32i) "); + extraLayoutQualifiers = "rgba32i"; imageTypePrefix[0] = 'i'; break; default: @@ -2833,6 +2854,12 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } } + { + ResourceBinding* psBinding = 0; + int found = GetResourceFromBindingPoint(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, extraLayoutQualifiers, glsl); + } + switch(psDecl->value.eResourceDimension) { case RESOURCE_DIMENSION_BUFFER: From 6ced4a12a7391e05ec176e8f47eea8e3f2055115 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Wed, 27 Apr 2016 19:51:37 +0900 Subject: [PATCH 20/47] Passing ResourceBinding information through to the "evaluate binding" function for buffers - this allows us to distinquish between StructuredBuffer types and ConstantBuffers - both types have a "ConstantBuffer" object - but the true type can be determined from the "eType" member of the ResourceBinding object --- src/toGLSLDeclaration.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index f085ec9..3171e56 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1354,7 +1354,7 @@ void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui3 } void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, - ConstantBuffer* psCBuf, const Operand* psOperand, + ConstantBuffer* psCBuf, ResourceBinding* pResourceBinding, const Operand* psOperand, const uint32_t ui32GloballyCoherentAccess, const ResourceType eResourceType, bstring glsl) @@ -1386,7 +1386,7 @@ void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t u &psCBuf->asVars[0].sType); /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - WriteUniformLayout(psContext, NULL, psCBuf, ui32BindingPoint, psContext->psShader->eShaderType, NULL, glsl); + WriteUniformLayout(psContext, pResourceBinding, psCBuf, ui32BindingPoint, psContext->psShader->eShaderType, NULL, glsl); if(ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) { @@ -2924,6 +2924,7 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! { const uint32_t ui32BindingPoint = psDecl->asOperands[0].aui32ArraySizes[0]; ConstantBuffer* psCBuf = NULL; + ResourceBinding* pResBinding = NULL; if(psDecl->sUAV.bCounter) { @@ -2933,8 +2934,9 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } GetConstantBufferFromBindingPoint(RGROUP_UAV, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); + GetResourceFromBindingPoint(RGROUP_UAV, ui32BindingPoint, &psContext->psShader->sInfo, &pResBinding); - DeclareBufferVariable(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], + DeclareBufferVariable(psContext, ui32BindingPoint, psCBuf, pResBinding, &psDecl->asOperands[0], psDecl->sUAV.ui32GloballyCoherentAccess, RTYPE_UAV_RWSTRUCTURED, glsl); break; } @@ -2956,10 +2958,12 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! case OPCODE_DCL_RESOURCE_STRUCTURED: { ConstantBuffer* psCBuf = NULL; + ResourceBinding* pResBinding = NULL; GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + GetResourceFromBindingPoint(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &pResBinding); - DeclareBufferVariable(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, &psDecl->asOperands[0], + DeclareBufferVariable(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, pResBinding, &psDecl->asOperands[0], 0, RTYPE_STRUCTURED, glsl); break; } From cd2c8af2f1ba3445b85b451b7a151576895660b0 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Thu, 28 Apr 2016 12:07:03 +0900 Subject: [PATCH 21/47] Fix for using textureSize() with separated textures and samplers --- src/toGLSLInstruction.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index e83fa0d..8c3c04f 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -967,6 +967,7 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in RESOURCE_DIMENSION eResDim; const char* queryFunction = "textureSize"; int includeLODParameter = 1; + int isUAV = 0; // "UAV" types in HLSL become "image" types in GLSL. // In these cases, we must use "imageSize" rather than "textureSize" @@ -979,6 +980,7 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in eResDim = psContext->psShader->aeUAVResourceDims[psInst->asOperands[2].ui32RegisterNumber]; queryFunction = "imageSize"; includeLODParameter = 0; + isUAV = 1; } else { ASSERT(psInst->asOperands[2].eType == OPERAND_TYPE_RESOURCE); ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); @@ -1005,7 +1007,16 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in { bformata(glsl, "vec%d(%s(", dim, queryFunction); } - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + + // For "texture" types, we still need to write the sampler expression + // This will expand to something like sampler2d(textureName, DummySampler) when using + // GL_KHR_vulkan_glsl. + if (!isUAV) { + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0u, 0); + } else { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + } + if (includeLODParameter) { bcatcstr(glsl, ", "); TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); From fdf08ed7c02efcbd1a97b8e970f5ca7b0b0bc412 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Thu, 28 Apr 2016 19:39:18 +0900 Subject: [PATCH 22/47] Changed the naming conventions for RWStructuredBuffers to match StructuredBuffers - this allows the RWStructedBuffer's "buffer" object to contain the true name - that name will be preserved in the SPIR-V code and allows us to get at it using reflection on the SPIR-V bytecode --- src/toGLSLDeclaration.c | 4 ++-- src/toGLSLInstruction.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 3171e56..903937f 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1378,7 +1378,7 @@ void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t u } else { - ResourceName(StructName, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); + bformata(StructName, "StorageBuffer%d", psOperand->ui32RegisterNumber); } PreDeclareStructType(glsl, @@ -1398,7 +1398,7 @@ void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t u bcatcstr(glsl, "readonly "); } - bformata(glsl, "buffer Block%d {\n", psOperand->ui32RegisterNumber); + bformata(glsl, "buffer %s {\n", psCBuf->Name); DeclareConstBufferShaderVariable(glsl, bstr2cstr(StructName, '\0'), diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 8c3c04f..eed965e 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -1047,7 +1047,7 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in else bcatcstr(glsl, "float("); bcatcstr(glsl, "textureQueryLevels("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0u, 0); bcatcstr(glsl, "))"); } AddAssignPrologue(psContext, numParenthesis); @@ -1439,7 +1439,7 @@ static void TranslateShaderStorageStore(HLSLCrossCompilerContext* psContext, Ins } else { - TranslateOperand(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); + bformata(glsl, "StorageBuffer%d", psDest->ui32RegisterNumber); } bformata(glsl, "["); if (structured) //Dest address and dest byte offset @@ -1640,7 +1640,7 @@ static void TranslateShaderStorageLoad(HLSLCrossCompilerContext* psContext, Inst } if (psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) { - bformata(glsl, "%s[", psCBuf->Name); + bformata(glsl, "StorageBuffer%d[", psSrc->ui32RegisterNumber); TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); bcatcstr(glsl, "]"); if (strcmp(psVar->Name, "$Element") != 0) From ea29040c7fc144f89985e3fdfd4683b6624b6ff9 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 2 May 2016 14:47:29 +0900 Subject: [PATCH 23/47] More robust handling of swizzling for FTOI, FTOU, ITOF, UTOF and RESINFO instructions - these instructions were interpreted incorrectly for cases where the destination swizzle was not a contiguous sequence from .x - the new method handles more cases... - but this is only applied to a few instructions - it should really effect many instructions! --- src/internal_includes/toGLSLOperand.h | 2 ++ src/toGLSLInstruction.c | 24 +++++++------- src/toGLSLOperand.c | 47 +++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/internal_includes/toGLSLOperand.h b/src/internal_includes/toGLSLOperand.h index b142d3d..a135960 100644 --- a/src/internal_includes/toGLSLOperand.h +++ b/src/internal_includes/toGLSLOperand.h @@ -39,6 +39,8 @@ uint32_t GetNumSwizzleElements(const Operand* psOperand); uint32_t GetNumSwizzleElementsWithMask(const Operand *psOperand, uint32_t ui32CompMask); uint32_t GetOrderedSwizzleElements(const Operand *psOperand, uint32_t ui32CompMask, uint32_t result[4]); void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count); +void AddSwizzleUsingOrderedElements(HLSLCrossCompilerContext* psContext, const Operand *psOperand, uint32_t ui32CompMask); +void AddSwizzleUsingOrderedElementsDstMask(HLSLCrossCompilerContext* psContext, const Operand *psSrcOperand, const Operand *psMaskingOperand); int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); uint32_t IsSwizzleReplicated(const Operand* psOperand); diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index eed965e..07049e8 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -2745,7 +2745,6 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn case OPCODE_FTOI: case OPCODE_FTOU: { - uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); uint32_t ui32DstFlags = TO_FLAG_DESTINATION; const SHADER_VARIABLE_TYPE eSrcType = GetOperandDataType(psContext, &psInst->asOperands[1]); @@ -2762,13 +2761,15 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn AddIndentation(psContext); AddAssignToDest(psContext, &psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount, &numParenthesis); - bcatcstr(glsl, GetConstructorForType(psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount == dstCount ? dstCount : 4)); + bcatcstr(glsl, GetConstructorForType(psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, 4)); bcatcstr(glsl, "("); // 1 TranslateOperand(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT); + // we have to smear out the scalars here... + if (srcCount == 1) bcatcstr(glsl, ".xxxx"); bcatcstr(glsl, ")"); // 1 - // Add destination writemask if the component counts do not match - if (srcCount != dstCount) - TranslateOperandSwizzleWithMask(psContext, &psInst->asOperands[0], OPERAND_4_COMPONENT_MASK_ALL); + + // this seems like the only reliable way to catch every swizzling case --- + AddSwizzleUsingOrderedElementsDstMask(psContext, &psInst->asOperands[1], &psInst->asOperands[0]); AddAssignPrologue(psContext, numParenthesis); //*/ break; @@ -2789,7 +2790,6 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn { const SHADER_VARIABLE_TYPE eDestType = GetOperandDataType(psContext, &psInst->asOperands[0]); const SHADER_VARIABLE_TYPE eSrcType = GetOperandDataType(psContext, &psInst->asOperands[1]); - uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); #ifdef _DEBUG @@ -2805,13 +2805,15 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn #endif AddIndentation(psContext); AddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, srcCount, &numParenthesis); - bcatcstr(glsl, GetConstructorForType(SVT_FLOAT, srcCount == dstCount ? dstCount : 4)); + bcatcstr(glsl, GetConstructorForType(SVT_FLOAT, 4)); bcatcstr(glsl, "("); // 1 TranslateOperand(psContext, &psInst->asOperands[1], psInst->eOpcode == OPCODE_UTOF ? TO_AUTO_BITCAST_TO_UINT : TO_AUTO_BITCAST_TO_INT); + // we have to smear out the scalars here... + if (srcCount == 1) bcatcstr(glsl, ".xxxx"); bcatcstr(glsl, ")"); // 1 - // Add destination writemask if the component counts do not match - if (srcCount != dstCount) - AddSwizzleUsingElementCount(psContext, dstCount); + + // this seems like the only reliable way to catch every swizzling case --- + AddSwizzleUsingOrderedElementsDstMask(psContext, &psInst->asOperands[1], &psInst->asOperands[0]); AddAssignPrologue(psContext, numParenthesis); break; } @@ -4606,7 +4608,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn // GLSL expressions. GetResInfoData( psContext, psInst, - srcSwizzle[eleIndex], + srcSwizzle[min(destSwizzle[eleIndex], srcElemCount-1)], // (min causes a smear for scalar types) destSwizzle[eleIndex]); } diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 404f7d7..a09d0ac 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -454,6 +454,53 @@ void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t c } } +void AddSwizzleUsingOrderedElements(HLSLCrossCompilerContext* psContext, const Operand *psOperand, uint32_t ui32CompMask) +{ + bstring glsl = *psContext->currentGLSLString; + uint32_t elements[4]; + uint32_t count = GetOrderedSwizzleElements(psOperand, ui32CompMask, elements); + ASSERT(count!=0); + + bcatcstr(glsl, "."); + const char* eles[] = { "x", "y", "z", "w" }; + for (unsigned c=0; ccurrentGLSLString; + const char* eles[] = { "x", "y", "z", "w" }; + + uint32_t srcElements[4]; + uint32_t srcCount = GetOrderedSwizzleElements(psSrcOperand, OPERAND_4_COMPONENT_MASK_ALL, srcElements); + ASSERT(srcCount!=0); + + uint32_t dstElements[4]; + uint32_t dstCount = GetOrderedSwizzleElements(psMaskingOperand, OPERAND_4_COMPONENT_MASK_ALL, dstElements); + ASSERT(dstCount!=0); + + // We want to write only those components that properly overlap with the destination operand. + // It appears that if we have a situation like: + // value0.zw = value1.xy; + // + // Then psSrcOperand will have the swizzle "xxxy" + // and psMaskingOperand will have the swizzle "zw" + + bcatcstr(glsl, "."); + + // (for scalar src values, we just smear across the scalar value) + for (unsigned c=0; c Date: Mon, 2 May 2016 15:25:14 +0900 Subject: [PATCH 24/47] Another fix to FTOU/UTOF swizzling --- src/toGLSLInstruction.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 07049e8..08d352a 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -2769,7 +2769,9 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn bcatcstr(glsl, ")"); // 1 // this seems like the only reliable way to catch every swizzling case --- - AddSwizzleUsingOrderedElementsDstMask(psContext, &psInst->asOperands[1], &psInst->asOperands[0]); + // (note that this is using the swizzle on the write element, because we took care of the swizzle + // on operands[1] in the translate operand call) + AddSwizzleUsingOrderedElements(psContext, &psInst->asOperands[0], OPERAND_4_COMPONENT_MASK_ALL); AddAssignPrologue(psContext, numParenthesis); //*/ break; @@ -2813,7 +2815,9 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn bcatcstr(glsl, ")"); // 1 // this seems like the only reliable way to catch every swizzling case --- - AddSwizzleUsingOrderedElementsDstMask(psContext, &psInst->asOperands[1], &psInst->asOperands[0]); + // (note that this is using the swizzle on the write element, because we took care of the swizzle + // on operands[1] in the translate operand call) + AddSwizzleUsingOrderedElements(psContext, &psInst->asOperands[0], OPERAND_4_COMPONENT_MASK_ALL); AddAssignPrologue(psContext, numParenthesis); break; } From 94b5bd6b7e664fdf6619935c391ff9525c2b4023 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Mon, 2 May 2016 20:08:34 +0900 Subject: [PATCH 25/47] Fix for binding information for StructuredBuffer types --- src/toGLSLDeclaration.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 903937f..29e80bf 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -2961,7 +2961,7 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! ResourceBinding* pResBinding = NULL; GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - GetResourceFromBindingPoint(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &pResBinding); + GetResourceFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &pResBinding); DeclareBufferVariable(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, pResBinding, &psDecl->asOperands[0], 0, RTYPE_STRUCTURED, glsl); From 9a74ca375a48d5408262ce549b14291c213d3ab1 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Tue, 3 May 2016 12:43:07 +0900 Subject: [PATCH 26/47] Better logic for selecting method for "vec1", "uvec1", etc - selecting a #define for languages that support scalar swizzle, or falling back to old solution otherwise --- src/internal_includes/languages.h | 7 ++++++ src/toGLSL.c | 37 ++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/internal_includes/languages.h b/src/internal_includes/languages.h index ad3098a..ed400a0 100644 --- a/src/internal_includes/languages.h +++ b/src/internal_includes/languages.h @@ -98,6 +98,13 @@ static int HaveSeparateTexturesAndSamplers(const GLLang eLang, const struct GlEx return extensions && ((GlExtensions*)extensions)->GL_KHR_vulkan_glsl; } +static int HaveScalarSwizzle(const GLLang eLang, const struct GlExtensions *extensions) +{ + return + (eLang >= LANG_420) + || (extensions && ((GlExtensions*)extensions)->ARB_shading_language_420pack); +} + static int DualSourceBlendSupported(const GLLang eLang) { if(eLang >= LANG_330) diff --git a/src/toGLSL.c b/src/toGLSL.c index cbdc44b..3ac5b99 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -339,16 +339,33 @@ void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) // That's fine with true vectors; but does not produce the // correct result when using a "struct" to stand in for vec1. // - // Note -- this is still not going to work correctly, because "value.x" - // isn't valid for scalar types in GLSL! - bcatcstr(glsl, "#define vec1 float\n"); - - if(HaveUVec(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "#define uvec1 uint\n"); - } - - bcatcstr(glsl, "#define ivec1 int\n"); + // Note -- this requires GLSL 4.20 or ARB_shading_language_420pack to work + // correctly. When targetting older versions of OpenGL, some input + // HLSL code will generate incorrect results. + if (HaveScalarSwizzle(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + bcatcstr(glsl, "#define vec1 float\n"); + if(HaveUVec(psContext->psShader->eTargetLanguage)) + bcatcstr(glsl, "#define uvec1 uint\n"); + bcatcstr(glsl, "#define ivec1 int\n"); + } + else + { + bcatcstr(glsl,"struct vec1 {\n"); + bcatcstr(glsl,"\tfloat x;\n"); + bcatcstr(glsl,"};\n"); + + if(HaveUVec(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl,"struct uvec1 {\n"); + bcatcstr(glsl,"\tuint x;\n"); + bcatcstr(glsl,"};\n"); + } + + bcatcstr(glsl,"struct ivec1 {\n"); + bcatcstr(glsl,"\tint x;\n"); + bcatcstr(glsl,"};\n"); + } // In HLSL, we can use "Load" on a texture object and access it without a sampler. // For GLSL, we have 2 options: From 8a8bf5c839e6249a1be09862fbf620a946f6b71b Mon Sep 17 00:00:00 2001 From: djewsbury Date: Tue, 3 May 2016 16:12:21 +0900 Subject: [PATCH 27/47] Fix for single intructions that load from multiple cbuffer variables - Sometimes a single instruction will use values from multiple constant buffer variables. - So, for example, a constant buffer might look like this: cbuffer Buffer { float3 Vector; float Scalar; } - Now consider the following statement: variable = float4(Vector, Scalar); - this can become a single instruction, because both Vector and Scalar are packed into the same 4d vector in the cbuffer - new code for loading from a cbuffer that handles these cases - also some improvements to the swizzling code to handle more cases --- src/reflect.c | 28 ++++----- src/toGLSLInstruction.c | 9 ++- src/toGLSLOperand.c | 127 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 134 insertions(+), 30 deletions(-) diff --git a/src/reflect.c b/src/reflect.c index f047f87..b19f080 100644 --- a/src/reflect.c +++ b/src/reflect.c @@ -740,25 +740,23 @@ static int IsOffsetInType(ShaderVarType* psType, { pi32Index[0] = (offsetToFind - thisOffset) / 16; } - else if(psType->Class == SVC_VECTOR && psType->Columns > 1) - { - //Check for vector starting at a non-vec4 offset. + + //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 1; } diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 08d352a..2b6ea1c 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -2332,8 +2332,13 @@ static void SetCBOperandComponents(HLSLCrossCompilerContext *psContext, Operand GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - if (psVarType->Class == SVC_SCALAR) - psOperand->iNumComponents = 1; + // DavidJ -- Disabled this. It's causing problems with swizzling sometimes because + // we can't distinguish between operands with swizzle settings and those + // wihtout. + // It's not clear what the intended reason for it... So might be best + // just to get rid of it. + // if (psVarType->Class == SVC_SCALAR) + // psOperand->iNumComponents = 1; } diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index a09d0ac..eb876ce 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -323,7 +323,7 @@ uint32_t GetNumSwizzleElementsWithMask(const Operand *psOperand, uint32_t ui32Co static uint32_t FindBitsInMask(uint32_t mask, uint32_t result[4]) { uint32_t outputCount = 0; - for (unsigned c=0; c<4; ++c) + for (uint32_t c=0; c<4; ++c) if (mask & (1<eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + //Component Select 1 + if(psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) { - if (ui32CompMask & psOperand->aui32Swizzle[0]) - result[count++] = psOperand->aui32Swizzle[0]; + // (comp mask should be ignored in this case) + result[count++] = psOperand->aui32Swizzle[0]; } - - //Component Select 1 } if(!count) { - // Translate numComponents into bitmask - // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 - uint32_t compMask = (1 << psOperand->iNumComponents) - 1; - - compMask &= ui32CompMask; - // Calculate bits left in compMask - return FindBitsInMask(compMask, result); + for (uint32_t c=0; c<4; ++c) { + if (ui32CompMask & (1<iNumComponents-1)); + } + } } return count; @@ -1347,6 +1344,110 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c if((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) { + // Sometimes a single instruction will use values from multiple constant buffer variables. + // So, for example, a constant buffer might look like this: + // cbuffer Buffer { float3 Vector; float Scalar; } + // Now consider the following statement: + // variable = float4(Vector, Scalar); + // Because Vector and Scalar are contiguous and aligned as a 4d vector in the constant buffer, + // the statement can become a single 4d vector load in the HLSL bytecode. In order to generate + // correct GLSL, we must handle these cases. + + const uint32_t useNewPath = + psCBuf + && (psOperand->psSubOperand[0] == NULL) + && (psOperand->psSubOperand[1] == NULL) && (index == -1); + if (useNewPath) { + uint32_t opSwizzle[4]; + uint32_t eleCount = GetOrderedSwizzleElements(psOperand, ui32CompMask, opSwizzle); + ASSERT(eleCount > 0); + + // For each separate element, find the cbuffer element that matches + ShaderVarType* vars[4]; + uint32_t indices[4]; + uint32_t rebases[4]; + for (uint32_t c=0; caui32ArraySizes[1], &opSwizzle[c], + psCBuf, &vars[c], &indices[c], &rebases[c]); + } + + // We should expect that the Type of each variable is the same. + uint32_t needConstructorExpression = 0; + for (uint32_t c=1; cType == vars[0]->Type); + + needConstructorExpression = vars[c] != vars[0]; + } + + // In cases where we're stitching together elements from multiple + // variables, we need to use "constructor" syntax. But we can skip + // in this the more common case where just a single variable is used. + if (needConstructorExpression) { + const char* constructor = GetConstructorForType(vars[0]->Type, eleCount); + bformata(glsl, "%s(", constructor); + } + + int pendingComma = 0; + for (uint32_t c=0; cFullName); + + if(indices[c] != -1) + { + if ((vars[c]->Class == SVC_MATRIX_COLUMNS || vars[c]->Class == SVC_MATRIX_ROWS) && (vars[c]->Elements > 1)) + { + // Special handling for matrix arrays, open them up into vec4's + size_t matidx = indices[c] / 4; + size_t rowidx = indices[c] - (matidx*4); + bformata(glsl, "[%d][%d]", matidx, rowidx); + } + else + { + bformata(glsl, "[%d]", indices[c]); + } + } + + if (vars[c]->Class == SVC_SCALAR && end == c+1) { + for (uint32_t c2=c; c2>2))==0); + } + } else { + bcatcstr(glsl, "."); + const char* postfixes[4] = {"x", "y", "z", "w"}; + for (uint32_t c2=c; c2>2), 3)]); + } + } + + c = end; + pendingComma = 1; + } + + if (needConstructorExpression) { + bcatcstr(glsl, ")"); + } + + // if (!needConstructorExpression && vars[0]->Class == SVC_SCALAR) { + *pui32IgnoreSwizzle = 1; + // } + break; + } + //Work out the variable name. Don't apply swizzle to that variable yet. int32_t rebase = 0; From 8444828f9ea064ac2d466b750a3e8804224c3e33 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Tue, 3 May 2016 17:46:13 +0900 Subject: [PATCH 28/47] Support for shadow samplers when using separated samplers and textures --- include/hlslcc.h | 5 +++++ src/toGLSL.c | 4 ++-- src/toGLSLDeclaration.c | 22 +++++++++++++++------- src/toGLSLInstruction.c | 10 ++++++---- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/include/hlslcc.h b/include/hlslcc.h index ce6a1eb..0b5b0fa 100644 --- a/include/hlslcc.h +++ b/include/hlslcc.h @@ -160,6 +160,11 @@ typedef enum REFLECT_RESOURCE_DIMENSION REFLECT_RESOURCE_DIMENSION_BUFFEREX = 11, } REFLECT_RESOURCE_DIMENSION; +typedef enum REFLECT_RESOURCE_FLAGS +{ + REFLECT_RESOURCE_FLAGS_COMPARISON_SAMPLER = 0x2, +} REFLECT_RESOURCE_FLAGS; + typedef struct ResourceBinding_TAG { char Name[MAX_REFLECT_STRING_LENGTH]; diff --git a/src/toGLSL.c b/src/toGLSL.c index 3ac5b99..3cbc8d1 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -382,7 +382,7 @@ void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) // objects for consistancy. But, we will need to declare a dummy sampler to use with texelFetch. if (HaveSeparateTexturesAndSamplers(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) { ResourceBinding resBinding; - strcpy(resBinding.Name, "DummySampler"); + strcpy(resBinding.Name, "hlslcc_DummySampler"); resBinding.eType = RTYPE_SAMPLER; resBinding.ui32BindPoint = 16; resBinding.ui32BindCount = 1; @@ -393,7 +393,7 @@ void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) WriteUniformLayout( psContext, &resBinding, NULL, resBinding.ui32BindPoint, psContext->psShader->eShaderType, glsl); - bcatcstr(glsl, "uniform sampler DummySampler;\n"); + bcatcstr(glsl, "uniform sampler hlslcc_DummySampler;\n"); } /* diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 29e80bf..6b02cac 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -2380,6 +2380,10 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, NULL, glsl); } + int canDoShadowCmp = 1; + if (HaveSeparateTexturesAndSamplers(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + canDoShadowCmp = 0; + switch(psDecl->value.eResourceDimension) { case RESOURCE_DIMENSION_BUFFER: @@ -2402,12 +2406,12 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } case RESOURCE_DIMENSION_TEXTURE1D: { - TranslateResourceTexture(psContext, psDecl, 1); + TranslateResourceTexture(psContext, psDecl, canDoShadowCmp); break; } case RESOURCE_DIMENSION_TEXTURE2D: { - TranslateResourceTexture(psContext, psDecl, 1); + TranslateResourceTexture(psContext, psDecl, canDoShadowCmp); break; } case RESOURCE_DIMENSION_TEXTURE2DMS: @@ -2422,17 +2426,17 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } case RESOURCE_DIMENSION_TEXTURECUBE: { - TranslateResourceTexture(psContext, psDecl, 1); + TranslateResourceTexture(psContext, psDecl, canDoShadowCmp); break; } case RESOURCE_DIMENSION_TEXTURE1DARRAY: { - TranslateResourceTexture(psContext, psDecl, 1); + TranslateResourceTexture(psContext, psDecl, canDoShadowCmp); break; } case RESOURCE_DIMENSION_TEXTURE2DARRAY: { - TranslateResourceTexture(psContext, psDecl, 1); + TranslateResourceTexture(psContext, psDecl, canDoShadowCmp); break; } case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: @@ -2442,7 +2446,7 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } case RESOURCE_DIMENSION_TEXTURECUBEARRAY: { - TranslateResourceTexture(psContext, psDecl, 1); + TranslateResourceTexture(psContext, psDecl, canDoShadowCmp); break; } } @@ -2798,7 +2802,11 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! int found = GetResourceFromBindingPoint(RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, NULL, glsl); - bformata(glsl, "uniform sampler "); + if (psBinding->ui32Flags & REFLECT_RESOURCE_FLAGS_COMPARISON_SAMPLER) { + bformata(glsl, "uniform samplerShadow "); + } else { + bformata(glsl, "uniform sampler "); + } TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); bcatcstr(glsl, ";\n"); } diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 2b6ea1c..38dee1a 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -693,16 +693,18 @@ static void WriteSamplerExpression(HLSLCrossCompilerContext* psContext, uint32_t } else if (HaveSeparateTexturesAndSamplers(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) { char* combinedSamplerType = GetSamplerType(psContext, psContext->psShader->aeResourceDims[textureRegisterNumber], textureRegisterNumber); bcatcstr(glsl, combinedSamplerType); + if (bZCompare) + bcatcstr(glsl, "Shadow"); bcatcstr(glsl, "("); - ResourceName(glsl, psContext, RGROUP_TEXTURE, textureRegisterNumber, bZCompare); + ResourceName(glsl, psContext, RGROUP_TEXTURE, textureRegisterNumber, 0); bcatcstr(glsl, ", "); if (samplerRegisterNumber != ~0) { - ResourceName(glsl, psContext, RGROUP_SAMPLER, samplerRegisterNumber, bZCompare); + ResourceName(glsl, psContext, RGROUP_SAMPLER, samplerRegisterNumber, 0); } else { // These cases are generated by methods such as "Load" in HLSL. Load takes no // sampler in HLSL, but GLSL requires some sampler object (see the description of "GL_KHR_vulkan_glsl") // We must provide a dummy sampler to get valid GLSL output. - bcatcstr(glsl, "DummySampler"); + bcatcstr(glsl, "hlslcc_DummySampler"); } bcatcstr(glsl, ")"); } else { @@ -1009,7 +1011,7 @@ void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, in } // For "texture" types, we still need to write the sampler expression - // This will expand to something like sampler2d(textureName, DummySampler) when using + // This will expand to something like sampler2d(textureName, hlslcc_DummySampler) when using // GL_KHR_vulkan_glsl. if (!isUAV) { WriteSamplerExpression(psContext, psInst->asOperands[2].ui32RegisterNumber, ~0u, 0); From 3f8370c3c745b8cb6b0958eeb187d7940c798fc5 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Tue, 3 May 2016 20:15:56 +0900 Subject: [PATCH 29/47] Fixes for geometry shader input variables --- src/toGLSLDeclaration.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 6b02cac..4c52c23 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -287,7 +287,7 @@ const char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, cons if (eShaderType == VERTEX_SHADER) /* We cannot have input and output names conflict, but vs output must match ps input. Prefix vs input. */ inputName = bformat("in_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); else - inputName = bformat("%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); + inputName = bformat("%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); } else if(eShaderType == GEOMETRY_SHADER) { @@ -486,6 +486,9 @@ static void DeclareInput( } } + if (!psDecl->asOperands[0].iNumComponents) + return; + int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) int lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); int iNumComponents = highestComponent - lowestComponent + 1; @@ -521,7 +524,7 @@ static void DeclareInput( bformata(glsl, "%s %s %s %s [%d];\n", StorageQualifier, Precision, scalarType, InputName, arraySize); - bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "%s1 Input%d[%d];\n", vecType, psDecl->asOperands[0].ui32RegisterNumber, arraySize); psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; } @@ -545,35 +548,23 @@ static void DeclareInput( InputName = "TexCoord"; } - if(iNumComponents == 1) + if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) { - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = 1; + bformata(glsl, "%s %s %s %s%d %s", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); + bformata(glsl, "[%d];\n", psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - bformata(glsl, "%s %s %s %s %s;\n", Interpolation, StorageQualifier, Precision, scalarType, InputName); - bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "%s%d Input%d[%d];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, + psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; } else { - if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) - { - bformata(glsl, "%s %s %s %s%d %s", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - bformata(glsl, "[%d];\n", psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - - bformata(glsl, "%s%d Input%d[%d];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, - psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); + bformata(glsl, "%s%d Input%d;\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; - } - else - { - bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - bformata(glsl, "%s%d Input%d;\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; - } + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; } break; } From ca20f3788d0974fffb5292296a2df2f0911234c3 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Tue, 17 May 2016 11:51:58 +0900 Subject: [PATCH 30/47] Minor change to the cmake config to make it easier to generate separate Win32/x64 target builds --- mk/CMakeLists.txt | 11 +++++++++-- offline/toGLSLStandalone.cpp | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/mk/CMakeLists.txt b/mk/CMakeLists.txt index bceb17b..68f4641 100644 --- a/mk/CMakeLists.txt +++ b/mk/CMakeLists.txt @@ -17,8 +17,15 @@ IF( BUILD_SHARED_LIBS) ADD_DEFINITIONS(-DHLSLCC_DYNLIB) ENDIF( BUILD_SHARED_LIBS ) -SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin" ) -SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "../lib" ) +OPTION(TARGET_32BIT "Target 32 bit architexture" OFF) + +IF(TARGET_32BIT) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin32" ) + SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "../lib32" ) +ELSE() + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin64" ) + SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "../lib64" ) +ENDIF() #INCLUDE(TestBigEndian) diff --git a/offline/toGLSLStandalone.cpp b/offline/toGLSLStandalone.cpp index bde667b..a4e53a9 100644 --- a/offline/toGLSLStandalone.cpp +++ b/offline/toGLSLStandalone.cpp @@ -606,7 +606,7 @@ int Run(const char* srcPath, const char* destPath, GLLang language, int flags, c ext.ARB_explicit_uniform_location = 0; ext.ARB_shading_language_420pack = 0; ext.GL_KHR_vulkan_glsl = 0; - compiledOK = TranslateHLSLFromFile(srcPath, flags, language, &ext , dependencies, &result); + compiledOK = TranslateHLSLFromFile(srcPath, flags, language, &ext , dependencies, NULL, NULL, &result); crossCompileTime = ReadTimer(&timer); if(compiledOK) From ce15153acca4087dbe2f753fdb3bb11c00bd6dca Mon Sep 17 00:00:00 2001 From: djewsbury Date: Tue, 17 May 2016 18:08:36 +0900 Subject: [PATCH 31/47] Fix for linking error when calling WriteUniformLayout() --- src/toGLSL.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/toGLSL.c b/src/toGLSL.c index 3cbc8d1..ddcb81f 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -82,6 +82,7 @@ void WriteUniformLayout( ResourceBinding* srcResBinding, ConstantBuffer* srcCBBinding, unsigned ui32BindingPoint, unsigned shaderStage, + const char* extraLayoutQualifiers, bstring glsl); void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) @@ -392,7 +393,7 @@ void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) resBinding.ui32NumSamples = 0; WriteUniformLayout( psContext, &resBinding, NULL, resBinding.ui32BindPoint, - psContext->psShader->eShaderType, glsl); + psContext->psShader->eShaderType, NULL, glsl); bcatcstr(glsl, "uniform sampler hlslcc_DummySampler;\n"); } From 1ec4781058a995285770e0f215aef89234c0e477 Mon Sep 17 00:00:00 2001 From: djewsbury Date: Thu, 19 May 2016 18:36:33 +0900 Subject: [PATCH 32/47] Using an "instance" name for all cbuffers when GL_KHR_vulkan_glsl is enabled - an instance name is required using the layout(push_constant) qualifier - so we use an instance name for all cbuffers to cover this case --- src/toGLSLDeclaration.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 4c52c23..96711d7 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1312,6 +1312,21 @@ void WriteUniformLayout( } } +static void InsertUBOInstName(ShaderVarType* dst, const char uboInstName[]) +{ + uint32_t i; + size_t len = strlen(uboInstName); + size_t dstLen = strlen(dst->FullName); + char* insert = dst->FullName; + + memmove_s(insert+len+1, MAX_REFLECT_STRING_LENGTH, insert, dstLen+1); + memcpy(insert, uboInstName, len); + insert[len] = '.'; + + for (i=0; iMemberCount; ++i) + InsertUBOInstName(&dst->Members[i], uboInstName); +} + void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* psCBuf, bstring glsl) @@ -1340,8 +1355,26 @@ void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui3 psCBuf->asVars[i].Name, &psCBuf->asVars[i].sType, 0); } - - bcatcstr(glsl, "};\n"); + + // When GL_KHR_vulkan_glsl is enabled, always use an "instance" name for cbuffers + // This is required when using the layout(push_constant) qualifier. But at this point, + // we can't easily see what binding was used. So we just use an instance name for all + // cbuffers. + uint32_t useUBOInstName = + psContext->psShader->extensions && ((GlExtensions*)psContext->psShader->extensions)->GL_KHR_vulkan_glsl; + + if (useUBOInstName) { + char instName[MAX_REFLECT_STRING_LENGTH]; + strcpy_s(instName, MAX_REFLECT_STRING_LENGTH, Name); + strcat_s(instName, MAX_REFLECT_STRING_LENGTH, "_inst"); + for(i=0; i < psCBuf->ui32NumVars; ++i) + { + InsertUBOInstName(&psCBuf->asVars[i].sType, instName); + } + bformata(glsl, "} %s;\n", instName); + } else { + bcatcstr(glsl, "};\n"); + } } void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, From bd1096e274dea0aa46ec5a50109da0809053b7f6 Mon Sep 17 00:00:00 2001 From: MrShoor Date: Wed, 24 Aug 2016 16:21:50 -0700 Subject: [PATCH 33/47] Domain shader input arrays now sized using gl_MaxPatchVertices (like Hull shader) Fixes the following error seen on an NVIDIA driver. Number components of parameters for domain shader should match with number components of input parameters of fragment shader --- src/toGLSLDeclaration.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 8e27322..d7b036b 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -514,7 +514,7 @@ static void DeclareInput( { case INDEX_2D: { - if(psShader->eShaderType == HULL_SHADER) + if ((psShader->eShaderType == HULL_SHADER) || (psShader->eShaderType == DOMAIN_SHADER)) { if(iNumComponents == 1) { @@ -1136,13 +1136,17 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec } case DOMAIN_SHADER: { + int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) + int lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); + int iNumComponents = highestComponent - lowestComponent + 1; + int stream = 0; const char* OutputName = GetDeclaredOutputName(psContext, DOMAIN_SHADER, psOperand, &stream); if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) { bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); } - bformata(glsl, "out %s4 %s;\n", type, OutputName); + bformata(glsl, "out %s%d %s;\n", type, iNumComponents, OutputName); bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); break; } From a601b5da7b9b2f0dcfebfba691fd7e5ea902c6e6 Mon Sep 17 00:00:00 2001 From: MrShoor Date: Thu, 25 Aug 2016 16:31:54 -0700 Subject: [PATCH 34/47] OPERAND_TYPE_INPUT_FORK_INSTANCE_ID should be presented as SVT_INT data type HS_CTRL_POINT_PHASE require post shader code phase (because it contain writing to gl_out) SetDataTypes current working wrong, because for case: 8: mov r0.x, vForkInstanceID.x 9: mov o[r0.x + 0].x, l(5.000000) will generated incorrect code: //MOV Temp_int[0].x = ivec4(floatBitsToInt(forkInstanceID)).x; // writing to Temp_int //MOV Output0[int(Temp[0].x)].x = vec4(immediateConstBufferF(int(Temp_int[0].x)).x).x; // but reading from Temp due psOperand->psSubOperand[0]->aeDataType == SVT_FLOAT of destination operand o[r0.x + 0].x --- src/decode.c | 6 ++++++ src/toGLSL.c | 2 +- src/toGLSLInstruction.c | 2 +- src/toGLSLOperand.c | 4 ++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/decode.c b/src/decode.c index 46e5bbd..fbf447c 100644 --- a/src/decode.c +++ b/src/decode.c @@ -269,6 +269,12 @@ uint32_t DecodeOperand (const uint32_t *pui32Tokens, Operand* psOperand) psOperand->aeDataType[0] = SVT_UINT; } + if (psOperand->eType == OPERAND_TYPE_INPUT_FORK_INSTANCE_ID) + { + eNumComponents = OPERAND_1_COMPONENT; + psOperand->aeDataType[0] = SVT_INT; + } + switch(eNumComponents) { case OPERAND_1_COMPONENT: diff --git a/src/toGLSL.c b/src/toGLSL.c index ddcb81f..3c4e714 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -627,7 +627,7 @@ void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,cons TranslateInstruction(psContext, psShader->asPhase[ui32Phase].ppsInst[ui32Instance]+i, NULL); } - if(haveInstancedForkPhase) + if(haveInstancedForkPhase||(ui32Phase==HS_CTRL_POINT_PHASE)) { psContext->indent--; AddIndentation(psContext); diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 78a2a81..469d5f2 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -2381,7 +2381,7 @@ void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, cons SHADER_VARIABLE_TYPE aeTempVecType[MAX_TEMP_VEC4 * 4]; - if (psContext->psShader->ui32MajorVersion <= 3) + if ((psContext->psShader->ui32MajorVersion <= 3) || (psContext->psShader->eShaderType==HULL_SHADER)) { for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) { diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index eb876ce..c8d5ce0 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -1970,6 +1970,10 @@ SHADER_VARIABLE_TYPE GetOperandDataTypeEx(HLSLCrossCompilerContext* psContext, c { return SVT_INT; } + case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: + { + return SVT_INT; + } default: { return SVT_FLOAT; From 73e624d4aecb551823f1ae97142d9b626a280fd4 Mon Sep 17 00:00:00 2001 From: MrShoor Date: Thu, 25 Aug 2016 17:44:20 -0700 Subject: [PATCH 35/47] fixes for no control point phase case --- src/toGLSL.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/toGLSL.c b/src/toGLSL.c index 3c4e714..4a1835e 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -669,30 +669,42 @@ void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,cons AddIndentation(psContext); bcatcstr(glsl, "//--- End Early Main ---\n"); #endif + if (psShader->asPhase[HS_CTRL_POINT_PHASE].ui32InstanceCount == 0) //empty HS_CTRL_POINT_PHASE case workaround + { + bcatcstr(glsl, " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"); + } + else + { + for (ui32Instance = 0; ui32Instance < psShader->asPhase[HS_CTRL_POINT_PHASE].ui32InstanceCount; ++ui32Instance) + { + AddIndentation(psContext); + bformata(glsl, " %s%d();\n", asPhaseFuncNames[HS_CTRL_POINT_PHASE], ui32Instance); + } + } - ui32PhaseFuncCallOrder[0] = HS_CTRL_POINT_PHASE; - ui32PhaseFuncCallOrder[1] = HS_FORK_PHASE; - ui32PhaseFuncCallOrder[2] = HS_JOIN_PHASE; - - for(ui32PhaseCallIndex=0; ui32PhaseCallIndex<3; ui32PhaseCallIndex++) + bcatcstr(glsl, " if (gl_InvocationID == 0) {\n"); //all other phase should be called once + ui32PhaseFuncCallOrder[0] = HS_FORK_PHASE; + ui32PhaseFuncCallOrder[1] = HS_JOIN_PHASE; + for (ui32PhaseCallIndex = 0; ui32PhaseCallIndex < 2; ui32PhaseCallIndex++) { ui32Phase = ui32PhaseFuncCallOrder[ui32PhaseCallIndex]; - for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) + for (ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) { AddIndentation(psContext); - bformata(glsl, "%s%d();\n", asPhaseFuncNames[ui32Phase], ui32Instance); + bformata(glsl, " %s%d();\n", asPhaseFuncNames[ui32Phase], ui32Instance); - if(ui32Phase == HS_FORK_PHASE) + if (ui32Phase == HS_FORK_PHASE) { - if(psShader->asPhase[HS_JOIN_PHASE].ui32InstanceCount || - (ui32Instance+1 < psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount)) + if (psShader->asPhase[HS_JOIN_PHASE].ui32InstanceCount || + (ui32Instance + 1 < psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount)) { AddIndentation(psContext); - bcatcstr(glsl, "barrier();\n"); + bcatcstr(glsl, " barrier();\n"); } } } } + if (ui32Phase>HS_CTRL_POINT_PHASE) bcatcstr(glsl, " }\n"); psContext->indent--; From 6c9c8010d4b6b67154f7172c3cc484fe67a54d2b Mon Sep 17 00:00:00 2001 From: MrShoor Date: Thu, 25 Aug 2016 17:58:44 -0700 Subject: [PATCH 36/47] barrier should be placed between control point stage and fork stage --- src/toGLSL.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/toGLSL.c b/src/toGLSL.c index 4a1835e..fa20b65 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -681,6 +681,7 @@ void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,cons bformata(glsl, " %s%d();\n", asPhaseFuncNames[HS_CTRL_POINT_PHASE], ui32Instance); } } + bcatcstr(glsl, " barrier();\n"); bcatcstr(glsl, " if (gl_InvocationID == 0) {\n"); //all other phase should be called once ui32PhaseFuncCallOrder[0] = HS_FORK_PHASE; @@ -699,7 +700,6 @@ void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,cons (ui32Instance + 1 < psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount)) { AddIndentation(psContext); - bcatcstr(glsl, " barrier();\n"); } } } From e64ed958cdcd4f2792b4fa88ff11f20f7ab5eff5 Mon Sep 17 00:00:00 2001 From: MrShoor Date: Fri, 26 Aug 2016 15:31:03 -0700 Subject: [PATCH 37/47] fixes fixes fixes for Hull Shader. Looks like working now. --- src/internal_includes/toGLSLDeclaration.h | 1 + src/internal_includes/toGLSLOperand.h | 1 + src/toGLSL.c | 40 +++++++++++++++++++--- src/toGLSLDeclaration.c | 41 ++++++++++++++++++++++- src/toGLSLOperand.c | 2 +- 5 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/internal_includes/toGLSLDeclaration.h b/src/internal_includes/toGLSLDeclaration.h index bf6c6bc..6dcc982 100644 --- a/src/internal_includes/toGLSLDeclaration.h +++ b/src/internal_includes/toGLSLDeclaration.h @@ -12,5 +12,6 @@ const char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, con //Each phase has its own temps. //Convert to global temps for GLSL. void ConsolidateHullTempVars(Shader* psShader); +void TranslateDeclaration_HS_NoControlPointStage(HLSLCrossCompilerContext* psContext); #endif diff --git a/src/internal_includes/toGLSLOperand.h b/src/internal_includes/toGLSLOperand.h index a135960..2d3139c 100644 --- a/src/internal_includes/toGLSLOperand.h +++ b/src/internal_includes/toGLSLOperand.h @@ -35,6 +35,7 @@ void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); void TranslateOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask); +uint32_t GetNumberBitsSet(uint32_t a); uint32_t GetNumSwizzleElements(const Operand* psOperand); uint32_t GetNumSwizzleElementsWithMask(const Operand *psOperand, uint32_t ui32CompMask); uint32_t GetOrderedSwizzleElements(const Operand *psOperand, uint32_t ui32CompMask, uint32_t result[4]); diff --git a/src/toGLSL.c b/src/toGLSL.c index fa20b65..4f83d7e 100644 --- a/src/toGLSL.c +++ b/src/toGLSL.c @@ -584,15 +584,25 @@ void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,cons asPhaseFuncNames[HS_JOIN_PHASE] = "join_phase"; ConsolidateHullTempVars(psShader); + int ControlPointCountValue = 1; for(i=0; i < psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount[0]; ++i) { - TranslateDeclaration(psContext, psShader->asPhase[HS_GLOBAL_DECL].ppsDecl[0]+i); + Declaration* ppsDecl = psShader->asPhase[HS_GLOBAL_DECL].ppsDecl[0] + i; + TranslateDeclaration(psContext, ppsDecl); + if (ppsDecl->eOpcode == OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT) ControlPointCountValue = ppsDecl->value.ui32MaxOutputVertexCount; } for(ui32Phase=HS_CTRL_POINT_PHASE; ui32PhasecurrentPhase = ui32Phase; + int DummyControlPointPhase = (ui32Phase == HS_CTRL_POINT_PHASE) && (psShader->asPhase[HS_CTRL_POINT_PHASE].ui32InstanceCount == 0); + + if (DummyControlPointPhase) + { + TranslateDeclaration_HS_NoControlPointStage(psContext); + } + for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) { isCurrentForkPhasedInstanced = 0; //reset for each fork phase for cases we don't have a fork phase instance count opcode. @@ -669,9 +679,30 @@ void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,cons AddIndentation(psContext); bcatcstr(glsl, "//--- End Early Main ---\n"); #endif - if (psShader->asPhase[HS_CTRL_POINT_PHASE].ui32InstanceCount == 0) //empty HS_CTRL_POINT_PHASE case workaround - { + if (psShader->asPhase[HS_CTRL_POINT_PHASE].ui32InstanceCount == 0) + { //copying control points data for empty control point phase bcatcstr(glsl, " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"); + bcatcstr(glsl, " gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n"); + //bcatcstr(glsl, " gl_out[gl_InvocationID].gl_ClipDistance[] = gl_in[gl_InvocationID].gl_ClipDistance[];\n"); todoooo copy all gl_ClipDistance + for (uint32_t outI = 0; outI < psShader->sInfo.ui32NumOutputSignatures; outI++) + { + InOutSignature outSeg = psShader->sInfo.psOutputSignatures[outI]; + if (outSeg.eSystemValueType != NAME_UNDEFINED) continue; + InOutSignature inSeg; + int inIndex = -1; + for (uint32_t inI = 0; inI < psShader->sInfo.ui32NumInputSignatures; inI++) + { + inSeg = psShader->sInfo.psInputSignatures[inI]; + if (inSeg.eSystemValueType != NAME_UNDEFINED) continue; + if (inSeg.ui32Register == outSeg.ui32Register) + { + inIndex = inI; + break; + } + } + if (inIndex < 0) continue; + bformata(glsl, " %s%d[gl_InvocationID] = %s%d[gl_InvocationID];\n", outSeg.SemanticName, outSeg.ui32SemanticIndex, inSeg.SemanticName, inSeg.ui32SemanticIndex); + } } else { @@ -682,8 +713,7 @@ void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage,cons } } bcatcstr(glsl, " barrier();\n"); - - bcatcstr(glsl, " if (gl_InvocationID == 0) {\n"); //all other phase should be called once + bformata(glsl, " if (gl_InvocationID == %d) {\n", ControlPointCountValue-1); //all other phases should be called once ui32PhaseFuncCallOrder[0] = HS_FORK_PHASE; ui32PhaseFuncCallOrder[1] = HS_JOIN_PHASE; for (ui32PhaseCallIndex = 0; ui32PhaseCallIndex < 2; ui32PhaseCallIndex++) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index d7b036b..b8771b8 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -1118,6 +1118,10 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec ASSERT(psDecl->asOperands[0].ui32RegisterNumber!=0);//Reg 0 should be gl_out[gl_InvocationID].gl_Position. + int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) + int lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); + int iNumComponents = highestComponent - lowestComponent + 1; + if(psContext->currentPhase == HS_JOIN_PHASE) { bformata(glsl, "out patch %s4 %s[];\n", type, OutputName); @@ -1129,7 +1133,7 @@ void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDec bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); } - bformata(glsl, "out %s4 %s[];\n", type, OutputName); + bformata(glsl, "out %s%d %s[];\n", type, iNumComponents, OutputName); } bformata(glsl, "#define Output%d %s[gl_InvocationID]\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); break; @@ -3093,6 +3097,41 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } } +void TranslateDeclSignatureFmt(HLSLCrossCompilerContext* psContext, char* fmt, InOutSignature sig) +{ + bstring glsl = psContext->glsl; + char* chVec; + switch (sig.eComponentType) { + case INOUT_COMPONENT_FLOAT32:{ + chVec = "vec"; + break; + } + case INOUT_COMPONENT_SINT32: { + chVec = "ivec"; + break; + } + case INOUT_COMPONENT_UINT32: { + chVec = "uvec"; + break; + } + } + bformata(glsl, fmt, chVec, GetNumberBitsSet(sig.ui32Mask), sig.SemanticName, sig.ui32SemanticIndex); +} + +void TranslateDeclaration_HS_NoControlPointStage(HLSLCrossCompilerContext* psContext) +{ + Shader* sh = psContext->psShader; + bstring glsl = psContext->glsl; + for (uint32_t i = 0; i < sh->sInfo.ui32NumInputSignatures; i++){ + if (sh->sInfo.psInputSignatures[i].eSystemValueType != NAME_UNDEFINED) continue; + TranslateDeclSignatureFmt(psContext, "in %s%d %s%d[];\n", sh->sInfo.psInputSignatures[i]); + } + for (uint32_t i = 0; i < sh->sInfo.ui32NumOutputSignatures; i++){ + if (sh->sInfo.psOutputSignatures[i].eSystemValueType != NAME_UNDEFINED) continue; + TranslateDeclSignatureFmt(psContext, "out %s%d %s%d[];\n", sh->sInfo.psOutputSignatures[i]); + } +} + //Convert from per-phase temps to global temps for GLSL. void ConsolidateHullTempVars(Shader* psShader) { diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index c8d5ce0..477ba04 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -161,7 +161,7 @@ uint32_t IsSwizzleReplicated(const Operand* psOperand) return 0; } -static uint32_t GetNumberBitsSet(uint32_t a) +uint32_t GetNumberBitsSet(uint32_t a) { // Calculate number of bits in a // Taken from https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 From 5522379fb2965729c83db5d35622268906168a76 Mon Sep 17 00:00:00 2001 From: MrShoor Date: Wed, 28 Sep 2016 17:04:20 -0700 Subject: [PATCH 38/47] flag HLSLCC_FLAG_DISABLE_VULKAN_DUMMIES added --- include/hlslcc.h | 3 +++ src/toGLSLDeclaration.c | 26 +++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/hlslcc.h b/include/hlslcc.h index 1b86a8f..9b3f48d 100644 --- a/include/hlslcc.h +++ b/include/hlslcc.h @@ -471,6 +471,9 @@ 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, no dummy materials will generated for Vulkan +static const unsigned int HLSLCC_FLAG_DISABLE_VULKAN_DUMMIES = 0x1000; + #ifdef __cplusplus extern "C" { #endif diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index b8771b8..c7c8454 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -2868,19 +2868,23 @@ Would generate a vec2 and a vec3. We discard the second one making .z invalid! } case OPCODE_DCL_SAMPLER: { - if ((psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) != HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) - { - ResourceBinding* psBinding = 0; - int found = GetResourceFromBindingPoint(RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, NULL, glsl); + if ((psContext->flags & HLSLCC_FLAG_DISABLE_VULKAN_DUMMIES) != HLSLCC_FLAG_DISABLE_VULKAN_DUMMIES) + { + if ((psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) != HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) + { + ResourceBinding* psBinding = 0; + int found = GetResourceFromBindingPoint(RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + WriteUniformLayout(psContext, psBinding, NULL, psDecl->asOperands[0].ui32RegisterNumber, psContext->psShader->eShaderType, NULL, glsl); - if (psBinding->ui32Flags & REFLECT_RESOURCE_FLAGS_COMPARISON_SAMPLER) { - bformata(glsl, "uniform samplerShadow "); - } else { - bformata(glsl, "uniform sampler "); + if (psBinding->ui32Flags & REFLECT_RESOURCE_FLAGS_COMPARISON_SAMPLER) { + bformata(glsl, "uniform samplerShadow "); + } + else { + bformata(glsl, "uniform sampler "); + } + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bcatcstr(glsl, ";\n"); } - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bcatcstr(glsl, ";\n"); } break; } From 0751d579d8a8bb1cf6aa1940c138017cb01340c3 Mon Sep 17 00:00:00 2001 From: mrshoor Date: Tue, 6 Dec 2016 15:12:46 +0800 Subject: [PATCH 39/47] fix swizling case for vec1 inputs: vec1 Input6; //.... Temp[123] = Input6.xxx + Input3.xyz; should be represented as: vec1 Input6; //.... Temp[123] = vec3(Input6.x) + Input3.xyz; --- src/toGLSLOperand.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 477ba04..3bfbc56 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -1140,12 +1140,19 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c if(ui32TOFlag & TO_FLAG_DECLARATION_NAME) { const char* name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); - bcatcstr(glsl, name); + bcatcstr(glsl, name); + } + else + { + const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; + InOutSignature* psIn; + GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn); + if ((psIn->ui32Mask == 1) && (psOperand->iNumComponents > 1)) { + bformata(glsl, "vec%d(Input%d.x)", requestedComponents, psOperand->ui32RegisterNumber); + pui32IgnoreSwizzle[0] = 1; + } else + bformata(glsl, "Input%d", psOperand->ui32RegisterNumber); } - else - { - bformata(glsl, "Input%d", psOperand->ui32RegisterNumber); - } } } break; From 509c9b88b069844550d516140e73cb4e77c9f1a8 Mon Sep 17 00:00:00 2001 From: mrshoor Date: Tue, 6 Dec 2016 16:08:05 +0800 Subject: [PATCH 40/47] fix link error due optimization --- src/toGLSLDeclaration.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index c7c8454..3cf3986 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -477,6 +477,7 @@ static void DeclareInput( } } } + else psSignature = NULL; if(psContext->psDependencies) { @@ -487,11 +488,18 @@ static void DeclareInput( } if (!psDecl->asOperands[0].iNumComponents) - return; - - int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) - int lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); - int iNumComponents = highestComponent - lowestComponent + 1; + return; + + int lowestComponent = 0; + int iNumComponents = 0; + if (psSignature) { + iNumComponents = MSBBit(psSignature->ui32Mask) + 1; + } else { + int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) + lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); + iNumComponents = highestComponent - lowestComponent + 1; + } + //int iNumComponents = highestComponent - lowestComponent + 1; if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags) || (psShader->eShaderType == VERTEX_SHADER && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->flags))) From bf332426c471bbf1809738cee25c2832ae3faca9 Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Sun, 22 Jan 2017 17:56:26 +0000 Subject: [PATCH 41/47] fix compilation error in Visual Studio --- src/decode.c | 24 ++++++++++++------------ src/decodeDX9.c | 2 +- src/internal_includes/structs.h | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/decode.c b/src/decode.c index c292673..8ea46b5 100644 --- a/src/decode.c +++ b/src/decode.c @@ -10,18 +10,18 @@ #include "internal_includes/toGLSLOperand.h" #define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )) -static enum {FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C')}; //DirectX byte code -static enum {FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R')}; //Shader model 4 code -static enum {FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X')}; //Shader model 5 code -static enum {FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F')}; //Resource definition (e.g. constant buffers) -static enum {FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N')}; //Input signature -static enum {FOURCC_IFCE = FOURCC('I', 'F', 'C', 'E')}; //Interface (for dynamic linking) -static enum {FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N')}; //Output signature -static enum {FOURCC_PSGN = FOURCC('P', 'C', 'S', 'G')}; //Patch-constant signature - -static enum {FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1')}; //Input signature with Stream and MinPrecision -static enum {FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1')}; //Output signature with Stream and MinPrecision -static enum {FOURCC_OSG5 = FOURCC('O', 'S', 'G', '5')}; //Output signature with Stream +enum {FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C')}; //DirectX byte code +enum {FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R')}; //Shader model 4 code +enum {FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X')}; //Shader model 5 code +enum {FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F')}; //Resource definition (e.g. constant buffers) +enum {FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N')}; //Input signature +enum {FOURCC_IFCE = FOURCC('I', 'F', 'C', 'E')}; //Interface (for dynamic linking) +enum {FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N')}; //Output signature +enum {FOURCC_PSGN = FOURCC('P', 'C', 'S', 'G')}; //Patch-constant signature + +enum {FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1')}; //Input signature with Stream and MinPrecision +enum {FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1')}; //Output signature with Stream and MinPrecision +enum {FOURCC_OSG5 = FOURCC('O', 'S', 'G', '5')}; //Output signature with Stream typedef struct DXBCContainerHeaderTAG { diff --git a/src/decodeDX9.c b/src/decodeDX9.c index 2495529..cf7833d 100644 --- a/src/decodeDX9.c +++ b/src/decodeDX9.c @@ -9,7 +9,7 @@ #include "internal_includes/hlslcc_malloc.h" #define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )) -static enum {FOURCC_CTAB = FOURCC('C', 'T', 'A', 'B')}; //Constant table +enum {FOURCC_CTAB = FOURCC('C', 'T', 'A', 'B')}; //Constant table #ifdef _DEBUG static uint64_t operandID = 0; diff --git a/src/internal_includes/structs.h b/src/internal_includes/structs.h index 241c851..af1e22a 100644 --- a/src/internal_includes/structs.h +++ b/src/internal_includes/structs.h @@ -157,14 +157,14 @@ enum {MAX_TEMP_VEC4 = 512}; enum {MAX_GROUPSHARED = 8}; -static enum {MAX_DX9_IMMCONST = 256}; +enum {MAX_DX9_IMMCONST = 256}; static const uint32_t MAIN_PHASE = 0; static const uint32_t HS_GLOBAL_DECL = 1; static const uint32_t HS_CTRL_POINT_PHASE = 2; static const uint32_t HS_FORK_PHASE = 3; static const uint32_t HS_JOIN_PHASE = 4; -static enum{ NUM_PHASES = 5}; +enum{ NUM_PHASES = 5}; typedef struct ShaderPhase_TAG { From c23bf2d865c16550d0aca511a3c949de70788978 Mon Sep 17 00:00:00 2001 From: mrshoor Date: Thu, 31 May 2018 16:50:49 -0700 Subject: [PATCH 42/47] fix: scalar type cannot be swizzled in GLSL fix: impossible assign vec1 to float --- src/toGLSLOperand.c | 101 ++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 3bfbc56..3c0605c 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -1147,7 +1147,7 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; InOutSignature* psIn; GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn); - if ((psIn->ui32Mask == 1) && (psOperand->iNumComponents > 1)) { + if ((psIn->ui32Mask == 1) && (requestedComponents > 1)) { bformata(glsl, "vec%d(Input%d.x)", requestedComponents, psOperand->ui32RegisterNumber); pui32IgnoreSwizzle[0] = 1; } else @@ -1391,6 +1391,23 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c needConstructorExpression = vars[c] != vars[0]; } + // For scalar types we should user constructor, because swizzling not allowed for scalar values + uint32_t isScalarValue = 0; + if (needConstructorExpression == 0) + { + if ((eleCount > 1) && (psOperand->ui32Swizzle == XXXX_SWIZZLE)) { + isScalarValue = 1; + for (uint32_t c = 0; c < eleCount; ++c) { + if (psOperand->aui32Swizzle[c] != OPERAND_4_COMPONENT_X){ + isScalarValue = 0; + break; + } + } + } + if (isScalarValue) needConstructorExpression = 1; + } + + // In cases where we're stitching together elements from multiple // variables, we need to use "constructor" syntax. But we can skip // in this the more common case where just a single variable is used. @@ -1399,50 +1416,54 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c bformata(glsl, "%s(", constructor); } - int pendingComma = 0; - for (uint32_t c=0; cFullName); + if (isScalarValue) { + bcatcstr(glsl, vars[0]->FullName); + } else { + int pendingComma = 0; + for (uint32_t c=0; cClass == SVC_MATRIX_COLUMNS || vars[c]->Class == SVC_MATRIX_ROWS) && (vars[c]->Elements > 1)) - { - // Special handling for matrix arrays, open them up into vec4's - size_t matidx = indices[c] / 4; - size_t rowidx = indices[c] - (matidx*4); - bformata(glsl, "[%d][%d]", matidx, rowidx); - } - else - { - bformata(glsl, "[%d]", indices[c]); - } - } + // Write the variable name, plus the swizzle sequence. + // Let's skip the swizzle in the case of scalars (unless + // they are smeared out over multiple elements) + bcatcstr(glsl, vars[c]->FullName); - if (vars[c]->Class == SVC_SCALAR && end == c+1) { - for (uint32_t c2=c; c2>2))==0); + if(indices[c] != -1) + { + if ((vars[c]->Class == SVC_MATRIX_COLUMNS || vars[c]->Class == SVC_MATRIX_ROWS) && (vars[c]->Elements > 1)) + { + // Special handling for matrix arrays, open them up into vec4's + size_t matidx = indices[c] / 4; + size_t rowidx = indices[c] - (matidx*4); + bformata(glsl, "[%d][%d]", matidx, rowidx); + } + else + { + bformata(glsl, "[%d]", indices[c]); + } } - } else { - bcatcstr(glsl, "."); - const char* postfixes[4] = {"x", "y", "z", "w"}; - for (uint32_t c2=c; c2>2), 3)]); + + if (vars[c]->Class == SVC_SCALAR && end == c+1) { + for (uint32_t c2=c; c2>2))==0); + } + } else { + bcatcstr(glsl, "."); + const char* postfixes[4] = {"x", "y", "z", "w"}; + for (uint32_t c2=c; c2>2), 3)]); + } } - } - c = end; - pendingComma = 1; + c = end; + pendingComma = 1; + } } if (needConstructorExpression) { From 78c8d63378d6cf75b03735665e75875d9a32dc54 Mon Sep 17 00:00:00 2001 From: mrshoor Date: Fri, 1 Jun 2018 17:30:32 -0700 Subject: [PATCH 43/47] input declaration mapping fixed --- src/internal_includes/reflect.h | 2 +- src/reflect.c | 5 +- src/toGLSLDeclaration.c | 250 +++++++++++++++++--------------- src/toGLSLOperand.c | 4 +- 4 files changed, 142 insertions(+), 119 deletions(-) diff --git a/src/internal_includes/reflect.h b/src/internal_includes/reflect.h index d1c0c1b..efc005e 100644 --- a/src/internal_includes/reflect.h +++ b/src/internal_includes/reflect.h @@ -11,7 +11,7 @@ void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_ int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar); -int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut); +int GetInputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32CompMask, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut); int GetOutputSignatureFromRegister(const uint32_t currentPhase, const uint32_t ui32Register, const uint32_t ui32Stream, diff --git a/src/reflect.c b/src/reflect.c index eb41813..99dd04c 100644 --- a/src/reflect.c +++ b/src/reflect.c @@ -585,7 +585,7 @@ int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, Sha return 0; } -int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) +int GetInputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32CompMask, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) { uint32_t i; const uint32_t ui32NumVars = psShaderInfo->ui32NumInputSignatures; @@ -593,7 +593,8 @@ int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* for(i=0; ipsInputSignatures; - if(ui32Register == psInputSignatures[i].ui32Register) + if(ui32Register == psInputSignatures[i].ui32Register && + (ui32CompMask & psInputSignatures[i].ui32Mask)) { *ppsOut = psInputSignatures+i; return 1; diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 3cf3986..6ba2d02 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -280,7 +280,7 @@ const char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, cons bstring inputName; char* cstr; InOutSignature* psIn; - int found = GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, &psContext->psShader->sInfo, &psIn); + int found = GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn); if((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && found) { @@ -449,158 +449,164 @@ static void DeclareInput( if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) return; - if(psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) - { - const char* vecType = "vec"; - const char* scalarType = "float"; - InOutSignature* psSignature = NULL; + int registerNotDeclared = psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0; - if( GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psSignature) ) + const char* vecType = "vec"; + const char* scalarType = "float"; + InOutSignature* psSignature = NULL; + + if (GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32CompMask, &psShader->sInfo, &psSignature)) + { + switch(psSignature->eComponentType) { - switch(psSignature->eComponentType) + case INOUT_COMPONENT_UINT32: { - case INOUT_COMPONENT_UINT32: - { - vecType = "uvec"; - scalarType = "uint"; - break; - } - case INOUT_COMPONENT_SINT32: - { - vecType = "ivec"; - scalarType = "int"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } + vecType = "uvec"; + scalarType = "uint"; + break; + } + case INOUT_COMPONENT_SINT32: + { + vecType = "ivec"; + scalarType = "int"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; } } - else psSignature = NULL; + } + else psSignature = NULL; - if(psContext->psDependencies) + if(psContext->psDependencies) + { + if(psShader->eShaderType == PIXEL_SHADER) { - if(psShader->eShaderType == PIXEL_SHADER) - { - psContext->psDependencies->aePixelInputInterpolation[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eInterpolation; - } + psContext->psDependencies->aePixelInputInterpolation[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eInterpolation; } + } - if (!psDecl->asOperands[0].iNumComponents) - return; + if (!psDecl->asOperands[0].iNumComponents) + return; - int lowestComponent = 0; - int iNumComponents = 0; - if (psSignature) { - iNumComponents = MSBBit(psSignature->ui32Mask) + 1; - } else { - int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) - lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); - iNumComponents = highestComponent - lowestComponent + 1; - } - //int iNumComponents = highestComponent - lowestComponent + 1; + int lowestComponent = 0; + int iNumComponents = 0; + if (psSignature) { + int highestComponent = MSBBit(psSignature->ui32Mask); + lowestComponent = LSBBit(psSignature->ui32Mask); + iNumComponents = highestComponent - lowestComponent + 1; + } else { + int highestComponent = MSBBit(psDecl->asOperands[0].ui32CompMask); // (zero based bit indexes) + lowestComponent = LSBBit(psDecl->asOperands[0].ui32CompMask); + iNumComponents = highestComponent - lowestComponent + 1; + } + //int iNumComponents = highestComponent - lowestComponent + 1; - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags) || - (psShader->eShaderType == VERTEX_SHADER && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->flags))) + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags) || + (psShader->eShaderType == VERTEX_SHADER && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->flags))) + { + // Skip location if requested by the flags. + if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) { - // Skip location if requested by the flags. - if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) + if (HasInterfaceComponentQualifier(psContext->psShader->eTargetLanguage)) { - if (HasInterfaceComponentQualifier(psContext->psShader->eTargetLanguage)) - { - bformata(glsl, "layout(location = %d, component = %d) ", psDecl->asOperands[0].ui32RegisterNumber, lowestComponent); - } - else - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } + bformata(glsl, "layout(location = %d, component = %d) ", psDecl->asOperands[0].ui32RegisterNumber, lowestComponent); + } + else + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); } } + } - switch(eIndexDim) + switch(eIndexDim) + { + case INDEX_2D: { - case INDEX_2D: - { - if ((psShader->eShaderType == HULL_SHADER) || (psShader->eShaderType == DOMAIN_SHADER)) + if ((psShader->eShaderType == HULL_SHADER) || (psShader->eShaderType == DOMAIN_SHADER)) + { + if(iNumComponents == 1) { - if(iNumComponents == 1) - { - const uint32_t regNum = psDecl->asOperands[0].ui32RegisterNumber; - const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; - - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; - - bformata(glsl, "%s %s %s %s [gl_MaxPatchVertices];\n", StorageQualifier, Precision, scalarType, InputName); + const uint32_t regNum = psDecl->asOperands[0].ui32RegisterNumber; + const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; - bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); + psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; - } - else - { - bformata(glsl, "%s %s %s%d %s [gl_MaxPatchVertices];\n", StorageQualifier, Precision, vecType, iNumComponents, InputName); + if (registerNotDeclared) + bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); - bformata(glsl, "%s%d Input%d[gl_MaxPatchVertices];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "%s %s %s %s [gl_MaxPatchVertices];\n", StorageQualifier, Precision, scalarType, InputName); - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->asOperands[0].aui32ArraySizes[0]; - } + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; } else - if(iNumComponents == 1) - { - const uint32_t regNum = psDecl->asOperands[0].ui32RegisterNumber; - const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; + { + if (registerNotDeclared) + bformata(glsl, "%s%d Input%d[gl_MaxPatchVertices];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); + + bformata(glsl, "%s %s %s%d %s [gl_MaxPatchVertices];\n", StorageQualifier, Precision, vecType, iNumComponents, InputName); - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->asOperands[0].aui32ArraySizes[0]; + } + } + else + if(iNumComponents == 1) + { + const uint32_t regNum = psDecl->asOperands[0].ui32RegisterNumber; + const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; - bformata(glsl, "%s %s %s %s [%d];\n", StorageQualifier, Precision, scalarType, InputName, - arraySize); + psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; + if (registerNotDeclared) bformata(glsl, "%s1 Input%d[%d];\n", vecType, psDecl->asOperands[0].ui32RegisterNumber, arraySize); - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; - } - else - { - bformata(glsl, "%s %s %s%d %s [%d];\n", StorageQualifier, Precision, vecType, iNumComponents, InputName, - psDecl->asOperands[0].aui32ArraySizes[0]); + bformata(glsl, "%s %s %s %s [%d];\n", StorageQualifier, Precision, scalarType, InputName, + arraySize); + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; + } + else + { + if (registerNotDeclared) bformata(glsl, "%s%d Input%d[%d];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, - psDecl->asOperands[0].aui32ArraySizes[0]); + psDecl->asOperands[0].aui32ArraySizes[0]); - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->asOperands[0].aui32ArraySizes[0]; - } - break; + bformata(glsl, "%s %s %s%d %s [%d];\n", StorageQualifier, Precision, vecType, iNumComponents, InputName, + psDecl->asOperands[0].aui32ArraySizes[0]); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->asOperands[0].aui32ArraySizes[0]; } - default: - { + break; + } + default: + { - if(psDecl->asOperands[0].eType == OPERAND_TYPE_SPECIAL_TEXCOORD) - { - InputName = "TexCoord"; - } + if(psDecl->asOperands[0].eType == OPERAND_TYPE_SPECIAL_TEXCOORD) + { + InputName = "TexCoord"; + } - if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) - { - bformata(glsl, "%s %s %s %s%d %s", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - bformata(glsl, "[%d];\n", psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - + if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) + { + if (registerNotDeclared) bformata(glsl, "%s%d Input%d[%d];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, - psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + bformata(glsl, "%s %s %s %s%d %s", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); + bformata(glsl, "[%d];\n", psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; - } - else - { - bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - bformata(glsl, "%s%d Input%d;\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; + } + else + { + if (registerNotDeclared) + bformata(glsl, "%s4 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; - } - break; + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; } + break; } } @@ -611,8 +617,24 @@ static void DeclareInput( if(psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == -1) //Not an array { + uint32_t mask32; + if (psSignature) + mask32 = psSignature->ui32Mask; + else + mask32 = psDecl->asOperands[0].ui32CompMask; + char maskDest[6] = { 0 }; + int maskpos = 0; + maskDest[maskpos++] = '.'; + if (mask32 & OPERAND_4_COMPONENT_MASK_X) maskDest[maskpos++] = 'x'; + if (mask32 & OPERAND_4_COMPONENT_MASK_Y) maskDest[maskpos++] = 'y'; + if (mask32 & OPERAND_4_COMPONENT_MASK_Z) maskDest[maskpos++] = 'z'; + if (mask32 & OPERAND_4_COMPONENT_MASK_W) maskDest[maskpos++] = 'w'; + + char maskSrc[6] = { '.', 'x', 'y', 'z', 'w', 0 }; + maskSrc[iNumComponents+1] = 0; + AddIndentation(psContext); - bformata(psContext->earlyMain, "Input%d = %s;\n", psDecl->asOperands[0].ui32RegisterNumber, InputName); + bformata(psContext->earlyMain, "Input%d%s = %s%s;\n", psDecl->asOperands[0].ui32RegisterNumber, &maskDest[0], InputName, &maskSrc[0]); } else { diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 3c0605c..8d94a0a 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -1146,7 +1146,7 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c { const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; InOutSignature* psIn; - GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn); + GetInputSignatureFromRegister(ui32Register, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn); if ((psIn->ui32Mask == 1) && (requestedComponents > 1)) { bformata(glsl, "vec%d(Input%d.x)", requestedComponents, psOperand->ui32RegisterNumber); pui32IgnoreSwizzle[0] = 1; @@ -1933,7 +1933,7 @@ SHADER_VARIABLE_TYPE GetOperandDataTypeEx(HLSLCrossCompilerContext* psContext, c return SVT_INT; } - if(GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) + if (GetInputSignatureFromRegister(ui32Register, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn)) { if( psIn->eComponentType == INOUT_COMPONENT_UINT32) { From d70f910639d84ca497eea542246ac4a07d3a6108 Mon Sep 17 00:00:00 2001 From: mrshoor Date: Mon, 4 Jun 2018 16:19:33 -0700 Subject: [PATCH 44/47] fix swizzling at scalar types fix input declaraion crashes --- offline/toGLSLStandalone.cpp | 4 ++++ src/internal_includes/reflect.h | 2 +- src/reflect.c | 8 ++++++-- src/toGLSLDeclaration.c | 4 ++-- src/toGLSLInstruction.c | 2 +- src/toGLSLOperand.c | 12 ++++++------ 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/offline/toGLSLStandalone.cpp b/offline/toGLSLStandalone.cpp index 2baafb5..5a71a1f 100644 --- a/offline/toGLSLStandalone.cpp +++ b/offline/toGLSLStandalone.cpp @@ -640,6 +640,10 @@ int Run(const char* srcPath, const char* destPath, GLLang language, int flags, c FreeGLSLShader(&result); } + else + { + printf("HLSLcc failed\n"); + } return compiledOK; } diff --git a/src/internal_includes/reflect.h b/src/internal_includes/reflect.h index efc005e..cca4753 100644 --- a/src/internal_includes/reflect.h +++ b/src/internal_includes/reflect.h @@ -11,7 +11,7 @@ void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_ int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar); -int GetInputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32CompMask, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut); +int GetInputSignatureFromRegister(const uint32_t ui32Register, const int eSelMode, uint32_t ui32CompMask, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut); int GetOutputSignatureFromRegister(const uint32_t currentPhase, const uint32_t ui32Register, const uint32_t ui32Stream, diff --git a/src/reflect.c b/src/reflect.c index 99dd04c..0c3bbb0 100644 --- a/src/reflect.c +++ b/src/reflect.c @@ -585,21 +585,25 @@ int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, Sha return 0; } -int GetInputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32CompMask, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) +int GetInputSignatureFromRegister(const uint32_t ui32Register, const int eSelMode, uint32_t ui32CompMask, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) { uint32_t i; const uint32_t ui32NumVars = psShaderInfo->ui32NumInputSignatures; + if (eSelMode != OPERAND_4_COMPONENT_MASK_MODE) + ui32CompMask = 0; + for(i=0; ipsInputSignatures; if(ui32Register == psInputSignatures[i].ui32Register && - (ui32CompMask & psInputSignatures[i].ui32Mask)) + ((ui32CompMask == 0)||(ui32CompMask & psInputSignatures[i].ui32Mask))) { *ppsOut = psInputSignatures+i; return 1; } } + ppsOut = NULL; return 0; } diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 6ba2d02..1b3d3d3 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -280,7 +280,7 @@ const char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, cons bstring inputName; char* cstr; InOutSignature* psIn; - int found = GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn); + int found = GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, psOperand->eSelMode, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn); if((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && found) { @@ -455,7 +455,7 @@ static void DeclareInput( const char* scalarType = "float"; InOutSignature* psSignature = NULL; - if (GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32CompMask, &psShader->sInfo, &psSignature)) + if (GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].eSelMode, psDecl->asOperands[0].ui32CompMask, &psShader->sInfo, &psSignature)) { switch(psSignature->eComponentType) { diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 469d5f2..3b0a436 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -2847,7 +2847,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn bcatcstr(glsl, "("); // 1 TranslateOperand(psContext, &psInst->asOperands[1], psInst->eOpcode == OPCODE_UTOF ? TO_AUTO_BITCAST_TO_UINT : TO_AUTO_BITCAST_TO_INT); // we have to smear out the scalars here... - if (srcCount == 1) bcatcstr(glsl, ".xxxx"); + //if (srcCount == 1) bcatcstr(glsl, ".xxxx"); bcatcstr(glsl, ")"); // 1 // this seems like the only reliable way to catch every swizzling case --- diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 8d94a0a..3f4c24e 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -1146,7 +1146,7 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c { const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; InOutSignature* psIn; - GetInputSignatureFromRegister(ui32Register, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn); + GetInputSignatureFromRegister(ui32Register, psOperand->eSelMode, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn); if ((psIn->ui32Mask == 1) && (requestedComponents > 1)) { bformata(glsl, "vec%d(Input%d.x)", requestedComponents, psOperand->ui32RegisterNumber); pui32IgnoreSwizzle[0] = 1; @@ -1933,7 +1933,7 @@ SHADER_VARIABLE_TYPE GetOperandDataTypeEx(HLSLCrossCompilerContext* psContext, c return SVT_INT; } - if (GetInputSignatureFromRegister(ui32Register, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn)) + if (GetInputSignatureFromRegister(ui32Register, psOperand->eSelMode, psOperand->ui32CompMask, &psContext->psShader->sInfo, &psIn)) { if( psIn->eComponentType == INOUT_COMPONENT_UINT32) { @@ -2026,13 +2026,13 @@ void TranslateOperandWithMask(HLSLCrossCompilerContext* psContext, const Operand { ui32TOFlag &= ~(TO_AUTO_BITCAST_TO_FLOAT|TO_AUTO_BITCAST_TO_INT|TO_AUTO_BITCAST_TO_UINT); } - + if(ui32TOFlag & TO_FLAG_NAME_ONLY) { TranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); return; } - + switch(psOperand->eModifier) { case OPERAND_MODIFIER_NONE: @@ -2057,12 +2057,12 @@ void TranslateOperandWithMask(HLSLCrossCompilerContext* psContext, const Operand } TranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle, ui32ComponentMask); - + if(!ui32IgnoreSwizzle) { TranslateOperandSwizzleWithMask(psContext, psOperand, ui32ComponentMask); } - + switch(psOperand->eModifier) { case OPERAND_MODIFIER_NONE: From 22a61ce9d6e2bf6ecf73c5e0e9816150c3e8adce Mon Sep 17 00:00:00 2001 From: mrshoor Date: Thu, 26 Jul 2018 18:15:29 -0700 Subject: [PATCH 45/47] fix swizzling for scalar values --- src/toGLSLInstruction.c | 2 +- src/toGLSLOperand.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/toGLSLInstruction.c b/src/toGLSLInstruction.c index 3b0a436..fa8b9ba 100644 --- a/src/toGLSLInstruction.c +++ b/src/toGLSLInstruction.c @@ -2801,7 +2801,7 @@ void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psIn bcatcstr(glsl, "("); // 1 TranslateOperand(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT); // we have to smear out the scalars here... - if (srcCount == 1) bcatcstr(glsl, ".xxxx"); + //if (srcCount == 1) bcatcstr(glsl, ".xxxx"); bcatcstr(glsl, ")"); // 1 // this seems like the only reliable way to catch every swizzling case --- diff --git a/src/toGLSLOperand.c b/src/toGLSLOperand.c index 3f4c24e..c7a8e78 100644 --- a/src/toGLSLOperand.c +++ b/src/toGLSLOperand.c @@ -1393,6 +1393,16 @@ static void TranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, c // For scalar types we should user constructor, because swizzling not allowed for scalar values uint32_t isScalarValue = 0; + if (vars[0]->Class == SVC_SCALAR){ + isScalarValue = 1; + for (uint32_t c = 1; c 1) && (psOperand->ui32Swizzle == XXXX_SWIZZLE)) { From 2f57479a59b38090f2d18935f4bc5b27537a9346 Mon Sep 17 00:00:00 2001 From: mrshoor Date: Thu, 30 Aug 2018 16:19:49 -0700 Subject: [PATCH 46/47] structs can't be used as input semantics --- src/toGLSLDeclaration.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 1b3d3d3..2a6a3dd 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -602,7 +602,10 @@ static void DeclareInput( { if (registerNotDeclared) bformata(glsl, "%s4 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); - bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); + if ((lowestComponent == 0) && (iNumComponents == 1)) + bformata(glsl, "%s %s %s %s %s;\n", Interpolation, StorageQualifier, Precision, scalarType, InputName); + else + bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; } @@ -631,7 +634,10 @@ static void DeclareInput( if (mask32 & OPERAND_4_COMPONENT_MASK_W) maskDest[maskpos++] = 'w'; char maskSrc[6] = { '.', 'x', 'y', 'z', 'w', 0 }; - maskSrc[iNumComponents+1] = 0; + if ((lowestComponent == 0) && (iNumComponents == 1)) + maskSrc[0] = 0; + else + maskSrc[iNumComponents+1] = 0; AddIndentation(psContext); bformata(psContext->earlyMain, "Input%d%s = %s%s;\n", psDecl->asOperands[0].ui32RegisterNumber, &maskDest[0], InputName, &maskSrc[0]); From 0276f425d856cd8789550294ced4a80f68bab652 Mon Sep 17 00:00:00 2001 From: mrshoor Date: Sun, 16 Sep 2018 14:37:04 -0700 Subject: [PATCH 47/47] * structs can't be used as input semantics upd. for vertex shaders only --- src/toGLSLDeclaration.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/toGLSLDeclaration.c b/src/toGLSLDeclaration.c index 2a6a3dd..9a37d08 100644 --- a/src/toGLSLDeclaration.c +++ b/src/toGLSLDeclaration.c @@ -602,7 +602,7 @@ static void DeclareInput( { if (registerNotDeclared) bformata(glsl, "%s4 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); - if ((lowestComponent == 0) && (iNumComponents == 1)) + if ((lowestComponent == 0) && (iNumComponents == 1) && (psShader->eShaderType == VERTEX_SHADER)) bformata(glsl, "%s %s %s %s %s;\n", Interpolation, StorageQualifier, Precision, scalarType, InputName); else bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); @@ -634,7 +634,7 @@ static void DeclareInput( if (mask32 & OPERAND_4_COMPONENT_MASK_W) maskDest[maskpos++] = 'w'; char maskSrc[6] = { '.', 'x', 'y', 'z', 'w', 0 }; - if ((lowestComponent == 0) && (iNumComponents == 1)) + if ((lowestComponent == 0) && (iNumComponents == 1) && (psShader->eShaderType == VERTEX_SHADER)) maskSrc[0] = 0; else maskSrc[iNumComponents+1] = 0;