// // Copyright 2016 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //
// validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters
bool ValidateNamedProgramInterface(GLenum programInterface)
{ switch (programInterface)
{ case GL_UNIFORM: case GL_UNIFORM_BLOCK: case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_TRANSFORM_FEEDBACK_VARYING: case GL_BUFFER_VARIABLE: case GL_SHADER_STORAGE_BLOCK: returntrue; default: returnfalse;
}
}
bool ValidateLocationProgramInterface(GLenum programInterface)
{ switch (programInterface)
{ case GL_UNIFORM: case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: returntrue; default: returnfalse;
}
}
bool ValidateProgramResourceProperty(const Context *context,
angle::EntryPoint entryPoint,
GLenum prop)
{
ASSERT(context); switch (prop)
{ case GL_ACTIVE_VARIABLES: case GL_BUFFER_BINDING: case GL_NUM_ACTIVE_VARIABLES:
case GL_ARRAY_SIZE:
case GL_ARRAY_STRIDE: case GL_BLOCK_INDEX: case GL_IS_ROW_MAJOR: case GL_MATRIX_STRIDE:
case GL_ATOMIC_COUNTER_BUFFER_INDEX:
case GL_BUFFER_DATA_SIZE:
case GL_LOCATION:
case GL_NAME_LENGTH:
case GL_OFFSET:
case GL_REFERENCED_BY_VERTEX_SHADER: case GL_REFERENCED_BY_FRAGMENT_SHADER: case GL_REFERENCED_BY_COMPUTE_SHADER:
case GL_TOP_LEVEL_ARRAY_SIZE: case GL_TOP_LEVEL_ARRAY_STRIDE:
case GL_TYPE: returntrue;
case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT: return context->getExtensions().geometryShaderAny() ||
context->getClientVersion() >= ES_3_2;
case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT: case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT: case GL_IS_PER_PATCH_EXT: return context->getExtensions().tessellationShaderEXT ||
context->getClientVersion() >= ES_3_2;
case GL_LOCATION_INDEX_EXT: return context->getExtensions().blendFuncExtendedEXT;
default: returnfalse;
}
}
// GLES 3.10 spec: Page 82 -- Table 7.2 bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
{ switch (prop)
{ case GL_ACTIVE_VARIABLES: case GL_BUFFER_BINDING: case GL_NUM_ACTIVE_VARIABLES:
{ switch (programInterface)
{ case GL_ATOMIC_COUNTER_BUFFER: case GL_SHADER_STORAGE_BLOCK: case GL_UNIFORM_BLOCK: returntrue; default: returnfalse;
}
}
case GL_ARRAY_SIZE:
{ switch (programInterface)
{ case GL_BUFFER_VARIABLE: case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_TRANSFORM_FEEDBACK_VARYING: case GL_UNIFORM: returntrue; default: returnfalse;
}
}
case GL_ARRAY_STRIDE: case GL_BLOCK_INDEX: case GL_IS_ROW_MAJOR: case GL_MATRIX_STRIDE:
{ switch (programInterface)
{ case GL_BUFFER_VARIABLE: case GL_UNIFORM: returntrue; default: returnfalse;
}
}
case GL_ATOMIC_COUNTER_BUFFER_INDEX:
{ if (programInterface == GL_UNIFORM)
{ returntrue;
} returnfalse;
}
case GL_BUFFER_DATA_SIZE:
{ switch (programInterface)
{ case GL_ATOMIC_COUNTER_BUFFER: case GL_SHADER_STORAGE_BLOCK: case GL_UNIFORM_BLOCK: returntrue; default: returnfalse;
}
}
case GL_LOCATION:
{ return ValidateLocationProgramInterface(programInterface);
}
case GL_LOCATION_INDEX_EXT:
{ // EXT_blend_func_extended return (programInterface == GL_PROGRAM_OUTPUT);
}
case GL_NAME_LENGTH:
{ return ValidateNamedProgramInterface(programInterface);
}
case GL_OFFSET:
{ switch (programInterface)
{ case GL_BUFFER_VARIABLE: case GL_UNIFORM: returntrue; default: returnfalse;
}
}
case GL_REFERENCED_BY_VERTEX_SHADER: case GL_REFERENCED_BY_FRAGMENT_SHADER: case GL_REFERENCED_BY_COMPUTE_SHADER: case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT: case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT: case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
{ switch (programInterface)
{ case GL_ATOMIC_COUNTER_BUFFER: case GL_BUFFER_VARIABLE: case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_SHADER_STORAGE_BLOCK: case GL_UNIFORM: case GL_UNIFORM_BLOCK: returntrue; default: returnfalse;
}
}
case GL_TOP_LEVEL_ARRAY_SIZE: case GL_TOP_LEVEL_ARRAY_STRIDE:
{ if (programInterface == GL_BUFFER_VARIABLE)
{ returntrue;
} returnfalse;
}
case GL_TYPE:
{ switch (programInterface)
{ case GL_BUFFER_VARIABLE: case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: case GL_TRANSFORM_FEEDBACK_VARYING: case GL_UNIFORM: returntrue; default: returnfalse;
}
} case GL_IS_PER_PATCH_EXT: switch (programInterface)
{ case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: returntrue;
} returnfalse;
default: returnfalse;
}
}
bool ValidateProgramResourceIndex(const Program *programObject,
GLenum programInterface,
GLuint index)
{ switch (programInterface)
{ case GL_PROGRAM_INPUT: return (index < static_cast<GLuint>(programObject->getState().getProgramInputs().size()));
case GL_PROGRAM_OUTPUT: return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
case GL_UNIFORM: return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
case GL_BUFFER_VARIABLE: return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
case GL_SHADER_STORAGE_BLOCK: return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
case GL_UNIFORM_BLOCK: return (index < programObject->getActiveUniformBlockCount());
case GL_ATOMIC_COUNTER_BUFFER: return (index < programObject->getActiveAtomicCounterBufferCount());
case GL_TRANSFORM_FEEDBACK_VARYING: return (index < static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()));
// [OpenGL ES 3.1] Section 10.3.1 page 243: // An INVALID_OPERATION error is generated if the default vertex array object is bound. if (context->getState().getVertexArrayId().value == 0)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray); returnfalse;
}
// Here the third parameter 1 is only to pass the count validation. if (!ValidateDrawBase(context, entryPoint, mode))
{ returnfalse;
}
const State &state = context->getState();
// An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING, // DRAW_INDIRECT_BUFFER or to any enabled vertex array. if (state.getVertexArrayId().value == 0)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray); returnfalse;
}
if (context->getStateCache().hasAnyActiveClientAttrib())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kClientDataInVertexArray); returnfalse;
}
// An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic // machine units, of uint.
GLint64 offset = reinterpret_cast<GLint64>(indirect); if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidIndirectOffset); returnfalse;
}
returntrue;
}
bool ValidateDrawArraysIndirect(const Context *context,
angle::EntryPoint entryPoint,
PrimitiveMode mode, constvoid *indirect)
{ const State &state = context->getState();
TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); if (curTransformFeedback && curTransformFeedback->isActive() &&
!curTransformFeedback->isPaused())
{ // EXT_geometry_shader allows transform feedback to work with all draw commands. // [EXT_geometry_shader] Section 12.1, "Transform Feedback" if (context->getExtensions().geometryShaderAny() || context->getClientVersion() >= ES_3_2)
{ if (!ValidateTransformFeedbackPrimitiveMode(
context, entryPoint, curTransformFeedback->getPrimitiveMode(), mode))
{
context->validationError(entryPoint, GL_INVALID_OPERATION,
kInvalidDrawModeTransformFeedback); returnfalse;
}
} else
{ // An INVALID_OPERATION error is generated if transform feedback is active and not // paused.
context->validationError(entryPoint, GL_INVALID_OPERATION,
kUnsupportedDrawModeForTransformFeedback); returnfalse;
}
}
if (!ValidateDrawIndirectBase(context, entryPoint, mode, indirect)) returnfalse;
Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect)); // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand // which's size is 4 * sizeof(uint). auto checkedSum = checkedOffset + 4 * sizeof(GLuint); if (!checkedSum.IsValid() ||
checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kParamOverflow); returnfalse;
}
// An INVALID_VALUE error is generated if stride is neither 0 nor a multiple of 4. if ((stride & 3) != 0)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDrawBufferValue); returnfalse;
}
// An INVALID_VALUE error is generated if drawcount is not positive. if (drawcount <= 0)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidValueNonPositive); returnfalse;
}
// [OpenGL ES 3.1] Section 10.3.1 page 244: // An INVALID_OPERATION error is generated if the default vertex array object is bound. if (context->getState().getVertexArrayId().value == 0)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray); returnfalse;
}
// [OpenGL ES 3.1] Section 10.3.1 page 243: // An INVALID_OPERATION error is generated if the default vertex array object is bound. if (context->getState().getVertexArrayId().value == 0)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray); returnfalse;
}
// [OpenGL ES 3.1] Section 10.3.1 page 243: // An INVALID_OPERATION error is generated if the default vertex array object is bound. if (context->getState().getVertexArrayId().value == 0)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray); returnfalse;
}
switch (format)
{ case GL_RGBA32F: case GL_RGBA16F: case GL_R32F: case GL_RGBA32UI: case GL_RGBA16UI: case GL_RGBA8UI: case GL_R32UI: case GL_RGBA32I: case GL_RGBA16I: case GL_RGBA8I: case GL_R32I: case GL_RGBA8: case GL_RGBA8_SNORM: break; default:
context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidImageFormat); returnfalse;
}
if (texture.value != 0)
{
Texture *tex = context->getTexture(texture);
if (tex == nullptr)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kMissingTextureName); returnfalse;
}
if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
{ switch (programInterface)
{ case GL_ATOMIC_COUNTER_BUFFER: case GL_SHADER_STORAGE_BLOCK: case GL_UNIFORM_BLOCK: break;
bool ValidateUseProgramStagesBase(const Context *context,
angle::EntryPoint entryPoint,
ProgramPipelineID pipeline,
GLbitfield stages,
ShaderProgramID programId)
{ // GL_INVALID_VALUE is generated if shaders contains set bits that are not recognized, and is // not the reserved value GL_ALL_SHADER_BITS.
GLbitfield knownShaderBits =
GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT | GL_COMPUTE_SHADER_BIT;
// GL_INVALID_OPERATION is generated if pipeline is not a name previously returned from a call // to glGenProgramPipelines or if such a name has been deleted by a call to // glDeleteProgramPipelines. if (!context->isProgramPipelineGenerated({pipeline}))
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated); returnfalse;
}
// If program is zero, or refers to a program object with no valid shader executable for a given // stage, it is as if the pipeline object has no programmable stage configured for the indicated // shader stages. if (programId.value == 0)
{ returntrue;
}
Program *program = context->getProgramNoResolveLink(programId); if (!program)
{
context->validationError(entryPoint, GL_INVALID_VALUE, kProgramDoesNotExist); returnfalse;
}
// GL_INVALID_OPERATION is generated if program refers to a program object that was not linked // with its GL_PROGRAM_SEPARABLE status set. // resolveLink() may not have been called if glCreateShaderProgramv() was not used and // glDetachShader() was not called.
program->resolveLink(context); if (!program->isSeparable())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotSeparable); returnfalse;
}
// GL_INVALID_OPERATION is generated if program refers to a program object that has not been // successfully linked. if (!program->isLinked())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.