Commit d674e1e5 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: EXT_gpu_shader5: non-const offset in textureGatherOffset

This change includes preparatory work for textureGatherOffsets as well, though that requires special handling which is addressed in a follow-up change. This special handling is due to the fact that this family of functions is the only built-in with an array parameter, and our built-in table generation doesn't handle it correctly. Bug: angleproject:3569 Change-Id: Ic1c8dd03878a184be00f578ab9fc42af8f6e47ea Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1965435Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJiajia Qin <jiajia.qin@intel.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 634ee434
......@@ -5644,7 +5644,8 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
const TFunction *func = functionCall->getFunction();
if (BuiltInGroup::isTextureGather(func))
{
bool isTextureGatherOffset = BuiltInGroup::isTextureGatherOffset(func);
bool isTextureGatherOffsetOrOffsets =
BuiltInGroup::isTextureGatherOffset(func) || BuiltInGroup::isTextureGatherOffsets(func);
TIntermNode *componentNode = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
......@@ -5658,8 +5659,8 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
case EbtSampler2DArray:
case EbtISampler2DArray:
case EbtUSampler2DArray:
if ((!isTextureGatherOffset && arguments->size() == 3u) ||
(isTextureGatherOffset && arguments->size() == 4u))
if ((!isTextureGatherOffsetOrOffsets && arguments->size() == 3u) ||
(isTextureGatherOffsetOrOffsets && arguments->size() == 4u))
{
componentNode = arguments->back();
}
......@@ -5667,7 +5668,7 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
case EbtSamplerCube:
case EbtISamplerCube:
case EbtUSamplerCube:
ASSERT(!isTextureGatherOffset);
ASSERT(!isTextureGatherOffsetOrOffsets);
if (arguments->size() == 3u)
{
componentNode = arguments->back();
......@@ -5703,77 +5704,77 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
}
}
void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
void TParseContext::checkTextureOffset(TIntermAggregate *functionCall)
{
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const TFunction *func = functionCall->getFunction();
TIntermNode *offset = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
bool useTextureGatherOffsetConstraints = false;
if (BuiltInGroup::isTextureOffsetNoBias(func))
const TFunction *func = functionCall->getFunction();
TIntermNode *offset = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
if (BuiltInGroup::isTextureOffsetNoBias(func) ||
BuiltInGroup::isTextureGatherOffsetNoComp(func) ||
BuiltInGroup::isTextureGatherOffsetsNoComp(func))
{
offset = arguments->back();
}
else if (BuiltInGroup::isTextureOffsetBias(func))
else if (BuiltInGroup::isTextureOffsetBias(func) ||
BuiltInGroup::isTextureGatherOffsetComp(func) ||
BuiltInGroup::isTextureGatherOffsetsComp(func))
{
// A bias parameter follows the offset parameter.
// A bias or comp parameter follows the offset parameter.
ASSERT(arguments->size() >= 3);
offset = (*arguments)[2];
}
else if (BuiltInGroup::isTextureGatherOffset(func))
// If not one of the above built-ins, there's nothing to do here.
if (offset == nullptr)
{
ASSERT(arguments->size() >= 3u);
const TIntermTyped *sampler = arguments->front()->getAsTyped();
ASSERT(sampler != nullptr);
switch (sampler->getBasicType())
{
case EbtSampler2D:
case EbtISampler2D:
case EbtUSampler2D:
case EbtSampler2DArray:
case EbtISampler2DArray:
case EbtUSampler2DArray:
offset = (*arguments)[2];
break;
case EbtSampler2DShadow:
case EbtSampler2DArrayShadow:
offset = (*arguments)[3];
break;
default:
UNREACHABLE();
break;
}
useTextureGatherOffsetConstraints = true;
return;
}
if (offset != nullptr)
// 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)
{
TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
{
error(functionCall->getLine(), "Texture offset must be a constant expression",
func->name());
}
else
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 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;
for (size_t i = 0u; i < size; ++i)
{
int offsetValue = values[i].getIConst();
if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
{
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;
for (size_t i = 0u; i < size; ++i)
{
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());
}
}
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());
}
}
}
......@@ -6037,7 +6038,7 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
TIntermAggregate *callNode =
TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
callNode->setLine(loc);
checkTextureOffsetConst(callNode);
checkTextureOffset(callNode);
checkTextureGather(callNode);
checkImageMemoryAccessForBuiltinFunctions(callNode);
functionCallRValueLValueErrorCheck(fnCandidate, callNode);
......
......@@ -431,7 +431,7 @@ class TParseContext : angle::NonCopyable
void appendStatement(TIntermBlock *block, TIntermNode *statement);
void checkTextureGather(TIntermAggregate *functionCall);
void checkTextureOffsetConst(TIntermAggregate *functionCall);
void checkTextureOffset(TIntermAggregate *functionCall);
void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall);
void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition,
const TIntermAggregate *functionCall);
......
......@@ -1069,6 +1069,8 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledFeatures.features.fragmentStoresAndAtomics =
mPhysicalDeviceFeatures.fragmentStoresAndAtomics;
enabledFeatures.features.geometryShader = mPhysicalDeviceFeatures.geometryShader;
enabledFeatures.features.shaderImageGatherExtended =
mPhysicalDeviceFeatures.shaderImageGatherExtended;
if (!vk::CommandBuffer::ExecutesInline())
{
......
......@@ -484,7 +484,8 @@ namespace vk
bool CanSupportGPUShader5EXT(const VkPhysicalDeviceFeatures &features)
{
// We use the following Vulkan features to implement EXT_gpu_shader5:
// - shaderImageGatherExtended: textureGatherOffset family of functions
// - shaderImageGatherExtended: textureGatherOffset with non-constant offset and
// textureGatherOffsets family of functions.
// - shaderSampledImageArrayDynamicIndexing and shaderUniformBufferArrayDynamicIndexing:
// dynamically uniform indices for samplers and uniform buffers.
// - shaderStorageBufferArrayDynamicIndexing: While EXT_gpu_shader5 doesn't require dynamically
......
......@@ -709,5 +709,4 @@
// 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.offset_dynamic.* = FAIL
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