Commit a35aa03a by Shahbaz Youssefi Committed by Commit Bot

Vulkan: EXT_gpu_shader5: textureGatherOffsets

The validation of the offsets parameter is added in this change. Bug: angleproject:3569 Change-Id: Ide2ea4b9e88b28ca5ef34d5f3f5203f6e48d5f74 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1979133Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJiajia Qin <jiajia.qin@intel.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent beb33691
......@@ -5731,49 +5731,99 @@ void TParseContext::checkTextureOffset(TIntermAggregate *functionCall)
return;
}
// ES3.2 or ES3.1's EXT_gpu_shader5 allow non-const offsets to be passed to textureGatherOffset.
bool textureGatherOffsetMustBeConst =
mShaderVersion <= 310 && !isExtensionEnabled(TExtension::EXT_gpu_shader5);
TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
bool isOffsetConst =
offset->getAsTyped()->getQualifier() == EvqConst && offsetConstantUnion != nullptr;
bool isTextureGatherOffset = BuiltInGroup::isTextureGatherOffset(func);
bool offsetMustBeConst = !isTextureGatherOffset || textureGatherOffsetMustBeConst;
if (!isOffsetConst && offsetMustBeConst)
{
error(functionCall->getLine(), "Texture offset must be a constant expression",
func->name());
return;
}
// We cannot verify non-constant offsets to textureGatherOffset.
if (offsetConstantUnion == nullptr)
{
return;
}
bool isTextureGatherOffset = BuiltInGroup::isTextureGatherOffset(func);
bool isTextureGatherOffsets = BuiltInGroup::isTextureGatherOffsets(func);
bool useTextureGatherOffsetConstraints = isTextureGatherOffset || isTextureGatherOffsets;
ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
size_t size = offsetConstantUnion->getType().getObjectSize();
const TConstantUnion *values = offsetConstantUnion->getConstantValue();
int minOffsetValue =
useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset : mMinProgramTexelOffset;
int maxOffsetValue =
useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset : mMaxProgramTexelOffset;
if (isTextureGatherOffsets)
{
// If textureGatherOffsets, the offsets parameter is an array, which is expected as an
// aggregate constructor node.
TIntermAggregate *offsetAggregate = offset->getAsAggregate();
const TConstantUnion *offsetValues =
offsetAggregate ? offsetAggregate->getConstantValue() : nullptr;
if (offsetValues == nullptr)
{
error(functionCall->getLine(), "Texture offsets must be a constant expression",
func->name());
return;
}
constexpr unsigned int kOffsetsCount = 4;
const TType &offsetAggregateType = offsetAggregate->getType();
if (offsetAggregateType.getNumArraySizes() != 1 ||
offsetAggregateType.getArraySizes()[0] != kOffsetsCount)
{
error(functionCall->getLine(), "Texture offsets must be an array of 4 elements",
func->name());
return;
}
TIntermNode *firstOffset = offsetAggregate->getSequence()->front();
size_t size = firstOffset->getAsTyped()->getType().getObjectSize();
for (unsigned int i = 0; i < kOffsetsCount; ++i)
{
checkSingleTextureOffset(offset->getLine(), &offsetValues[i * size], size,
minOffsetValue, maxOffsetValue);
}
}
else
{
// If textureOffset or textureGatherOffset, the offset is expected to be found as a constant
// union.
TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
// ES3.2 or ES3.1's EXT_gpu_shader5 allow non-const offsets to be passed to
// textureGatherOffset.
bool textureGatherOffsetMustBeConst =
mShaderVersion <= 310 && !isExtensionEnabled(TExtension::EXT_gpu_shader5);
bool isOffsetConst =
offset->getAsTyped()->getQualifier() == EvqConst && offsetConstantUnion != nullptr;
bool offsetMustBeConst = !isTextureGatherOffset || textureGatherOffsetMustBeConst;
if (!isOffsetConst && offsetMustBeConst)
{
error(functionCall->getLine(), "Texture offset must be a constant expression",
func->name());
return;
}
// We cannot verify non-constant offsets to textureGatherOffset.
if (offsetConstantUnion == nullptr)
{
ASSERT(!offsetMustBeConst);
return;
}
size_t size = offsetConstantUnion->getType().getObjectSize();
const TConstantUnion *values = offsetConstantUnion->getConstantValue();
checkSingleTextureOffset(offset->getLine(), values, size, minOffsetValue, maxOffsetValue);
}
}
void TParseContext::checkSingleTextureOffset(const TSourceLoc &line,
const TConstantUnion *values,
size_t size,
int minOffsetValue,
int maxOffsetValue)
{
for (size_t i = 0u; i < size; ++i)
{
ASSERT(values[i].getType() == EbtInt);
int offsetValue = values[i].getIConst();
if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
{
std::stringstream tokenStream = sh::InitializeStream<std::stringstream>();
tokenStream << offsetValue;
std::string token = tokenStream.str();
error(offset->getLine(), "Texture offset value out of valid range", token.c_str());
error(line, "Texture offset value out of valid range", token.c_str());
}
}
}
......
......@@ -546,6 +546,12 @@ class TParseContext : angle::NonCopyable
bool checkUnsizedArrayConstructorArgumentDimensionality(const TIntermSequence &arguments,
TType type,
const TSourceLoc &line);
// Check texture offset is within range.
void checkSingleTextureOffset(const TSourceLoc &line,
const TConstantUnion *values,
size_t size,
int minOffsetValue,
int maxOffsetValue);
// Will set the size of the outermost array according to geometry shader input layout.
void checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
......
......@@ -673,7 +673,3 @@
4098 SWIFTSHADER : dEQP-GLES31.functional.compute.basic.write_multiple_unsized_arr_single_invocation = FAIL
// OpenGL ES 3.2 / 3.1 extensions
// EXT_gpu_shader5: Note: this extension is not yet fully implemented, so should be disabled in the
// Vulkan backend for the ES 3.1 conformance run.
3569 VULKAN : dEQP-GLES31.functional.texture.gather.offsets.* = FAIL
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment