HLSL: phase 3a: Add sub-vec4 rwtexture formats (qualifier.layoutFormat)
This PR sets the TQualifier layoutFormat according to the HLSL image type. For instance: RWTexture1D <float2> g_tTex1df2; becomes ElfRg32f. Similar on Buffers, e.g, Buffer<float4> mybuffer; The return type for image and buffer loads is now taken from the storage format. Also, the qualifier for the return type is now (properly) a temp, not a global.
This commit is contained in:
@@ -907,11 +907,11 @@ bool HlslGrammar::acceptTextureType(TType& type)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4) {
|
||||
// TODO: handle vec2/3 types
|
||||
expected("vector size not yet supported in texture type");
|
||||
return false;
|
||||
}
|
||||
// if (txType.getVectorSize() != 1 && txType.getVectorSize() != 4 && !image) {
|
||||
// // TODO: handle vec2/3 types
|
||||
// expected("vector size not yet supported in texture type");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (ms && acceptTokenClass(EHTokComma)) {
|
||||
// read sample count for multisample types, if given
|
||||
@@ -937,24 +937,14 @@ bool HlslGrammar::acceptTextureType(TType& type)
|
||||
}
|
||||
|
||||
TArraySizes* arraySizes = nullptr;
|
||||
const bool shadow = !image && (txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1));
|
||||
const bool shadow = false; // declared on the sampler
|
||||
|
||||
TSampler sampler;
|
||||
TLayoutFormat format = ElfNone;
|
||||
|
||||
// RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
|
||||
if (image) {
|
||||
if (txType.getVectorSize() != 4)
|
||||
expected("4 component image");
|
||||
|
||||
switch (txType.getBasicType()) {
|
||||
case EbtFloat: format = ElfRgba32f; break;
|
||||
case EbtInt: format = ElfRgba32i; break;
|
||||
case EbtUint: format = ElfRgba32ui; break;
|
||||
default:
|
||||
expected("unknown basic type in image format");
|
||||
}
|
||||
}
|
||||
// Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
|
||||
if (image || dim == EsdBuffer)
|
||||
format = parseContext.getLayoutFromTxType(token.loc, txType);
|
||||
|
||||
// Non-image Buffers are combined
|
||||
if (dim == EsdBuffer && !image) {
|
||||
|
||||
@@ -147,6 +147,28 @@ bool HlslParseContext::shouldConvertLValue(const TIntermNode* node) const
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Return a TLayoutFormat corresponding to the given texture type.
|
||||
//
|
||||
TLayoutFormat HlslParseContext::getLayoutFromTxType(const TSourceLoc& loc, const TType& txType)
|
||||
{
|
||||
const int components = txType.getVectorSize();
|
||||
|
||||
const auto select = [&](TLayoutFormat v1, TLayoutFormat v2, TLayoutFormat v4) {
|
||||
return components == 1 ? v1 :
|
||||
components == 2 ? v2 : v4;
|
||||
};
|
||||
|
||||
switch (txType.getBasicType()) {
|
||||
case EbtFloat: return select(ElfR32f, ElfRg32f, ElfRgba32f);
|
||||
case EbtInt: return select(ElfR32i, ElfRg32i, ElfRgba32i);
|
||||
case EbtUint: return select(ElfR32ui, ElfRg32ui, ElfRgba32ui);
|
||||
default:
|
||||
error(loc, "unknown basic type in image format", "", "");
|
||||
return ElfNone;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Both test and if necessary, spit out an error, to see if the node is really
|
||||
// an l-value that can be operated on this way.
|
||||
@@ -265,10 +287,14 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char*
|
||||
TIntermTyped* coord = lhsAsAggregate->getSequence()[1]->getAsTyped();
|
||||
|
||||
const TLayoutFormat fmt = object->getType().getQualifier().layoutFormat;
|
||||
// We only handle 4 component formats at the moment.
|
||||
|
||||
assert(fmt == ElfRgba32f || fmt == ElfRgba32i || fmt == ElfRgba32ui);
|
||||
const TType objDerefType(object->getType().getSampler().type, EvqTemporary, 4);
|
||||
// We only handle this subset of the possible formats.
|
||||
assert(fmt == ElfRgba32f || fmt == ElfRgba32i || fmt == ElfRgba32ui ||
|
||||
fmt == ElfRg32f || fmt == ElfRg32i || fmt == ElfRg32ui ||
|
||||
fmt == ElfR32f || fmt == ElfR32i || fmt == ElfR32ui);
|
||||
|
||||
const TType objDerefType(object->getType().getSampler().type, EvqTemporary,
|
||||
TQualifier::getLayoutComponentCount(fmt));
|
||||
|
||||
if (nodeAsBinary) {
|
||||
TIntermTyped* rhs = nodeAsBinary->getRight();
|
||||
@@ -578,7 +604,7 @@ TIntermTyped* HlslParseContext::handleBracketOperator(const TSourceLoc& loc, TIn
|
||||
if (base->getType().getBasicType() == EbtSampler && !base->isArray()) {
|
||||
const TSampler& sampler = base->getType().getSampler();
|
||||
if (sampler.isImage() || sampler.isTexture()) {
|
||||
const int vecSize = 4; // TODO: handle arbitrary sizes (get from qualifier)
|
||||
const int vecSize = TQualifier::getLayoutComponentCount(base->getType().getQualifier().layoutFormat);
|
||||
TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch);
|
||||
|
||||
load->setType(TType(sampler.type, EvqTemporary, vecSize));
|
||||
@@ -1781,7 +1807,9 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
|
||||
txfetch->getSequence().push_back(argOffset);
|
||||
}
|
||||
|
||||
txfetch->setType(node->getType());
|
||||
int vecSize = TQualifier::getLayoutComponentCount(argTex->getType().getQualifier().layoutFormat);
|
||||
|
||||
txfetch->setType(TType(node->getType().getBasicType(), EvqTemporary, vecSize));
|
||||
txfetch->setLoc(loc);
|
||||
node = txfetch;
|
||||
|
||||
|
||||
@@ -156,6 +156,8 @@ public:
|
||||
TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped* node);
|
||||
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
||||
|
||||
TLayoutFormat getLayoutFromTxType(const TSourceLoc&, const TType&);
|
||||
|
||||
protected:
|
||||
void inheritGlobalDefaults(TQualifier& dst) const;
|
||||
TVariable* makeInternalVariable(const char* name, const TType&) const;
|
||||
|
||||
Reference in New Issue
Block a user