зеркало из https://github.com/AvaloniaUI/angle.git
Program: clamp the number of uniforms to be copied
BUG=661413 Change-Id: I1a146dae0d01edeb272a58610355261b0e23dec1 Reviewed-on: https://chromium-review.googlesource.com/406745 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Родитель
8a9e4bcfe9
Коммит
9863a3ef18
|
@ -2855,12 +2855,18 @@ void Program::setUniformInternal(GLint location, GLsizei count, const T *v)
|
|||
LinkedUniform *linkedUniform = &mState.mUniforms[locationInfo.index];
|
||||
uint8_t *destPointer = linkedUniform->getDataPtrToElement(locationInfo.element);
|
||||
|
||||
// OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
|
||||
// element index used, as reported by GetActiveUniform, will be ignored by the GL."
|
||||
unsigned int remainingElements = linkedUniform->elementCount() - locationInfo.element;
|
||||
GLsizei clampedCount = std::min(
|
||||
count, static_cast<GLsizei>(remainingElements * linkedUniform->getElementComponents()));
|
||||
|
||||
if (VariableComponentType(linkedUniform->type) == GL_BOOL)
|
||||
{
|
||||
// Do a cast conversion for boolean types. From the spec:
|
||||
// "The uniform is set to FALSE if the input value is 0 or 0.0f, and set to TRUE otherwise."
|
||||
GLint *destAsInt = reinterpret_cast<GLint *>(destPointer);
|
||||
for (GLsizei component = 0; component < count; ++component)
|
||||
for (GLsizei component = 0; component < clampedCount; ++component)
|
||||
{
|
||||
destAsInt[component] = (v[component] != static_cast<T>(0) ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
@ -2868,12 +2874,12 @@ void Program::setUniformInternal(GLint location, GLsizei count, const T *v)
|
|||
else
|
||||
{
|
||||
// Invalide the validation cache if we modify the sampler data.
|
||||
if (linkedUniform->isSampler() && memcmp(destPointer, v, sizeof(T) * count) != 0)
|
||||
if (linkedUniform->isSampler() && memcmp(destPointer, v, sizeof(T) * clampedCount) != 0)
|
||||
{
|
||||
mCachedValidateSamplersResult.reset();
|
||||
}
|
||||
|
||||
memcpy(destPointer, v, sizeof(T) * count);
|
||||
memcpy(destPointer, v, sizeof(T) * clampedCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2893,7 +2899,13 @@ void Program::setMatrixUniformInternal(GLint location,
|
|||
const VariableLocation &locationInfo = mState.mUniformLocations[location];
|
||||
LinkedUniform *linkedUniform = &mState.mUniforms[locationInfo.index];
|
||||
T *destPtr = reinterpret_cast<T *>(linkedUniform->getDataPtrToElement(locationInfo.element));
|
||||
for (GLsizei element = 0; element < count; ++element)
|
||||
|
||||
// OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
|
||||
// element index used, as reported by GetActiveUniform, will be ignored by the GL."
|
||||
unsigned int remainingElements = linkedUniform->elementCount() - locationInfo.element;
|
||||
GLsizei clampedCount = std::min(count, static_cast<GLsizei>(remainingElements));
|
||||
|
||||
for (GLsizei element = 0; element < clampedCount; ++element)
|
||||
{
|
||||
size_t elementOffset = element * rows * cols;
|
||||
|
||||
|
|
|
@ -109,6 +109,11 @@ size_t LinkedUniform::getElementSize() const
|
|||
return VariableExternalSize(type);
|
||||
}
|
||||
|
||||
size_t LinkedUniform::getElementComponents() const
|
||||
{
|
||||
return VariableComponentCount(type);
|
||||
}
|
||||
|
||||
uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex)
|
||||
{
|
||||
ASSERT((!isArray() && elementIndex == 0) || (isArray() && elementIndex < arraySize));
|
||||
|
|
|
@ -36,6 +36,7 @@ struct LinkedUniform : public sh::Uniform
|
|||
bool isInDefaultBlock() const;
|
||||
bool isField() const;
|
||||
size_t getElementSize() const;
|
||||
size_t getElementComponents() const;
|
||||
uint8_t *getDataPtrToElement(size_t elementIndex);
|
||||
const uint8_t *getDataPtrToElement(size_t elementIndex) const;
|
||||
|
||||
|
|
|
@ -459,6 +459,54 @@ TEST_P(UniformTestES3, TranposedMatrixArrayUniformStateQuery)
|
|||
}
|
||||
}
|
||||
|
||||
// Check that trying setting too many elements of an array doesn't overflow
|
||||
TEST_P(UniformTestES3, OverflowArray)
|
||||
{
|
||||
const std::string &vertexShader =
|
||||
"#version 300 es\n"
|
||||
"void main() { gl_Position = vec4(1); }";
|
||||
const std::string &fragShader =
|
||||
"#version 300 es\n"
|
||||
"precision mediump float;\n"
|
||||
"uniform float uniF[5];\n"
|
||||
"uniform mat3x2 uniMat3x2[5];\n"
|
||||
"out vec4 color;\n"
|
||||
"void main() {\n"
|
||||
" color = vec4(uniMat3x2[0][0][0] + uniF[0]);\n"
|
||||
"}";
|
||||
|
||||
mProgram = CompileProgram(vertexShader, fragShader);
|
||||
ASSERT_NE(mProgram, 0u);
|
||||
|
||||
glUseProgram(mProgram);
|
||||
|
||||
const size_t kOverflowSize = 10000;
|
||||
std::vector<GLfloat> values(10000 * 6);
|
||||
|
||||
// Setting as a clump
|
||||
GLint floatLocation = glGetUniformLocation(mProgram, "uniF");
|
||||
ASSERT_NE(-1, floatLocation);
|
||||
GLint matLocation = glGetUniformLocation(mProgram, "uniMat3x2");
|
||||
ASSERT_NE(-1, matLocation);
|
||||
|
||||
// Set too many float uniforms
|
||||
glUniform1fv(floatLocation, kOverflowSize, &values[0]);
|
||||
|
||||
// Set too many matrix uniforms, transposed or not
|
||||
glUniformMatrix3x2fv(matLocation, kOverflowSize, GL_FALSE, &values[0]);
|
||||
glUniformMatrix3x2fv(matLocation, kOverflowSize, GL_TRUE, &values[0]);
|
||||
|
||||
// Same checks but with offsets
|
||||
GLint floatLocationOffset = glGetUniformLocation(mProgram, "uniF[3]");
|
||||
ASSERT_NE(-1, floatLocationOffset);
|
||||
GLint matLocationOffset = glGetUniformLocation(mProgram, "uniMat3x2[3]");
|
||||
ASSERT_NE(-1, matLocationOffset);
|
||||
|
||||
glUniform1fv(floatLocationOffset, kOverflowSize, &values[0]);
|
||||
glUniformMatrix3x2fv(matLocationOffset, kOverflowSize, GL_FALSE, &values[0]);
|
||||
glUniformMatrix3x2fv(matLocationOffset, kOverflowSize, GL_TRUE, &values[0]);
|
||||
}
|
||||
|
||||
// Check that sampler uniforms only show up one time in the list
|
||||
TEST_P(UniformTest, SamplerUniformsAppearOnce)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче