зеркало из https://github.com/AvaloniaUI/angle.git
Vulkan: Add OES_shader_multisample_interpolation support
Support OES_shader_multisample_interpolation extension if maxInterpolationOffset >= 0.5 Bug: angleproject:3589 Tests: dEQP-GLES31.functional.shaders.multisample_interpolation.* dEQP-GLES31.functional.state_query.multisample_interpolation.* Change-Id: I42997f10be82e3be8b63c56833cbbf791bf4be9b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2477905 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Родитель
5c4c37dcd4
Коммит
5d0458fa5c
|
@ -28,6 +28,7 @@ enum InterpolationType
|
|||
{
|
||||
INTERPOLATION_SMOOTH,
|
||||
INTERPOLATION_CENTROID,
|
||||
INTERPOLATION_SAMPLE,
|
||||
INTERPOLATION_FLAT,
|
||||
INTERPOLATION_NOPERSPECTIVE
|
||||
};
|
||||
|
|
|
@ -981,10 +981,12 @@ enum TQualifier
|
|||
EvqFlatOut,
|
||||
EvqNoPerspectiveOut,
|
||||
EvqCentroidOut, // Implies smooth
|
||||
EvqSampleOut,
|
||||
EvqSmoothIn,
|
||||
EvqFlatIn,
|
||||
EvqNoPerspectiveIn,
|
||||
EvqCentroidIn, // Implies smooth
|
||||
EvqSampleIn,
|
||||
|
||||
// GLSL ES 3.1 compute shader special variables
|
||||
EvqShared,
|
||||
|
@ -1042,6 +1044,7 @@ inline bool IsShaderIn(TQualifier qualifier)
|
|||
case EvqFlatIn:
|
||||
case EvqNoPerspectiveIn:
|
||||
case EvqCentroidIn:
|
||||
case EvqSampleIn:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -1060,6 +1063,7 @@ inline bool IsShaderOut(TQualifier qualifier)
|
|||
case EvqFlatOut:
|
||||
case EvqNoPerspectiveOut:
|
||||
case EvqCentroidOut:
|
||||
case EvqSampleOut:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -1333,6 +1337,9 @@ inline const char *getQualifierString(TQualifier q)
|
|||
case EvqPerVertexIn: return "gl_in";
|
||||
case EvqPrecise: return "precise";
|
||||
case EvqClipDistance: return "ClipDistance";
|
||||
case EvqSample: return "sample";
|
||||
case EvqSampleIn: return "sample in";
|
||||
case EvqSampleOut: return "sample out";
|
||||
default: UNREACHABLE(); return "unknown qualifier";
|
||||
}
|
||||
// clang-format on
|
||||
|
|
|
@ -732,6 +732,7 @@ ShaderVariable CollectVariablesTraverser::recordVarying(const TIntermSymbol &var
|
|||
case EvqNoPerspectiveOut:
|
||||
case EvqCentroidOut:
|
||||
case EvqGeometryOut:
|
||||
case EvqSampleOut:
|
||||
if (mSymbolTable->isVaryingInvariant(variable.variable()) || type.isInvariant())
|
||||
{
|
||||
varying.isInvariant = true;
|
||||
|
|
|
@ -1090,6 +1090,7 @@ void TCompiler::setResourceString()
|
|||
<< ":OES_texture_cube_map_array:" << mResources.OES_texture_cube_map_array
|
||||
<< ":EXT_texture_cube_map_array:" << mResources.EXT_texture_cube_map_array
|
||||
<< ":EXT_shadow_samplers:" << mResources.EXT_shadow_samplers
|
||||
<< ":OES_shader_multisample_interpolation:" << mResources.OES_shader_multisample_interpolation
|
||||
<< ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset
|
||||
<< ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset
|
||||
<< ":MaxImageUnits:" << mResources.MaxImageUnits
|
||||
|
|
|
@ -129,6 +129,10 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi
|
|||
{
|
||||
extBehavior[TExtension::EXT_shadow_samplers] = EBhUndefined;
|
||||
}
|
||||
if (resources.OES_shader_multisample_interpolation)
|
||||
{
|
||||
extBehavior[TExtension::OES_shader_multisample_interpolation] = EBhUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
void ResetExtensionBehavior(const ShBuiltInResources &resources,
|
||||
|
|
|
@ -128,6 +128,26 @@ bool IsBufferOrSharedVariable(TIntermTyped *var)
|
|||
return false;
|
||||
}
|
||||
|
||||
TIntermTyped *FindLValueBase(TIntermTyped *node)
|
||||
{
|
||||
do
|
||||
{
|
||||
const TIntermBinary *binary = node->getAsBinaryNode();
|
||||
if (binary == nullptr)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
TOperator op = binary->getOp();
|
||||
if (op != EOpIndexDirect && op != EOpIndexIndirect)
|
||||
{
|
||||
return static_cast<TIntermTyped *>(nullptr);
|
||||
}
|
||||
|
||||
node = binary->getLeft();
|
||||
} while (true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// This tracks each binding point's current default offset for inheritance of subsequent
|
||||
|
@ -534,6 +554,7 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn
|
|||
case EvqNoPerspectiveIn:
|
||||
case EvqSmoothIn:
|
||||
case EvqCentroidIn:
|
||||
case EvqSampleIn:
|
||||
message = "can't modify an input";
|
||||
break;
|
||||
case EvqUniform:
|
||||
|
@ -5983,6 +6004,41 @@ void TParseContext::checkSingleTextureOffset(const TSourceLoc &line,
|
|||
}
|
||||
}
|
||||
|
||||
void TParseContext::checkInterpolationFS(TIntermAggregate *functionCall)
|
||||
{
|
||||
const TFunction *func = functionCall->getFunction();
|
||||
if (!BuiltInGroup::isInterpolationFS(func))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TIntermTyped *arg0 = nullptr;
|
||||
|
||||
if (functionCall->getAsAggregate())
|
||||
{
|
||||
const TIntermSequence *argp = functionCall->getSequence();
|
||||
if (argp->size() > 0)
|
||||
arg0 = (*argp)[0]->getAsTyped();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(functionCall->getAsUnaryNode());
|
||||
arg0 = functionCall->getAsUnaryNode()->getOperand();
|
||||
}
|
||||
|
||||
// Make sure the first argument is an interpolant, or an array element of an interpolant
|
||||
if (!IsVaryingIn(arg0->getType().getQualifier()))
|
||||
{
|
||||
// It might still be an array element.
|
||||
const TIntermTyped *base = FindLValueBase(arg0);
|
||||
|
||||
if (base == nullptr || (!IsVaryingIn(base->getType().getQualifier())))
|
||||
error(arg0->getLine(),
|
||||
"first argument must be an interpolant, or interpolant-array element",
|
||||
func->name());
|
||||
}
|
||||
}
|
||||
|
||||
void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
|
||||
{
|
||||
const TFunction *func = functionCall->getFunction();
|
||||
|
@ -6248,6 +6304,7 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
|
|||
callNode->setLine(loc);
|
||||
checkTextureOffset(callNode);
|
||||
checkTextureGather(callNode);
|
||||
checkInterpolationFS(callNode);
|
||||
checkImageMemoryAccessForBuiltinFunctions(callNode);
|
||||
functionCallRValueLValueErrorCheck(fnCandidate, callNode);
|
||||
return callNode;
|
||||
|
|
|
@ -441,6 +441,7 @@ class TParseContext : angle::NonCopyable
|
|||
void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition,
|
||||
const TIntermAggregate *functionCall);
|
||||
void checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall);
|
||||
void checkInterpolationFS(TIntermAggregate *functionCall);
|
||||
|
||||
// fnCall is only storing the built-in op, and function name or constructor type. arguments
|
||||
// has the arguments.
|
||||
|
|
|
@ -440,6 +440,23 @@ bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storag
|
|||
}
|
||||
break;
|
||||
}
|
||||
case EvqSample:
|
||||
{
|
||||
switch (storageQualifier)
|
||||
{
|
||||
case EvqVertexOut:
|
||||
case EvqGeometryOut:
|
||||
*joinedQualifier = EvqSampleOut;
|
||||
break;
|
||||
case EvqFragmentIn:
|
||||
case EvqGeometryIn:
|
||||
*joinedQualifier = EvqSampleIn;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1063,6 +1063,8 @@ const char *InterpolationString(TQualifier qualifier)
|
|||
return "nointerpolation";
|
||||
case EvqCentroidOut:
|
||||
return "centroid";
|
||||
case EvqSampleIn:
|
||||
return "sample";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -1083,6 +1085,8 @@ const char *QualifierString(TQualifier qualifier)
|
|||
return "inout";
|
||||
case EvqConstReadOnly:
|
||||
return "const";
|
||||
case EvqSampleOut:
|
||||
return "sample";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ bool IsInterpolationIn(TQualifier qualifier)
|
|||
case EvqFlatIn:
|
||||
case EvqNoPerspectiveIn:
|
||||
case EvqCentroidIn:
|
||||
case EvqSampleIn:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -538,6 +539,7 @@ bool IsVaryingOut(TQualifier qualifier)
|
|||
case EvqCentroidOut:
|
||||
case EvqVertexOut:
|
||||
case EvqGeometryOut:
|
||||
case EvqSampleOut:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -558,6 +560,7 @@ bool IsVaryingIn(TQualifier qualifier)
|
|||
case EvqCentroidIn:
|
||||
case EvqFragmentIn:
|
||||
case EvqGeometryIn:
|
||||
case EvqSampleIn:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -604,6 +607,9 @@ InterpolationType GetInterpolationType(TQualifier qualifier)
|
|||
case EvqCentroidOut:
|
||||
return INTERPOLATION_CENTROID;
|
||||
|
||||
case EvqSampleIn:
|
||||
case EvqSampleOut:
|
||||
return INTERPOLATION_SAMPLE;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
#if !UNREACHABLE_IS_NORETURN
|
||||
|
|
|
@ -1036,6 +1036,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
|
|||
map["GL_EXT_buffer_storage"] = enableableExtension(&Extensions::bufferStorageEXT);
|
||||
map["GL_OES_texture_stencil8"] = enableableExtension(&Extensions::stencilIndex8);
|
||||
map["GL_OES_sample_shading"] = enableableExtension(&Extensions::sampleShadingOES);
|
||||
map["GL_OES_shader_multisample_interpolation"] = enableableExtension(&Extensions::multisampleInterpolationOES);
|
||||
map["GL_NV_robustness_video_memory_purge"] = esOnlyExtension(&Extensions::robustnessVideoMemoryPurgeNV);
|
||||
map["GL_ANGLE_get_tex_level_parameter"] = enableableExtension(&Extensions::getTexLevelParameterANGLE);
|
||||
// GLES1 extensions
|
||||
|
|
|
@ -654,6 +654,9 @@ struct Extensions
|
|||
// GL_OES_sample_shading
|
||||
bool sampleShadingOES = false;
|
||||
|
||||
// OES_shader_multisample_interpolation
|
||||
bool multisampleInterpolationOES = false;
|
||||
|
||||
// GL_NV_robustness_video_memory_purge
|
||||
bool robustnessVideoMemoryPurgeNV = false;
|
||||
|
||||
|
@ -746,6 +749,10 @@ struct Caps
|
|||
// be GLint instead of GLuint and call LimitToInt() to ensure
|
||||
// they will not overflow.
|
||||
|
||||
GLfloat minInterpolationOffset = 0;
|
||||
GLfloat maxInterpolationOffset = 0;
|
||||
GLint subPixelInterpolationOffsetBits = 0;
|
||||
|
||||
// ES 3.1 (April 29, 2015) 20.39: implementation dependent values
|
||||
GLint64 maxElementIndex = 0;
|
||||
GLint max3DTextureSize = 0;
|
||||
|
|
|
@ -110,7 +110,8 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp
|
|||
mResources.ANGLE_multi_draw = extensions.multiDraw;
|
||||
mResources.ANGLE_base_vertex_base_instance = extensions.baseVertexBaseInstance;
|
||||
mResources.APPLE_clip_distance = extensions.clipDistanceAPPLE;
|
||||
|
||||
// OES_shader_multisample_interpolation
|
||||
mResources.OES_shader_multisample_interpolation = extensions.multisampleInterpolationOES;
|
||||
// TODO: use shader precision caps to determine if high precision is supported?
|
||||
mResources.FragmentPrecisionHigh = 1;
|
||||
mResources.EXT_frag_depth = extensions.fragDepth;
|
||||
|
|
|
@ -1419,6 +1419,12 @@ void Context::getFloatvImpl(GLenum pname, GLfloat *params) const
|
|||
case GL_MAX_TEXTURE_LOD_BIAS:
|
||||
*params = mState.mCaps.maxLODBias;
|
||||
break;
|
||||
case GL_MIN_FRAGMENT_INTERPOLATION_OFFSET:
|
||||
*params = mState.mCaps.minInterpolationOffset;
|
||||
break;
|
||||
case GL_MAX_FRAGMENT_INTERPOLATION_OFFSET:
|
||||
*params = mState.mCaps.maxInterpolationOffset;
|
||||
break;
|
||||
default:
|
||||
mState.getFloatv(pname, params);
|
||||
break;
|
||||
|
@ -1850,7 +1856,10 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) const
|
|||
case GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT:
|
||||
*params = mState.mExtensions.maxDualSourceDrawBuffers;
|
||||
break;
|
||||
|
||||
// OES_shader_multisample_interpolation
|
||||
case GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES:
|
||||
*params = mState.mCaps.subPixelInterpolationOffsetBits;
|
||||
break;
|
||||
default:
|
||||
ANGLE_CONTEXT_TRY(mState.getIntegerv(this, pname, params));
|
||||
break;
|
||||
|
|
|
@ -3567,6 +3567,7 @@ bool GetQueryParameterInfo(const State &glState,
|
|||
case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
|
||||
case GL_UNPACK_IMAGE_HEIGHT:
|
||||
case GL_UNPACK_SKIP_IMAGES:
|
||||
case GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES:
|
||||
{
|
||||
*type = GL_INT;
|
||||
*numParams = 1;
|
||||
|
@ -3595,6 +3596,8 @@ bool GetQueryParameterInfo(const State &glState,
|
|||
}
|
||||
|
||||
case GL_MAX_TEXTURE_LOD_BIAS:
|
||||
case GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES:
|
||||
case GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES:
|
||||
{
|
||||
*type = GL_FLOAT;
|
||||
*numParams = 1;
|
||||
|
|
|
@ -435,6 +435,9 @@ void DynamicHLSL::generateVaryingLinkHLSL(const VaryingPacking &varyingPacking,
|
|||
case sh::INTERPOLATION_CENTROID:
|
||||
hlslStream << " centroid ";
|
||||
break;
|
||||
case sh::INTERPOLATION_SAMPLE:
|
||||
hlslStream << " sample ";
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
|
|
@ -272,7 +272,29 @@ void RendererVk::ensureCapsInitialized() const
|
|||
// VkPipelineMultisampleStateCreateInfo structure must be set to VK_FALSE and the
|
||||
// minSampleShading member is ignored. This also specifies whether shader modules can declare
|
||||
// the SampleRateShading capability
|
||||
mNativeExtensions.sampleShadingOES = (mPhysicalDeviceFeatures.sampleRateShading == VK_TRUE);
|
||||
bool supportSampleRateShading = (mPhysicalDeviceFeatures.sampleRateShading == VK_TRUE);
|
||||
mNativeExtensions.sampleShadingOES = supportSampleRateShading;
|
||||
|
||||
mNativeCaps.minInterpolationOffset = limitsVk.minInterpolationOffset;
|
||||
mNativeCaps.maxInterpolationOffset = limitsVk.maxInterpolationOffset;
|
||||
mNativeCaps.subPixelInterpolationOffsetBits = limitsVk.subPixelInterpolationOffsetBits;
|
||||
|
||||
// From the Vulkan spec:
|
||||
//
|
||||
// > The values minInterpolationOffset and maxInterpolationOffset describe the closed interval
|
||||
// > of supported interpolation offsets : [ minInterpolationOffset, maxInterpolationOffset ].
|
||||
// > The ULP is determined by subPixelInterpolationOffsetBits. If
|
||||
// > subPixelInterpolationOffsetBits is 4, this provides increments of(1 / 2^4) = 0.0625, and
|
||||
// > thus the range of supported interpolation offsets would be[-0.5, 0.4375]
|
||||
//
|
||||
// OES_shader_multisample_interpolation requires a maximum value of -0.5 for
|
||||
// MIN_FRAGMENT_INTERPOLATION_OFFSET_OES and minimum 0.5 for
|
||||
// MAX_FRAGMENT_INTERPOLATION_OFFSET_OES. Vulkan has an identical limit for
|
||||
// minInterpolationOffset, but it's limit for maxInterpolationOffset is 0.5-(1/ULP).
|
||||
// OES_shader_multisample_interpolation is therefore only supported if
|
||||
// maxInterpolationOffset is at least 0.5.
|
||||
mNativeExtensions.multisampleInterpolationOES =
|
||||
supportSampleRateShading && (mNativeCaps.maxInterpolationOffset >= 0.5);
|
||||
|
||||
// https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html
|
||||
mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
|
||||
|
|
|
@ -187,6 +187,12 @@
|
|||
// Cannot create 2D (array) view of 3D texture.
|
||||
3886 VULKAN : dEQP-GLES31.functional.image_load_store.3d.*layer = FAIL
|
||||
|
||||
// Conflict between "interpolateAtOffset()" and the viewport transformation for a default framebuffer
|
||||
3589 VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_offset.no_qualifiers.default_framebuffer = FAIL
|
||||
3589 VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_offset.centroid_qualifier.default_framebuffer = FAIL
|
||||
3589 VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_offset.sample_qualifier.default_framebuffer = FAIL
|
||||
3589 VULKAN : dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_offset.array_element.default_framebuffer = FAIL
|
||||
|
||||
////
|
||||
//// Android (i.e. Pixel*) Vulkan expectations
|
||||
////
|
||||
|
|
Загрузка…
Ссылка в новой задаче