Commit beb0c946 by Geoff Lang Committed by Commit Bot

Vulkan: Make sure the default uniform info arrays match indices.

When inserting uniform layout info into the default uniform block, the array sizes need to match but insertion was skipped when the uniform was a sampler. This caused heap corruption when uniform data was written to the wrong offset in the buffer. BUG=angleproject:2859 Change-Id: Ia58a68870e2a4805391266dfe73fe8c8d238931d Reviewed-on: https://chromium-review.googlesource.com/1249562 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 122919bd
......@@ -68,6 +68,7 @@ void UpdateDefaultUniformBlock(GLsizei count,
{
uint32_t arrayOffset = arrayIndex * layoutInfo.arrayStride;
uint8_t *writePtr = dst + arrayOffset;
ASSERT(writePtr + (elementSize * count) <= uniformData->data() + uniformData->size());
memcpy(writePtr, v, elementSize * count);
}
else
......@@ -80,6 +81,7 @@ void UpdateDefaultUniformBlock(GLsizei count,
const int arrayOffset = writeIndex * layoutInfo.arrayStride;
uint8_t *writePtr = dst + arrayOffset;
const T *readPtr = v + (readIndex * componentCount);
ASSERT(writePtr + elementSize <= uniformData->data() + uniformData->size());
memcpy(writePtr, readPtr, elementSize);
}
}
......@@ -372,30 +374,29 @@ angle::Result ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
if (location.used() && !location.ignored)
{
const auto &uniform = uniforms[location.index];
if (uniform.isSampler())
continue;
std::string uniformName = uniform.name;
if (uniform.isArray())
if (!uniform.isSampler())
{
// Gets the uniform name without the [0] at the end.
uniformName = gl::ParseResourceName(uniformName, nullptr);
}
std::string uniformName = uniform.name;
if (uniform.isArray())
{
// Gets the uniform name without the [0] at the end.
uniformName = gl::ParseResourceName(uniformName, nullptr);
}
bool found = false;
bool found = false;
for (vk::ShaderType shaderType : vk::AllShaderTypes())
{
auto it = layoutMap[shaderType].find(uniformName);
if (it != layoutMap[shaderType].end())
for (vk::ShaderType shaderType : vk::AllShaderTypes())
{
found = true;
layoutInfo[shaderType] = it->second;
auto it = layoutMap[shaderType].find(uniformName);
if (it != layoutMap[shaderType].end())
{
found = true;
layoutInfo[shaderType] = it->second;
}
}
}
ASSERT(found);
ASSERT(found);
}
}
for (vk::ShaderType shaderType : vk::AllShaderTypes())
......
......@@ -7,6 +7,7 @@
// BindUniformLocationTest.cpp : Tests of the GL_CHROMIUM_bind_uniform_location extension.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include <cmath>
......@@ -111,6 +112,73 @@ TEST_P(BindUniformLocationTest, Basic)
EXPECT_PIXEL_NEAR(0, 0, 64, 128, 192, 255, 1.0);
}
// Force a sampler location and make sure it samples the correct texture
TEST_P(BindUniformLocationTest, SamplerLocation)
{
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_CHROMIUM_bind_uniform_location"));
ASSERT_NE(mBindUniformLocation, nullptr);
const std::string fsSource =
R"(precision mediump float;
uniform vec4 u_colorA;
uniform vec4 u_colorB[2];
uniform sampler2D u_sampler;
void main()
{
gl_FragColor = u_colorA + u_colorB[0] + u_colorB[1] + texture2D(u_sampler, vec2(0, 0));
})";
GLint colorALocation = 3;
GLint colorBLocation = 10;
GLint samplerLocation = 1;
GLuint vs = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
mProgram = glCreateProgram();
mBindUniformLocation(mProgram, colorALocation, "u_colorA");
mBindUniformLocation(mProgram, colorBLocation, "u_colorB[0]");
mBindUniformLocation(mProgram, samplerLocation, "u_sampler");
glAttachShader(mProgram, vs);
glDeleteShader(vs);
glAttachShader(mProgram, fs);
glDeleteShader(fs);
// Link the mProgram
glLinkProgram(mProgram);
// Check the link status
GLint linked = 0;
glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
ASSERT_EQ(1, linked);
glUseProgram(mProgram);
static const float colorB[] = {
0.0f, 0.50f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.0f,
};
glUniform4f(colorALocation, 0.25f, 0.0f, 0.0f, 0.0f);
glUniform4fv(colorBLocation, 2, colorB);
// Point the texture at texture unit 2
glUniform1i(samplerLocation, 2);
GLTexture texture;
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texture);
constexpr GLubyte kTextureData[] = {32, 32, 32, 255};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kTextureData);
drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_NEAR(0, 0, 96, 160, 224, 255, 1.0);
}
// Test that conflicts are detected when two uniforms are bound to the same location
TEST_P(BindUniformLocationTest, ConflictsDetection)
{
......
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