Collection of updates from Unity internal repo at changeset 17a9acd02335496aff4e2eec1b2685085c9b5b0d
This commit is contained in:
Родитель
d8176fd55a
Коммит
5f8fc43675
|
@ -43,6 +43,8 @@ typedef struct GlExtensions {
|
|||
uint32_t ARB_explicit_attrib_location : 1;
|
||||
uint32_t ARB_explicit_uniform_location : 1;
|
||||
uint32_t ARB_shading_language_420pack : 1;
|
||||
uint32_t OVR_multiview : 1;
|
||||
uint32_t EXT_shader_framebuffer_fetch : 1;
|
||||
} GlExtensions;
|
||||
|
||||
#include "ShaderInfo.h"
|
||||
|
@ -197,13 +199,17 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
typedef std::map<std::string, uint32_t> SpecializationConstantMap;
|
||||
SpecializationConstantMap m_SpecConstantMap;
|
||||
uint32_t m_NextSpecID;
|
||||
|
||||
public:
|
||||
GLSLCrossDependencyData()
|
||||
: eTessPartitioning(),
|
||||
eTessOutPrim(),
|
||||
ui32ProgramStages(0)
|
||||
ui32ProgramStages(0),
|
||||
m_ExtBlendModes(),
|
||||
m_NextSpecID(0)
|
||||
{
|
||||
memset(nextAvailableVaryingLocation, 0, sizeof(nextAvailableVaryingLocation));
|
||||
memset(m_NextAvailableVulkanResourceBinding, 0, sizeof(m_NextAvailableVulkanResourceBinding));
|
||||
|
@ -289,6 +295,8 @@ public:
|
|||
// Needed so we can construct proper shader input and output names
|
||||
uint32_t ui32ProgramStages;
|
||||
|
||||
std::vector<std::string> m_ExtBlendModes; // The blend modes (from KHR_blend_equation_advanced) requested for this shader. See ext spec for list.
|
||||
|
||||
inline INTERPOLATION_MODE GetInterpolationMode(uint32_t regNo)
|
||||
{
|
||||
if (regNo >= pixelInterpolation.size())
|
||||
|
@ -313,9 +321,21 @@ public:
|
|||
varyingLocationsMap[i].clear();
|
||||
nextAvailableVaryingLocation[i] = 0;
|
||||
}
|
||||
m_NextSpecID = 0;
|
||||
m_SpecConstantMap.clear();
|
||||
}
|
||||
|
||||
// Retrieve or allocate a layout slot for Vulkan specialization constant
|
||||
inline uint32_t GetSpecializationConstantSlot(const std::string &name)
|
||||
{
|
||||
SpecializationConstantMap::iterator itr = m_SpecConstantMap.find(name);
|
||||
if (itr != m_SpecConstantMap.end())
|
||||
return itr->second;
|
||||
|
||||
m_SpecConstantMap.insert(std::make_pair(std::string(name), m_NextSpecID));
|
||||
|
||||
return m_NextSpecID++;
|
||||
}
|
||||
};
|
||||
|
||||
struct GLSLShader
|
||||
|
@ -339,16 +359,17 @@ public:
|
|||
|
||||
virtual void OnInputBinding(const std::string &name, int bindIndex) {}
|
||||
|
||||
// Returns false if this constant buffer is not needed for this shader. This info can be used for pruning unused
|
||||
// constant buffers and vars from compute shaders where we need broader context than a single kernel to know
|
||||
// if something can be dropped, as the constant buffers are shared between all kernels in a .compute file.
|
||||
virtual bool OnConstantBuffer(const std::string &name, size_t bufferSize, size_t memberCount) { return true; }
|
||||
|
||||
// Returns false if this constant var is not needed for this shader. See above.
|
||||
virtual bool OnConstant(const std::string &name, int bindIndex, SHADER_VARIABLE_TYPE cType, int rows, int cols, bool isMatrix, int arraySize) { return true; }
|
||||
|
||||
virtual void OnConstantBufferBinding(const std::string &name, int bindIndex) {}
|
||||
|
||||
virtual void OnTextureBinding(const std::string &name, int bindIndex, HLSLCC_TEX_DIMENSION dim, bool isUAV) {}
|
||||
|
||||
virtual void OnTextureBinding(const std::string &name, int bindIndex, int samplerIndex, HLSLCC_TEX_DIMENSION dim, bool isUAV) {}
|
||||
virtual void OnBufferBinding(const std::string &name, int bindIndex, bool isUAV) {}
|
||||
|
||||
virtual void OnThreadGroupSize(unsigned int xSize, unsigned int ySize, unsigned int zSize) {}
|
||||
};
|
||||
|
||||
|
@ -423,6 +444,16 @@ static const unsigned int HLSLCC_FLAG_VULKAN_BINDINGS = 0x40000;
|
|||
// If set, metal output will use linear sampler for shadow compares, otherwise point sampler.
|
||||
static const unsigned int HLSLCC_FLAG_METAL_SHADOW_SAMPLER_LINEAR = 0x80000;
|
||||
|
||||
// If set, emits for NVN, the Nvidia-provided graphics API for Nintendo Switch.
|
||||
static const unsigned int HLSLCC_FLAG_NVN_TARGET = 0x100000;
|
||||
|
||||
// If set, and generating Vulkan shaders, attempts to detect static branching and transforms them into specialization constants
|
||||
static const unsigned int HLSLCC_FLAG_VULKAN_SPECIALIZATION_CONSTANTS = 0x200000;
|
||||
|
||||
// If set, this shader uses the GLSL extension EXT_shader_framebuffer_fetch
|
||||
static const unsigned int HLSLCC_FLAG_SHADER_FRAMEBUFFER_FETCH = 0x400000;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -250,11 +250,10 @@ void HLSLcc::DataTypeAnalysis::SetDataTypes(HLSLCrossCompilerContext* psContext,
|
|||
// Only ever to int->float promotion (or int->uint), never the other way around
|
||||
for (i = 0; i < (uint32_t)instructions.size(); ++i, psInst++)
|
||||
{
|
||||
int k = 0;
|
||||
if (psInst->ui32NumOperands == 0)
|
||||
continue;
|
||||
#ifdef _DEBUG
|
||||
for (k = 0; k < (int)psInst->ui32NumOperands; k++)
|
||||
for (int k = 0; k < (int)psInst->ui32NumOperands; k++)
|
||||
{
|
||||
if (psInst->asOperands[k].eType == OPERAND_TYPE_TEMP)
|
||||
{
|
||||
|
|
|
@ -95,6 +95,14 @@ void HLSLCrossCompilerContext::AddIndentation()
|
|||
}
|
||||
}
|
||||
|
||||
void HLSLCrossCompilerContext::RequireExtension(const std::string &extName)
|
||||
{
|
||||
if (m_EnabledExtensions.find(extName) != m_EnabledExtensions.end())
|
||||
return;
|
||||
|
||||
m_EnabledExtensions.insert(extName);
|
||||
bformata(extensions, "#extension %s : require\n", extName.c_str());
|
||||
}
|
||||
|
||||
std::string HLSLCrossCompilerContext::GetDeclaredInputName(const Operand* psOperand, int *piRebase, int iIgnoreRedirect, uint32_t *puiIgnoreSwizzle) const
|
||||
{
|
||||
|
@ -186,7 +194,13 @@ std::string HLSLCrossCompilerContext::GetDeclaredOutputName(const Operand* psOpe
|
|||
std::string res = "";
|
||||
if (psTranslator->TranslateSystemValue(psOperand, psOut, res, puiIgnoreSwizzle, psShader->aIndexedOutput[regSpace][psOperand->ui32RegisterNumber], false))
|
||||
{
|
||||
if (psShader->eTargetLanguage == LANG_METAL && (iIgnoreRedirect == 0))
|
||||
// HACK: i couldnt find better way to handle it
|
||||
// clip planes will always have interim variable, as HLSL operates on float4 but we need to size output accordingly with actual planes count
|
||||
// for some reason TranslateSystemValue return *outSkipPrefix = true for ALL system vars and then we simply ignore it here
|
||||
const bool isClipPlanes = psOut && psOut->eSystemValueType == NAME_CLIP_DISTANCE;
|
||||
|
||||
if (psShader->eTargetLanguage == LANG_METAL && (iIgnoreRedirect == 0) && !isClipPlanes)
|
||||
|
||||
return outputPrefix + res;
|
||||
else
|
||||
return res;
|
||||
|
@ -247,6 +261,13 @@ bool HLSLCrossCompilerContext::OutputNeedsDeclaring(const Operand* psOperand, co
|
|||
{
|
||||
psShader->acOutputDeclared[regSpace][startIndex + offset] |= compMask;
|
||||
}
|
||||
|
||||
if (psSignature && (psSignature->semanticName == "PSIZE") && (psShader->eTargetLanguage != LANG_METAL))
|
||||
{
|
||||
// gl_PointSize, doesn't need declaring. TODO: Metal doesn't have pointsize at all?
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -402,11 +402,13 @@ namespace HLSLcc
|
|||
case RESOURCE_DIMENSION_TEXTURE1D:
|
||||
return 1;
|
||||
case RESOURCE_DIMENSION_TEXTURE2D:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DMS:
|
||||
case RESOURCE_DIMENSION_TEXTURE1DARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURECUBE:
|
||||
return 2;
|
||||
case RESOURCE_DIMENSION_TEXTURE3D:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURE2DMSARRAY:
|
||||
case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
|
||||
return 3;
|
||||
default:
|
||||
|
|
|
@ -123,10 +123,17 @@ static Operand *GetSrcSwizzleOperand(Instruction *psInst)
|
|||
case OPCODE_LD_STRUCTURED:
|
||||
return &psInst->asOperands[3];
|
||||
|
||||
case OPCODE_SAMPLE_INFO:
|
||||
return &psInst->asOperands[1];
|
||||
|
||||
case OPCODE_ISHL:
|
||||
case OPCODE_ISHR:
|
||||
case OPCODE_USHR:
|
||||
// sm4 variant has single component selection on src1 -> only src0 has swizzle
|
||||
if (psInst->asOperands[2].eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE)
|
||||
return &psInst->asOperands[1];
|
||||
else // whereas sm5 variant has swizzle also on src1
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
|
|
|
@ -274,7 +274,7 @@ SHADER_VARIABLE_TYPE Operand::GetDataType(HLSLCrossCompilerContext* psContext, S
|
|||
{
|
||||
case OPERAND_TYPE_TEMP:
|
||||
{
|
||||
SHADER_VARIABLE_TYPE eCurrentType;
|
||||
SHADER_VARIABLE_TYPE eCurrentType = SVT_FLOAT;
|
||||
int i = 0;
|
||||
|
||||
if (eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE)
|
||||
|
|
|
@ -861,6 +861,7 @@ void ShaderPhase::ExpandSWAPCs()
|
|||
swapItr->eOpcode = OPCODE_MOVC;
|
||||
swapItr->ui32NumOperands = 4;
|
||||
swapItr->ui32FirstSrc = 1;
|
||||
swapItr->asOperands[0] = origSwapInst.asOperands[0];
|
||||
swapItr->asOperands[0].eType = OPERAND_TYPE_TEMP;
|
||||
swapItr->asOperands[0].ui32RegisterNumber = extraTemp;
|
||||
// mask is already fine
|
||||
|
@ -923,12 +924,10 @@ void Shader::ForcePositionToHighp()
|
|||
{
|
||||
if (decl.eOpcode == OPCODE_DCL_OUTPUT_SIV)
|
||||
{
|
||||
if (decl.asOperands[0].eSpecialName == NAME_POSITION)
|
||||
return true;
|
||||
if (decl.asOperands[0].eSpecialName != NAME_UNDEFINED)
|
||||
return false;
|
||||
|
||||
// This might be SV_Position (because d3dcompiler is weird). Get signature and check
|
||||
const SPECIAL_NAME specialName = decl.asOperands[0].eSpecialName;
|
||||
if (specialName == NAME_POSITION ||
|
||||
specialName == NAME_UNDEFINED) // This might be SV_Position (because d3dcompiler is weird).
|
||||
{
|
||||
const ShaderInfo::InOutSignature *sig = NULL;
|
||||
sInfo.GetOutputSignatureFromRegister(decl.asOperands[0].ui32RegisterNumber, decl.asOperands[0].GetAccessMask(), 0, &sig);
|
||||
ASSERT(sig != NULL);
|
||||
|
@ -937,6 +936,7 @@ void Shader::ForcePositionToHighp()
|
|||
((ShaderInfo::InOutSignature *)sig)->eMinPrec = MIN_PRECISION_DEFAULT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (decl.eOpcode == OPCODE_DCL_OUTPUT)
|
||||
|
|
|
@ -145,10 +145,6 @@ static DefineUseChainEntry *GetOrCreateDefinition(const BasicBlock::Definition &
|
|||
// Do flow control analysis on the instructions and build the define-use and use-define chains
|
||||
void BuildUseDefineChains(std::vector<Instruction> &instructions, uint32_t ui32NumTemps, DefineUseChains &psDUChain, UseDefineChains &psUDChain, HLSLcc::ControlFlow::ControlFlowGraph &cfg)
|
||||
{
|
||||
|
||||
Instruction *psFirstInstruction = &instructions[0];
|
||||
Instruction *psLastInstruction = &instructions[instructions.size() - 1];
|
||||
|
||||
ActiveDefinitions lastSeenDefinitions(ui32NumTemps * 4, NULL); // Array of pointers to the currently active definition for each temp
|
||||
|
||||
psDUChain.clear();
|
||||
|
|
|
@ -193,10 +193,6 @@ int i, l, c;
|
|||
}
|
||||
|
||||
static size_t readNothing (void *buff, size_t elsize, size_t nelem, void *parm) {
|
||||
buff = buff;
|
||||
elsize = elsize;
|
||||
nelem = nelem;
|
||||
parm = parm;
|
||||
return 0; /* Immediately indicate EOF. */
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ static void MarkTextureSamplerPair(ShaderInfo* psShaderInfo, std::vector<Declara
|
|||
// set::insert returns a pair of which .second tells whether a new element was actually added
|
||||
if (psDecl->samplersUsed.insert(psSamplerOperand->ui32RegisterNumber).second)
|
||||
{
|
||||
// Record the texturename_X_samplername string in the TextureSamplerPair array that we return to the client
|
||||
// Record the <texturename>TEX_with_SMP<samplername> string in the TextureSamplerPair array that we return to the client
|
||||
std::string combinedname = TextureSamplerName(psShaderInfo, psTextureOperand->ui32RegisterNumber, psSamplerOperand->ui32RegisterNumber, psDecl->ui32IsShadowTex);
|
||||
samplers.push_back(combinedname);
|
||||
}
|
||||
|
@ -1112,7 +1112,7 @@ const uint32_t* DecodeInstruction(const uint32_t* pui32Token, Instruction* psIns
|
|||
{
|
||||
psInst->ui32NumOperands = 4;
|
||||
|
||||
if(eOpcode == OPCODE_IMUL)
|
||||
if(eOpcode == OPCODE_IMUL || eOpcode == OPCODE_UDIV)
|
||||
{
|
||||
psInst->ui32FirstSrc = 2;
|
||||
}
|
||||
|
@ -1244,6 +1244,16 @@ const uint32_t* DecodeInstruction(const uint32_t* pui32Token, Instruction* psIns
|
|||
ui32OperandOffset += DecodeOperand(pui32Token+ui32OperandOffset, &psInst->asOperands[2]);
|
||||
break;
|
||||
}
|
||||
case OPCODE_SAMPLE_INFO:
|
||||
{
|
||||
psInst->ui32NumOperands = 2;
|
||||
|
||||
psInst->eResInfoReturnType = DecodeResInfoReturnType(pui32Token[0]);
|
||||
|
||||
ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]);
|
||||
ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]);
|
||||
break;
|
||||
}
|
||||
case OPCODE_MSAD:
|
||||
default:
|
||||
{
|
||||
|
@ -1254,8 +1264,8 @@ const uint32_t* DecodeInstruction(const uint32_t* pui32Token, Instruction* psIns
|
|||
|
||||
// For opcodes that sample textures, mark which samplers are used by each texture
|
||||
{
|
||||
uint32_t ui32TextureRegisterNumber;
|
||||
uint32_t ui32SamplerRegisterNumber;
|
||||
uint32_t ui32TextureRegisterNumber = 0;
|
||||
uint32_t ui32SamplerRegisterNumber = 0;
|
||||
uint32_t bTextureSampleInstruction = 0;
|
||||
switch (eOpcode)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "bstrlib.h"
|
||||
|
||||
class Shader;
|
||||
|
@ -47,4 +48,8 @@ public:
|
|||
|
||||
bool OutputNeedsDeclaring(const Operand* psOperand, const int count);
|
||||
|
||||
void RequireExtension(const std::string &extName);
|
||||
|
||||
private:
|
||||
std::set<std::string> m_EnabledExtensions;
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "bstrlib.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "internal_includes/Instruction.h"
|
||||
#include "internal_includes/Operand.h"
|
||||
|
|
|
@ -30,6 +30,8 @@ struct Instruction
|
|||
, m_SkipTranslation(false)
|
||||
, m_InductorRegister(0)
|
||||
, bSaturate(0)
|
||||
, m_IsStaticBranch(false)
|
||||
, m_StaticBranchCondition(NULL)
|
||||
{
|
||||
m_LoopInductors[0] = m_LoopInductors[1] = m_LoopInductors[2] = m_LoopInductors[3] = 0;
|
||||
}
|
||||
|
@ -85,6 +87,20 @@ struct Instruction
|
|||
asOperands[3].eSelMode = OPERAND_4_COMPONENT_MASK_MODE;
|
||||
}
|
||||
|
||||
// Returns true if this instruction is a conditional branch
|
||||
bool IsConditionalBranchInstruction() const
|
||||
{
|
||||
switch (eOpcode)
|
||||
{
|
||||
case OPCODE_IF:
|
||||
case OPCODE_BREAKC:
|
||||
case OPCODE_CONTINUEC:
|
||||
case OPCODE_RETC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPartialPrecisionSamplerInstruction(const ShaderInfo &info, OPERAND_MIN_PRECISION *pType) const;
|
||||
|
||||
|
@ -114,6 +130,10 @@ struct Instruction
|
|||
RESOURCE_DIMENSION eResDim;
|
||||
int8_t iCausedSplit; // Nonzero if has caused a temp split. Later used by sampler datatype tweaking
|
||||
|
||||
bool m_IsStaticBranch; // If true, this instruction is a static branch
|
||||
const Instruction *m_StaticBranchCondition; // If this is a static branch, this instruction points to the condition instruction. Can also be NULL if the operand itself is the condition
|
||||
std::string m_StaticBranchName; // The name of the static branch variable, with the condition encoded in it.
|
||||
|
||||
struct Use
|
||||
{
|
||||
Use() : m_Inst(0), m_Op(0) {}
|
||||
|
|
|
@ -104,6 +104,9 @@ public:
|
|||
uint32_t m_NextFreeTempRegister; // A counter for creating new temporaries for for-loops.
|
||||
uint32_t m_NextTexCoordTemp; // A counter for creating tex coord temps for driver issue workarounds
|
||||
|
||||
// Instructions that are static branches (branches based on constant buffer values only)
|
||||
std::vector<Instruction *> m_StaticBranchInstructions;
|
||||
|
||||
private:
|
||||
bool m_CFGInitialized;
|
||||
HLSLcc::ControlFlow::ControlFlowGraph m_CFG;
|
||||
|
@ -142,10 +145,7 @@ public:
|
|||
ui32CurrentVertexOutputStream(0),
|
||||
textureSamplers(),
|
||||
aui32StructuredBufferBindingPoints(MAX_RESOURCE_BINDINGS, 0),
|
||||
ui32CurrentStructuredBufferIndex(),
|
||||
m_CubemapArrayExtensionDeclared(false),
|
||||
m_TextureBufferExtensionDeclared(false),
|
||||
m_ClipDistanceExtensionDeclared(false)
|
||||
ui32CurrentStructuredBufferIndex()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -246,10 +246,6 @@ public:
|
|||
std::vector<uint32_t> aui32StructuredBufferBindingPoints;
|
||||
uint32_t ui32CurrentStructuredBufferIndex;
|
||||
|
||||
bool m_CubemapArrayExtensionDeclared;
|
||||
bool m_TextureBufferExtensionDeclared;
|
||||
bool m_ClipDistanceExtensionDeclared;
|
||||
|
||||
std::vector<char> psIntTempSizes; // Array for whether this temp register needs declaration as int temp
|
||||
std::vector<char> psInt16TempSizes; // min16ints
|
||||
std::vector<char> psInt12TempSizes; // min12ints
|
||||
|
|
|
@ -12,7 +12,9 @@ static void CustomAssert(int expression)
|
|||
}
|
||||
}
|
||||
#else
|
||||
#define ASSERT(expr)
|
||||
#define UNUSED(EXPR_) \
|
||||
do { if (false) (void)(EXPR_); } while(0)
|
||||
#define ASSERT(expr) UNUSED(expr)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define LANGUAGES_H
|
||||
|
||||
#include "hlslcc.h"
|
||||
#include "HLSLCrossCompilerContext.h"
|
||||
#include "Shader.h"
|
||||
|
||||
static int InOutSupported(const GLLang eLang)
|
||||
{
|
||||
|
@ -42,9 +44,13 @@ static int HaveOverloadedTextureFuncs(const GLLang eLang)
|
|||
}
|
||||
|
||||
//Only enable for ES.
|
||||
//Not present in 120, ignored in other desktop languages.
|
||||
static int HavePrecisionQualifers(const GLLang eLang)
|
||||
//Not present in 120, ignored in other desktop languages. Specifically enabled on Vulkan.
|
||||
static int HavePrecisionQualifiers(const HLSLCrossCompilerContext *psContext)
|
||||
{
|
||||
if ((psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0)
|
||||
return 1;
|
||||
|
||||
const GLLang eLang = psContext->psShader->eTargetLanguage;
|
||||
if(eLang >= LANG_ES_100 && eLang <= LANG_ES_310)
|
||||
{
|
||||
return 1;
|
||||
|
|
|
@ -20,10 +20,17 @@ public:
|
|||
virtual void SetIOPrefixes();
|
||||
|
||||
private:
|
||||
// Vulkan-only: detect which branches only depend on uniforms and immediate values and can be turned into specialization constants.
|
||||
void IdentifyStaticBranches(ShaderPhase *psPhase);
|
||||
void BuildStaticBranchNameForInstruction(Instruction &inst);
|
||||
|
||||
void DeclareSpecializationConstants(ShaderPhase &phase);
|
||||
|
||||
void TranslateOperand(bstring glsl, const Operand *psOp, uint32_t flags, uint32_t ui32ComponentMask = OPERAND_4_COMPONENT_MASK_ALL);
|
||||
void TranslateOperand(const Operand *psOp, uint32_t flags, uint32_t ui32ComponentMask = OPERAND_4_COMPONENT_MASK_ALL);
|
||||
void TranslateInstruction(Instruction* psInst, bool isEmbedded = false);
|
||||
|
||||
void TranslateVariableNameWithMask(bstring glsl, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase);
|
||||
void TranslateVariableNameWithMask(const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase);
|
||||
|
||||
void TranslateOperandIndex(const Operand* psOperand, int index);
|
||||
|
|
|
@ -12,6 +12,7 @@ class HLSLCrossCompilerContext;
|
|||
//void TranslateOperandWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask);
|
||||
|
||||
void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int iRebase);
|
||||
void TranslateOperandSwizzleWithMask(bstring glsl, HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, int iRebase);
|
||||
void TranslateOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, int iRebase);
|
||||
|
||||
void ResourceName(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare);
|
||||
|
|
|
@ -26,7 +26,11 @@ class BindingSlotAllocator
|
|||
typedef std::map<uint32_t, uint32_t> SlotMap;
|
||||
SlotMap m_Allocations;
|
||||
public:
|
||||
BindingSlotAllocator() : m_Allocations(), m_NextFreeSlot(0) {}
|
||||
BindingSlotAllocator() : m_Allocations()
|
||||
{
|
||||
for(int i = MAX_RESOURCE_BINDINGS-1; i >= 0; i --)
|
||||
m_FreeSlots.push_back(i);
|
||||
}
|
||||
|
||||
enum BindType
|
||||
{
|
||||
|
@ -36,8 +40,6 @@ public:
|
|||
UAV
|
||||
};
|
||||
|
||||
// isUAV is only meaningful for texture slots
|
||||
|
||||
uint32_t GetBindingSlot(uint32_t regNo, BindType type)
|
||||
{
|
||||
// The key is regNumber with the bindtype stored to highest 16 bits
|
||||
|
@ -45,14 +47,47 @@ public:
|
|||
SlotMap::iterator itr = m_Allocations.find(key);
|
||||
if(itr == m_Allocations.end())
|
||||
{
|
||||
m_Allocations.insert(std::make_pair(key, m_NextFreeSlot));
|
||||
return m_NextFreeSlot++;
|
||||
uint32_t slot = m_FreeSlots.back();
|
||||
m_FreeSlots.pop_back();
|
||||
m_Allocations.insert(std::make_pair(key, slot));
|
||||
return slot;
|
||||
}
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// Func for reserving binding slots with the original reg number.
|
||||
// Used for fragment shader UAVs (SetRandomWriteTarget etc).
|
||||
void ReserveBindingSlot(uint32_t regNo, BindType type)
|
||||
{
|
||||
uint32_t key = regNo | (uint32_t(type) << 16);
|
||||
m_Allocations.insert(std::make_pair(key, regNo));
|
||||
|
||||
// Remove regNo from free slots
|
||||
for (int i = m_FreeSlots.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (m_FreeSlots[i] == regNo)
|
||||
{
|
||||
m_FreeSlots.erase(m_FreeSlots.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_NextFreeSlot;
|
||||
std::vector<uint32_t> m_FreeSlots;
|
||||
};
|
||||
|
||||
struct SamplerDesc
|
||||
{
|
||||
std::string name;
|
||||
uint32_t reg, slot;
|
||||
};
|
||||
struct TextureSamplerDesc
|
||||
{
|
||||
std::string name;
|
||||
int textureBind, samplerBind;
|
||||
HLSLCC_TEX_DIMENSION dim;
|
||||
bool uav;
|
||||
};
|
||||
|
||||
|
||||
|
@ -61,7 +96,12 @@ class ToMetal : public Translator
|
|||
protected:
|
||||
GLLang language;
|
||||
public:
|
||||
explicit ToMetal(HLSLCrossCompilerContext *ctx) : Translator(ctx), m_ShadowSamplerDeclared(false) {}
|
||||
explicit ToMetal(HLSLCrossCompilerContext *ctx)
|
||||
: Translator(ctx)
|
||||
, m_ShadowSamplerDeclared(false)
|
||||
, m_NeedFBOutputRemapDecl(false)
|
||||
, m_NeedFBInputRemapDecl(false)
|
||||
{}
|
||||
|
||||
virtual bool Translate();
|
||||
virtual void TranslateDeclaration(const Declaration *psDecl);
|
||||
|
@ -75,6 +115,8 @@ private:
|
|||
|
||||
void DeclareBuiltinInput(const Declaration *psDecl);
|
||||
void DeclareBuiltinOutput(const Declaration *psDecl);
|
||||
void DeclareClipPlanes(const Declaration* decl, unsigned declCount);
|
||||
void GenerateTexturesReflection(HLSLccReflection* refl);
|
||||
|
||||
// Retrieve the name of the output struct for this shader
|
||||
std::string GetOutputStructName() const;
|
||||
|
@ -88,7 +130,7 @@ private:
|
|||
void DeclareStructType(const std::string &name, const std::vector<ShaderVarType> &contents, bool withinCB = false, uint32_t cumulativeOffset = 0);
|
||||
void DeclareStructVariable(const std::string &parentName, const ShaderVar &var, bool withinCB = false, uint32_t cumulativeOffset = 0);
|
||||
void DeclareStructVariable(const std::string &parentName, const ShaderVarType &var, bool withinCB = false, uint32_t cumulativeOffset = 0);
|
||||
void DeclareBufferVariable(const Declaration *psDecl, const bool isRaw, const bool isUAV);
|
||||
void DeclareBufferVariable(const Declaration *psDecl, bool isRaw, bool isUAV);
|
||||
|
||||
void DeclareResource(const Declaration *psDecl);
|
||||
void TranslateResourceTexture(const Declaration* psDecl, uint32_t samplerCanDoShadowCmp, HLSLCC_TEX_DIMENSION texDim);
|
||||
|
@ -174,11 +216,18 @@ private:
|
|||
// A <function name, body text> map of extra helper functions we'll need.
|
||||
FunctionDefinitions m_FunctionDefinitions;
|
||||
|
||||
BindingSlotAllocator m_TextureSlots;
|
||||
BindingSlotAllocator m_TextureSlots, m_SamplerSlots;
|
||||
BindingSlotAllocator m_BufferSlots;
|
||||
|
||||
std::vector<SamplerDesc> m_Samplers;
|
||||
std::vector<TextureSamplerDesc> m_Textures;
|
||||
|
||||
std::string m_ExtraGlobalDefinitions;
|
||||
|
||||
// Flags for whether we need to add the declaration for the FB IO remaps
|
||||
bool m_NeedFBInputRemapDecl;
|
||||
bool m_NeedFBOutputRemapDecl;
|
||||
|
||||
bool m_ShadowSamplerDeclared;
|
||||
|
||||
void EnsureShadowSamplerDeclared();
|
||||
|
@ -188,6 +237,9 @@ private:
|
|||
|
||||
// Move all lowp -> mediump
|
||||
void ClampPartialPrecisions();
|
||||
|
||||
// Reseve UAV slots in advance to match the original HLSL bindings -> correct bindings in SetRandomWriteTarget()
|
||||
void ReserveUAVBindingSlots(ShaderPhase *phase);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -306,7 +306,6 @@ static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo,
|
|||
//D3D11_SHADER_VARIABLE_DESC
|
||||
ShaderVar * const psVar = &psBuffer->asVars[i];
|
||||
|
||||
uint32_t ui32Flags;
|
||||
uint32_t ui32TypeOffset;
|
||||
uint32_t ui32DefaultValueOffset;
|
||||
|
||||
|
@ -317,7 +316,10 @@ static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo,
|
|||
|
||||
psVar->ui32StartOffset = *pui32VarToken++;
|
||||
psVar->ui32Size = *pui32VarToken++;
|
||||
ui32Flags = *pui32VarToken++;
|
||||
|
||||
//skip ui32Flags
|
||||
pui32VarToken++;
|
||||
|
||||
ui32TypeOffset = *pui32VarToken++;
|
||||
|
||||
psVar->sType.name = psVar->name;
|
||||
|
@ -367,12 +369,12 @@ static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo,
|
|||
|
||||
|
||||
{
|
||||
uint32_t ui32Flags;
|
||||
uint32_t ui32BufferType;
|
||||
|
||||
psBuffer->ui32TotalSizeInBytes = *pui32Tokens++;
|
||||
ui32Flags = *pui32Tokens++;
|
||||
ui32BufferType = *pui32Tokens++;
|
||||
|
||||
//skip ui32Flags
|
||||
pui32Tokens++;
|
||||
//skip ui32BufferType
|
||||
pui32Tokens++;
|
||||
}
|
||||
|
||||
return pui32Tokens;
|
||||
|
|
288
src/toGLSL.cpp
288
src/toGLSL.cpp
|
@ -95,6 +95,7 @@ static void AddVersionDependentCode(HLSLCrossCompilerContext* psContext)
|
|||
bstring glsl = *psContext->currentGLSLString;
|
||||
bstring extensions = psContext->extensions;
|
||||
bool isES = (psContext->psShader->eTargetLanguage >= LANG_ES_100 && psContext->psShader->eTargetLanguage <= LANG_ES_310);
|
||||
bool GL_ARB_shader_storage_buffer_object = false;
|
||||
bool GL_ARB_shader_image_load_store = false;
|
||||
|
||||
if(psContext->psShader->ui32MajorVersion > 3 && psContext->psShader->eTargetLanguage != LANG_ES_300 && psContext->psShader->eTargetLanguage != LANG_ES_310 && !(psContext->psShader->eTargetLanguage >= LANG_330))
|
||||
|
@ -114,7 +115,7 @@ static void AddVersionDependentCode(HLSLCrossCompilerContext* psContext)
|
|||
psContext->psShader->aiOpcodeUsed[OPCODE_DCL_RESOURCE_STRUCTURED] ||
|
||||
psContext->psShader->aiOpcodeUsed[OPCODE_DCL_RESOURCE_RAW])
|
||||
{
|
||||
bcatcstr(extensions, "#extension GL_ARB_shader_storage_buffer_object : enable\n");
|
||||
GL_ARB_shader_storage_buffer_object = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,8 +130,6 @@ static void AddVersionDependentCode(HLSLCrossCompilerContext* psContext)
|
|||
}
|
||||
}
|
||||
|
||||
if (!HaveImageAtomics(psContext->psShader->eTargetLanguage))
|
||||
{
|
||||
if (psContext->psShader->aiOpcodeUsed[OPCODE_ATOMIC_CMP_STORE] ||
|
||||
psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_AND] ||
|
||||
psContext->psShader->aiOpcodeUsed[OPCODE_ATOMIC_AND] ||
|
||||
|
@ -148,6 +147,11 @@ static void AddVersionDependentCode(HLSLCrossCompilerContext* psContext)
|
|||
psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_XOR] ||
|
||||
psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_EXCH] ||
|
||||
psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_CMP_EXCH])
|
||||
{
|
||||
if (!HaveAtomicMem(psContext->psShader->eTargetLanguage))
|
||||
GL_ARB_shader_storage_buffer_object = true;
|
||||
|
||||
if (!HaveImageAtomics(psContext->psShader->eTargetLanguage))
|
||||
{
|
||||
if (isES)
|
||||
bcatcstr(extensions, "#extension GL_OES_shader_image_atomic : enable\n");
|
||||
|
@ -189,9 +193,15 @@ static void AddVersionDependentCode(HLSLCrossCompilerContext* psContext)
|
|||
if(psContext->psShader->aiOpcodeUsed[OPCODE_RESINFO])
|
||||
{
|
||||
bcatcstr(extensions,"#extension GL_ARB_texture_query_levels : enable\n");
|
||||
bcatcstr(extensions, "#extension GL_ARB_shader_image_size : enable\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (psContext->psShader->aiOpcodeUsed[OPCODE_SAMPLE_INFO ])
|
||||
{
|
||||
bcatcstr(extensions, "#extension GL_ARB_shader_texture_image_samples : enable\n");
|
||||
}
|
||||
|
||||
if(!HaveImageLoadStore(psContext->psShader->eTargetLanguage))
|
||||
{
|
||||
if(psContext->psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] ||
|
||||
|
@ -236,9 +246,24 @@ static void AddVersionDependentCode(HLSLCrossCompilerContext* psContext)
|
|||
}
|
||||
}
|
||||
|
||||
if (GL_ARB_shader_storage_buffer_object)
|
||||
bcatcstr(extensions, "#extension GL_ARB_shader_storage_buffer_object : enable\n");
|
||||
|
||||
if (GL_ARB_shader_image_load_store)
|
||||
bcatcstr(extensions, "#extension GL_ARB_shader_image_load_store : enable\n");
|
||||
|
||||
if(psContext->psShader->eShaderType == PIXEL_SHADER && psContext->psShader->eTargetLanguage >= LANG_120 && !HaveFragmentCoordConventions(psContext->psShader->eTargetLanguage))
|
||||
{
|
||||
bcatcstr(extensions,"#extension GL_ARB_fragment_coord_conventions : require\n");
|
||||
}
|
||||
|
||||
if (psContext->psShader->extensions->EXT_shader_framebuffer_fetch && psContext->psShader->eShaderType == PIXEL_SHADER && psContext->flags & HLSLCC_FLAG_SHADER_FRAMEBUFFER_FETCH)
|
||||
{
|
||||
bcatcstr(extensions, "#ifdef GL_EXT_shader_framebuffer_fetch\n");
|
||||
bcatcstr(extensions, "#extension GL_EXT_shader_framebuffer_fetch : enable\n");
|
||||
bcatcstr(extensions, "#endif\n");
|
||||
}
|
||||
|
||||
//Handle fragment shader default precision
|
||||
if ((psContext->psShader->eShaderType == PIXEL_SHADER) &&
|
||||
(psContext->psShader->eTargetLanguage == LANG_ES_100 || psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310))
|
||||
|
@ -253,11 +278,6 @@ static void AddVersionDependentCode(HLSLCrossCompilerContext* psContext)
|
|||
bcatcstr(glsl, "precision highp int;\n");
|
||||
}
|
||||
|
||||
if(psContext->psShader->eShaderType == PIXEL_SHADER && psContext->psShader->eTargetLanguage >= LANG_120 && !HaveFragmentCoordConventions(psContext->psShader->eTargetLanguage))
|
||||
{
|
||||
bcatcstr(extensions,"#extension GL_ARB_fragment_coord_conventions : require\n");
|
||||
}
|
||||
|
||||
if(psContext->psShader->eShaderType == PIXEL_SHADER && psContext->psShader->eTargetLanguage >= LANG_150)
|
||||
{
|
||||
if(psContext->flags & HLSLCC_FLAG_ORIGIN_UPPER_LEFT)
|
||||
|
@ -435,7 +455,7 @@ static void DoHullShaderPassthrough(HLSLCrossCompilerContext *psContext)
|
|||
outputName = oss.str();
|
||||
}
|
||||
|
||||
const char * prec = HavePrecisionQualifers(psContext->psShader->eTargetLanguage) ? "highp ": "";
|
||||
const char * prec = HavePrecisionQualifiers(psContext) ? "highp ": "";
|
||||
|
||||
psContext->AddIndentation();
|
||||
if (ui32NumComponents > 1) // TODO Precision
|
||||
|
@ -519,6 +539,8 @@ bool ToGLSL::Translate()
|
|||
|
||||
if (psShader->extensions)
|
||||
{
|
||||
if(psContext->flags & HLSLCC_FLAG_NVN_TARGET)
|
||||
bcatcstr(extensions, "#extension GL_ARB_separate_shader_objects : enable\n");
|
||||
if (psShader->extensions->ARB_explicit_attrib_location)
|
||||
bcatcstr(extensions, "#extension GL_ARB_explicit_attrib_location : require\n");
|
||||
if (psShader->extensions->ARB_explicit_uniform_location)
|
||||
|
@ -531,6 +553,25 @@ bool ToGLSL::Translate()
|
|||
|
||||
AddVersionDependentCode(psContext);
|
||||
|
||||
if(psShader->eShaderType == VERTEX_SHADER &&
|
||||
HaveLimitedInOutLocationQualifier(language, psShader->extensions) &&
|
||||
psContext->flags & HLSLCC_FLAG_NVN_TARGET)
|
||||
{
|
||||
bcatcstr(glsl, "out gl_PerVertex { vec4 gl_Position; };\n");
|
||||
}
|
||||
|
||||
if (!psContext->psDependencies->m_ExtBlendModes.empty() && psShader->eShaderType == PIXEL_SHADER)
|
||||
{
|
||||
bcatcstr(extensions, "#extension GL_KHR_blend_equation_advanced : enable\n");
|
||||
bcatcstr(glsl, "#if GL_KHR_blend_equation_advanced\n");
|
||||
for (i = 0; i < psContext->psDependencies->m_ExtBlendModes.size(); i++)
|
||||
{
|
||||
bformata(glsl, "layout(%s) out;\n", psContext->psDependencies->m_ExtBlendModes[i].c_str());
|
||||
}
|
||||
bcatcstr(glsl, "#endif\n");
|
||||
}
|
||||
|
||||
|
||||
psShader->PrepareStructuredBufferBindingSlots();
|
||||
|
||||
for (ui32Phase = 0; ui32Phase < psShader->asPhases.size(); ui32Phase++)
|
||||
|
@ -541,6 +582,7 @@ bool ToGLSL::Translate()
|
|||
phase.ResolveUAVProperties();
|
||||
psShader->ResolveStructuredBufferBindingSlots(&phase);
|
||||
phase.PruneConstArrays();
|
||||
|
||||
}
|
||||
|
||||
psShader->PruneTempRegisters();
|
||||
|
@ -550,6 +592,12 @@ bool ToGLSL::Translate()
|
|||
// Loop transform can only be done after the temps have been pruned
|
||||
ShaderPhase &phase = psShader->asPhases[ui32Phase];
|
||||
HLSLcc::DoLoopTransform(phase);
|
||||
|
||||
if ((psContext->flags & HLSLCC_FLAG_VULKAN_SPECIALIZATION_CONSTANTS) != 0)
|
||||
{
|
||||
IdentifyStaticBranches(&phase);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Special case. Can have multiple phases.
|
||||
|
@ -593,6 +641,12 @@ bool ToGLSL::Translate()
|
|||
TranslateDeclaration(&psPhase->psDecl[i]);
|
||||
}
|
||||
|
||||
if ((psContext->flags & HLSLCC_FLAG_VULKAN_SPECIALIZATION_CONSTANTS) != 0)
|
||||
{
|
||||
DeclareSpecializationConstants(psShader->asPhases[i]);
|
||||
}
|
||||
|
||||
|
||||
bformata(glsl, "void %s%d(int phaseInstanceID)\n{\n", GetPhaseFuncName(psPhase->ePhase), ui32Phase);
|
||||
psContext->indent++;
|
||||
|
||||
|
@ -768,6 +822,11 @@ bool ToGLSL::Translate()
|
|||
TranslateDeclaration(&psShader->asPhases[0].psDecl[i]);
|
||||
}
|
||||
|
||||
if ((psContext->flags & HLSLCC_FLAG_VULKAN_SPECIALIZATION_CONSTANTS) != 0)
|
||||
{
|
||||
DeclareSpecializationConstants(psShader->asPhases[0]);
|
||||
}
|
||||
|
||||
bcatcstr(glsl, "void main()\n{\n");
|
||||
|
||||
psContext->indent++;
|
||||
|
@ -803,4 +862,215 @@ bool ToGLSL::Translate()
|
|||
return true;
|
||||
}
|
||||
|
||||
void ToGLSL::DeclareSpecializationConstants(ShaderPhase &phase)
|
||||
{
|
||||
bstring glsl = psContext->glsl;
|
||||
// There may be several uses for the same branch condition, so we'll need to keep track of what we've already declared.
|
||||
std::set<uint32_t> alreadyDeclared;
|
||||
for (std::vector<Instruction *>::iterator itr = phase.m_StaticBranchInstructions.begin(); itr != phase.m_StaticBranchInstructions.end(); itr++)
|
||||
{
|
||||
Instruction &i = **itr;
|
||||
uint32_t slot = psContext->psDependencies->GetSpecializationConstantSlot(i.m_StaticBranchName);
|
||||
if(alreadyDeclared.insert(slot).second) // Only declare if the insertion actually succeeded
|
||||
bformata(glsl, "layout(constant_id = %d) const bool %s = false;\n", slot, i.m_StaticBranchName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string to64(uint32_t in)
|
||||
{
|
||||
const char to64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
char c_[2];
|
||||
c_[0] = to64[in];
|
||||
c_[1] = 0;
|
||||
char c = c_[0];
|
||||
if (c == 'X')
|
||||
return "XX";
|
||||
if (c == '+')
|
||||
return "XA";
|
||||
if (c == '/')
|
||||
return "XB";
|
||||
return std::string(c_);
|
||||
}
|
||||
|
||||
// Slightly custom base64, espace non-identifier chars with 'X'
|
||||
static void Base64Encode(const std::string &in, std::string& result)
|
||||
{
|
||||
|
||||
size_t len = in.length();
|
||||
size_t outputLen = (len + 2) / 3 * 4;
|
||||
unsigned char *bytes = (unsigned char *)&in[0];
|
||||
|
||||
result.clear();
|
||||
result.reserve(outputLen);
|
||||
|
||||
int i = 0;
|
||||
unsigned char b1, b2, b3;
|
||||
for (int chunk = 0; len > 0; len -= 3, chunk++) {
|
||||
b1 = bytes[i++];
|
||||
b2 = len > 1 ? bytes[i++] : '\0';
|
||||
result += to64(b1 >> 2);
|
||||
result += to64(((b1 & 3) << 4) | ((b2 & 0xf0) >> 4));
|
||||
if (len > 2)
|
||||
{
|
||||
b3 = bytes[i++];
|
||||
result += to64(((b2 & 0xF) << 2) | ((b3 & 0xC0) >> 6));
|
||||
result += to64(b3 & 0x3F);
|
||||
}
|
||||
else if (len == 2)
|
||||
{
|
||||
result += to64((b2 & 0xF) << 2);
|
||||
result += "XC";
|
||||
break;
|
||||
}
|
||||
else /* len == 1 */
|
||||
{
|
||||
result += "XC";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ToGLSL::BuildStaticBranchNameForInstruction(Instruction &inst)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (!inst.m_StaticBranchCondition)
|
||||
{
|
||||
// Simple case, just get the value, check if nonzero
|
||||
bstring varname = bfromcstr("");
|
||||
SHADER_VARIABLE_TYPE argType = inst.asOperands[0].GetDataType(psContext);
|
||||
uint32_t flag = TO_FLAG_NONE;
|
||||
switch (argType)
|
||||
{
|
||||
case SVT_BOOL:
|
||||
flag = TO_FLAG_BOOL;
|
||||
break;
|
||||
case SVT_INT:
|
||||
case SVT_INT12:
|
||||
case SVT_INT16:
|
||||
flag = TO_FLAG_INTEGER;
|
||||
break;
|
||||
case SVT_UINT:
|
||||
case SVT_UINT16:
|
||||
case SVT_UINT8:
|
||||
flag = TO_FLAG_UNSIGNED_INTEGER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TranslateOperand(varname, &inst.asOperands[0], flag);
|
||||
char *str = bstr2cstr(varname, '\0');
|
||||
oss << str;
|
||||
bcstrfree(str);
|
||||
bdestroy(varname);
|
||||
oss << "!=0";
|
||||
Base64Encode(oss.str(), inst.m_StaticBranchName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indirect, just store the whole previous instruction and then the condition
|
||||
bstring res = bfromcstr("");
|
||||
|
||||
bstring *oldglsl = psContext->currentGLSLString;
|
||||
psContext->currentGLSLString = &res;
|
||||
TranslateInstruction((Instruction *)inst.m_StaticBranchCondition, true);
|
||||
psContext->currentGLSLString = oldglsl;
|
||||
|
||||
SHADER_VARIABLE_TYPE argType = inst.asOperands[0].GetDataType(psContext);
|
||||
uint32_t flag = TO_FLAG_NONE;
|
||||
switch (argType)
|
||||
{
|
||||
case SVT_BOOL:
|
||||
flag = TO_FLAG_BOOL;
|
||||
break;
|
||||
case SVT_INT:
|
||||
case SVT_INT12:
|
||||
case SVT_INT16:
|
||||
flag = TO_FLAG_INTEGER;
|
||||
break;
|
||||
case SVT_UINT:
|
||||
case SVT_UINT16:
|
||||
case SVT_UINT8:
|
||||
flag = TO_FLAG_UNSIGNED_INTEGER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (argType == SVT_BOOL)
|
||||
{
|
||||
if (inst.eBooleanTestType == INSTRUCTION_TEST_ZERO)
|
||||
bcatcstr(res, "!");
|
||||
}
|
||||
|
||||
TranslateOperand(res, &inst.asOperands[0], flag);
|
||||
char *str = bstr2cstr(res, '\0');
|
||||
oss << str;
|
||||
bcstrfree(str);
|
||||
bdestroy(res);
|
||||
if(argType != SVT_BOOL)
|
||||
oss << "!=0";
|
||||
Base64Encode(oss.str(), inst.m_StaticBranchName);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ToGLSL::IdentifyStaticBranches(ShaderPhase *psPhase)
|
||||
{
|
||||
for (std::vector<Instruction>::iterator itr = psPhase->psInst.begin(); itr != psPhase->psInst.end(); itr++)
|
||||
{
|
||||
Instruction &i = *itr;
|
||||
|
||||
if (!i.IsConditionalBranchInstruction())
|
||||
continue;
|
||||
|
||||
// Simple case, direct conditional branch
|
||||
if (i.asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER)
|
||||
{
|
||||
psPhase->m_StaticBranchInstructions.push_back(&i);
|
||||
i.m_IsStaticBranch = true;
|
||||
i.m_StaticBranchCondition = NULL;
|
||||
BuildStaticBranchNameForInstruction(i);
|
||||
}
|
||||
// Indirect, comparison via another instruction
|
||||
if (i.asOperands[0].eType == OPERAND_TYPE_TEMP)
|
||||
{
|
||||
// Check that the temp only has one visible definition
|
||||
if (i.asOperands[0].m_Defines.size() == 1)
|
||||
{
|
||||
// ...and that it only uses constant buffers and immediates
|
||||
|
||||
Instruction &def = *i.asOperands[0].m_Defines[0].m_Inst;
|
||||
bool isStatic = true;
|
||||
for (uint32_t k = def.ui32FirstSrc; k < def.ui32NumOperands; k++)
|
||||
{
|
||||
Operand &o = def.asOperands[k];
|
||||
if (!(o.eType == OPERAND_TYPE_CONSTANT_BUFFER || o.eType == OPERAND_TYPE_IMMEDIATE32))
|
||||
{
|
||||
isStatic = false;
|
||||
break;
|
||||
}
|
||||
// Also check that the constant buffer access is "simple"
|
||||
if (o.eType == OPERAND_TYPE_CONSTANT_BUFFER)
|
||||
{
|
||||
if (o.m_SubOperands[0].get() || o.m_SubOperands[1].get())
|
||||
{
|
||||
isStatic = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isStatic)
|
||||
{
|
||||
psPhase->m_StaticBranchInstructions.push_back(&i);
|
||||
i.m_IsStaticBranch = true;
|
||||
i.m_StaticBranchCondition = &def;
|
||||
BuildStaticBranchNameForInstruction(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,7 +237,8 @@ static void DeclareInput(
|
|||
|
||||
std::string locationQualifier = "";
|
||||
|
||||
if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage))
|
||||
if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage) ||
|
||||
((psContext->flags & HLSLCC_FLAG_NVN_TARGET) && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)))
|
||||
{
|
||||
bool addLocation = false;
|
||||
|
||||
|
@ -365,10 +366,9 @@ void ToGLSL::AddBuiltinOutput(const Declaration* psDecl, int arrayElements, cons
|
|||
{
|
||||
int max = psDecl->asOperands[0].GetMaxComponent();
|
||||
|
||||
if (IsESLanguage(psShader->eTargetLanguage) && !psShader->m_ClipDistanceExtensionDeclared)
|
||||
if (IsESLanguage(psShader->eTargetLanguage))
|
||||
{
|
||||
bcatcstr(psContext->extensions, "#extension GL_EXT_clip_cull_distance : require\n");
|
||||
psShader->m_ClipDistanceExtensionDeclared = true;
|
||||
psContext->RequireExtension("GL_EXT_clip_cull_distance");
|
||||
}
|
||||
|
||||
int applySwizzle = psDecl->asOperands[0].GetNumSwizzleElements() > 1 ? 1 : 0;
|
||||
|
@ -551,7 +551,7 @@ void ToGLSL::AddUserOutput(const Declaration* psDecl)
|
|||
const Operand* psOperand = &psDecl->asOperands[0];
|
||||
const char* Precision = "";
|
||||
int iNumComponents;
|
||||
bstring type;
|
||||
bstring type = NULL;
|
||||
int regSpace = psDecl->asOperands[0].GetRegisterSpace(psContext);
|
||||
uint32_t ui32Reg = psDecl->asOperands[0].ui32RegisterNumber;
|
||||
|
||||
|
@ -604,7 +604,7 @@ void ToGLSL::AddUserOutput(const Declaration* psDecl)
|
|||
break;
|
||||
}
|
||||
|
||||
if(HavePrecisionQualifers(psShader->eTargetLanguage))
|
||||
if(HavePrecisionQualifiers(psContext))
|
||||
{
|
||||
switch(psOperand->eMinPrecision)
|
||||
{
|
||||
|
@ -664,8 +664,7 @@ void ToGLSL::AddUserOutput(const Declaration* psDecl)
|
|||
{
|
||||
bcatcstr(extensions, "#ifdef GL_ARB_conservative_depth\n");
|
||||
bcatcstr(extensions, "#extension GL_ARB_conservative_depth : enable\n");
|
||||
bcatcstr(extensions, "layout (depth_less) out float gl_FragDepth;\n");
|
||||
bcatcstr(glsl, "#endif\n");
|
||||
bcatcstr(extensions, "#endif\n");
|
||||
bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n");
|
||||
bcatcstr(glsl, "layout (depth_less) out float gl_FragDepth;\n");
|
||||
bcatcstr(glsl, "#endif\n");
|
||||
|
@ -685,6 +684,13 @@ void ToGLSL::AddUserOutput(const Declaration* psDecl)
|
|||
strncpy(OutputName, (char *)oname->data, 512);
|
||||
bdestroy(oname);
|
||||
|
||||
bstring layoutQualifier = bformat("");
|
||||
bool haveFramebufferFetch = (psShader->extensions->EXT_shader_framebuffer_fetch &&
|
||||
psShader->eShaderType == PIXEL_SHADER &&
|
||||
psContext->flags & HLSLCC_FLAG_SHADER_FRAMEBUFFER_FETCH);
|
||||
if (haveFramebufferFetch)
|
||||
bcatcstr(glsl, "#ifdef GL_EXT_shader_framebuffer_fetch\n");
|
||||
|
||||
if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage) ||
|
||||
HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions))
|
||||
{
|
||||
|
@ -698,15 +704,23 @@ void ToGLSL::AddUserOutput(const Declaration* psDecl)
|
|||
renderTarget = 0;
|
||||
index = 1;
|
||||
}
|
||||
bformata(glsl, "layout(location = %d, index = %d) ", renderTarget, index);
|
||||
layoutQualifier = bformat("layout(location = %d, index = %d) ", renderTarget, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
bformata(glsl, "layout(location = %d) ", renderTarget);
|
||||
layoutQualifier = bformat("layout(location = %d) ", renderTarget);
|
||||
}
|
||||
}
|
||||
|
||||
bformata(glsl, "out %s%s %s;\n", Precision, type->data, OutputName);
|
||||
if (haveFramebufferFetch)
|
||||
{
|
||||
bformata(glsl, "%sinout %s%s %s;\n", bstr2cstr(layoutQualifier, '\0'), Precision, type->data, OutputName);
|
||||
bcatcstr(glsl, "#else\n");
|
||||
bformata(glsl, "%sout %s%s %s;\n", bstr2cstr(layoutQualifier, '\0'), Precision, type->data, OutputName);
|
||||
bcatcstr(glsl, "#endif\n");
|
||||
}
|
||||
else
|
||||
bformata(glsl, "%sout %s%s %s;\n", bstr2cstr(layoutQualifier, '\0'), Precision, type->data, OutputName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1005,6 +1019,8 @@ static const char* GetSamplerType(HLSLCrossCompilerContext* psContext,
|
|||
{
|
||||
case RESOURCE_DIMENSION_BUFFER:
|
||||
{
|
||||
if (IsESLanguage(psContext->psShader->eTargetLanguage))
|
||||
psContext->RequireExtension("GL_EXT_texture_buffer");
|
||||
switch(eType)
|
||||
{
|
||||
case RETURN_TYPE_SINT:
|
||||
|
@ -1151,9 +1167,9 @@ static const char* GetSamplerType(HLSLCrossCompilerContext* psContext,
|
|||
return "sampler2D";
|
||||
}
|
||||
|
||||
static const char *GetSamplerPrecision(GLLang langVersion, REFLECT_RESOURCE_PRECISION ePrec)
|
||||
static const char *GetSamplerPrecision(const HLSLCrossCompilerContext *psContext, REFLECT_RESOURCE_PRECISION ePrec)
|
||||
{
|
||||
if (!HavePrecisionQualifers(langVersion))
|
||||
if (!HavePrecisionQualifiers(psContext))
|
||||
return " ";
|
||||
|
||||
switch (ePrec)
|
||||
|
@ -1181,23 +1197,20 @@ static void TranslateResourceTexture(HLSLCrossCompilerContext* psContext, const
|
|||
psDecl->asOperands[0].ui32RegisterNumber);
|
||||
|
||||
if (psDecl->value.eResourceDimension == RESOURCE_DIMENSION_TEXTURECUBEARRAY
|
||||
&& !HaveCubemapArray(psContext->psShader->eTargetLanguage)
|
||||
&& !psContext->psShader->m_CubemapArrayExtensionDeclared)
|
||||
&& !HaveCubemapArray(psContext->psShader->eTargetLanguage))
|
||||
{
|
||||
// Need to enable extension (either OES or ARB), but we only need to add it once
|
||||
if (IsESLanguage(psContext->psShader->eTargetLanguage))
|
||||
bformata(psContext->extensions, "#extension GL_OES_texture_cube_map_array : enable\n");
|
||||
psContext->RequireExtension("GL_OES_texture_cube_map_array");
|
||||
else
|
||||
bformata(psContext->extensions, "#extension GL_ARB_texture_cube_map_array : enable\n");
|
||||
|
||||
psContext->psShader->m_CubemapArrayExtensionDeclared = true;
|
||||
psContext->RequireExtension("GL_ARB_texture_cube_map_array");
|
||||
}
|
||||
|
||||
const ResourceBinding *psBinding = NULL;
|
||||
psShader->sInfo.GetResourceFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psBinding);
|
||||
ASSERT(psBinding != NULL);
|
||||
|
||||
samplerPrecision = GetSamplerPrecision(psContext->psShader->eTargetLanguage, psBinding ? psBinding->ePrecision : REFLECT_RESOURCE_PRECISION_UNKNOWN);
|
||||
samplerPrecision = GetSamplerPrecision(psContext, psBinding ? psBinding->ePrecision : REFLECT_RESOURCE_PRECISION_UNKNOWN);
|
||||
|
||||
if (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS)
|
||||
{
|
||||
|
@ -1669,7 +1682,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
StorageQualifier = "in";
|
||||
}
|
||||
|
||||
if(HavePrecisionQualifers(psShader->eTargetLanguage))
|
||||
if(HavePrecisionQualifiers(psContext))
|
||||
{
|
||||
switch(psOperand->eMinPrecision)
|
||||
{
|
||||
|
@ -1741,6 +1754,16 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
const char* Interpolation = "";
|
||||
int hasNoPerspective = psContext->psShader->eTargetLanguage <= LANG_ES_310 ? 0 : 1;
|
||||
inputName = psContext->GetDeclaredInputName(psOperand, NULL, 1, NULL);
|
||||
|
||||
// If this is a SV_Target input and framebuffer fetch is enabled then skip the declaration
|
||||
if (psShader->extensions->EXT_shader_framebuffer_fetch &&
|
||||
psShader->eShaderType == PIXEL_SHADER &&
|
||||
psContext->flags & HLSLCC_FLAG_SHADER_FRAMEBUFFER_FETCH)
|
||||
{
|
||||
if(inputName == "vs_SV_Target0")
|
||||
break;
|
||||
}
|
||||
|
||||
if (InOutSupported(psContext->psShader->eTargetLanguage))
|
||||
{
|
||||
StorageQualifier = "in";
|
||||
|
@ -1787,7 +1810,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
break;
|
||||
}
|
||||
|
||||
if(HavePrecisionQualifers(psShader->eTargetLanguage))
|
||||
if(HavePrecisionQualifiers(psContext))
|
||||
{
|
||||
switch(psOperand->eMinPrecision)
|
||||
{
|
||||
|
@ -1830,7 +1853,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
{
|
||||
uint32_t i = 0;
|
||||
const uint32_t ui32NumTemps = psDecl->value.ui32NumTemps;
|
||||
bool usePrecision = (HavePrecisionQualifers(psShader->eTargetLanguage) != 0);
|
||||
bool usePrecision = (HavePrecisionQualifiers(psContext) != 0);
|
||||
|
||||
for (i = 0; i < ui32NumTemps; i++)
|
||||
{
|
||||
|
@ -1867,8 +1890,6 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
const Operand* psOperand = &psDecl->asOperands[0];
|
||||
const uint32_t ui32BindingPoint = psOperand->aui32ArraySizes[0];
|
||||
|
||||
const char* StageName = "VS";
|
||||
|
||||
const ConstantBuffer* psCBuf = NULL;
|
||||
psContext->psShader->sInfo.GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, ui32BindingPoint, &psCBuf);
|
||||
|
||||
|
@ -1882,37 +1903,109 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
break;
|
||||
}
|
||||
|
||||
switch(psContext->psShader->eShaderType)
|
||||
if (psCBuf->name.substr(0, 20) == "hlslcc_SubpassInput_" && psCBuf->name.length() >= 23 && !psCBuf->asVars.empty())
|
||||
{
|
||||
case PIXEL_SHADER:
|
||||
// Special case for vulkan subpass input.
|
||||
|
||||
// The multisample versions have multiple members in the cbuffer, but we must only declare once.
|
||||
// We still need to loop through all the variables and adjust names
|
||||
|
||||
// Pick up the type and index
|
||||
char ty = psCBuf->name[20];
|
||||
int idx = psCBuf->name[22] - '0';
|
||||
bool isMS = false;
|
||||
std::pair<uint32_t, uint32_t> binding = psContext->psDependencies->GetVulkanResourceBinding((std::string &)psCBuf->name, false, 2);
|
||||
|
||||
bool declared = false;
|
||||
for (std::vector<ShaderVar>::const_iterator itr = psCBuf->asVars.begin(); itr != psCBuf->asVars.end(); itr++)
|
||||
{
|
||||
StageName = "PS";
|
||||
ShaderVar &sv = (ShaderVar &)*itr;
|
||||
if (sv.name.substr(0, 15) == "hlslcc_fbinput_")
|
||||
{
|
||||
if (!declared)
|
||||
{
|
||||
switch (ty)
|
||||
{
|
||||
case 'f':
|
||||
bformata(glsl, "layout(input_attachment_index = %d, set = %d, binding = %d) uniform highp subpassInput %s;\n", idx, binding.first, binding.second, sv.name.c_str());
|
||||
break;
|
||||
}
|
||||
case HULL_SHADER:
|
||||
{
|
||||
StageName = "HS";
|
||||
case 'h':
|
||||
bformata(glsl, "layout(input_attachment_index = %d, set = %d, binding = %d) uniform mediump subpassInput %s;\n", idx, binding.first, binding.second, sv.name.c_str());
|
||||
break;
|
||||
}
|
||||
case DOMAIN_SHADER:
|
||||
{
|
||||
StageName = "DS";
|
||||
case 'i':
|
||||
bformata(glsl, "layout(input_attachment_index = %d, set = %d, binding = %d) uniform isubpassInput %s;\n", idx, binding.first, binding.second, sv.name.c_str());
|
||||
break;
|
||||
}
|
||||
case GEOMETRY_SHADER:
|
||||
{
|
||||
StageName = "GS";
|
||||
case 'u':
|
||||
bformata(glsl, "layout(input_attachment_index = %d, set = %d, binding = %d) uniform usubpassInput %s;\n", idx, binding.first, binding.second, sv.name.c_str());
|
||||
break;
|
||||
}
|
||||
case COMPUTE_SHADER:
|
||||
{
|
||||
StageName = "CS";
|
||||
case 'F':
|
||||
bformata(glsl, "layout(input_attachment_index = %d, set = %d, binding = %d) uniform highp subpassInputMS %s;\n", idx, binding.first, binding.second, sv.name.substr(0, 16).c_str());
|
||||
isMS = true;
|
||||
break;
|
||||
case 'H':
|
||||
bformata(glsl, "layout(input_attachment_index = %d, set = %d, binding = %d) uniform mediump subpassInputMS %s;\n", idx, binding.first, binding.second, sv.name.substr(0, 16).c_str());
|
||||
isMS = true;
|
||||
break;
|
||||
case 'I':
|
||||
bformata(glsl, "layout(input_attachment_index = %d, set = %d, binding = %d) uniform isubpassInputMS %s;\n", idx, binding.first, binding.second, sv.name.substr(0, 16).c_str());
|
||||
isMS = true;
|
||||
break;
|
||||
case 'U':
|
||||
bformata(glsl, "layout(input_attachment_index = %d, set = %d, binding = %d) uniform usubpassInputMS %s;\n", idx, binding.first, binding.second, sv.name.substr(0, 16).c_str());
|
||||
isMS = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
declared = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ty == 'F' || ty == 'I' || ty == 'U')
|
||||
isMS = true;
|
||||
}
|
||||
// Munge the name so it'll get the correct function call in GLSL directly
|
||||
sv.name.insert(0, "subpassLoad(");
|
||||
if (isMS)
|
||||
sv.name[sv.name.length() - 2] = ',';
|
||||
sv.name.append(")");
|
||||
// Also update the type name
|
||||
sv.sType.name = sv.name;
|
||||
sv.sType.fullName = sv.name;
|
||||
}
|
||||
}
|
||||
|
||||
// Break out so this doesn't get declared.
|
||||
break;
|
||||
}
|
||||
|
||||
if(psCBuf->name == "OVR_multiview")
|
||||
{
|
||||
// Special case for piggy-backing multiview info out
|
||||
// This is not really a cbuffer, but if we see this being accessed, we know we need viewID
|
||||
|
||||
// Extract numViews
|
||||
uint32_t numViews = 0;
|
||||
for(std::vector<ShaderVar>::const_iterator itr = psCBuf->asVars.begin(); itr != psCBuf->asVars.end(); itr++)
|
||||
{
|
||||
if(strncmp(itr->name.c_str(), "numViews_", 9) == 0)
|
||||
{
|
||||
// I really don't think we'll ever have more than 9 multiviews
|
||||
numViews = itr->name[9] - '0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(numViews > 0 && numViews < 10)
|
||||
{
|
||||
bcatcstr(extensions, "#extension GL_OVR_multiview : require\n");
|
||||
bcatcstr(extensions, "#extension GL_OVR_multiview2 : enable\n");
|
||||
|
||||
if(psShader->eShaderType == VERTEX_SHADER)
|
||||
bformata(glsl, "layout(num_views = %d) in;\n", numViews);
|
||||
|
||||
break; // Break out so we don't actually declare this cbuffer
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT)
|
||||
|
@ -1934,7 +2027,9 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
}
|
||||
case OPCODE_DCL_RESOURCE:
|
||||
{
|
||||
if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags))
|
||||
// Skip the location declaration on Vulkan
|
||||
if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)
|
||||
&& ((psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS) == 0))
|
||||
{
|
||||
// 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.
|
||||
|
@ -1950,7 +2045,19 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
{
|
||||
case RESOURCE_DIMENSION_BUFFER:
|
||||
{
|
||||
bformata(glsl, "uniform %s ", GetSamplerType(psContext,
|
||||
if ((psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0)
|
||||
{
|
||||
const ResourceBinding *psBinding = NULL;
|
||||
psShader->sInfo.GetResourceFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psBinding);
|
||||
std::string tname = psBinding->name;
|
||||
GLSLCrossDependencyData::VulkanResourceBinding binding = psContext->psDependencies->GetVulkanResourceBinding(tname);
|
||||
bformata(glsl, "layout(set = %d, binding = %d) ", binding.first, binding.second);
|
||||
}
|
||||
|
||||
bcatcstr(glsl, "uniform ");
|
||||
if (IsESLanguage(psContext->psShader->eTargetLanguage))
|
||||
bcatcstr(glsl, "highp ");
|
||||
bformata(glsl, "%s ", GetSamplerType(psContext,
|
||||
RESOURCE_DIMENSION_BUFFER,
|
||||
psDecl->asOperands[0].ui32RegisterNumber));
|
||||
TranslateOperand(&psDecl->asOperands[0], TO_FLAG_NONE);
|
||||
|
@ -2347,7 +2454,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
|
||||
}
|
||||
|
||||
if (HavePrecisionQualifers(psShader->eTargetLanguage))
|
||||
if (HavePrecisionQualifiers(psContext))
|
||||
{
|
||||
switch (psSignature->eMinPrec) // TODO What if the inputs in the indexed range are of different precisions?
|
||||
{
|
||||
|
@ -2560,7 +2667,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
// non-float images need either 'i' or 'u' prefix.
|
||||
char imageTypePrefix[2] = { 0, 0 };
|
||||
uint32_t bindpoint = psDecl->asOperands[0].ui32RegisterNumber;
|
||||
const bool isVulkan = (psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS);
|
||||
const bool isVulkan = (psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0;
|
||||
|
||||
if(psDecl->sUAV.ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS)
|
||||
{
|
||||
|
@ -2585,12 +2692,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
if ((psDecl->sUAV.ui32AccessFlags & ACCESS_FLAG_WRITE) && IsESLanguage(psShader->eTargetLanguage))
|
||||
{
|
||||
// Need to require the extension
|
||||
if (!psShader->m_TextureBufferExtensionDeclared)
|
||||
{
|
||||
bcatcstr(psContext->extensions, "#extension GL_EXT_texture_buffer : require\n");
|
||||
psShader->m_TextureBufferExtensionDeclared = true;
|
||||
}
|
||||
|
||||
psContext->RequireExtension("GL_EXT_texture_buffer");
|
||||
}
|
||||
|
||||
if(isVulkan)
|
||||
|
@ -2642,6 +2744,9 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
{
|
||||
case RESOURCE_DIMENSION_BUFFER:
|
||||
{
|
||||
if(IsESLanguage(psShader->eTargetLanguage))
|
||||
psContext->RequireExtension("GL_EXT_texture_buffer");
|
||||
|
||||
bformata(glsl, "uniform %simageBuffer ", imageTypePrefix);
|
||||
break;
|
||||
}
|
||||
|
@ -2701,7 +2806,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
}
|
||||
case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED:
|
||||
{
|
||||
const bool isVulkan = (psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS);
|
||||
const bool isVulkan = (psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0;
|
||||
if(psDecl->sUAV.bCounter)
|
||||
{
|
||||
if (isVulkan)
|
||||
|
@ -2715,7 +2820,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
{
|
||||
bcatcstr(glsl, "layout (binding = 0) uniform ");
|
||||
|
||||
if (HavePrecisionQualifers(psShader->eTargetLanguage))
|
||||
if (HavePrecisionQualifiers(psContext))
|
||||
bcatcstr(glsl, "highp ");
|
||||
bcatcstr(glsl, "atomic_uint ");
|
||||
ResourceName(glsl, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0);
|
||||
|
@ -2729,7 +2834,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
}
|
||||
case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW:
|
||||
{
|
||||
const bool isVulkan = (psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS);
|
||||
const bool isVulkan = (psContext->flags & HLSLCC_FLAG_VULKAN_BINDINGS) != 0;
|
||||
if(psDecl->sUAV.bCounter)
|
||||
{
|
||||
if (isVulkan)
|
||||
|
@ -2742,7 +2847,7 @@ void ToGLSL::TranslateDeclaration(const Declaration* psDecl)
|
|||
else
|
||||
{
|
||||
bcatcstr(glsl, "layout (binding = 0) uniform ");
|
||||
if (HavePrecisionQualifers(psShader->eTargetLanguage))
|
||||
if (HavePrecisionQualifiers(psContext))
|
||||
bcatcstr(glsl, "highp ");
|
||||
bcatcstr(glsl, "atomic_uint ");
|
||||
ResourceName(glsl, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0);
|
||||
|
@ -2989,6 +3094,13 @@ bool ToGLSL::TranslateSystemValue(const Operand *psOperand, const ShaderInfo::In
|
|||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (sig->semanticName == "PSIZE")
|
||||
{
|
||||
result = "gl_PointSize";
|
||||
if (pui32IgnoreSwizzle)
|
||||
*pui32IgnoreSwizzle = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ void ToGLSL::AddOpAssignToDestWithMask(const Operand* psDest,
|
|||
case SVT_FLOAT:
|
||||
case SVT_FLOAT10:
|
||||
case SVT_FLOAT16:
|
||||
ASSERT(eSrcType != SVT_INT12 || eSrcType != SVT_INT16 && eSrcType != SVT_UINT16);
|
||||
ASSERT(eSrcType != SVT_INT12 || (eSrcType != SVT_INT16 && eSrcType != SVT_UINT16));
|
||||
if (psContext->psShader->ui32MajorVersion > 3)
|
||||
{
|
||||
if (eSrcType == SVT_INT)
|
||||
|
@ -892,7 +892,8 @@ void ToGLSL::GetResInfoData(Instruction* psInst, int index, int destElem)
|
|||
bstring glsl = *psContext->currentGLSLString;
|
||||
int numParenthesis = 0;
|
||||
const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType;
|
||||
const int isUAV = (psInst->asOperands[2].eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW);
|
||||
bool isUAV = (psInst->asOperands[2].eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW);
|
||||
bool isMS = psInst->eResDim == RESOURCE_DIMENSION_TEXTURE2DMS || psInst->eResDim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY;
|
||||
|
||||
psContext->AddIndentation();
|
||||
AddOpAssignToDestWithMask(&psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, "=", &numParenthesis, 1 << destElem);
|
||||
|
@ -922,7 +923,7 @@ void ToGLSL::GetResInfoData(Instruction* psInst, int index, int destElem)
|
|||
|
||||
TranslateOperand(&psInst->asOperands[2], TO_FLAG_NONE);
|
||||
|
||||
if (!isUAV)
|
||||
if (!isUAV && !isMS)
|
||||
{
|
||||
bcatcstr(glsl, ", ");
|
||||
TranslateOperand(&psInst->asOperands[1], TO_FLAG_INTEGER);
|
||||
|
@ -1077,7 +1078,7 @@ void ToGLSL::TranslateTextureSample(Instruction* psInst,
|
|||
if (ui32Flags & TEXSMP_FLAG_GATHER)
|
||||
funcName = "textureGather";
|
||||
|
||||
uint32_t uniqueNameCounter;
|
||||
uint32_t uniqueNameCounter = 0;
|
||||
|
||||
// In GLSL, for every texture sampling func overload, except for cubemap arrays, the
|
||||
// depth compare reference value is given as the last component of the texture coord vector.
|
||||
|
@ -1391,7 +1392,6 @@ void ToGLSL::TranslateShaderStorageLoad(Instruction* psInst)
|
|||
}
|
||||
for (component = 0; component < 4; component++)
|
||||
{
|
||||
const ShaderVarType *psVar = NULL;
|
||||
int addedBitcast = 0;
|
||||
if (!(destMask & (1 << component)))
|
||||
continue;
|
||||
|
@ -1835,6 +1835,14 @@ void ToGLSL::TranslateConditional(
|
|||
statement = "return";
|
||||
}
|
||||
|
||||
if (psInst->m_IsStaticBranch)
|
||||
{
|
||||
// Instead of the actual condition, use the specialization constant instead
|
||||
|
||||
// But first we'll have to make sure the original values don't get dropped out (we rely on glslang not being very smart)
|
||||
bcatcstr(glsl, "if(false)\n {\n");
|
||||
}
|
||||
|
||||
SHADER_VARIABLE_TYPE argType = psInst->asOperands[0].GetDataType(psContext);
|
||||
if (argType == SVT_BOOL)
|
||||
{
|
||||
|
@ -1884,6 +1892,32 @@ void ToGLSL::TranslateConditional(
|
|||
bcatcstr(glsl, " {\n");
|
||||
}
|
||||
}
|
||||
if (psInst->m_IsStaticBranch)
|
||||
{
|
||||
if (psInst->eOpcode == OPCODE_IF)
|
||||
{
|
||||
bcatcstr(glsl, "}\n}\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
bcatcstr(glsl, "}\n");
|
||||
}
|
||||
bcatcstr(glsl, "if(");
|
||||
if (psInst->eBooleanTestType != INSTRUCTION_TEST_NONZERO)
|
||||
bcatcstr(glsl, "!");
|
||||
bcatcstr(glsl, psInst->m_StaticBranchName.c_str());
|
||||
if (psInst->eOpcode != OPCODE_IF)
|
||||
{
|
||||
bformata(glsl, "){%s;}\n", statement);
|
||||
}
|
||||
else
|
||||
{
|
||||
bcatcstr(glsl, "){\n");
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ToGLSL::TranslateInstruction(Instruction* psInst, bool isEmbedded /* = false */)
|
||||
|
@ -1896,8 +1930,9 @@ void ToGLSL::TranslateInstruction(Instruction* psInst, bool isEmbedded /* = fals
|
|||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
psContext->AddIndentation();
|
||||
bformata(glsl, "//Instruction %d\n", psInst->id);
|
||||
// Uncomment to print instruction IDs
|
||||
//psContext->AddIndentation();
|
||||
//bformata(glsl, "//Instruction %d\n", psInst->id);
|
||||
#if 0
|
||||
if (psInst->id == 73)
|
||||
{
|
||||
|
@ -2751,10 +2786,7 @@ void ToGLSL::TranslateInstruction(Instruction* psInst, bool isEmbedded /* = fals
|
|||
uint32_t varFound;
|
||||
|
||||
uint32_t funcPointer;
|
||||
uint32_t funcTableIndex;
|
||||
uint32_t funcTable;
|
||||
uint32_t funcBodyIndex;
|
||||
uint32_t funcBody;
|
||||
uint32_t ui32NumBodiesPerTable;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -2765,15 +2797,10 @@ void ToGLSL::TranslateInstruction(Instruction* psInst, bool isEmbedded /* = fals
|
|||
ASSERT(psInst->asOperands[0].eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32);
|
||||
|
||||
funcPointer = psInst->asOperands[0].aui32ArraySizes[0];
|
||||
funcTableIndex = psInst->asOperands[0].aui32ArraySizes[1];
|
||||
funcBodyIndex = psInst->ui32FuncIndexWithinInterface;
|
||||
|
||||
ui32NumBodiesPerTable = psContext->psShader->funcPointer[funcPointer].ui32NumBodiesPerTable;
|
||||
|
||||
funcTable = psContext->psShader->funcPointer[funcPointer].aui32FuncTables[funcTableIndex];
|
||||
|
||||
funcBody = psContext->psShader->funcTable[funcTable].aui32FuncBodies[funcBodyIndex];
|
||||
|
||||
varFound = psContext->psShader->sInfo.GetInterfaceVarFromOffset(funcPointer, &psVar);
|
||||
|
||||
ASSERT(varFound);
|
||||
|
@ -3630,7 +3657,7 @@ void ToGLSL::TranslateInstruction(Instruction* psInst, bool isEmbedded /* = fals
|
|||
break;
|
||||
}
|
||||
|
||||
SHADER_VARIABLE_TYPE srcDataType;
|
||||
SHADER_VARIABLE_TYPE srcDataType = SVT_FLOAT;
|
||||
const ResourceBinding* psBinding = 0;
|
||||
psContext->psShader->sInfo.GetResourceFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psBinding);
|
||||
switch (psBinding->ui32ReturnType)
|
||||
|
@ -4005,13 +4032,13 @@ void ToGLSL::TranslateInstruction(Instruction* psInst, bool isEmbedded /* = fals
|
|||
psContext->AddIndentation();
|
||||
AddAssignToDest(&psInst->asOperands[0], SVT_UINT, 1, &numParenthesis);
|
||||
if (isVulkan)
|
||||
bcatcstr(glsl, "atomicAdd(");
|
||||
bcatcstr(glsl, "(atomicAdd(");
|
||||
else
|
||||
bcatcstr(glsl, "atomicCounterDecrement(");
|
||||
ResourceName(glsl, psContext, RGROUP_UAV, psInst->asOperands[1].ui32RegisterNumber, 0);
|
||||
bformata(glsl, "_counter");
|
||||
if (isVulkan)
|
||||
bcatcstr(glsl, ", 0xffffffffu)");
|
||||
bcatcstr(glsl, ", 0xffffffffu) + 0xffffffffu)");
|
||||
else
|
||||
bcatcstr(glsl, ")");
|
||||
AddAssignPrologue(numParenthesis);
|
||||
|
@ -4071,7 +4098,21 @@ void ToGLSL::TranslateInstruction(Instruction* psInst, bool isEmbedded /* = fals
|
|||
AddAssignPrologue(numParenthesis);
|
||||
break;
|
||||
}
|
||||
|
||||
case OPCODE_SAMPLE_INFO:
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
psContext->AddIndentation();
|
||||
bcatcstr(glsl, "//SAMPLE_INFO\n");
|
||||
#endif
|
||||
const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType;
|
||||
psContext->AddIndentation();
|
||||
AddAssignToDest(&psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, &numParenthesis);
|
||||
bcatcstr(glsl, "textureSamples(");
|
||||
TranslateOperand(&psInst->asOperands[1], TO_FLAG_NAME_ONLY);
|
||||
bcatcstr(glsl, ")");
|
||||
AddAssignPrologue(numParenthesis);
|
||||
break;
|
||||
}
|
||||
case OPCODE_DMAX:
|
||||
case OPCODE_DMIN:
|
||||
case OPCODE_DMUL:
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "internal_includes/debug.h"
|
||||
#include "internal_includes/Shader.h"
|
||||
#include "internal_includes/toGLSL.h"
|
||||
#include "internal_includes/languages.h"
|
||||
#include <cmath>
|
||||
|
||||
#include <sstream>
|
||||
|
@ -57,7 +58,11 @@ void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand*
|
|||
|
||||
void TranslateOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, int iRebase)
|
||||
{
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
TranslateOperandSwizzleWithMask(*psContext->currentGLSLString, psContext, psOperand, ui32ComponentMask, iRebase);
|
||||
}
|
||||
|
||||
void TranslateOperandSwizzleWithMask(bstring glsl, HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, int iRebase)
|
||||
{
|
||||
uint32_t accessMask = ui32ComponentMask & psOperand->GetAccessMask();
|
||||
if(psOperand->eType == OPERAND_TYPE_INPUT)
|
||||
{
|
||||
|
@ -400,11 +405,15 @@ static void printImmediate32(HLSLCrossCompilerContext *psContext, uint32_t value
|
|||
}
|
||||
|
||||
void ToGLSL::TranslateVariableNameWithMask(const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase)
|
||||
{
|
||||
TranslateVariableNameWithMask(*psContext->currentGLSLString, psOperand, ui32TOFlag, pui32IgnoreSwizzle, ui32CompMask, piRebase);
|
||||
}
|
||||
|
||||
void ToGLSL::TranslateVariableNameWithMask(bstring glsl, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask, int *piRebase)
|
||||
{
|
||||
int numParenthesis = 0;
|
||||
int hasCtor = 0;
|
||||
int needsBoolUpscale = 0; // If nonzero, bools need * 0xffffffff in them
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
SHADER_VARIABLE_TYPE requestedType = TypeFlagsToSVTType(ui32TOFlag);
|
||||
SHADER_VARIABLE_TYPE eType = psOperand->GetDataType(psContext, requestedType);
|
||||
int numComponents = psOperand->GetNumSwizzleElements(ui32CompMask);
|
||||
|
@ -606,8 +615,22 @@ void ToGLSL::TranslateVariableNameWithMask(const Operand* psOperand, uint32_t ui
|
|||
else
|
||||
{
|
||||
std::string name = psContext->GetDeclaredInputName(psOperand, piRebase, 0, pui32IgnoreSwizzle);
|
||||
|
||||
// Rewrite the variable name if we're using framebuffer fetch
|
||||
if (psContext->psShader->extensions->EXT_shader_framebuffer_fetch &&
|
||||
psContext->psShader->eShaderType == PIXEL_SHADER &&
|
||||
psContext->flags & HLSLCC_FLAG_SHADER_FRAMEBUFFER_FETCH)
|
||||
{
|
||||
if(name == "vs_SV_Target0")
|
||||
bcatcstr(glsl, "SV_Target0");
|
||||
else
|
||||
bcatcstr(glsl, name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
bcatcstr(glsl, name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -781,7 +804,7 @@ void ToGLSL::TranslateVariableNameWithMask(const Operand* psOperand, uint32_t ui
|
|||
const ShaderVarType* psVarType = NULL;
|
||||
int32_t index = -1;
|
||||
std::vector<uint32_t> arrayIndices;
|
||||
bool isArray;
|
||||
bool isArray = false;
|
||||
psContext->psShader->sInfo.GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psCBuf);
|
||||
|
||||
switch(psContext->psShader->eShaderType)
|
||||
|
@ -817,6 +840,14 @@ void ToGLSL::TranslateVariableNameWithMask(const Operand* psOperand, uint32_t ui
|
|||
}
|
||||
}
|
||||
|
||||
if(psCBuf && psCBuf->name == "OVR_multiview")
|
||||
{
|
||||
pui32IgnoreSwizzle[0] = 1;
|
||||
bformata(glsl, "gl_ViewID_OVR");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(ui32TOFlag & TO_FLAG_DECLARATION_NAME)
|
||||
{
|
||||
pui32IgnoreSwizzle[0] = 1;
|
||||
|
@ -1411,7 +1442,11 @@ void ToGLSL::TranslateVariableNameWithMask(const Operand* psOperand, uint32_t ui
|
|||
|
||||
void ToGLSL::TranslateOperand(const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask)
|
||||
{
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
TranslateOperand(*psContext->currentGLSLString, psOperand, ui32TOFlag, ui32ComponentMask);
|
||||
}
|
||||
|
||||
void ToGLSL::TranslateOperand(bstring glsl, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask)
|
||||
{
|
||||
uint32_t ui32IgnoreSwizzle = 0;
|
||||
int iRebase = 0;
|
||||
|
||||
|
@ -1426,7 +1461,7 @@ void ToGLSL::TranslateOperand(const Operand* psOperand, uint32_t ui32TOFlag, uin
|
|||
|
||||
if(ui32TOFlag & TO_FLAG_NAME_ONLY)
|
||||
{
|
||||
TranslateVariableNameWithMask(psOperand, ui32TOFlag, &ui32IgnoreSwizzle, OPERAND_4_COMPONENT_MASK_ALL, &iRebase);
|
||||
TranslateVariableNameWithMask(glsl, psOperand, ui32TOFlag, &ui32IgnoreSwizzle, OPERAND_4_COMPONENT_MASK_ALL, &iRebase);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1453,7 +1488,7 @@ void ToGLSL::TranslateOperand(const Operand* psOperand, uint32_t ui32TOFlag, uin
|
|||
}
|
||||
}
|
||||
|
||||
TranslateVariableNameWithMask(psOperand, ui32TOFlag, &ui32IgnoreSwizzle, ui32ComponentMask, &iRebase);
|
||||
TranslateVariableNameWithMask(glsl, psOperand, ui32TOFlag, &ui32IgnoreSwizzle, ui32ComponentMask, &iRebase);
|
||||
|
||||
if(psContext->psShader->eShaderType == HULL_SHADER && psOperand->eType == OPERAND_TYPE_OUTPUT &&
|
||||
psOperand->ui32RegisterNumber != 0 && psOperand->iArrayElements != 0 && psOperand->eIndexRep[0] != OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE
|
||||
|
@ -1464,7 +1499,7 @@ void ToGLSL::TranslateOperand(const Operand* psOperand, uint32_t ui32TOFlag, uin
|
|||
|
||||
if(!ui32IgnoreSwizzle)
|
||||
{
|
||||
TranslateOperandSwizzleWithMask(psContext, psOperand, ui32ComponentMask, iRebase);
|
||||
TranslateOperandSwizzleWithMask(glsl, psContext, psOperand, ui32ComponentMask, iRebase);
|
||||
}
|
||||
|
||||
switch(psOperand->eModifier)
|
||||
|
@ -1592,18 +1627,11 @@ std::string TextureSamplerName(ShaderInfo* psShaderInfo, const uint32_t ui32Text
|
|||
|
||||
if(ui32ArrayOffset)
|
||||
{
|
||||
oss << texName << ui32ArrayOffset << "_X_" << psSamplerBinding->name;
|
||||
oss << texName << ui32ArrayOffset << "TEX_with_SMP" << psSamplerBinding->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((i>0) && (texName[i-1] == '_'))//Prevent double underscore which is reserved
|
||||
{
|
||||
oss << texName << "X_" << psSamplerBinding->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << texName << "_X_" << psSamplerBinding->name;
|
||||
}
|
||||
oss << texName << "TEX_with_SMP" << psSamplerBinding->name;
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
|
|
|
@ -81,13 +81,11 @@ bool ToMetal::Translate()
|
|||
|
||||
ClampPartialPrecisions();
|
||||
|
||||
psShader->PrepareStructuredBufferBindingSlots();
|
||||
|
||||
ShaderPhase &phase = psShader->asPhases[0];
|
||||
phase.UnvectorizeImmMoves();
|
||||
psContext->DoDataTypeAnalysis(&phase);
|
||||
phase.ResolveUAVProperties();
|
||||
psShader->ResolveStructuredBufferBindingSlots(&phase);
|
||||
ReserveUAVBindingSlots(&phase); // TODO: unify slot allocation code between gl/metal/vulkan
|
||||
phase.PruneConstArrays();
|
||||
HLSLcc::DoLoopTransform(phase);
|
||||
|
||||
|
@ -95,11 +93,17 @@ bool ToMetal::Translate()
|
|||
|
||||
bcatcstr(glsl, "#include <metal_stdlib>\n#include <metal_texture>\nusing namespace metal;\n");
|
||||
|
||||
|
||||
for (i = 0; i < psShader->asPhases[0].psDecl.size(); ++i)
|
||||
{
|
||||
TranslateDeclaration(&psShader->asPhases[0].psDecl[i]);
|
||||
}
|
||||
|
||||
// Output default implementations for framebuffer index remap if needed
|
||||
if(m_NeedFBOutputRemapDecl)
|
||||
bcatcstr(glsl, "#ifndef XLT_REMAP_O\n#define XLT_REMAP_O {0, 1, 2, 3, 4, 5, 6, 7}\n#endif\nconstexpr constant uint xlt_remap_o[] = XLT_REMAP_O;\n");
|
||||
if(m_NeedFBInputRemapDecl)
|
||||
bcatcstr(glsl, "#ifndef XLT_REMAP_I\n#define XLT_REMAP_I {0, 1, 2, 3, 4, 5, 6, 7}\n#endif\nconstexpr constant uint xlt_remap_i[] = XLT_REMAP_I;\n");
|
||||
|
||||
DeclareClipPlanes(&psShader->asPhases[0].psDecl[0], psShader->asPhases[0].psDecl.size());
|
||||
GenerateTexturesReflection(&psContext->m_Reflection);
|
||||
|
||||
if (m_StructDefinitions[GetInputStructName()].m_Members.size() > 0)
|
||||
{
|
||||
|
@ -263,3 +267,25 @@ void ToMetal::ClampPartialPrecisions()
|
|||
o->eMinPrecision = OPERAND_MIN_PRECISION_FLOAT_16;
|
||||
});
|
||||
}
|
||||
|
||||
void ToMetal::ReserveUAVBindingSlots(ShaderPhase *phase)
|
||||
{
|
||||
for (uint32_t p = 0; p < phase->psDecl.size(); ++p)
|
||||
{
|
||||
uint32_t regNo = phase->psDecl[p].asOperands[0].ui32RegisterNumber;
|
||||
|
||||
if (phase->psDecl[p].eOpcode == OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW ||
|
||||
phase->psDecl[p].eOpcode == OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED)
|
||||
{
|
||||
m_BufferSlots.ReserveBindingSlot(regNo, BindingSlotAllocator::RWBuffer);
|
||||
}
|
||||
else if (phase->psDecl[p].eOpcode == OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED)
|
||||
{
|
||||
// Typed buffers are atm faked using structured buffers -> bind in buffer space
|
||||
if (phase->psDecl[p].value.eResourceDimension == RESOURCE_DIMENSION_BUFFER)
|
||||
m_BufferSlots.ReserveBindingSlot(regNo, BindingSlotAllocator::RWBuffer);
|
||||
else
|
||||
m_TextureSlots.ReserveBindingSlot(regNo, BindingSlotAllocator::UAV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,13 @@ bool ToMetal::TranslateSystemValue(const Operand *psOperand, const ShaderInfo::I
|
|||
if (outSkipPrefix != NULL) *outSkipPrefix = true;
|
||||
return true;
|
||||
case NAME_CLIP_DISTANCE:
|
||||
result = "mtl_ClipDistance";
|
||||
{
|
||||
// this is temp variabe, declaration and redirecting to actual output is handled in DeclareClipPlanes
|
||||
char tmpName[128]; sprintf(tmpName, "phase%d_ClipDistance%d", psContext->currentPhase, sig->ui32SemanticIndex);
|
||||
result = tmpName;
|
||||
if (outSkipPrefix != NULL) *outSkipPrefix = true;
|
||||
return true;
|
||||
}
|
||||
/* case NAME_VIEWPORT_ARRAY_INDEX:
|
||||
result = "gl_ViewportIndex";
|
||||
if (puiIgnoreSwizzle)
|
||||
|
@ -179,6 +183,80 @@ void ToMetal::DeclareBuiltinInput(const Declaration *psDecl)
|
|||
}
|
||||
}
|
||||
|
||||
void ToMetal::DeclareClipPlanes(const Declaration* decl, unsigned declCount)
|
||||
{
|
||||
unsigned planeCount = 0;
|
||||
for(unsigned i = 0, n = declCount ; i < n ; ++i)
|
||||
{
|
||||
const Operand* operand = &decl[i].asOperands[0];
|
||||
if(operand->eSpecialName == NAME_CLIP_DISTANCE)
|
||||
planeCount += operand->GetMaxComponent();
|
||||
}
|
||||
if(planeCount == 0) return;
|
||||
|
||||
std::ostringstream oss; oss << "float mtl_ClipDistance [[ clip_distance ]]";
|
||||
if(planeCount > 1) oss << "[" << planeCount << "]";
|
||||
m_StructDefinitions[GetOutputStructName()].m_Members.push_back(oss.str());
|
||||
|
||||
Shader* shader = psContext->psShader;
|
||||
|
||||
unsigned compCount = 1;
|
||||
const ShaderInfo::InOutSignature* psFirstClipSignature;
|
||||
if(shader->sInfo.GetOutputSignatureFromSystemValue(NAME_CLIP_DISTANCE, 0, &psFirstClipSignature))
|
||||
{
|
||||
if(psFirstClipSignature->ui32Mask & (1 << 3)) compCount = 4;
|
||||
else if(psFirstClipSignature->ui32Mask & (1 << 2)) compCount = 3;
|
||||
else if(psFirstClipSignature->ui32Mask & (1 << 1)) compCount = 2;
|
||||
}
|
||||
|
||||
ShaderPhase* phase = &shader->asPhases[psContext->currentPhase];
|
||||
for(unsigned i = 0, n = declCount ; i < n ; ++i)
|
||||
{
|
||||
const Operand* operand = &decl[i].asOperands[0];
|
||||
if(operand->eSpecialName != NAME_CLIP_DISTANCE) continue;
|
||||
|
||||
const ShaderInfo::InOutSignature* signature = 0;
|
||||
shader->sInfo.GetOutputSignatureFromRegister(operand->ui32RegisterNumber, operand->ui32CompMask, 0, &signature);
|
||||
const int semanticIndex = signature->ui32SemanticIndex;
|
||||
|
||||
bformata(phase->earlyMain, " float4 phase%d_ClipDistance%d;\n", psContext->currentPhase, signature->ui32SemanticIndex);
|
||||
|
||||
const char* swizzleStr[] = { "x", "y", "z", "w" };
|
||||
phase->hasPostShaderCode = 1;
|
||||
if(planeCount > 1)
|
||||
{
|
||||
for(int i = 0 ; i < compCount ; ++i)
|
||||
{
|
||||
bformata(phase->postShaderCode, " %s.mtl_ClipDistance[%d] = phase%d_ClipDistance%d.%s;\n",
|
||||
"output", semanticIndex*compCount + i, psContext->currentPhase, semanticIndex, swizzleStr[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bformata(phase->postShaderCode, " %s.mtl_ClipDistance = phase%d_ClipDistance%d.x;\n", "output", psContext->currentPhase, semanticIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ToMetal::GenerateTexturesReflection(HLSLccReflection* refl)
|
||||
{
|
||||
for(unsigned i = 0, n = m_Textures.size() ; i < n ; ++i)
|
||||
{
|
||||
const std::string samplerName1 = m_Textures[i].name, samplerName2 = "sampler"+m_Textures[i].name;
|
||||
for(unsigned j = 0, m = m_Samplers.size() ; j < m ; ++j)
|
||||
{
|
||||
if(m_Samplers[j].name == samplerName1 || m_Samplers[j].name == samplerName2)
|
||||
{
|
||||
m_Textures[i].samplerBind = m_Samplers[j].slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned i = 0, n = m_Textures.size() ; i < n ; ++i)
|
||||
refl->OnTextureBinding(m_Textures[i].name, m_Textures[i].textureBind, m_Textures[i].samplerBind, m_Textures[i].dim, m_Textures[i].uav);
|
||||
}
|
||||
|
||||
void ToMetal::DeclareBuiltinOutput(const Declaration *psDecl)
|
||||
{
|
||||
std::string out = GetOutputStructName();
|
||||
|
@ -198,7 +276,7 @@ void ToMetal::DeclareBuiltinOutput(const Declaration *psDecl)
|
|||
#endif
|
||||
break;
|
||||
case NAME_CLIP_DISTANCE:
|
||||
m_StructDefinitions[out].m_Members.push_back("float4 mtl_ClipDistance [[ clip_distance ]]");
|
||||
// it will be done separately in DeclareClipPlanes
|
||||
break;
|
||||
|
||||
case NAME_VIEWPORT_ARRAY_INDEX:
|
||||
|
@ -329,7 +407,6 @@ void ToMetal::HandleOutputRedirect(const Declaration *psDecl, const std::string
|
|||
{
|
||||
const Operand *psOperand = &psDecl->asOperands[0];
|
||||
Shader *psShader = psContext->psShader;
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
int needsRedirect = 0;
|
||||
const ShaderInfo::InOutSignature *psSig = NULL;
|
||||
|
||||
|
@ -425,7 +502,6 @@ void ToMetal::HandleInputRedirect(const Declaration *psDecl, const std::string &
|
|||
{
|
||||
Operand *psOperand = (Operand *)&psDecl->asOperands[0];
|
||||
Shader *psShader = psContext->psShader;
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
int needsRedirect = 0;
|
||||
const ShaderInfo::InOutSignature *psSig = NULL;
|
||||
|
||||
|
@ -525,7 +601,7 @@ void ToMetal::HandleInputRedirect(const Declaration *psDecl, const std::string &
|
|||
}
|
||||
|
||||
static std::string TranslateResourceDeclaration(HLSLCrossCompilerContext* psContext,
|
||||
const Declaration *psDecl,
|
||||
const Declaration *psDecl, const std::string& textureName,
|
||||
bool isDepthSampler, bool isUAV)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
@ -591,7 +667,15 @@ static std::string TranslateResourceDeclaration(HLSLCrossCompilerContext* psCont
|
|||
access = "read";
|
||||
}
|
||||
|
||||
std::string typeName = HLSLcc::GetConstructorForTypeMetal(HLSLcc::ResourceReturnTypeToSVTType(eType, ePrec), 1);
|
||||
SHADER_VARIABLE_TYPE svtType = HLSLcc::ResourceReturnTypeToSVTType(eType, ePrec);
|
||||
std::string typeName = HLSLcc::GetConstructorForTypeMetal(svtType, 1);
|
||||
|
||||
if ((textureName == "_CameraDepthTexture" || textureName == "_LastCameraDepthTexture") && svtType != SVT_FLOAT)
|
||||
{
|
||||
std::string msg = textureName + " should be float on Metal (use sampler2D or sampler2D_float). Incorrect type "
|
||||
"can cause Metal validation failures or undefined results on some devices.";
|
||||
psContext->m_Reflection.OnDiagnostics(msg, 0, false);
|
||||
}
|
||||
|
||||
switch (eDimension)
|
||||
{
|
||||
|
@ -870,19 +954,16 @@ void ToMetal::DeclareConstantBuffer(const ConstantBuffer *psCBuf, uint32_t ui32B
|
|||
|
||||
}
|
||||
|
||||
void ToMetal::DeclareBufferVariable(const Declaration *psDecl, const bool isRaw, const bool isUAV)
|
||||
void ToMetal::DeclareBufferVariable(const Declaration *psDecl, bool isRaw, bool isUAV)
|
||||
{
|
||||
uint32_t ui32BindingPoint = psDecl->asOperands[0].ui32RegisterNumber;
|
||||
std::string BufName, BufType;
|
||||
uint32_t regNo = psDecl->asOperands[0].ui32RegisterNumber;
|
||||
std::string BufName, BufType, BufConst;
|
||||
|
||||
BufName = "";
|
||||
BufType = "";
|
||||
BufConst = "";
|
||||
|
||||
// Use original HLSL bindings for UAVs only. For non-UAV buffers we have resolved new binding points from the same register space.
|
||||
if (!isUAV)
|
||||
ui32BindingPoint = psContext->psShader->aui32StructuredBufferBindingPoints[psContext->psShader->ui32CurrentStructuredBufferIndex++];
|
||||
|
||||
BufName = ResourceName(isUAV ? RGROUP_UAV : RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber);
|
||||
BufName = ResourceName(isUAV ? RGROUP_UAV : RGROUP_TEXTURE, regNo);
|
||||
|
||||
if (!isRaw) // declare struct containing uint array when needed
|
||||
{
|
||||
|
@ -898,7 +979,8 @@ void ToMetal::DeclareBufferVariable(const Declaration *psDecl, const bool isRaw,
|
|||
|
||||
if (!isUAV || ((psDecl->sUAV.ui32AccessFlags & ACCESS_FLAG_WRITE) == 0))
|
||||
{
|
||||
oss << "const ";
|
||||
BufConst = "const ";
|
||||
oss << BufConst;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -911,11 +993,138 @@ void ToMetal::DeclareBufferVariable(const Declaration *psDecl, const bool isRaw,
|
|||
else
|
||||
oss << "device " << BufType << " *" << BufName;
|
||||
|
||||
uint32_t loc = m_BufferSlots.GetBindingSlot(ui32BindingPoint, BindingSlotAllocator::RWBuffer);
|
||||
uint32_t loc = m_BufferSlots.GetBindingSlot(regNo, isUAV ? BindingSlotAllocator::RWBuffer : BindingSlotAllocator::Texture);
|
||||
oss << " [[ buffer(" << loc << ") ]]";
|
||||
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
psContext->m_Reflection.OnBufferBinding(BufName, loc, isUAV);
|
||||
|
||||
|
||||
// In addition to the actual declaration, we need pointer modification and possible counter declaration
|
||||
// in early main:
|
||||
std::ostringstream earlymainoss;
|
||||
|
||||
// Possible counter is always in the beginning of the buffer
|
||||
if (isUAV && psDecl->sUAV.bCounter)
|
||||
{
|
||||
earlymainoss << " device atomic_uint *" << BufName << "_counter = reinterpret_cast<device atomic_uint *> (" << BufName << ");\n";
|
||||
}
|
||||
|
||||
// Some GPUs don't allow memory access below buffer binding offset in the shader so always bind compute buffer
|
||||
// at offset 0 instead of GetDataOffset().
|
||||
// We can't tell at shader compile time if the buffer actually has counter or not. Therefore we'll always reserve
|
||||
// space for the counter and bump the data pointer to beginning of the actual data here.
|
||||
earlymainoss << " " << BufName << " = reinterpret_cast<" << BufConst
|
||||
<< "device " << (isRaw ? "uint" : BufType) << " *> (reinterpret_cast<device "
|
||||
<< BufConst << "atomic_uint *> (" << BufName << ") + 1);\n";
|
||||
|
||||
bformata(psContext->psShader->asPhases[psContext->currentPhase].earlyMain, earlymainoss.str().c_str());
|
||||
}
|
||||
|
||||
|
||||
static int ParseInlineSamplerWrapMode(const std::string& samplerName, const std::string& wrapName)
|
||||
{
|
||||
int res = 0;
|
||||
const bool hasWrap = (samplerName.find(wrapName) != std::string::npos);
|
||||
if (!hasWrap)
|
||||
return res;
|
||||
|
||||
const bool hasU = (samplerName.find(wrapName + 'u') != std::string::npos);
|
||||
const bool hasV = (samplerName.find(wrapName + 'v') != std::string::npos);
|
||||
const bool hasW = (samplerName.find(wrapName + 'w') != std::string::npos);
|
||||
|
||||
if (hasWrap) res |= 1;
|
||||
if (hasU) res |= 2;
|
||||
if (hasV) res |= 4;
|
||||
if (hasW) res |= 8;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static bool EmitInlineSampler(HLSLCrossCompilerContext* ctx, const std::string& name)
|
||||
{
|
||||
// See if it's a sampler that goes with the texture, or an "inline" sampler
|
||||
// where sampler states are hardcoded in the shader directly.
|
||||
//
|
||||
// The logic for "inline" samplers below must match what is recognized
|
||||
// by other shader platforms in Unity (ParseInlineSamplerName function
|
||||
// in the shader compiler).
|
||||
|
||||
std::string samplerName(name); std::transform(samplerName.begin(), samplerName.end(), samplerName.begin(), ::tolower);
|
||||
|
||||
// filter modes
|
||||
const bool hasPoint = (samplerName.find("point") != std::string::npos);
|
||||
const bool hasTrilinear = (samplerName.find("trilinear") != std::string::npos);
|
||||
const bool hasLinear = (samplerName.find("linear") != std::string::npos);
|
||||
const bool hasAnyFilter = hasPoint || hasTrilinear || hasLinear;
|
||||
|
||||
// wrap modes
|
||||
const int bitsClamp = ParseInlineSamplerWrapMode(samplerName, "clamp");
|
||||
const int bitsRepeat = ParseInlineSamplerWrapMode(samplerName, "repeat");
|
||||
const int bitsMirror = ParseInlineSamplerWrapMode(samplerName, "mirror");
|
||||
const int bitsMirrorOnce = ParseInlineSamplerWrapMode(samplerName, "mirroronce");
|
||||
|
||||
const bool hasAnyWrap = bitsClamp != 0 || bitsRepeat != 0 || bitsMirror != 0 || bitsMirrorOnce != 0;
|
||||
|
||||
// depth comparison
|
||||
const bool hasCompare = (samplerName.find("compare") != std::string::npos);
|
||||
|
||||
// name must contain a filter mode and a wrap mode at least
|
||||
if (!hasAnyFilter || !hasAnyWrap)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bstring str = ctx->psShader->asPhases[ctx->currentPhase].earlyMain;
|
||||
bformata(str, "\tconstexpr sampler %s(", name.c_str());
|
||||
|
||||
if (hasCompare)
|
||||
bformata(str, "compare_func::greater_equal,");
|
||||
|
||||
if (hasTrilinear)
|
||||
bformata(str, "filter::linear,mip_filter::linear,");
|
||||
else if (hasLinear)
|
||||
bformata(str, "filter::linear,");
|
||||
else
|
||||
bformata(str, "filter::nearest,");
|
||||
|
||||
const char* kTexWrapClamp = "clamp_to_edge";
|
||||
const char* kTexWrapRepeat = "repeat";
|
||||
const char* kTexWrapMirror = "mirrored_repeat";
|
||||
const char* kTexWrapMirrorOnce = "mirrored_repeat"; // currently Metal shading language does not have syntax for inline sampler state that would do "mirror clamp to edge"
|
||||
const char* wrapU = kTexWrapRepeat;
|
||||
const char* wrapV = kTexWrapRepeat;
|
||||
const char* wrapW = kTexWrapRepeat;
|
||||
|
||||
if (bitsClamp == 1) wrapU = wrapV = wrapW = kTexWrapClamp;
|
||||
else if (bitsRepeat == 1) wrapU = wrapV = wrapW = kTexWrapRepeat;
|
||||
else if (bitsMirrorOnce == 1) wrapU = wrapV = wrapW = kTexWrapMirrorOnce;
|
||||
else if (bitsMirror == 1) wrapU = wrapV = wrapW = kTexWrapMirror;
|
||||
|
||||
if ((bitsClamp & 2) != 0) wrapU = kTexWrapClamp;
|
||||
if ((bitsClamp & 4) != 0) wrapV = kTexWrapClamp;
|
||||
if ((bitsClamp & 8) != 0) wrapW = kTexWrapClamp;
|
||||
|
||||
if ((bitsRepeat & 2) != 0) wrapU = kTexWrapRepeat;
|
||||
if ((bitsRepeat & 4) != 0) wrapV = kTexWrapRepeat;
|
||||
if ((bitsRepeat & 8) != 0) wrapW = kTexWrapRepeat;
|
||||
|
||||
if ((bitsMirrorOnce & 2) != 0) wrapU = kTexWrapMirrorOnce;
|
||||
if ((bitsMirrorOnce & 4) != 0) wrapV = kTexWrapMirrorOnce;
|
||||
if ((bitsMirrorOnce & 8) != 0) wrapW = kTexWrapMirrorOnce;
|
||||
|
||||
if ((bitsMirror & 2) != 0) wrapU = kTexWrapMirror;
|
||||
if ((bitsMirror & 4) != 0) wrapV = kTexWrapMirror;
|
||||
if ((bitsMirror & 8) != 0) wrapW = kTexWrapMirror;
|
||||
|
||||
if (wrapU == wrapV && wrapU == wrapW)
|
||||
bformata(str, "address::%s", wrapU);
|
||||
else
|
||||
bformata(str, "s_address::%s,t_address::%s,r_address::%s", wrapU, wrapV, wrapW);
|
||||
|
||||
bformata(str, ");\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -946,12 +1155,10 @@ void ToMetal::TranslateDeclaration(const Declaration* psDecl)
|
|||
|
||||
std::string name = psContext->GetDeclaredInputName(psOperand, nullptr, 1, nullptr);
|
||||
|
||||
//Already declared as part of an array?
|
||||
if (psShader->aIndexedInput[0][psDecl->asOperands[0].ui32RegisterNumber] == -1)
|
||||
{
|
||||
ASSERT(0); // Find out what's happening
|
||||
break;
|
||||
}
|
||||
// NB: unlike GL we keep arrays of 2-component vectors as is (without collapsing into float4)
|
||||
// if(psShader->aIndexedInput[0][psDecl->asOperands[0].ui32RegisterNumber] == -1)
|
||||
// break;
|
||||
|
||||
// Already declared?
|
||||
if ((ui32CompMask != 0) && ((ui32CompMask & ~psShader->acInputDeclared[0][ui32Reg]) == 0))
|
||||
{
|
||||
|
@ -1041,7 +1248,8 @@ void ToMetal::TranslateDeclaration(const Declaration* psDecl)
|
|||
//
|
||||
// TODO: Improve later when GLES3 support arrives, it requires
|
||||
// single declaration through inout
|
||||
oss << "color(" << psSig->ui32SemanticIndex << ")";
|
||||
oss << "color(xlt_remap_i[" << psSig->ui32SemanticIndex << "])";
|
||||
m_NeedFBInputRemapDecl = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1115,6 +1323,49 @@ void ToMetal::TranslateDeclaration(const Declaration* psDecl)
|
|||
const ConstantBuffer* psCBuf = NULL;
|
||||
psContext->psShader->sInfo.GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psDecl->asOperands[0].aui32ArraySizes[0], &psCBuf);
|
||||
ASSERT(psCBuf != NULL);
|
||||
|
||||
if (psCBuf->name.substr(0, 20) == "hlslcc_SubpassInput_" && psCBuf->name.length() >= 23 && !psCBuf->asVars.empty())
|
||||
{
|
||||
// Special case for framebuffer fetch.
|
||||
char ty = psCBuf->name[20];
|
||||
int idx = psCBuf->name[22] - '0';
|
||||
|
||||
const ShaderVar &sv = psCBuf->asVars[0];
|
||||
if (sv.name.substr(0, 15) == "hlslcc_fbinput_")
|
||||
{
|
||||
// Pick up the type and index
|
||||
std::ostringstream oss;
|
||||
m_NeedFBInputRemapDecl = true;
|
||||
switch (ty)
|
||||
{
|
||||
case 'f':
|
||||
case 'F':
|
||||
oss << "float4 " << sv.name << " [[ color(xlt_remap_i["<< idx <<"]) ]]";
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
oss << "half4 " << sv.name << " [[ color(xlt_remap_i[" << idx << "]) ]]";
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
oss << "int4 " << sv.name << " [[ color(xlt_remap_i[" << idx << "]) ]]";
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
oss << "uint4 " << sv.name << " [[ color(xlt_remap_i[" << idx << "]) ]]";
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Break out so this doesn't get declared.
|
||||
break;
|
||||
}
|
||||
|
||||
DeclareConstantBuffer(psCBuf, psDecl->asOperands[0].aui32ArraySizes[0]);
|
||||
break;
|
||||
}
|
||||
|
@ -1373,9 +1624,9 @@ void ToMetal::TranslateDeclaration(const Declaration* psDecl)
|
|||
uint32_t destMask = psDecl->asOperands[0].ui32CompMask;
|
||||
uint32_t rebase = 0;
|
||||
const ShaderInfo::InOutSignature *psSig = NULL;
|
||||
uint32_t regSpace = psDecl->asOperands[0].GetRegisterSpace(psContext) == 0;
|
||||
uint32_t regSpace = psDecl->asOperands[0].GetRegisterSpace(psContext);
|
||||
|
||||
if (regSpace)
|
||||
if (regSpace == 0)
|
||||
if (isInput)
|
||||
psContext->psShader->sInfo.GetInputSignatureFromRegister(startReg + i, destMask, &psSig);
|
||||
else
|
||||
|
@ -1414,8 +1665,9 @@ void ToMetal::TranslateDeclaration(const Declaration* psDecl)
|
|||
}
|
||||
}
|
||||
}
|
||||
bcatcstr(glsl, " = ");
|
||||
bcatcstr(glsl, realName.c_str());
|
||||
|
||||
// for some reason input struct is missed here from GetDeclaredInputName result, so add it manually
|
||||
bformata(glsl, " = input.%s", realName.c_str());
|
||||
if (destMask != OPERAND_4_COMPONENT_MASK_ALL && destMask != psSig->ui32Mask)
|
||||
{
|
||||
int k;
|
||||
|
@ -1537,25 +1789,20 @@ void ToMetal::TranslateDeclaration(const Declaration* psDecl)
|
|||
}
|
||||
case OPCODE_DCL_SAMPLER:
|
||||
{
|
||||
// Find out if the sampler is good for a builtin
|
||||
std::string name = TranslateOperand(&psDecl->asOperands[0], TO_FLAG_NAME_ONLY);
|
||||
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
||||
bool linear = (name.find("linear") != std::string::npos);
|
||||
bool point = (name.find("point") != std::string::npos);
|
||||
bool clamp = (name.find("clamp") != std::string::npos);
|
||||
bool repeat = (name.find("repeat") != std::string::npos);
|
||||
|
||||
// Declare only builtin samplers here. Default samplers are declared together with the texture.
|
||||
if ((linear != point) && (clamp != repeat))
|
||||
if (!EmitInlineSampler(psContext, name))
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "constexpr sampler " << TranslateOperand(&psDecl->asOperands[0], TO_FLAG_NAME_ONLY) << "(";
|
||||
oss << (linear ? "filter::linear, " : "filter::nearest, ");
|
||||
oss << (clamp ? "address::clamp_to_edge" : "address::repeat");
|
||||
oss << ")";
|
||||
// for some reason we have some samplers start with "sampler" and some not
|
||||
const bool startsWithSampler = name.find("sampler") == 0;
|
||||
const uint32_t slot = m_SamplerSlots.GetBindingSlot(psDecl->asOperands[0].ui32RegisterNumber, BindingSlotAllocator::Texture);
|
||||
std::ostringstream oss; oss << "sampler " << (startsWithSampler ? "" : "sampler") << name << " [[ sampler (" << slot << ") ]]";
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
|
||||
bformata(psContext->psShader->asPhases[psContext->currentPhase].earlyMain, "\t%s;\n", oss.str().c_str());
|
||||
SamplerDesc desc = { name, psDecl->asOperands[0].ui32RegisterNumber, slot };
|
||||
m_Samplers.push_back(desc);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case OPCODE_DCL_HS_MAX_TESSFACTOR:
|
||||
|
@ -1565,57 +1812,48 @@ void ToMetal::TranslateDeclaration(const Declaration* psDecl)
|
|||
}
|
||||
case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED:
|
||||
{
|
||||
std::string samplerTypeName = TranslateResourceDeclaration(psContext,
|
||||
psDecl, false, true);
|
||||
// A hack to support single component 32bit RWBuffers: Declare as raw buffer.
|
||||
// TODO: Use textures for RWBuffers when the scripting API has actual format selection etc
|
||||
// way to flag the created ComputeBuffer as typed. Even then might want to leave this
|
||||
// hack path for 32bit (u)int typed buffers to continue support atomic ops on those formats.
|
||||
if (psDecl->value.eResourceDimension == RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
DeclareBufferVariable(psDecl, true, true);
|
||||
break;
|
||||
}
|
||||
std::string texName = ResourceName(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber);
|
||||
std::string samplerTypeName = TranslateResourceDeclaration(psContext, psDecl, texName, false, true);
|
||||
uint32_t slot = m_TextureSlots.GetBindingSlot(psDecl->asOperands[0].ui32RegisterNumber, BindingSlotAllocator::UAV); std::ostringstream oss;
|
||||
oss << samplerTypeName << " " << texName
|
||||
<< " [[ texture (" << slot << ") ]] ";
|
||||
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
psContext->m_Reflection.OnTextureBinding(texName, slot, TD_2D, true); // TODO: translate psDecl->value.eResourceDimension into HLSLCC_TEX_DIMENSION
|
||||
|
||||
// TODO: translate psDecl->value.eResourceDimension into HLSLCC_TEX_DIMENSION
|
||||
TextureSamplerDesc desc = {texName, (int)slot, -1, TD_2D, true};
|
||||
m_Textures.push_back(desc);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED:
|
||||
{
|
||||
if (psDecl->sUAV.bCounter)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::string bufName = ResourceName(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber);
|
||||
|
||||
// Some GPUs don't allow memory access below buffer binding offset in the shader so always bind compute buffer
|
||||
// at offset 0 instead of GetDataOffset() to access counter value and translate the buffer pointer in the shader.
|
||||
oss << "device atomic_uint *" << bufName << "_counter = reinterpret_cast<device atomic_uint *> (" << bufName << ");";
|
||||
oss << "\n " << bufName << " = reinterpret_cast<device " << bufName << "_Type *> (reinterpret_cast<device atomic_uint *> (" << bufName << ") + 1)";
|
||||
bformata(psContext->psShader->asPhases[psContext->currentPhase].earlyMain, " %s;\n", oss.str().c_str());
|
||||
}
|
||||
|
||||
DeclareBufferVariable(psDecl, 0, 1);
|
||||
DeclareBufferVariable(psDecl, false, true);
|
||||
break;
|
||||
}
|
||||
case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW:
|
||||
{
|
||||
if (psDecl->sUAV.bCounter)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::string bufName = ResourceName(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber);
|
||||
oss << "device atomic_uint *" << bufName << "_counter = reinterpret_cast<atomic_uint *> (" << bufName << ") - 1";
|
||||
bformata(psContext->psShader->asPhases[psContext->currentPhase].earlyMain, "\t%s;\n", oss.str().c_str()); }
|
||||
|
||||
DeclareBufferVariable(psDecl, 1, 1);
|
||||
|
||||
DeclareBufferVariable(psDecl, true, true);
|
||||
break;
|
||||
}
|
||||
case OPCODE_DCL_RESOURCE_STRUCTURED:
|
||||
{
|
||||
DeclareBufferVariable(psDecl, 0, 0);
|
||||
DeclareBufferVariable(psDecl, false, false);
|
||||
break;
|
||||
}
|
||||
case OPCODE_DCL_RESOURCE_RAW:
|
||||
{
|
||||
DeclareBufferVariable(psDecl, 1, 0);
|
||||
DeclareBufferVariable(psDecl, true, false);
|
||||
break;
|
||||
}
|
||||
case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED:
|
||||
|
@ -1718,22 +1956,19 @@ std::string ToMetal::ResourceName(ResourceGroup group, const uint32_t ui32Regist
|
|||
void ToMetal::TranslateResourceTexture(const Declaration* psDecl, uint32_t samplerCanDoShadowCmp, HLSLCC_TEX_DIMENSION texDim)
|
||||
{
|
||||
|
||||
std::string texName = ResourceName(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber);
|
||||
std::string samplerTypeName = TranslateResourceDeclaration(psContext,
|
||||
psDecl, (samplerCanDoShadowCmp && psDecl->ui32IsShadowTex), false);
|
||||
psDecl, texName, (samplerCanDoShadowCmp && psDecl->ui32IsShadowTex), false);
|
||||
|
||||
uint32_t slot = m_TextureSlots.GetBindingSlot(psDecl->asOperands[0].ui32RegisterNumber, BindingSlotAllocator::Texture);
|
||||
std::string texName = ResourceName(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber);
|
||||
std::ostringstream oss;
|
||||
oss << samplerTypeName << " " << texName
|
||||
<< " [[ texture (" << slot << ") ]] ";
|
||||
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
psContext->m_Reflection.OnTextureBinding(texName, slot, texDim, false);
|
||||
oss.str("");
|
||||
// the default sampler for a texture is named after the texture with a "sampler" prefix
|
||||
oss << "sampler sampler" << texName
|
||||
<< " [[ sampler (" << slot << ") ]] ";
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
|
||||
TextureSamplerDesc desc = {texName, (int)slot, -1, texDim, false};
|
||||
m_Textures.push_back(desc);
|
||||
|
||||
if (samplerCanDoShadowCmp && psDecl->ui32IsShadowTex)
|
||||
EnsureShadowSamplerDeclared();
|
||||
|
@ -1746,17 +1981,21 @@ void ToMetal::DeclareResource(const Declaration *psDecl)
|
|||
{
|
||||
case RESOURCE_DIMENSION_BUFFER:
|
||||
{
|
||||
// Fake single comp 32bit texel buffers by using raw buffer
|
||||
DeclareBufferVariable(psDecl, true, false);
|
||||
break;
|
||||
|
||||
/* TODO: re-enable this code for buffer textures when sripting API has proper support for it
|
||||
uint32_t slot = m_TextureSlots.GetBindingSlot(psDecl->asOperands[0].ui32RegisterNumber, BindingSlotAllocator::Texture);
|
||||
std::string texName = TranslateOperand(&psDecl->asOperands[0], TO_FLAG_NAME_ONLY);
|
||||
std::ostringstream oss;
|
||||
oss << "device " << TranslateResourceDeclaration(psContext,
|
||||
psDecl, false, false);
|
||||
oss << "device " << TranslateResourceDeclaration(psContext, psDecl, texName, false, false);
|
||||
|
||||
oss << texName << " [[ texture(" << slot << ") ]]";
|
||||
|
||||
m_StructDefinitions[""].m_Members.push_back(oss.str());
|
||||
psContext->m_Reflection.OnTextureBinding(texName, slot, TD_2D, false); //TODO: correct HLSLCC_TEX_DIMENSION?
|
||||
break;
|
||||
break;*/
|
||||
|
||||
}
|
||||
default:
|
||||
|
@ -1816,7 +2055,6 @@ void ToMetal::DeclareResource(const Declaration *psDecl)
|
|||
|
||||
void ToMetal::DeclareOutput(const Declaration *psDecl)
|
||||
{
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
Shader* psShader = psContext->psShader;
|
||||
|
||||
if (!psContext->OutputNeedsDeclaring(&psDecl->asOperands[0], 1))
|
||||
|
@ -1934,7 +2172,8 @@ void ToMetal::DeclareOutput(const Declaration *psDecl)
|
|||
default:
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << type << " " << name << " [[ color(" << psSignature->ui32SemanticIndex << ") ]]";
|
||||
oss << type << " " << name << " [[ color(xlt_remap_o[" << psSignature->ui32SemanticIndex << "]) ]]";
|
||||
m_NeedFBOutputRemapDecl = true;
|
||||
m_StructDefinitions[GetOutputStructName()].m_Members.push_back(oss.str());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ void ToMetal::AddOpAssignToDestWithMask(const Operand* psDest,
|
|||
case SVT_FLOAT:
|
||||
case SVT_FLOAT10:
|
||||
case SVT_FLOAT16:
|
||||
ASSERT(eSrcType != SVT_INT12 || eSrcType != SVT_INT16 && eSrcType != SVT_UINT16);
|
||||
ASSERT(eSrcType != SVT_INT12 || (eSrcType != SVT_INT16 && eSrcType != SVT_UINT16));
|
||||
if (psContext->psShader->ui32MajorVersion > 3)
|
||||
{
|
||||
if (ui32DestElementCount > 1)
|
||||
|
@ -646,7 +646,6 @@ void ToMetal::TranslateTexelFetch(
|
|||
bstring glsl)
|
||||
{
|
||||
int numParenthesis = 0;
|
||||
uint32_t destCount = psInst->asOperands[0].GetNumSwizzleElements();
|
||||
psContext->AddIndentation();
|
||||
AddAssignToDest(&psInst->asOperands[0], psContext->psShader->sInfo.GetTextureDataType(psInst->asOperands[2].ui32RegisterNumber), 4, &numParenthesis);
|
||||
glsl << TranslateOperand(&psInst->asOperands[2], TO_FLAG_NONE);
|
||||
|
@ -714,7 +713,7 @@ void ToMetal::TranslateTexelFetch(
|
|||
}
|
||||
bcatcstr(glsl, ")");
|
||||
|
||||
AddSwizzleUsingElementCount(glsl, destCount);
|
||||
glsl << TranslateOperandSwizzle(&psInst->asOperands[2], psInst->asOperands[0].GetAccessMask(), 0);
|
||||
AddAssignPrologue(numParenthesis);
|
||||
}
|
||||
|
||||
|
@ -724,7 +723,6 @@ void ToMetal::TranslateTexelFetchOffset(
|
|||
bstring glsl)
|
||||
{
|
||||
int numParenthesis = 0;
|
||||
uint32_t destCount = psInst->asOperands[0].GetNumSwizzleElements();
|
||||
psContext->AddIndentation();
|
||||
AddAssignToDest(&psInst->asOperands[0], psContext->psShader->sInfo.GetTextureDataType(psInst->asOperands[2].ui32RegisterNumber), 4, &numParenthesis);
|
||||
|
||||
|
@ -799,7 +797,7 @@ void ToMetal::TranslateTexelFetchOffset(
|
|||
}
|
||||
bcatcstr(glsl, ")");
|
||||
|
||||
AddSwizzleUsingElementCount(glsl, destCount);
|
||||
glsl << TranslateOperandSwizzle(&psInst->asOperands[2], psInst->asOperands[0].GetAccessMask(), 0);
|
||||
AddAssignPrologue(numParenthesis);
|
||||
}
|
||||
|
||||
|
@ -813,6 +811,7 @@ void ToMetal::TranslateTexCoord(
|
|||
{
|
||||
uint32_t flags = TO_AUTO_BITCAST_TO_FLOAT;
|
||||
uint32_t opMask = OPERAND_4_COMPONENT_MASK_ALL;
|
||||
bool isArray = false;
|
||||
|
||||
switch (eResDim)
|
||||
{
|
||||
|
@ -822,8 +821,21 @@ void ToMetal::TranslateTexCoord(
|
|||
opMask = OPERAND_4_COMPONENT_MASK_X;
|
||||
break;
|
||||
}
|
||||
case RESOURCE_DIMENSION_TEXTURE2D:
|
||||
case RESOURCE_DIMENSION_TEXTURE1DARRAY:
|
||||
{
|
||||
// x for coord, y for array element
|
||||
opMask = OPERAND_4_COMPONENT_MASK_X;
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
glsl << TranslateOperand(psTexCoordOperand, flags, opMask);
|
||||
|
||||
bcatcstr(glsl, ", round(");
|
||||
|
||||
opMask = OPERAND_4_COMPONENT_MASK_Y;
|
||||
flags = TO_AUTO_BITCAST_TO_FLOAT;
|
||||
isArray = true;
|
||||
break;
|
||||
}
|
||||
case RESOURCE_DIMENSION_TEXTURE2D:
|
||||
{
|
||||
//Vec2 texcoord. Mask out the other components.
|
||||
opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y;
|
||||
|
@ -840,22 +852,34 @@ void ToMetal::TranslateTexCoord(
|
|||
}
|
||||
case RESOURCE_DIMENSION_TEXTURE2DARRAY:
|
||||
{
|
||||
// xy for coord, z for array element
|
||||
opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y;
|
||||
flags |= TO_AUTO_EXPAND_TO_VEC2;
|
||||
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
glsl << TranslateOperand(psTexCoordOperand, flags, opMask);
|
||||
|
||||
bcatcstr(glsl, ", ");
|
||||
bcatcstr(glsl, ", round(");
|
||||
|
||||
opMask = OPERAND_4_COMPONENT_MASK_Z;
|
||||
flags = TO_AUTO_BITCAST_TO_FLOAT;
|
||||
|
||||
isArray = true;
|
||||
break;
|
||||
}
|
||||
case RESOURCE_DIMENSION_TEXTURECUBEARRAY:
|
||||
{
|
||||
flags |= TO_AUTO_EXPAND_TO_VEC4;
|
||||
// xyz for coord, w for array element
|
||||
opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z;
|
||||
flags |= TO_AUTO_EXPAND_TO_VEC3;
|
||||
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
glsl << TranslateOperand(psTexCoordOperand, flags, opMask);
|
||||
|
||||
bcatcstr(glsl, ", round(");
|
||||
|
||||
opMask = OPERAND_4_COMPONENT_MASK_W;
|
||||
flags = TO_AUTO_BITCAST_TO_FLOAT;
|
||||
isArray = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -868,6 +892,10 @@ void ToMetal::TranslateTexCoord(
|
|||
//FIXME detect when integer coords are needed.
|
||||
bstring glsl = *psContext->currentGLSLString;
|
||||
glsl << TranslateOperand(psTexCoordOperand, flags, opMask);
|
||||
|
||||
if (isArray)
|
||||
bcatcstr(glsl, ")");
|
||||
|
||||
}
|
||||
|
||||
void ToMetal::GetResInfoData(Instruction* psInst, int index, int destElem)
|
||||
|
@ -875,12 +903,11 @@ void ToMetal::GetResInfoData(Instruction* psInst, int index, int destElem)
|
|||
bstring glsl = *psContext->currentGLSLString;
|
||||
int numParenthesis = 0;
|
||||
const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType;
|
||||
const int isUAV = (psInst->asOperands[2].eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW);
|
||||
|
||||
psContext->AddIndentation();
|
||||
AddOpAssignToDestWithMask(&psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, "=", &numParenthesis, 1 << destElem);
|
||||
|
||||
const char *metalGetters[] = { ".get_width()", ".get_height()", ".get_depth()", ".get_num_mip_levels()" };
|
||||
const char *metalGetters[] = { ".get_width(", ".get_height(", ".get_depth(", ".get_num_mip_levels()" };
|
||||
int dim = GetNumTextureDimensions(psInst->eResDim);
|
||||
if (dim < (index + 1) && index != 3)
|
||||
{
|
||||
|
@ -899,17 +926,25 @@ void ToMetal::GetResInfoData(Instruction* psInst, int index, int destElem)
|
|||
numParenthesis++;
|
||||
}
|
||||
glsl << TranslateOperand(&psInst->asOperands[2], TO_FLAG_NONE);
|
||||
if (index == 2 &&
|
||||
(psInst->eResDim == RESOURCE_DIMENSION_TEXTURE1DARRAY ||
|
||||
psInst->eResDim == RESOURCE_DIMENSION_TEXTURE2DARRAY ||
|
||||
psInst->eResDim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY))
|
||||
if ((index == 1 && psInst->eResDim == RESOURCE_DIMENSION_TEXTURE1DARRAY) ||
|
||||
(index == 2 && (psInst->eResDim == RESOURCE_DIMENSION_TEXTURE2DARRAY ||
|
||||
psInst->eResDim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY)))
|
||||
{
|
||||
bcatcstr(glsl, ".get_array_size()");
|
||||
}
|
||||
else
|
||||
{
|
||||
bcatcstr(glsl, metalGetters[index]);
|
||||
|
||||
// TODO Metal has no way to query for info on lower mip levels, now always returns info for highest.
|
||||
if (index < 3)
|
||||
{
|
||||
if (psInst->eResDim != RESOURCE_DIMENSION_TEXTURE2DMS &&
|
||||
psInst->eResDim != RESOURCE_DIMENSION_TEXTURE2DMSARRAY)
|
||||
glsl << TranslateOperand(&psInst->asOperands[1], TO_FLAG_INTEGER); //mip level
|
||||
|
||||
bcatcstr(glsl, ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
AddAssignPrologue(numParenthesis);
|
||||
}
|
||||
|
@ -933,7 +968,6 @@ void ToMetal::TranslateTextureSample(Instruction* psInst,
|
|||
Operand* psSrcBias = (ui32Flags & TEXSMP_FLAG_BIAS) ? &psInst->asOperands[4] : 0;
|
||||
|
||||
const char *funcName = "";
|
||||
const char* offset = "";
|
||||
const char* gradSwizzle = "";
|
||||
const char *gradientName = "";
|
||||
|
||||
|
@ -1165,7 +1199,6 @@ void ToMetal::TranslateTextureSample(Instruction* psInst,
|
|||
AddAssignPrologue(numParenthesis);
|
||||
}
|
||||
|
||||
static const char* swizzleString[] = { ".x", ".y", ".z", ".w" };
|
||||
|
||||
// Handle cases where vector components are accessed with dynamic index ([] notation).
|
||||
// A bit ugly hack because compiled HLSL uses byte offsets to access data in structs => we are converting
|
||||
|
@ -1212,6 +1245,7 @@ void ToMetal::TranslateShaderStorageStore(Instruction* psInst)
|
|||
|
||||
break;
|
||||
case OPCODE_STORE_RAW:
|
||||
case OPCODE_STORE_UAV_TYPED: // Hack typed buffer as raw buf
|
||||
psDest = &psInst->asOperands[0];
|
||||
psDestByteOff = &psInst->asOperands[1];
|
||||
psSrc = &psInst->asOperands[2];
|
||||
|
@ -1243,6 +1277,12 @@ void ToMetal::TranslateShaderStorageStore(Instruction* psInst)
|
|||
|
||||
bcatcstr(glsl, "[(");
|
||||
glsl << TranslateOperand(psDestByteOff, dstOffFlag);
|
||||
if (psInst->eOpcode == OPCODE_STORE_UAV_TYPED)
|
||||
{
|
||||
bcatcstr(glsl, ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
bcatcstr(glsl, " >> 2");
|
||||
if (dstOffFlag == TO_FLAG_UNSIGNED_INTEGER)
|
||||
bcatcstr(glsl, "u");
|
||||
|
@ -1254,7 +1294,7 @@ void ToMetal::TranslateShaderStorageStore(Instruction* psInst)
|
|||
if (dstOffFlag == TO_FLAG_UNSIGNED_INTEGER)
|
||||
bcatcstr(glsl, "u");
|
||||
}
|
||||
|
||||
}
|
||||
bcatcstr(glsl, "]");
|
||||
|
||||
//Dest type is currently always a uint array.
|
||||
|
@ -1287,6 +1327,7 @@ void ToMetal::TranslateShaderStorageLoad(Instruction* psInst)
|
|||
psSrc = &psInst->asOperands[3];
|
||||
break;
|
||||
case OPCODE_LD_RAW:
|
||||
case OPCODE_LD_UAV_TYPED: // Hack typed buffer as raw buf
|
||||
psDest = &psInst->asOperands[0];
|
||||
psSrcByteOff = &psInst->asOperands[1];
|
||||
psSrc = &psInst->asOperands[2];
|
||||
|
@ -1348,6 +1389,12 @@ void ToMetal::TranslateShaderStorageLoad(Instruction* psInst)
|
|||
}
|
||||
bcatcstr(glsl, "[(");
|
||||
glsl << TranslateOperand(psSrcByteOff, srcOffFlag);
|
||||
if (psInst->eOpcode == OPCODE_LD_UAV_TYPED)
|
||||
{
|
||||
bcatcstr(glsl, ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
bcatcstr(glsl, " >> 2");
|
||||
if (srcOffFlag == TO_FLAG_UNSIGNED_INTEGER)
|
||||
bcatcstr(glsl, "u");
|
||||
|
@ -1355,7 +1402,7 @@ void ToMetal::TranslateShaderStorageLoad(Instruction* psInst)
|
|||
bformata(glsl, ") + %d", psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component);
|
||||
if (srcOffFlag == TO_FLAG_UNSIGNED_INTEGER)
|
||||
bcatcstr(glsl, "u");
|
||||
|
||||
}
|
||||
bcatcstr(glsl, "]");
|
||||
|
||||
if (addedBitcast)
|
||||
|
@ -1635,9 +1682,9 @@ void ToMetal::TranslateAtomicMemOp(Instruction* psInst)
|
|||
|
||||
psContext->AddIndentation();
|
||||
|
||||
const ResourceBinding* psBinding = 0;
|
||||
if (dest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)
|
||||
{
|
||||
const ResourceBinding* psBinding = 0;
|
||||
psContext->psShader->sInfo.GetResourceFromBindingPoint(RGROUP_UAV, dest->ui32RegisterNumber, &psBinding);
|
||||
|
||||
if (psBinding->eType == RTYPE_UAV_RWTYPED)
|
||||
|
@ -1662,6 +1709,8 @@ void ToMetal::TranslateAtomicMemOp(Instruction* psInst)
|
|||
case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY:
|
||||
texDim = 3;
|
||||
break;
|
||||
case REFLECT_RESOURCE_DIMENSION_BUFFER: // Hack typed buffer as raw buf
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
|
@ -1683,14 +1732,14 @@ void ToMetal::TranslateAtomicMemOp(Instruction* psInst)
|
|||
if (shouldExtractCompare)
|
||||
{
|
||||
bcatcstr(glsl, "{\n");
|
||||
psContext->AddIndentation();
|
||||
++psContext->indent;
|
||||
psContext->AddIndentation();
|
||||
bcatcstr(glsl, "uint compare_value = ");
|
||||
glsl << TranslateOperand(compare, ui32DataTypeFlag);
|
||||
bcatcstr(glsl, "; ");
|
||||
bcatcstr(glsl, ";\n");
|
||||
psContext->AddIndentation();
|
||||
}
|
||||
|
||||
if (previousValue)
|
||||
else if (previousValue)
|
||||
AddAssignToDest(previousValue, isUint ? SVT_UINT : SVT_INT, 1, &numParenthesis);
|
||||
|
||||
bcatcstr(glsl, func);
|
||||
|
@ -1709,6 +1758,8 @@ void ToMetal::TranslateAtomicMemOp(Instruction* psInst)
|
|||
bcatcstr(glsl, "[");
|
||||
glsl << TranslateOperand(destAddr, destAddrFlag, OPERAND_4_COMPONENT_MASK_X);
|
||||
|
||||
if (!psBinding || psBinding->eType != RTYPE_UAV_RWTYPED)
|
||||
{
|
||||
// Structured buf if we have both x & y swizzles. Raw buf has only x -> no .value[]
|
||||
if (destAddr->GetNumSwizzleElements(OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y) == 2)
|
||||
{
|
||||
|
@ -1720,7 +1771,7 @@ void ToMetal::TranslateAtomicMemOp(Instruction* psInst)
|
|||
bcatcstr(glsl, " >> 2");//bytes to floats
|
||||
if (destAddrFlag == TO_FLAG_UNSIGNED_INTEGER)
|
||||
bcatcstr(glsl, "u");
|
||||
|
||||
}
|
||||
bcatcstr(glsl, "]), ");
|
||||
|
||||
if (compare)
|
||||
|
@ -1750,6 +1801,14 @@ void ToMetal::TranslateAtomicMemOp(Instruction* psInst)
|
|||
|
||||
if (shouldExtractCompare)
|
||||
{
|
||||
if (previousValue)
|
||||
{
|
||||
psContext->AddIndentation();
|
||||
AddAssignToDest(previousValue, SVT_UINT, 1, &numParenthesis);
|
||||
bcatcstr(glsl, "compare_value");
|
||||
AddAssignPrologue(numParenthesis);
|
||||
}
|
||||
--psContext->indent;
|
||||
psContext->AddIndentation();
|
||||
bcatcstr(glsl, "}\n");
|
||||
}
|
||||
|
@ -1834,8 +1893,9 @@ void ToMetal::TranslateInstruction(Instruction* psInst)
|
|||
int numParenthesis = 0;
|
||||
|
||||
#ifdef _DEBUG
|
||||
psContext->AddIndentation();
|
||||
bformata(glsl, "//Instruction %d\n", psInst->id);
|
||||
// Uncomment to print instruction IDs
|
||||
//psContext->AddIndentation();
|
||||
//bformata(glsl, "//Instruction %d\n", psInst->id);
|
||||
#if 0
|
||||
if(psInst->id == 73)
|
||||
{
|
||||
|
@ -2003,7 +2063,6 @@ void ToMetal::TranslateInstruction(Instruction* psInst)
|
|||
psContext->AddIndentation();
|
||||
bcatcstr(glsl, "//OR\n");
|
||||
#endif
|
||||
uint32_t destMask = psInst->asOperands[0].GetAccessMask();
|
||||
if (psInst->asOperands[0].GetDataType(psContext) == SVT_BOOL)
|
||||
{
|
||||
uint32_t destMask = psInst->asOperands[0].GetAccessMask();
|
||||
|
@ -3011,6 +3070,16 @@ void ToMetal::TranslateInstruction(Instruction* psInst)
|
|||
|
||||
psContext->psShader->sInfo.GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psBinding);
|
||||
|
||||
if (psInst->eResDim == RESOURCE_DIMENSION_BUFFER) // Hack typed buffer as raw buf
|
||||
{
|
||||
psInst->eOpcode = OPCODE_LD_UAV_TYPED;
|
||||
psInst->asOperands[1].eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE;
|
||||
if (psInst->asOperands[1].eType == OPERAND_TYPE_IMMEDIATE32)
|
||||
psInst->asOperands[1].iNumComponents = 1;
|
||||
TranslateShaderStorageLoad(psInst);
|
||||
break;
|
||||
}
|
||||
|
||||
if (psInst->bAddressOffset)
|
||||
{
|
||||
TranslateTexelFetchOffset(psInst, psBinding, glsl);
|
||||
|
@ -3153,6 +3222,20 @@ void ToMetal::TranslateInstruction(Instruction* psInst)
|
|||
Operand* psSrc = &psInst->asOperands[2];
|
||||
Operand* psSrcAddr = &psInst->asOperands[1];
|
||||
|
||||
const ResourceBinding* psRes = 0;
|
||||
psContext->psShader->sInfo.GetResourceFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psRes);
|
||||
SHADER_VARIABLE_TYPE srcDataType = ResourceReturnTypeToSVTType(psRes->ui32ReturnType, psRes->ePrecision);
|
||||
|
||||
if (psInst->eResDim == RESOURCE_DIMENSION_BUFFER) // Hack typed buffer as raw buf
|
||||
{
|
||||
psSrc->aeDataType[0] = srcDataType;
|
||||
psSrcAddr->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE;
|
||||
if (psSrcAddr->eType == OPERAND_TYPE_IMMEDIATE32)
|
||||
psSrcAddr->iNumComponents = 1;
|
||||
TranslateShaderStorageLoad(psInst);
|
||||
break;
|
||||
}
|
||||
|
||||
int srcCount = psSrc->GetNumSwizzleElements();
|
||||
int numParenthesis = 0;
|
||||
uint32_t compMask = 0;
|
||||
|
@ -3177,25 +3260,6 @@ void ToMetal::TranslateInstruction(Instruction* psInst)
|
|||
break;
|
||||
}
|
||||
|
||||
SHADER_VARIABLE_TYPE srcDataType;
|
||||
const ResourceBinding* psBinding = 0;
|
||||
psContext->psShader->sInfo.GetResourceFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psBinding);
|
||||
switch (psBinding->ui32ReturnType)
|
||||
{
|
||||
case RETURN_TYPE_FLOAT:
|
||||
srcDataType = SVT_FLOAT;
|
||||
break;
|
||||
case RETURN_TYPE_SINT:
|
||||
srcDataType = SVT_INT;
|
||||
break;
|
||||
case RETURN_TYPE_UINT:
|
||||
srcDataType = SVT_UINT;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
psContext->AddIndentation();
|
||||
AddAssignToDest(psDest, srcDataType, srcCount, &numParenthesis);
|
||||
glsl << TranslateOperand(psSrc, TO_FLAG_NAME_ONLY);
|
||||
|
@ -3235,14 +3299,23 @@ void ToMetal::TranslateInstruction(Instruction* psInst)
|
|||
psContext->AddIndentation();
|
||||
bcatcstr(glsl, "//STORE_UAV_TYPED\n");
|
||||
#endif
|
||||
psContext->AddIndentation();
|
||||
|
||||
foundResource = psContext->psShader->sInfo.GetResourceFromBindingPoint(RGROUP_UAV,
|
||||
psInst->asOperands[0].ui32RegisterNumber,
|
||||
&psRes);
|
||||
|
||||
ASSERT(foundResource);
|
||||
|
||||
if (psRes->eDimension == REFLECT_RESOURCE_DIMENSION_BUFFER) // Hack typed buffer as raw buf
|
||||
{
|
||||
psInst->asOperands[0].aeDataType[0] = ResourceReturnTypeToSVTType(psRes->ui32ReturnType, psRes->ePrecision);
|
||||
psInst->asOperands[1].eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE;
|
||||
if (psInst->asOperands[1].eType == OPERAND_TYPE_IMMEDIATE32)
|
||||
psInst->asOperands[1].iNumComponents = 1;
|
||||
TranslateShaderStorageStore(psInst);
|
||||
break;
|
||||
}
|
||||
|
||||
psContext->AddIndentation();
|
||||
|
||||
glsl << TranslateOperand(&psInst->asOperands[0], TO_FLAG_NAME_ONLY);
|
||||
bcatcstr(glsl, ".write(");
|
||||
|
||||
|
@ -3685,6 +3758,21 @@ template <int N> vec<int, N> bitFieldExtractI(const vec<uint, N> width, const ve
|
|||
break;
|
||||
}
|
||||
|
||||
case OPCODE_SAMPLE_INFO:
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
psContext->AddIndentation();
|
||||
bcatcstr(glsl, "//SAMPLE_INFO\n");
|
||||
#endif
|
||||
const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType;
|
||||
psContext->AddIndentation();
|
||||
AddAssignToDest(&psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, &numParenthesis);
|
||||
TranslateOperand(&psInst->asOperands[1], TO_FLAG_NAME_ONLY);
|
||||
bcatcstr(glsl, ".get_num_samples()");
|
||||
AddAssignPrologue(numParenthesis);
|
||||
break;
|
||||
}
|
||||
|
||||
case OPCODE_DMAX:
|
||||
case OPCODE_DMIN:
|
||||
case OPCODE_DMUL:
|
||||
|
|
|
@ -14,7 +14,11 @@
|
|||
using namespace HLSLcc;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if _MSC_VER < 1900
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define fpcheck(x) (_isnan(x) || !_finite(x))
|
||||
#else
|
||||
#define fpcheck(x) (std::isnan(x) || std::isinf(x))
|
||||
|
@ -379,6 +383,7 @@ std::string ToMetal::TranslateVariableName(const Operand* psOperand, uint32_t ui
|
|||
((Operand *)psOperand)->aeDataType[3] = requestedType;
|
||||
}
|
||||
|
||||
bool bitcast = false;
|
||||
if (AreTypesCompatible(eType, ui32TOFlag) == 0)
|
||||
{
|
||||
if (CanDoDirectCast(eType, requestedType))
|
||||
|
@ -394,15 +399,16 @@ std::string ToMetal::TranslateVariableName(const Operand* psOperand, uint32_t ui
|
|||
// Direct cast not possible, need to do bitcast.
|
||||
oss << "as_type<"<< GetConstructorForTypeMetal(requestedType, requestedComponents) << ">(";
|
||||
hasCtor = 1;
|
||||
bitcast = true;
|
||||
numParenthesis++;
|
||||
}
|
||||
}
|
||||
|
||||
// Add ctor if needed (upscaling). Type conversion is already handled above, so here we must
|
||||
// use the original type to not make type conflicts in bitcasts
|
||||
if (((numComponents < requestedComponents)||(scalarWithSwizzle != 0)) && (hasCtor == 0))
|
||||
if (((numComponents < requestedComponents)||(scalarWithSwizzle != 0)) && (hasCtor == 0 || bitcast))
|
||||
{
|
||||
oss << GetConstructorForType(psContext, requestedType, requestedComponents, false) << "(";
|
||||
oss << GetConstructorForType(psContext, eType, requestedComponents, false) << "(";
|
||||
|
||||
numParenthesis++;
|
||||
hasCtor = 1;
|
||||
|
@ -623,7 +629,7 @@ std::string ToMetal::TranslateVariableName(const Operand* psOperand, uint32_t ui
|
|||
const ShaderVarType* psVarType = NULL;
|
||||
int32_t index = -1;
|
||||
std::vector<uint32_t> arrayIndices;
|
||||
bool isArray;
|
||||
bool isArray = false;
|
||||
psContext->psShader->sInfo.GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psCBuf);
|
||||
ASSERT(psCBuf != NULL);
|
||||
|
||||
|
@ -644,6 +650,9 @@ std::string ToMetal::TranslateVariableName(const Operand* psOperand, uint32_t ui
|
|||
cbName = psCBuf->name;
|
||||
}
|
||||
cbName += ".";
|
||||
// Drop the constant buffer name from subpass inputs
|
||||
if (cbName.substr(0, 19) == "hlslcc_SubpassInput")
|
||||
cbName = "";
|
||||
}
|
||||
|
||||
if((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME)
|
||||
|
|
Загрузка…
Ссылка в новой задаче