Path: blob/main_old/src/tests/gl_tests/ComputeShaderTest.cpp
1693 views
//1// Copyright 2016 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// ComputeShaderTest:6// Compute shader specific tests.78#include <vector>9#include "test_utils/ANGLETest.h"10#include "test_utils/gl_raii.h"1112using namespace angle;1314namespace15{1617class ComputeShaderTest : public ANGLETest18{19protected:20ComputeShaderTest() {}2122void createMockOutputImage(GLuint texture, GLenum internalFormat, GLint width, GLint height)23{24glBindTexture(GL_TEXTURE_2D, texture);25glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, width, height);26EXPECT_GL_NO_ERROR();2728glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalFormat);29EXPECT_GL_NO_ERROR();30}3132template <class T, GLint kWidth, GLint kHeight>33void runSharedMemoryTest(const char *kCS,34GLenum internalFormat,35GLenum format,36const std::array<T, kWidth * kHeight> &inputData,37const std::array<T, kWidth * kHeight> &expectedValues)38{39GLTexture texture[2];40GLFramebuffer framebuffer;4142glBindTexture(GL_TEXTURE_2D, texture[0]);43glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kWidth, kHeight);44glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, format,45inputData.data());46EXPECT_GL_NO_ERROR();4748constexpr T initData[kWidth * kHeight] = {};49glBindTexture(GL_TEXTURE_2D, texture[1]);50glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kWidth, kHeight);51glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, format, initData);52EXPECT_GL_NO_ERROR();5354ANGLE_GL_COMPUTE_PROGRAM(program, kCS);55glUseProgram(program.get());5657glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalFormat);58EXPECT_GL_NO_ERROR();5960glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalFormat);61EXPECT_GL_NO_ERROR();6263glDispatchCompute(1, 1, 1);64EXPECT_GL_NO_ERROR();6566glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);6768T outputValues[kWidth * kHeight] = {};69glUseProgram(0);70glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);7172glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1],730);74EXPECT_GL_NO_ERROR();75glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, format, outputValues);76EXPECT_GL_NO_ERROR();7778for (int i = 0; i < kWidth * kHeight; i++)79{80EXPECT_EQ(expectedValues[i], outputValues[i]);81}82}83};8485class ComputeShaderTestES3 : public ANGLETest86{87protected:88ComputeShaderTestES3() {}89};9091class WebGL2ComputeTest : public ComputeShaderTest92{93protected:94WebGL2ComputeTest() { setWebGLCompatibilityEnabled(true); }95};9697// link a simple compute program. It should be successful.98TEST_P(ComputeShaderTest, LinkComputeProgram)99{100constexpr char kCS[] = R"(#version 310 es101layout(local_size_x=1) in;102void main()103{104})";105106ANGLE_GL_COMPUTE_PROGRAM(program, kCS);107108EXPECT_GL_NO_ERROR();109}110111// Link a simple compute program. Then detach the shader and dispatch compute.112// It should be successful.113TEST_P(ComputeShaderTest, DetachShaderAfterLinkSuccess)114{115constexpr char kCS[] = R"(#version 310 es116layout(local_size_x=1) in;117void main()118{119})";120121GLuint program = glCreateProgram();122123GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);124EXPECT_NE(0u, cs);125126glAttachShader(program, cs);127glDeleteShader(cs);128129glLinkProgram(program);130GLint linkStatus;131glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);132EXPECT_GL_TRUE(linkStatus);133134glDetachShader(program, cs);135EXPECT_GL_NO_ERROR();136137glUseProgram(program);138glDispatchCompute(8, 4, 2);139EXPECT_GL_NO_ERROR();140}141142// link a simple compute program. There is no local size and linking should fail.143TEST_P(ComputeShaderTest, LinkComputeProgramNoLocalSizeLinkError)144{145constexpr char kCS[] = R"(#version 310 es146void main()147{148})";149150GLuint program = CompileComputeProgram(kCS, false);151EXPECT_EQ(0u, program);152153glDeleteProgram(program);154155EXPECT_GL_NO_ERROR();156}157158// link a simple compute program.159// make sure that uniforms and uniform samplers get recorded160TEST_P(ComputeShaderTest, LinkComputeProgramWithUniforms)161{162constexpr char kCS[] = R"(#version 310 es163precision mediump sampler2D;164layout(local_size_x=1) in;165uniform int myUniformInt;166uniform sampler2D myUniformSampler;167layout(rgba32i) uniform highp writeonly iimage2D imageOut;168void main()169{170int q = myUniformInt;171vec4 v = textureLod(myUniformSampler, vec2(0.0), 0.0);172imageStore(imageOut, ivec2(0), ivec4(v) * q);173})";174175ANGLE_GL_COMPUTE_PROGRAM(program, kCS);176177GLint uniformLoc = glGetUniformLocation(program.get(), "myUniformInt");178EXPECT_NE(-1, uniformLoc);179180uniformLoc = glGetUniformLocation(program.get(), "myUniformSampler");181EXPECT_NE(-1, uniformLoc);182183EXPECT_GL_NO_ERROR();184}185186// Attach both compute and non-compute shaders. A link time error should occur.187// OpenGL ES 3.10, 7.3 Program Objects188TEST_P(ComputeShaderTest, AttachMultipleShaders)189{190constexpr char kCS[] = R"(#version 310 es191layout(local_size_x=1) in;192void main()193{194})";195196constexpr char kVS[] = R"(#version 310 es197void main()198{199})";200201constexpr char kFS[] = R"(#version 310 es202void main()203{204})";205206GLuint program = glCreateProgram();207208GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);209GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);210GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);211212EXPECT_NE(0u, vs);213EXPECT_NE(0u, fs);214EXPECT_NE(0u, cs);215216glAttachShader(program, vs);217glDeleteShader(vs);218219glAttachShader(program, fs);220glDeleteShader(fs);221222glAttachShader(program, cs);223glDeleteShader(cs);224225glLinkProgram(program);226227GLint linkStatus;228glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);229230EXPECT_GL_FALSE(linkStatus);231232EXPECT_GL_NO_ERROR();233}234235// Attach a vertex, fragment and compute shader.236// Query for the number of attached shaders and check the count.237TEST_P(ComputeShaderTest, AttachmentCount)238{239constexpr char kCS[] = R"(#version 310 es240layout(local_size_x=1) in;241void main()242{243})";244245constexpr char kVS[] = R"(#version 310 es246void main()247{248})";249250constexpr char kFS[] = R"(#version 310 es251void main()252{253})";254255GLuint program = glCreateProgram();256257GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);258GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);259GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);260261EXPECT_NE(0u, vs);262EXPECT_NE(0u, fs);263EXPECT_NE(0u, cs);264265glAttachShader(program, vs);266glDeleteShader(vs);267268glAttachShader(program, fs);269glDeleteShader(fs);270271glAttachShader(program, cs);272glDeleteShader(cs);273274GLint numAttachedShaders;275glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);276277EXPECT_EQ(3, numAttachedShaders);278279glDeleteProgram(program);280281EXPECT_GL_NO_ERROR();282}283284// Attach a compute shader and link, but start rendering.285TEST_P(ComputeShaderTest, StartRenderingWithComputeProgram)286{287constexpr char kCS[] = R"(#version 310 es288layout(local_size_x=1) in;289void main()290{291})";292293ANGLE_GL_COMPUTE_PROGRAM(program, kCS);294EXPECT_GL_NO_ERROR();295296glUseProgram(program);297glDrawArrays(GL_POINTS, 0, 2);298EXPECT_GL_NO_ERROR();299}300301// Attach a vertex and fragment shader and link, but dispatch compute.302TEST_P(ComputeShaderTest, DispatchComputeWithRenderingProgram)303{304constexpr char kVS[] = R"(#version 310 es305void main() {})";306307constexpr char kFS[] = R"(#version 310 es308void main() {})";309310GLuint program = glCreateProgram();311312GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);313GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);314315EXPECT_NE(0u, vs);316EXPECT_NE(0u, fs);317318glAttachShader(program, vs);319glDeleteShader(vs);320321glAttachShader(program, fs);322glDeleteShader(fs);323324glLinkProgram(program);325326GLint linkStatus;327glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);328EXPECT_GL_TRUE(linkStatus);329330EXPECT_GL_NO_ERROR();331332glUseProgram(program);333glDispatchCompute(8, 4, 2);334EXPECT_GL_ERROR(GL_INVALID_OPERATION);335}336337// Access all compute shader special variables.338TEST_P(ComputeShaderTest, AccessAllSpecialVariables)339{340constexpr char kCS[] = R"(#version 310 es341layout(local_size_x=4, local_size_y=3, local_size_z=2) in;342layout(rgba32ui) uniform highp writeonly uimage2D imageOut;343void main()344{345uvec3 temp1 = gl_NumWorkGroups;346uvec3 temp2 = gl_WorkGroupSize;347uvec3 temp3 = gl_WorkGroupID;348uvec3 temp4 = gl_LocalInvocationID;349uvec3 temp5 = gl_GlobalInvocationID;350uint temp6 = gl_LocalInvocationIndex;351imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2 + temp3 + temp4 + temp5, temp6));352})";353354ANGLE_GL_COMPUTE_PROGRAM(program, kCS);355}356357// Access part compute shader special variables.358TEST_P(ComputeShaderTest, AccessPartSpecialVariables)359{360constexpr char kCS[] = R"(#version 310 es361layout(local_size_x=4, local_size_y=3, local_size_z=2) in;362layout(rgba32ui) uniform highp writeonly uimage2D imageOut;363void main()364{365uvec3 temp1 = gl_WorkGroupSize;366uvec3 temp2 = gl_WorkGroupID;367uint temp3 = gl_LocalInvocationIndex;368imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2, temp3));369})";370371ANGLE_GL_COMPUTE_PROGRAM(program, kCS);372}373374// Use glDispatchCompute to define work group count.375TEST_P(ComputeShaderTest, DispatchCompute)376{377constexpr char kCS[] = R"(#version 310 es378layout(local_size_x=4, local_size_y=3, local_size_z=2) in;379layout(rgba32ui) uniform highp writeonly uimage2D imageOut;380void main()381{382uvec3 temp = gl_NumWorkGroups;383imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u));384})";385386ANGLE_GL_COMPUTE_PROGRAM(program, kCS);387388GLTexture texture;389createMockOutputImage(texture, GL_RGBA32UI, 4, 3);390391glUseProgram(program.get());392glDispatchCompute(8, 4, 2);393EXPECT_GL_NO_ERROR();394}395396// Binds a storage buffer to slot 0, then binds a storage image to slot 0, then buffer again.397TEST_P(ComputeShaderTest, BufferImageBuffer)398{399// See http://anglebug.com/3536400ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());401402constexpr char kCS0[] = R"(#version 310 es403layout(local_size_x=1, local_size_y=1, local_size_z=1) in;404layout(binding = 0, offset = 4) uniform atomic_uint ac[2];405void main()406{407atomicCounterIncrement(ac[0]);408atomicCounterDecrement(ac[1]);409})";410411ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);412glUseProgram(program0);413414unsigned int bufferData[3] = {11u, 4u, 4u};415GLBuffer atomicCounterBuffer;416glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);417glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);418419glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);420421glDispatchCompute(1, 1, 1);422EXPECT_GL_NO_ERROR();423424glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);425void *mappedBuffer =426glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);427memcpy(bufferData, mappedBuffer, sizeof(bufferData));428glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);429430EXPECT_EQ(11u, bufferData[0]);431EXPECT_EQ(5u, bufferData[1]);432EXPECT_EQ(3u, bufferData[2]);433434constexpr char kCS1[] = R"(#version 310 es435layout(local_size_x=4, local_size_y=3, local_size_z=2) in;436layout(rgba32ui) uniform highp writeonly uimage2D imageOut;437void main()438{439uvec3 temp = gl_NumWorkGroups;440imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u));441})";442443ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);444445GLTexture texture;446createMockOutputImage(texture, GL_RGBA32UI, 4, 3);447448glUseProgram(program1);449glDispatchCompute(8, 4, 2);450451glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);452glUseProgram(program0);453glDispatchCompute(1, 1, 1);454glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);455mappedBuffer =456glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);457memcpy(bufferData, mappedBuffer, sizeof(bufferData));458glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);459460EXPECT_EQ(11u, bufferData[0]);461EXPECT_EQ(6u, bufferData[1]);462EXPECT_EQ(2u, bufferData[2]);463464EXPECT_GL_NO_ERROR();465}466467// Test that binds UAV with type image to slot 0, then binds UAV with type buffer to slot 0.468TEST_P(ComputeShaderTest, ImageAtomicCounterBuffer)469{470// Flaky hang. http://anglebug.com/3636471ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsDesktopOpenGL());472473constexpr char kCS0[] = R"(#version 310 es474layout(local_size_x=1, local_size_y=1, local_size_z=1) in;475layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];476void main()477{478imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,4790, 0));480imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,4810, 0));482})";483484ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);485glUseProgram(program0);486int width = 1, height = 1;487GLuint inputValues[] = {200};488GLTexture mTexture[2];489glBindTexture(GL_TEXTURE_2D, mTexture[0]);490glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);491glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,492inputValues);493494glBindTexture(GL_TEXTURE_2D, mTexture[1]);495glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);496glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,497inputValues);498499glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);500glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);501502glDispatchCompute(1, 1, 1);503EXPECT_GL_NO_ERROR();504505constexpr char kCS1[] = R"(#version 310 es506layout(local_size_x=1, local_size_y=1, local_size_z=1) in;507layout(binding = 0, offset = 4) uniform atomic_uint ac[2];508void main()509{510atomicCounterIncrement(ac[0]);511atomicCounterDecrement(ac[1]);512})";513514ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);515516unsigned int bufferData[3] = {11u, 4u, 4u};517GLBuffer atomicCounterBuffer;518glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);519glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);520521glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);522523glUseProgram(program1);524glDispatchCompute(1, 1, 1);525EXPECT_GL_NO_ERROR();526527glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);528void *mappedBuffer =529glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);530memcpy(bufferData, mappedBuffer, sizeof(bufferData));531glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);532533EXPECT_EQ(11u, bufferData[0]);534EXPECT_EQ(5u, bufferData[1]);535EXPECT_EQ(3u, bufferData[2]);536537EXPECT_GL_NO_ERROR();538}539540// Test that binds UAV with type image to slot 0, then binds UAV with type buffer to slot 0.541TEST_P(ComputeShaderTest, ImageShaderStorageBuffer)542{543constexpr char kCS0[] = R"(#version 310 es544layout(local_size_x=1, local_size_y=1, local_size_z=1) in;545layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];546void main()547{548imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,5490, 0));550imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,5510, 0));552})";553554ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);555glUseProgram(program0);556int width = 1, height = 1;557GLuint inputValues[] = {200};558GLTexture mTexture[2];559glBindTexture(GL_TEXTURE_2D, mTexture[0]);560glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);561glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,562inputValues);563564glBindTexture(GL_TEXTURE_2D, mTexture[1]);565glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);566glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,567inputValues);568569glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);570glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);571572glDispatchCompute(1, 1, 1);573EXPECT_GL_NO_ERROR();574575constexpr char kCS1[] =576R"(#version 310 es577layout(local_size_x=1, local_size_y=1, local_size_z=1) in;578layout(std140, binding = 0) buffer blockOut {579uvec2 data;580} instanceOut;581layout(std140, binding = 1) buffer blockIn {582uvec2 data;583} instanceIn;584void main()585{586instanceOut.data = instanceIn.data;587}588)";589590ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);591592constexpr unsigned int kBufferSize = 2;593constexpr unsigned int kBufferData[kBufferSize] = {10, 20};594595GLBuffer blockIn;596glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockIn);597glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);598glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, blockIn);599600GLBuffer blockOut;601glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockOut);602glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferData), nullptr, GL_STATIC_DRAW);603glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, blockOut);604605glUseProgram(program1);606glDispatchCompute(1, 1, 1);607EXPECT_GL_NO_ERROR();608609glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);610611glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockOut);612unsigned int bufferDataOut[kBufferSize] = {};613const GLColor *ptr = reinterpret_cast<GLColor *>(614glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferData), GL_MAP_READ_BIT));615memcpy(bufferDataOut, ptr, sizeof(kBufferData));616glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);617618for (unsigned int index = 0; index < kBufferSize; ++index)619{620EXPECT_EQ(bufferDataOut[index], kBufferData[index]) << " index " << index;621}622}623624// Basic test for DispatchComputeIndirect.625TEST_P(ComputeShaderTest, DispatchComputeIndirect)626{627// Flaky crash on teardown, see http://anglebug.com/3349628ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());629630const char kCSSource[] = R"(#version 310 es631layout(local_size_x=1, local_size_y=1, local_size_z=1) in;632layout(r32ui, binding = 0) uniform highp uimage2D uImage;633void main()634{635imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));636})";637638ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);639glUseProgram(program.get());640const int kWidth = 4, kHeight = 6;641GLuint inputValues[kWidth][kHeight] = {};642643GLBuffer buffer;644glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);645GLuint params[] = {kWidth, kHeight, 1};646glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(params), params, GL_STATIC_DRAW);647648GLTexture texture;649glBindTexture(GL_TEXTURE_2D, texture);650glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);651glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,652inputValues);653EXPECT_GL_NO_ERROR();654655glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);656EXPECT_GL_NO_ERROR();657658glDispatchComputeIndirect(0);659EXPECT_GL_NO_ERROR();660661glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);662663GLuint outputValues[kWidth][kHeight];664665GLFramebuffer framebuffer;666glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);667glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);668EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);669EXPECT_GL_NO_ERROR();670671glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);672EXPECT_GL_NO_ERROR();673674constexpr GLuint kExpectedValue = 100u;675for (int x = 0; x < kWidth; x++)676{677for (int y = 0; y < kHeight; y++)678{679EXPECT_EQ(kExpectedValue, outputValues[x][y]);680}681}682}683684// Test that uploading data to buffer that's in use then using it as indirect buffer works.685TEST_P(ComputeShaderTest, UseAsUBOThenUpdateThenDispatchComputeIndirect)686{687// Flaky crash on teardown, see http://anglebug.com/3349688ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());689690constexpr GLsizei kWidth = 4, kHeight = 6;691692const std::array<uint32_t, 4> kInitialData = {1, 2, 3, 4};693const std::array<uint32_t, 4> kUpdateData = {kWidth, kHeight, 1, 0};694695GLBuffer buffer;696glBindBuffer(GL_UNIFORM_BUFFER, buffer);697glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);698glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);699EXPECT_GL_NO_ERROR();700701constexpr char kVerifyUBO[] = R"(#version 310 es702precision mediump float;703layout(binding = 0) uniform block {704uvec4 data;705} ubo;706out vec4 colorOut;707void main()708{709if (all(equal(ubo.data, uvec4(1, 2, 3, 4))))710colorOut = vec4(0, 1.0, 0, 1.0);711else712colorOut = vec4(1.0, 0, 0, 1.0);713})";714715ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);716drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);717EXPECT_GL_NO_ERROR();718719// Update buffer data720glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());721EXPECT_GL_NO_ERROR();722723const char kCS[] = R"(#version 310 es724layout(local_size_x=1, local_size_y=1, local_size_z=1) in;725layout(r32ui, binding = 0) uniform highp uimage2D uImage;726void main()727{728imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));729})";730731ANGLE_GL_COMPUTE_PROGRAM(program, kCS);732glUseProgram(program.get());733734glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);735736const std::vector<GLuint> inputValues(kWidth * kHeight, 0);737738GLTexture texture;739glBindTexture(GL_TEXTURE_2D, texture);740glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);741glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,742inputValues.data());743EXPECT_GL_NO_ERROR();744745glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);746EXPECT_GL_NO_ERROR();747748glDispatchComputeIndirect(0);749EXPECT_GL_NO_ERROR();750751glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);752753EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);754755GLuint outputValues[kWidth][kHeight];756757GLFramebuffer framebuffer;758glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);759glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);760EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);761EXPECT_GL_NO_ERROR();762763glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);764EXPECT_GL_NO_ERROR();765766constexpr GLuint kExpectedValue = 100u;767for (int x = 0; x < kWidth; x++)768{769for (int y = 0; y < kHeight; y++)770{771EXPECT_EQ(kExpectedValue, outputValues[x][y]);772}773}774}775776// Use image uniform to write texture in compute shader, and verify the content is expected.777TEST_P(ComputeShaderTest, BindImageTexture)778{779GLTexture mTexture[2];780GLFramebuffer mFramebuffer;781constexpr char kCS[] = R"(#version 310 es782layout(local_size_x=1, local_size_y=1, local_size_z=1) in;783layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];784void main()785{786imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,7870, 0));788imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,7890, 0));790})";791792ANGLE_GL_COMPUTE_PROGRAM(program, kCS);793glUseProgram(program.get());794int width = 1, height = 1;795GLuint inputValues[] = {200};796797glBindTexture(GL_TEXTURE_2D, mTexture[0]);798glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);799glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,800inputValues);801EXPECT_GL_NO_ERROR();802803glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);804EXPECT_GL_NO_ERROR();805806glBindTexture(GL_TEXTURE_2D, mTexture[1]);807glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);808glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,809inputValues);810EXPECT_GL_NO_ERROR();811812glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);813EXPECT_GL_NO_ERROR();814815glDispatchCompute(1, 1, 1);816EXPECT_GL_NO_ERROR();817818glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);819glUseProgram(0);820GLuint outputValues[2][1];821GLuint expectedValue = 100;822glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);823824glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[0],8250);826EXPECT_GL_NO_ERROR();827glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);828EXPECT_GL_NO_ERROR();829830glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[1],8310);832EXPECT_GL_NO_ERROR();833glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);834EXPECT_GL_NO_ERROR();835836for (int i = 0; i < width * height; i++)837{838EXPECT_EQ(expectedValue, outputValues[0][i]);839EXPECT_EQ(expectedValue, outputValues[1][i]);840}841}842843// When declare a image array without a binding qualifier, all elements are bound to unit zero.844TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)845{846ANGLE_SKIP_TEST_IF(IsD3D11());847848// TODO([email protected]): On AMD desktop OpenGL, bind two image variables to unit 0,849// only one variable is valid.850ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());851852GLTexture mTexture;853GLFramebuffer mFramebuffer;854constexpr char kCS[] = R"(#version 310 es855layout(local_size_x=1, local_size_y=1, local_size_z=1) in;856layout(r32ui) writeonly uniform highp uimage2D uImage[2];857void main()858{859imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, 0), uvec4(100, 0, 0, 0));860imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, 1), uvec4(100, 0, 0, 0));861})";862863ANGLE_GL_COMPUTE_PROGRAM(program, kCS);864glUseProgram(program.get());865constexpr int kTextureWidth = 1, kTextureHeight = 2;866GLuint inputValues[] = {200, 200};867868glBindTexture(GL_TEXTURE_2D, mTexture);869glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);870glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,871GL_UNSIGNED_INT, inputValues);872EXPECT_GL_NO_ERROR();873874glBindImageTexture(0, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);875glDispatchCompute(1, 1, 1);876EXPECT_GL_NO_ERROR();877878glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);879glUseProgram(0);880glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);881882glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);883GLuint outputValues[kTextureWidth * kTextureHeight];884glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,885outputValues);886EXPECT_GL_NO_ERROR();887888GLuint expectedValue = 100;889for (int i = 0; i < kTextureWidth * kTextureHeight; i++)890{891EXPECT_EQ(expectedValue, outputValues[i]);892}893}894895// When an image array is declared without a binding qualifier, all elements are bound to unit zero.896// Check that the unused uniform image array element does not cause any corruption. Checks for a bug897// where unused element could make the whole array seem as unused.898TEST_P(ComputeShaderTest, ImageArrayUnusedElement)899{900ANGLE_SKIP_TEST_IF(IsD3D11());901902// TODO([email protected]): On AMD desktop OpenGL, bind two image variables to unit 0,903// only one variable is valid.904ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());905906// Vulkan is currently unable to handle unbound image units in compute shaders.907// http://anglebug.com/5026908ANGLE_SKIP_TEST_IF(IsVulkan());909910GLFramebuffer framebuffer;911constexpr char kCS[] = R"(#version 310 es912layout(local_size_x=1, local_size_y=1, local_size_z=1) in;913layout(r32ui, binding=0) writeonly uniform highp uimage2D uOut;914layout(r32ui, binding=1) readonly uniform highp uimage2D uIn[2];915916void main()917{918uvec4 inValue = imageLoad(uIn[0], ivec2(gl_LocalInvocationID.xy));919imageStore(uOut, ivec2(gl_LocalInvocationIndex, 0), inValue);920imageStore(uOut, ivec2(gl_LocalInvocationIndex, 1), inValue);921})";922923ANGLE_GL_COMPUTE_PROGRAM(program, kCS);924glUseProgram(program.get());925constexpr int kTextureWidth = 1, kTextureHeight = 2;926GLuint inputValues[] = {100, 100};927GLTexture in;928glBindTexture(GL_TEXTURE_2D, in);929glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);930glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,931GL_UNSIGNED_INT, inputValues);932EXPECT_GL_NO_ERROR();933glBindImageTexture(1, in, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);934935GLuint initValues[] = {111, 111};936GLTexture out;937glBindTexture(GL_TEXTURE_2D, out);938glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);939glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,940GL_UNSIGNED_INT, initValues);941EXPECT_GL_NO_ERROR();942943glBindImageTexture(0, out, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);944glDispatchCompute(1, 1, 1);945EXPECT_GL_NO_ERROR();946947glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);948glUseProgram(0);949glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);950951glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, out, 0);952GLuint outputValues[kTextureWidth * kTextureHeight];953glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,954outputValues);955EXPECT_GL_NO_ERROR();956957GLuint expectedValue = 100;958for (int i = 0; i < kTextureWidth * kTextureHeight; i++)959{960EXPECT_EQ(expectedValue, outputValues[i]);961}962}963// imageLoad functions964TEST_P(ComputeShaderTest, ImageLoad)965{966constexpr char kCS[] = R"(#version 310 es967layout(local_size_x=8) in;968layout(rgba8) uniform highp readonly image2D mImage2DInput;969layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;970layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;971layout(r32i) uniform highp writeonly iimage2D imageOut;972void main()973{974vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));975ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));976uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));977imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(result2d) + resultCube + ivec4(result3d));978})";979980ANGLE_GL_COMPUTE_PROGRAM(program, kCS);981EXPECT_GL_NO_ERROR();982}983984// imageStore functions985TEST_P(ComputeShaderTest, ImageStore)986{987constexpr char kCS[] = R"(#version 310 es988layout(local_size_x=8) in;989layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;990layout(r32f) uniform highp writeonly image3D mImage3DOutput;991layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;992void main()993{994imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));995imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));996imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));997})";998999ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1000EXPECT_GL_NO_ERROR();1001}10021003// imageSize functions1004TEST_P(ComputeShaderTest, ImageSize)1005{1006constexpr char kCS[] = R"(#version 310 es1007layout(local_size_x=8) in;1008layout(rgba8) uniform highp readonly imageCube mImageCubeInput;1009layout(r32i) uniform highp readonly iimage2D mImage2DInput;1010layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;1011layout(r32i) uniform highp writeonly iimage2D imageOut;1012void main()1013{1014ivec2 sizeCube = imageSize(mImageCubeInput);1015ivec2 size2D = imageSize(mImage2DInput);1016ivec3 size2DArray = imageSize(mImage2DArrayInput);1017imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(sizeCube, size2D.x, size2DArray.x));1018})";10191020ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1021EXPECT_GL_NO_ERROR();1022}10231024// Test that texelFetch works well in compute shader.1025TEST_P(ComputeShaderTest, TexelFetchFunction)1026{1027// http://anglebug.com/40921028ANGLE_SKIP_TEST_IF(isSwiftshader());1029constexpr char kCS[] = R"(#version 310 es1030layout(local_size_x=16, local_size_y=12) in;1031precision highp usampler2D;1032uniform usampler2D tex;1033layout(std140, binding = 0) buffer buf {1034uint outData[12][16];1035};10361037void main()1038{1039uint x = gl_LocalInvocationID.x;1040uint y = gl_LocalInvocationID.y;1041outData[y][x] = texelFetch(tex, ivec2(x, y), 0).x;1042})";10431044constexpr unsigned int kWidth = 16;1045constexpr unsigned int kHeight = 12;1046GLTexture tex;1047glBindTexture(GL_TEXTURE_2D, tex);1048glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);1049glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);1050glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);1051GLuint texels[kHeight][kWidth] = {{0}};1052for (unsigned int y = 0; y < kHeight; ++y)1053{1054for (unsigned int x = 0; x < kWidth; ++x)1055{1056texels[y][x] = x + y * kWidth;1057}1058}1059glPixelStorei(GL_UNPACK_ALIGNMENT, 1);1060glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1061texels);1062glBindTexture(GL_TEXTURE_2D, 0);10631064// The array stride are rounded up to the base alignment of a vec4 for std140 layout.1065constexpr unsigned int kArrayStride = 16;1066GLBuffer ssbo;1067glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);1068glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,1069GL_STREAM_DRAW);1070glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);1071EXPECT_GL_NO_ERROR();10721073ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1074glUseProgram(program);10751076glActiveTexture(GL_TEXTURE0);1077glBindTexture(GL_TEXTURE_2D, tex);1078glUniform1i(glGetUniformLocation(program, "tex"), 0);1079glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);1080glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);10811082glDispatchCompute(1, 1, 1);10831084glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);1085const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(1086GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));1087EXPECT_GL_NO_ERROR();1088for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)1089{1090EXPECT_EQ(idx, *(ptr + idx * kArrayStride / 4));1091}1092}10931094// Test that texture function works well in compute shader.1095TEST_P(ComputeShaderTest, TextureFunction)1096{1097// http://anglebug.com/40921098ANGLE_SKIP_TEST_IF(isSwiftshader());1099constexpr char kCS[] = R"(#version 310 es1100layout(local_size_x=16, local_size_y=16) in;1101precision highp usampler2D;1102uniform usampler2D tex;1103layout(std140, binding = 0) buffer buf {1104uint outData[16][16];1105};11061107void main()1108{1109uint x = gl_LocalInvocationID.x;1110uint y = gl_LocalInvocationID.y;1111float xCoord = float(x) / float(16);1112float yCoord = float(y) / float(16);1113outData[y][x] = texture(tex, vec2(xCoord, yCoord)).x;1114})";11151116constexpr unsigned int kWidth = 16;1117constexpr unsigned int kHeight = 16;1118GLTexture tex;1119glBindTexture(GL_TEXTURE_2D, tex);1120glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);1121glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);1122glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);1123GLuint texels[kHeight][kWidth] = {{0}};1124for (unsigned int y = 0; y < kHeight; ++y)1125{1126for (unsigned int x = 0; x < kWidth; ++x)1127{1128texels[y][x] = x + y * kWidth;1129}1130}1131glPixelStorei(GL_UNPACK_ALIGNMENT, 1);1132glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1133texels);1134glBindTexture(GL_TEXTURE_2D, 0);11351136// The array stride are rounded up to the base alignment of a vec4 for std140 layout.1137constexpr unsigned int kArrayStride = 16;1138GLBuffer ssbo;1139glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);1140glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,1141GL_STREAM_DRAW);1142glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);1143EXPECT_GL_NO_ERROR();11441145ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1146glUseProgram(program);11471148glActiveTexture(GL_TEXTURE0);1149glBindTexture(GL_TEXTURE_2D, tex);1150glUniform1i(glGetUniformLocation(program, "tex"), 0);1151glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);1152glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);11531154glDispatchCompute(1, 1, 1);11551156glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);1157const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(1158GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));1159EXPECT_GL_NO_ERROR();1160for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)1161{1162EXPECT_EQ(idx, *(ptr + idx * kArrayStride / 4));1163}1164}11651166// Test mixed use of sampler and image.1167TEST_P(ComputeShaderTest, SamplingAndImageReadWrite)1168{1169GLTexture texture[3];1170GLFramebuffer framebuffer;1171constexpr char kCS[] = R"(#version 310 es1172layout(local_size_x=1, local_size_y=1, local_size_z=1) in;1173layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;1174layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;1175precision highp usampler2D;1176uniform usampler2D tex;1177void main()1178{1179uvec4 value_1 = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);1180uvec4 value_2 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));1181imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value_1 + value_2);1182})";11831184constexpr int kWidth = 1, kHeight = 1;1185constexpr GLuint kInputValues[3][1] = {{50}, {100}, {20}};11861187glBindTexture(GL_TEXTURE_2D, texture[0]);1188glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);1189glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1190kInputValues[0]);1191glBindTexture(GL_TEXTURE_2D, texture[2]);1192glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);1193glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1194kInputValues[2]);1195EXPECT_GL_NO_ERROR();1196glBindTexture(GL_TEXTURE_2D, 0);11971198glBindTexture(GL_TEXTURE_2D, texture[1]);1199glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);1200glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);1201glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);1202glPixelStorei(GL_UNPACK_ALIGNMENT, 1);1203glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1204kInputValues[1]);12051206EXPECT_GL_NO_ERROR();12071208ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1209glUseProgram(program.get());12101211glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);1212glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);1213EXPECT_GL_NO_ERROR();12141215glDispatchCompute(1, 1, 1);1216EXPECT_GL_NO_ERROR();12171218glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1219GLuint outputValues[kWidth * kHeight];1220constexpr GLuint expectedValue = 150;1221glUseProgram(0);1222glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);12231224glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);1225EXPECT_GL_NO_ERROR();1226glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1227EXPECT_GL_NO_ERROR();12281229for (int i = 0; i < kWidth * kHeight; i++)1230{1231EXPECT_EQ(expectedValue, outputValues[i]);1232}1233}12341235// Use image uniform to read and write Texture2D in compute shader, and verify the contents.1236TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)1237{1238GLTexture texture[2];1239GLFramebuffer framebuffer;1240constexpr char kCS[] = R"(#version 310 es1241layout(local_size_x=1, local_size_y=1, local_size_z=1) in;1242layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;1243layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;1244void main()1245{1246uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));1247imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);1248})";12491250constexpr int kWidth = 1, kHeight = 1;1251constexpr GLuint kInputValues[2][1] = {{200}, {100}};12521253glBindTexture(GL_TEXTURE_2D, texture[0]);1254glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);1255glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1256kInputValues[0]);1257EXPECT_GL_NO_ERROR();12581259glBindTexture(GL_TEXTURE_2D, texture[1]);1260glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);1261glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1262kInputValues[1]);1263EXPECT_GL_NO_ERROR();12641265ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1266glUseProgram(program.get());12671268glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);1269EXPECT_GL_NO_ERROR();12701271glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);1272EXPECT_GL_NO_ERROR();12731274glDispatchCompute(1, 1, 1);1275EXPECT_GL_NO_ERROR();12761277glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1278GLuint outputValues[kWidth * kHeight];1279constexpr GLuint expectedValue = 200;1280glUseProgram(0);1281glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);12821283glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);1284EXPECT_GL_NO_ERROR();1285glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1286EXPECT_GL_NO_ERROR();12871288for (int i = 0; i < kWidth * kHeight; i++)1289{1290EXPECT_EQ(expectedValue, outputValues[i]);1291}1292}12931294// Use image uniform to read and write Texture2D with non-zero base in compute shader, and verify1295// the contents.1296TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2D)1297{1298GLTexture texture[2];1299GLFramebuffer framebuffer;1300constexpr char kCS[] = R"(#version 310 es1301layout(local_size_x=1, local_size_y=1, local_size_z=1) in;1302layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;1303layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;1304void main()1305{1306uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));1307imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);1308})";13091310constexpr int kWidth = 1, kHeight = 1;1311constexpr GLuint kInputValues[2][1] = {{200}, {100}};13121313glBindTexture(GL_TEXTURE_2D, texture[0]);1314glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);1315glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1316kInputValues[0]);1317glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);1318EXPECT_GL_NO_ERROR();13191320glBindTexture(GL_TEXTURE_2D, texture[1]);1321glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);1322glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1323kInputValues[1]);1324glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);1325EXPECT_GL_NO_ERROR();13261327ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1328glUseProgram(program.get());13291330glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);1331EXPECT_GL_NO_ERROR();13321333glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);1334EXPECT_GL_NO_ERROR();13351336glDispatchCompute(1, 1, 1);1337EXPECT_GL_NO_ERROR();13381339glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1340GLuint outputValues[kWidth * kHeight];1341constexpr GLuint expectedValue = 200;1342glUseProgram(0);1343glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);13441345glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);1346EXPECT_GL_NO_ERROR();1347glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1348EXPECT_GL_NO_ERROR();13491350for (int i = 0; i < kWidth * kHeight; i++)1351{1352EXPECT_EQ(expectedValue, outputValues[i]) << " at index: " << i;1353}1354}13551356// Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.1357TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)1358{1359GLTexture texture[2];1360GLFramebuffer framebuffer;1361constexpr char kCS[] = R"(#version 310 es1362layout(local_size_x=2, local_size_y=2, local_size_z=2) in;1363layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;1364layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;1365void main()1366{1367uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));1368imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);1369})";13701371constexpr int kWidth = 1, kHeight = 1, kDepth = 2;1372constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};13731374glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);1375glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);1376glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1377GL_UNSIGNED_INT, kInputValues[0]);1378EXPECT_GL_NO_ERROR();13791380glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);1381glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);1382glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1383GL_UNSIGNED_INT, kInputValues[1]);1384EXPECT_GL_NO_ERROR();13851386ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1387glUseProgram(program.get());13881389glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);1390EXPECT_GL_NO_ERROR();13911392glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);1393EXPECT_GL_NO_ERROR();13941395glDispatchCompute(1, 1, 1);1396EXPECT_GL_NO_ERROR();13971398glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1399GLuint outputValues[kWidth * kHeight];1400constexpr GLuint expectedValue = 200;1401glUseProgram(0);1402glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);14031404glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);1405glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);1406EXPECT_GL_NO_ERROR();1407glReadBuffer(GL_COLOR_ATTACHMENT0);1408glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1409EXPECT_GL_NO_ERROR();1410for (int i = 0; i < kWidth * kHeight; i++)1411{1412EXPECT_EQ(expectedValue, outputValues[i]);1413}1414glReadBuffer(GL_COLOR_ATTACHMENT1);1415glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1416EXPECT_GL_NO_ERROR();1417for (int i = 0; i < kWidth * kHeight; i++)1418{1419EXPECT_EQ(expectedValue, outputValues[i]);1420}1421}14221423// Use image uniform to read and write Texture2DArray with non-zero base in compute shader, and1424// verify the contents.1425TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2DArray)1426{1427GLTexture texture[2];1428GLFramebuffer framebuffer;1429constexpr char kCS[] = R"(#version 310 es1430layout(local_size_x=2, local_size_y=2, local_size_z=2) in;1431layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;1432layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;1433void main()1434{1435uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));1436imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);1437})";14381439constexpr int kWidth = 1, kHeight = 1, kDepth = 2;1440constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};14411442glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);1443glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);1444glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1445GL_UNSIGNED_INT, kInputValues[0]);1446glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);1447EXPECT_GL_NO_ERROR();14481449glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);1450glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);1451glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1452GL_UNSIGNED_INT, kInputValues[1]);1453glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);1454EXPECT_GL_NO_ERROR();14551456ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1457glUseProgram(program.get());14581459glBindImageTexture(0, texture[0], 1, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);1460EXPECT_GL_NO_ERROR();14611462glBindImageTexture(1, texture[1], 1, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);1463EXPECT_GL_NO_ERROR();14641465glDispatchCompute(1, 1, 1);1466EXPECT_GL_NO_ERROR();14671468glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1469GLuint outputValues[kWidth * kHeight];1470constexpr GLuint expectedValue = 200;1471glUseProgram(0);1472glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);14731474glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 1, 0);1475glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 1, 1);1476EXPECT_GL_NO_ERROR();1477glReadBuffer(GL_COLOR_ATTACHMENT0);1478glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1479EXPECT_GL_NO_ERROR();1480for (int i = 0; i < kWidth * kHeight; i++)1481{1482EXPECT_EQ(expectedValue, outputValues[i]);1483}1484glReadBuffer(GL_COLOR_ATTACHMENT1);1485glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1486EXPECT_GL_NO_ERROR();1487for (int i = 0; i < kWidth * kHeight; i++)1488{1489EXPECT_EQ(expectedValue, outputValues[i]);1490}1491}14921493// Use image uniform to read and write Texture3D in compute shader, and verify the contents.1494TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)1495{1496GLTexture texture[2];1497GLFramebuffer framebuffer;1498constexpr char kCS[] = R"(#version 310 es1499layout(local_size_x=1, local_size_y=1, local_size_z=2) in;1500layout(r32ui, binding = 0) readonly uniform highp uimage3D uImage_1;1501layout(r32ui, binding = 1) writeonly uniform highp uimage3D uImage_2;1502void main()1503{1504uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));1505imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);1506})";15071508constexpr int kWidth = 1, kHeight = 1, kDepth = 2;1509constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};15101511glBindTexture(GL_TEXTURE_3D, texture[0]);1512glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);1513glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1514GL_UNSIGNED_INT, kInputValues[0]);1515EXPECT_GL_NO_ERROR();15161517glBindTexture(GL_TEXTURE_3D, texture[1]);1518glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);1519glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1520GL_UNSIGNED_INT, kInputValues[1]);1521EXPECT_GL_NO_ERROR();15221523ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1524glUseProgram(program.get());15251526glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);1527EXPECT_GL_NO_ERROR();15281529glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);1530EXPECT_GL_NO_ERROR();15311532glDispatchCompute(1, 1, 1);1533EXPECT_GL_NO_ERROR();15341535glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1536GLuint outputValues[kWidth * kHeight];1537constexpr GLuint expectedValue = 200;1538glUseProgram(0);1539glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);15401541glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);1542glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);1543EXPECT_GL_NO_ERROR();1544glReadBuffer(GL_COLOR_ATTACHMENT0);1545glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1546EXPECT_GL_NO_ERROR();1547for (int i = 0; i < kWidth * kHeight; i++)1548{1549EXPECT_EQ(expectedValue, outputValues[i]);1550}1551glReadBuffer(GL_COLOR_ATTACHMENT1);1552glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1553EXPECT_GL_NO_ERROR();1554for (int i = 0; i < kWidth * kHeight; i++)1555{1556EXPECT_EQ(expectedValue, outputValues[i]);1557}1558}15591560// Use image uniform to read and write TextureCube in compute shader, and verify the contents.1561TEST_P(ComputeShaderTest, BindImageTextureWithTextureCube)1562{1563GLTexture texture[2];1564GLFramebuffer framebuffer;1565constexpr char kCS[] = R"(#version 310 es1566layout(local_size_x=1, local_size_y=1, local_size_z=1) in;1567layout(r32ui, binding = 0) readonly uniform highp uimageCube uImage_1;1568layout(r32ui, binding = 1) writeonly uniform highp uimageCube uImage_2;1569void main()1570{1571for (int i = 0; i < 6; i++)1572{1573uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xy, i));1574imageStore(uImage_2, ivec3(gl_LocalInvocationID.xy, i), value);1575}1576})";15771578constexpr int kWidth = 1, kHeight = 1;1579constexpr GLuint kInputValues[2][1] = {{200}, {100}};15801581glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);1582glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);1583for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;1584face++)1585{1586glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1587kInputValues[0]);1588}1589EXPECT_GL_NO_ERROR();15901591glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);1592glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);1593for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;1594face++)1595{1596glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1597kInputValues[1]);1598}1599EXPECT_GL_NO_ERROR();16001601ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1602glUseProgram(program.get());16031604glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);1605EXPECT_GL_NO_ERROR();16061607glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);1608EXPECT_GL_NO_ERROR();16091610glDispatchCompute(1, 1, 1);1611EXPECT_GL_NO_ERROR();16121613glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1614GLuint outputValues[kWidth * kHeight];1615constexpr GLuint expectedValue = 200;1616glUseProgram(0);1617glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);16181619for (GLenum face = 0; face < 6; face++)1620{1621glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,1622GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);1623EXPECT_GL_NO_ERROR();1624glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1625EXPECT_GL_NO_ERROR();16261627for (int i = 0; i < kWidth * kHeight; i++)1628{1629EXPECT_EQ(expectedValue, outputValues[i]);1630}1631}1632}16331634// Use image uniform to read and write one layer of Texture2DArray in compute shader, and verify the1635// contents.1636TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)1637{1638GLTexture texture[2];1639GLFramebuffer framebuffer;1640constexpr char kCS[] = R"(#version 310 es1641layout(local_size_x=1, local_size_y=1, local_size_z=1) in;1642layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;1643layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;1644void main()1645{1646uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));1647imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);1648})";16491650constexpr int kWidth = 1, kHeight = 1, kDepth = 2;1651constexpr int kResultSize = kWidth * kHeight;1652constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};1653constexpr GLuint expectedValue_1 = 200;1654constexpr GLuint expectedValue_2 = 100;1655GLuint outputValues[kResultSize];16561657glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);1658glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);1659glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1660GL_UNSIGNED_INT, kInputValues[0]);1661EXPECT_GL_NO_ERROR();16621663glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);1664glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);1665glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1666GL_UNSIGNED_INT, kInputValues[1]);1667EXPECT_GL_NO_ERROR();16681669ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1670glUseProgram(program.get());16711672glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);1673EXPECT_GL_NO_ERROR();1674glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);1675EXPECT_GL_NO_ERROR();1676glDispatchCompute(1, 1, 1);1677EXPECT_GL_NO_ERROR();16781679glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1680glUseProgram(0);1681glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);1682glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);1683glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);1684EXPECT_GL_NO_ERROR();1685glReadBuffer(GL_COLOR_ATTACHMENT0);1686glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1687EXPECT_GL_NO_ERROR();1688for (int i = 0; i < kResultSize; i++)1689{1690EXPECT_EQ(expectedValue_2, outputValues[i]);1691}1692glReadBuffer(GL_COLOR_ATTACHMENT1);1693glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1694EXPECT_GL_NO_ERROR();1695for (int i = 0; i < kResultSize; i++)1696{1697EXPECT_EQ(expectedValue_1, outputValues[i]);1698}1699}17001701// Use image uniform to read and write one layer of Texture3D in compute shader, and verify the1702// contents.1703TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)1704{1705// Vulkan validation error creating a 2D image view of a 3D image layer.1706// http://anglebug.com/38861707ANGLE_SKIP_TEST_IF(IsVulkan());17081709GLTexture texture[2];1710GLFramebuffer framebuffer;1711constexpr char kCS[] = R"(#version 310 es1712layout(local_size_x=1, local_size_y=1, local_size_z=1) in;1713layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;1714layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;1715void main()1716{1717uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));1718imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);1719})";17201721constexpr int kWidth = 1, kHeight = 1, kDepth = 2;1722constexpr int kResultSize = kWidth * kHeight;1723constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};1724constexpr GLuint expectedValue_1 = 150;1725constexpr GLuint expectedValue_2 = 50;1726GLuint outputValues[kResultSize];17271728glBindTexture(GL_TEXTURE_3D, texture[0]);1729glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);1730glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1731GL_UNSIGNED_INT, kInputValues[0]);1732EXPECT_GL_NO_ERROR();17331734glBindTexture(GL_TEXTURE_3D, texture[1]);1735glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);1736glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1737GL_UNSIGNED_INT, kInputValues[1]);1738EXPECT_GL_NO_ERROR();17391740ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1741glUseProgram(program.get());17421743glBindImageTexture(0, texture[0], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);1744EXPECT_GL_NO_ERROR();1745glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);1746EXPECT_GL_NO_ERROR();1747glDispatchCompute(1, 1, 1);1748EXPECT_GL_NO_ERROR();17491750glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1751glUseProgram(0);1752glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);1753glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);1754glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);1755EXPECT_GL_NO_ERROR();1756glReadBuffer(GL_COLOR_ATTACHMENT0);1757glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1758EXPECT_GL_NO_ERROR();1759for (int i = 0; i < kResultSize; i++)1760{1761EXPECT_EQ(expectedValue_1, outputValues[i]);1762}1763glReadBuffer(GL_COLOR_ATTACHMENT1);1764glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1765EXPECT_GL_NO_ERROR();1766for (int i = 0; i < kResultSize; i++)1767{1768EXPECT_EQ(expectedValue_2, outputValues[i]);1769}1770}17711772// Use image uniform to read and write one layer of TextureCube in compute shader, and verify the1773// contents.1774TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)1775{1776// GL_FRAMEBUFFER_BARRIER_BIT is invalid on Nvidia Linux platform.1777// http://anglebug.com/37361778ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL() && IsLinux());17791780GLTexture texture[2];1781GLFramebuffer framebuffer;1782constexpr char kCS[] = R"(#version 310 es1783layout(local_size_x=1, local_size_y=1, local_size_z=1) in;1784layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;1785layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;1786void main()1787{1788uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));1789imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);1790})";17911792constexpr int kWidth = 1, kHeight = 1;1793constexpr int kResultSize = kWidth * kHeight;1794constexpr GLuint kInputValues[2][1] = {{200}, {100}};1795constexpr GLuint expectedValue_1 = 200;1796constexpr GLuint expectedValue_2 = 100;1797GLuint outputValues[kResultSize];17981799glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);1800glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);1801for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;1802face++)1803{1804glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1805kInputValues[0]);1806}1807EXPECT_GL_NO_ERROR();18081809glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);1810glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);1811for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;1812face++)1813{1814glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1815kInputValues[1]);1816}1817EXPECT_GL_NO_ERROR();18181819ANGLE_GL_COMPUTE_PROGRAM(program, kCS);1820glUseProgram(program.get());18211822glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);1823EXPECT_GL_NO_ERROR();1824glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);1825EXPECT_GL_NO_ERROR();1826glDispatchCompute(1, 1, 1);1827EXPECT_GL_NO_ERROR();18281829glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1830glUseProgram(0);1831glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);18321833for (GLenum face = 0; face < 6; face++)1834{1835glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,1836GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);1837EXPECT_GL_NO_ERROR();1838glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1839EXPECT_GL_NO_ERROR();18401841if (face == 4)1842{1843for (int i = 0; i < kResultSize; i++)1844{1845EXPECT_EQ(expectedValue_1, outputValues[i]);1846}1847}1848else1849{1850for (int i = 0; i < kResultSize; i++)1851{1852EXPECT_EQ(expectedValue_2, outputValues[i]);1853}1854}1855}1856}18571858// Test to bind kinds of texture types, bind either the entire texture1859// level or a single layer or face of the face level.1860TEST_P(ComputeShaderTest, BindImageTextureWithMixTextureTypes)1861{1862// GL_FRAMEBUFFER_BARRIER_BIT is invalid on Nvidia Linux platform.1863// http://anglebug.com/37361864ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL() && IsLinux());18651866// http://anglebug.com/50721867ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());18681869GLTexture texture[4];1870GLFramebuffer framebuffer;1871const char csSource[] =1872R"(#version 310 es1873layout(local_size_x=1, local_size_y=1, local_size_z=1) in;1874layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;1875layout(r32ui, binding = 1) readonly uniform highp uimage2D uImage_2;1876layout(r32ui, binding = 2) readonly uniform highp uimage3D uImage_3;1877layout(r32ui, binding = 3) writeonly uniform highp uimage2D uImage_4;1878void main()1879{1880uvec4 value_1 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));1881uvec4 value_2 = imageLoad(uImage_2, ivec2(gl_LocalInvocationID.xy));1882uvec4 value_3 = imageLoad(uImage_3, ivec3(gl_LocalInvocationID.xyz));1883imageStore(uImage_4, ivec2(gl_LocalInvocationID.xy), value_1 + value_2 + value_3);1884})";18851886constexpr int kWidth = 1, kHeight = 1, kDepth = 2;1887constexpr int kResultSize = kWidth * kHeight;1888constexpr GLuint kInputValues2D[1] = {11};1889constexpr GLuint KInputValues2DArray[2] = {23, 35};1890constexpr GLuint KInputValues3D[2] = {102, 67};1891constexpr GLuint KInputValuesCube[1] = {232};18921893constexpr GLuint expectedValue_1 = 148;1894constexpr GLuint expectedValue_2 = 232;1895GLuint outputValues[kResultSize];18961897glBindTexture(GL_TEXTURE_2D, texture[0]);1898glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);1899glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1900kInputValues2D);1901EXPECT_GL_NO_ERROR();19021903glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);1904glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);1905glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1906GL_UNSIGNED_INT, KInputValues2DArray);1907EXPECT_GL_NO_ERROR();19081909glBindTexture(GL_TEXTURE_3D, texture[2]);1910glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);1911glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,1912GL_UNSIGNED_INT, KInputValues3D);1913EXPECT_GL_NO_ERROR();19141915glBindTexture(GL_TEXTURE_CUBE_MAP, texture[3]);1916glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);1917for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;1918face++)1919{1920glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,1921KInputValuesCube);1922}1923EXPECT_GL_NO_ERROR();19241925ANGLE_GL_COMPUTE_PROGRAM(program, csSource);1926glUseProgram(program.get());19271928glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);1929EXPECT_GL_NO_ERROR();1930glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);1931EXPECT_GL_NO_ERROR();1932glBindImageTexture(2, texture[2], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);1933EXPECT_GL_NO_ERROR();1934glBindImageTexture(3, texture[3], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);1935EXPECT_GL_NO_ERROR();1936glDispatchCompute(1, 1, 1);1937EXPECT_GL_NO_ERROR();19381939glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);1940glUseProgram(0);1941glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);19421943for (GLenum face = 0; face < 6; face++)1944{1945glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,1946GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[3], 0);1947EXPECT_GL_NO_ERROR();1948glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);1949EXPECT_GL_NO_ERROR();19501951if (face == 4)1952{1953for (int i = 0; i < kResultSize; i++)1954{1955EXPECT_EQ(expectedValue_1, outputValues[i]);1956}1957}1958else1959{1960for (int i = 0; i < kResultSize; i++)1961{1962EXPECT_EQ(expectedValue_2, outputValues[i]);1963}1964}1965}1966}19671968// Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a1969// program which has not been linked successfully or which does not contain objects to form a1970// compute shader.1971TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)1972{1973constexpr char kVS[] = R"(#version 310 es1974void main()1975{1976})";19771978constexpr char kFS[] = R"(#version 310 es1979void main()1980{1981})";19821983GLint workGroupSize[3];19841985ANGLE_GL_PROGRAM(graphicsProgram, kVS, kFS);1986glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);1987EXPECT_GL_ERROR(GL_INVALID_OPERATION);19881989GLuint computeProgram = glCreateProgram();1990GLShader computeShader(GL_COMPUTE_SHADER);1991glAttachShader(computeProgram, computeShader);1992glLinkProgram(computeProgram);1993glDetachShader(computeProgram, computeShader);19941995GLint linkStatus;1996glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);1997ASSERT_GL_FALSE(linkStatus);19981999glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);2000EXPECT_GL_ERROR(GL_INVALID_OPERATION);20012002glDeleteProgram(computeProgram);20032004ASSERT_GL_NO_ERROR();2005}20062007// Use groupMemoryBarrier and barrier to sync reads/writes order and the execution2008// order of multiple shader invocations in compute shader.2009TEST_P(ComputeShaderTest, GroupMemoryBarrierAndBarrierTest)2010{2011// TODO([email protected]): Figure out why we get this error message2012// that shader uses features not recognized by this D3D version.2013ANGLE_SKIP_TEST_IF((IsAMD() || IsNVIDIA()) && IsD3D11());2014ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());20152016// http://anglebug.com/50722017ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());20182019GLTexture texture;2020GLFramebuffer framebuffer;20212022// Each invocation first stores a single value in an image, then each invocation sums up2023// all the values in the image and stores the sum in the image. groupMemoryBarrier is2024// used to order reads/writes to variables stored in memory accessible to other shader2025// invocations, and barrier is used to control the relative execution order of multiple2026// shader invocations used to process a local work group.2027constexpr char kCS[] = R"(#version 310 es2028layout(local_size_x=2, local_size_y=2, local_size_z=1) in;2029layout(r32i, binding = 0) uniform highp iimage2D image;2030void main()2031{2032uint x = gl_LocalInvocationID.x;2033uint y = gl_LocalInvocationID.y;2034imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(x + y));2035groupMemoryBarrier();2036barrier();2037int sum = 0;2038for (int i = 0; i < 2; i++)2039{2040for(int j = 0; j < 2; j++)2041{2042sum += imageLoad(image, ivec2(i, j)).x;2043}2044}2045groupMemoryBarrier();2046barrier();2047imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(sum));2048})";20492050constexpr int kWidth = 2, kHeight = 2;2051glBindTexture(GL_TEXTURE_2D, texture);2052glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kWidth, kHeight);2053EXPECT_GL_NO_ERROR();20542055ANGLE_GL_COMPUTE_PROGRAM(program, kCS);2056glUseProgram(program.get());20572058glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);2059EXPECT_GL_NO_ERROR();20602061glDispatchCompute(1, 1, 1);2062EXPECT_GL_NO_ERROR();20632064glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);2065GLuint outputValues[kWidth * kHeight];2066constexpr GLuint kExpectedValue = 4;2067glUseProgram(0);2068glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);20692070glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);2071EXPECT_GL_NO_ERROR();2072glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_INT, outputValues);2073EXPECT_GL_NO_ERROR();20742075for (int i = 0; i < kWidth * kHeight; i++)2076{2077EXPECT_EQ(kExpectedValue, outputValues[i]);2078}2079}20802081// Verify that a link error is generated when the sum of the number of active image uniforms and2082// active shader storage blocks in a compute shader exceeds GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.2083TEST_P(ComputeShaderTest, ExceedCombinedShaderOutputResourcesInCS)2084{2085GLint maxCombinedShaderOutputResources;2086GLint maxComputeShaderStorageBlocks;2087GLint maxComputeImageUniforms;20882089glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);2090glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);2091glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);20922093ANGLE_SKIP_TEST_IF(maxCombinedShaderOutputResources >=2094maxComputeShaderStorageBlocks + maxComputeImageUniforms);20952096std::ostringstream computeShaderStream;2097computeShaderStream << "#version 310 es\n"2098"layout(local_size_x = 3, local_size_y = 1, local_size_z = 1) in;\n"2099"layout(shared, binding = 0) buffer blockName"2100"{\n"2101" uint data;\n"2102"} instance["2103<< maxComputeShaderStorageBlocks << "];\n";21042105ASSERT_GE(maxComputeImageUniforms, 4);2106int numImagesInArray = maxComputeImageUniforms / 2;2107int numImagesNonArray = maxComputeImageUniforms - numImagesInArray;2108for (int i = 0; i < numImagesNonArray; ++i)2109{2110computeShaderStream << "layout(r32f, binding = " << i << ") uniform highp image2D image"2111<< i << ";\n";2112}21132114computeShaderStream << "layout(r32f, binding = " << numImagesNonArray2115<< ") uniform highp image2D imageArray[" << numImagesInArray << "];\n";21162117computeShaderStream << "void main()\n"2118"{\n"2119" uint val = 0u;\n"2120" vec4 val2 = vec4(0.0);\n";21212122for (int i = 0; i < maxComputeShaderStorageBlocks; ++i)2123{2124computeShaderStream << " val += instance[" << i << "].data; \n";2125}21262127for (int i = 0; i < numImagesNonArray; ++i)2128{2129computeShaderStream << " val2 += imageLoad(image" << i2130<< ", ivec2(gl_LocalInvocationID.xy)); \n";2131}21322133for (int i = 0; i < numImagesInArray; ++i)2134{2135computeShaderStream << " val2 += imageLoad(imageArray[" << i << "]"2136<< ", ivec2(gl_LocalInvocationID.xy)); \n";2137}21382139computeShaderStream << " instance[0].data = val + uint(val2.x);\n"2140"}\n";21412142GLuint computeProgram = CompileComputeProgram(computeShaderStream.str().c_str());2143EXPECT_EQ(0u, computeProgram);2144}21452146// Test that uniform block with struct member in compute shader is supported.2147TEST_P(ComputeShaderTest, UniformBlockWithStructMember)2148{2149constexpr char kCS[] = R"(#version 310 es2150layout(local_size_x=8) in;2151layout(rgba8) uniform highp readonly image2D mImage2DInput;2152layout(rgba8) uniform highp writeonly image2D mImage2DOutput;2153struct S {2154ivec3 a;2155ivec2 b;2156};21572158layout(std140, binding=0) uniform blockName {2159S bd;2160} instanceName;2161void main()2162{2163ivec2 t1 = instanceName.bd.b;2164vec4 result2d = imageLoad(mImage2DInput, t1);2165imageStore(mImage2DOutput, ivec2(gl_LocalInvocationID.xy), result2d);2166})";21672168ANGLE_GL_COMPUTE_PROGRAM(program, kCS);2169EXPECT_GL_NO_ERROR();2170}21712172// Verify shared non-array variables can work correctly.2173TEST_P(ComputeShaderTest, NonArraySharedVariable)2174{2175// http://anglebug.com/50722176ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());21772178const char kCSShader[] = R"(#version 310 es2179layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;2180layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;2181layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;2182shared uint temp;2183void main()2184{2185if (gl_LocalInvocationID == uvec3(0, 0, 0))2186{2187temp = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2188}2189groupMemoryBarrier();2190barrier();2191if (gl_LocalInvocationID == uvec3(1, 1, 0))2192{2193imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(temp));2194}2195else2196{2197uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2198imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(inputValue));2199}2200})";22012202const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};2203const std::array<GLuint, 4> expectedValues = {{250, 200, 150, 250}};2204runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,2205expectedValues);2206}22072208// Verify shared non-struct array variables can work correctly.2209TEST_P(ComputeShaderTest, NonStructArrayAsSharedVariable)2210{2211// http://anglebug.com/50722212ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());22132214const char kCSShader[] = R"(#version 310 es2215layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;2216layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;2217layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;2218shared uint sharedData[2][2];2219void main()2220{2221uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2222sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = inputData;2223groupMemoryBarrier();2224barrier();2225imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),2226uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x]));2227})";22282229const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};2230const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};2231runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,2232expectedValues);2233}22342235// Verify shared struct array variables work correctly.2236TEST_P(ComputeShaderTest, StructArrayAsSharedVariable)2237{2238// http://anglebug.com/50722239ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());22402241const char kCSShader[] = R"(#version 310 es2242layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;2243layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;2244layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;2245struct SharedStruct2246{2247uint data;2248};2249shared SharedStruct sharedData[2][2];2250void main()2251{2252uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2253sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y].data = inputData;2254groupMemoryBarrier();2255barrier();2256imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),2257uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x].data));2258})";22592260const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};2261const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};2262runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,2263expectedValues);2264}22652266// Verify using atomic functions without return value can work correctly.2267TEST_P(ComputeShaderTest, AtomicFunctionsNoReturnValue)2268{2269// http://anglebug.com/50722270ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());22712272// Fails on AMD windows drivers. http://anglebug.com/38722273ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());22742275// Fails to link on Android. http://anglebug.com/38742276ANGLE_SKIP_TEST_IF(IsAndroid());22772278ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());22792280const char kCSShader[] = R"(#version 310 es2281layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in;2282layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;2283layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;22842285const uint kSumIndex = 0u;2286const uint kMinIndex = 1u;2287const uint kMaxIndex = 2u;2288const uint kOrIndex = 3u;2289const uint kAndIndex = 4u;2290const uint kXorIndex = 5u;2291const uint kExchangeIndex = 6u;2292const uint kCompSwapIndex = 7u;22932294shared highp uint results[8];22952296void main()2297{2298if (gl_LocalInvocationID.x == kMinIndex || gl_LocalInvocationID.x == kAndIndex)2299{2300results[gl_LocalInvocationID.x] = 0xFFFFu;2301}2302else if (gl_LocalInvocationID.x == kCompSwapIndex)2303{2304results[gl_LocalInvocationID.x] = 1u;2305}2306else2307{2308results[gl_LocalInvocationID.x] = 0u;2309}2310memoryBarrierShared();2311barrier();23122313uint value = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2314atomicAdd(results[kSumIndex], value);2315atomicMin(results[kMinIndex], value);2316atomicMax(results[kMaxIndex], value);2317atomicOr(results[kOrIndex], value);2318atomicAnd(results[kAndIndex], value);2319atomicXor(results[kXorIndex], value);2320atomicExchange(results[kExchangeIndex], value);2321atomicCompSwap(results[kCompSwapIndex], value, 256u);2322memoryBarrierShared();2323barrier();23242325imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),2326uvec4(results[gl_LocalInvocationID.x]));2327})";23282329const std::array<GLuint, 8> inputData = {{1, 2, 4, 8, 16, 32, 64, 128}};2330const std::array<GLuint, 8> expectedValues = {{255, 1, 128, 255, 0, 255, 128, 256}};2331runSharedMemoryTest<GLuint, 8, 1>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,2332expectedValues);2333}23342335// Verify using atomic functions in a non-initializer single assignment can work correctly.2336TEST_P(ComputeShaderTest, AtomicFunctionsInNonInitializerSingleAssignment)2337{2338// http://anglebug.com/50722339ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());23402341// Fails on AMD windows drivers. http://anglebug.com/38722342ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());23432344const char kCSShader[] = R"(#version 310 es2345layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;2346layout (r32i, binding = 0) readonly uniform highp iimage2D srcImage;2347layout (r32i, binding = 1) writeonly uniform highp iimage2D dstImage;23482349shared highp int sharedVariable;23502351shared highp int inputData[9];2352shared highp int outputData[9];23532354void main()2355{2356int inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2357inputData[gl_LocalInvocationID.x] = inputValue;2358memoryBarrierShared();2359barrier();23602361if (gl_LocalInvocationID.x == 0u)2362{2363sharedVariable = 0;23642365outputData[0] = atomicAdd(sharedVariable, inputData[0]);2366outputData[1] = atomicMin(sharedVariable, inputData[1]);2367outputData[2] = atomicMax(sharedVariable, inputData[2]);2368outputData[3] = atomicAnd(sharedVariable, inputData[3]);2369outputData[4] = atomicOr(sharedVariable, inputData[4]);2370outputData[5] = atomicXor(sharedVariable, inputData[5]);2371outputData[6] = atomicExchange(sharedVariable, inputData[6]);2372outputData[7] = atomicCompSwap(sharedVariable, 64, inputData[7]);2373outputData[8] = atomicAdd(sharedVariable, inputData[8]);2374}2375memoryBarrierShared();2376barrier();23772378imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),2379ivec4(outputData[gl_LocalInvocationID.x]));2380})";23812382const std::array<GLint, 9> inputData = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};2383const std::array<GLint, 9> expectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};2384runSharedMemoryTest<GLint, 9, 1>(kCSShader, GL_R32I, GL_INT, inputData, expectedValues);2385}23862387// Verify using atomic functions in an initializers and using unsigned int works correctly.2388TEST_P(ComputeShaderTest, AtomicFunctionsInitializerWithUnsigned)2389{2390// http://anglebug.com/50722391ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());23922393// Fails on AMD windows drivers. http://anglebug.com/38722394ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());23952396constexpr char kCShader[] = R"(#version 310 es2397layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;2398layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;2399layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;24002401shared highp uint sharedVariable;24022403shared highp uint inputData[9];2404shared highp uint outputData[9];24052406void main()2407{2408uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2409inputData[gl_LocalInvocationID.x] = inputValue;2410memoryBarrierShared();2411barrier();24122413if (gl_LocalInvocationID.x == 0u)2414{2415sharedVariable = 0u;24162417uint addValue = atomicAdd(sharedVariable, inputData[0]);2418outputData[0] = addValue;2419uint minValue = atomicMin(sharedVariable, inputData[1]);2420outputData[1] = minValue;2421uint maxValue = atomicMax(sharedVariable, inputData[2]);2422outputData[2] = maxValue;2423uint andValue = atomicAnd(sharedVariable, inputData[3]);2424outputData[3] = andValue;2425uint orValue = atomicOr(sharedVariable, inputData[4]);2426outputData[4] = orValue;2427uint xorValue = atomicXor(sharedVariable, inputData[5]);2428outputData[5] = xorValue;2429uint exchangeValue = atomicExchange(sharedVariable, inputData[6]);2430outputData[6] = exchangeValue;2431uint compSwapValue = atomicCompSwap(sharedVariable, 64u, inputData[7]);2432outputData[7] = compSwapValue;2433uint sharedVariable = atomicAdd(sharedVariable, inputData[8]);2434outputData[8] = sharedVariable;24352436}2437memoryBarrierShared();2438barrier();24392440imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),2441uvec4(outputData[gl_LocalInvocationID.x]));2442})";24432444constexpr std::array<GLuint, 9> kInputData = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};2445constexpr std::array<GLuint, 9> kExpectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};2446runSharedMemoryTest<GLuint, 9, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,2447kExpectedValues);2448}24492450// Verify using atomic functions inside expressions as unsigned int.2451TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithUnsigned)2452{2453// http://anglebug.com/50722454ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());24552456// Fails on AMD windows drivers. http://anglebug.com/38722457ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());24582459constexpr char kCShader[] = R"(#version 310 es2460layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;2461layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;2462layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;24632464shared highp uint sharedVariable;24652466shared highp uint inputData[9];2467shared highp uint outputData[9];24682469void main()2470{2471uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2472inputData[gl_LocalInvocationID.x] = inputValue;2473memoryBarrierShared();2474barrier();24752476if (gl_LocalInvocationID.x == 0u)2477{2478sharedVariable = 0u;24792480outputData[0] = 1u + atomicAdd(sharedVariable, inputData[0]);2481outputData[1] = 1u + atomicMin(sharedVariable, inputData[1]);2482outputData[2] = 1u + atomicMax(sharedVariable, inputData[2]);2483outputData[3] = 1u + atomicAnd(sharedVariable, inputData[3]);2484outputData[4] = 1u + atomicOr(sharedVariable, inputData[4]);2485outputData[5] = 1u + atomicXor(sharedVariable, inputData[5]);2486outputData[6] = 1u + atomicExchange(sharedVariable, inputData[6]);2487outputData[7] = 1u + atomicCompSwap(sharedVariable, 64u, inputData[7]);2488outputData[8] = 1u + atomicAdd(sharedVariable, inputData[8]);2489}2490memoryBarrierShared();2491barrier();24922493imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),2494uvec4(outputData[gl_LocalInvocationID.x]));2495})";24962497constexpr std::array<GLuint, 9> kInputData = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};2498constexpr std::array<GLuint, 9> kExpectedValues = {{1, 2, 2, 5, 1, 17, 49, 65, 129}};2499runSharedMemoryTest<GLuint, 9, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,2500kExpectedValues);2501}25022503// Verify using nested atomic functions in expressions.2504TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithMultipleTypes)2505{2506// http://anglebug.com/50722507ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());25082509constexpr char kCShader[] = R"(#version 310 es2510layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;2511layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;2512layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;25132514shared highp uint sharedVariable;2515shared highp int indexVariable;25162517shared highp uint inputData[4];2518shared highp uint outputData[4];25192520void main()2521{2522uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;2523inputData[gl_LocalInvocationID.x] = inputValue;2524memoryBarrierShared();2525barrier();25262527if (gl_LocalInvocationID.x == 0u)2528{2529sharedVariable = 0u;2530indexVariable = 2;25312532outputData[0] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);2533outputData[1] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);2534outputData[2] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);2535outputData[3] = atomicAdd(sharedVariable, 0u);25362537}2538memoryBarrierShared();2539barrier();25402541imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),2542uvec4(outputData[gl_LocalInvocationID.x]));2543})";25442545constexpr std::array<GLuint, 4> kInputData = {{1, 2, 3, 0}};2546constexpr std::array<GLuint, 4> kExpectedValues = {{1, 4, 6, 6}};2547runSharedMemoryTest<GLuint, 4, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,2548kExpectedValues);2549}25502551// Basic uniform buffer functionality.2552TEST_P(ComputeShaderTest, UniformBuffer)2553{2554// http://anglebug.com/50722555ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());25562557GLTexture texture;2558GLBuffer buffer;2559GLFramebuffer framebuffer;2560constexpr char kCS[] = R"(#version 310 es2561layout(local_size_x=1, local_size_y=1, local_size_z=1) in;2562uniform uni2563{2564uvec4 value;2565};2566layout(rgba32ui, binding = 0) writeonly uniform highp uimage2D uImage;2567void main()2568{2569imageStore(uImage, ivec2(gl_LocalInvocationID.xy), value);2570})";25712572constexpr int kWidth = 1, kHeight = 1;2573constexpr GLuint kInputValues[4] = {56, 57, 58, 59};25742575glBindTexture(GL_TEXTURE_2D, texture);2576glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth, kHeight);2577glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT,2578kInputValues);2579EXPECT_GL_NO_ERROR();25802581ANGLE_GL_COMPUTE_PROGRAM(program, kCS);2582glUseProgram(program.get());25832584GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");2585EXPECT_NE(uniformBufferIndex, -1);2586GLuint data[4] = {201, 202, 203, 204};2587glBindBuffer(GL_UNIFORM_BUFFER, buffer);2588glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint) * 4, data, GL_STATIC_DRAW);2589glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);2590glUniformBlockBinding(program, uniformBufferIndex, 0);2591EXPECT_GL_NO_ERROR();25922593glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);2594EXPECT_GL_NO_ERROR();25952596glDispatchCompute(1, 1, 1);2597EXPECT_GL_NO_ERROR();25982599glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);2600GLuint outputValues[kWidth * kHeight * 4];2601glUseProgram(0);2602glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);26032604glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);2605EXPECT_GL_NO_ERROR();2606glReadPixels(0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);2607EXPECT_GL_NO_ERROR();26082609for (int i = 0; i < kWidth * kHeight * 4; i++)2610{2611EXPECT_EQ(data[i], outputValues[i]);2612}2613}26142615// Test that storing data to image and then loading the same image data works correctly.2616TEST_P(ComputeShaderTest, StoreImageThenLoad)2617{2618// http://anglebug.com/50722619ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());26202621const char kCSSource[] = R"(#version 310 es2622layout(local_size_x=1, local_size_y=1, local_size_z=1) in;2623layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;2624layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;2625void main()2626{2627uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));2628imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);2629})";26302631constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};2632GLTexture texture[3];2633glBindTexture(GL_TEXTURE_2D, texture[0]);2634glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);2635glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);2636EXPECT_GL_NO_ERROR();26372638glBindTexture(GL_TEXTURE_2D, texture[1]);2639glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);2640glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);2641EXPECT_GL_NO_ERROR();26422643glBindTexture(GL_TEXTURE_2D, texture[2]);2644glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);2645glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);2646EXPECT_GL_NO_ERROR();26472648ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2649glUseProgram(program.get());26502651glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);2652glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);26532654glDispatchCompute(1, 1, 1);2655glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);2656EXPECT_GL_NO_ERROR();26572658glBindImageTexture(0, texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);2659glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);26602661glDispatchCompute(1, 1, 1);2662glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);2663EXPECT_GL_NO_ERROR();26642665GLuint outputValue;2666GLFramebuffer framebuffer;2667glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);2668glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);2669glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);2670EXPECT_GL_NO_ERROR();26712672EXPECT_EQ(300u, outputValue);2673}26742675// Test that loading image data and then storing data to the same image works correctly.2676TEST_P(ComputeShaderTest, LoadImageThenStore)2677{2678// http://anglebug.com/50722679ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());26802681const char kCSSource[] = R"(#version 310 es2682layout(local_size_x=1, local_size_y=1, local_size_z=1) in;2683layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;2684layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;2685void main()2686{2687uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));2688imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);2689})";26902691constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};2692GLTexture texture[3];2693glBindTexture(GL_TEXTURE_2D, texture[0]);2694glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);2695glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);2696EXPECT_GL_NO_ERROR();26972698glBindTexture(GL_TEXTURE_2D, texture[1]);2699glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);2700glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);2701EXPECT_GL_NO_ERROR();27022703glBindTexture(GL_TEXTURE_2D, texture[2]);2704glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);2705glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);2706EXPECT_GL_NO_ERROR();27072708ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2709glUseProgram(program.get());27102711glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);2712glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);27132714glDispatchCompute(1, 1, 1);2715glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);2716EXPECT_GL_NO_ERROR();27172718glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);2719glBindImageTexture(1, texture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);27202721glDispatchCompute(1, 1, 1);2722glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);2723EXPECT_GL_NO_ERROR();27242725GLuint outputValue;2726GLFramebuffer framebuffer;2727glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);2728glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);2729glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);2730EXPECT_GL_NO_ERROR();27312732EXPECT_EQ(100u, outputValue);2733}27342735// Test that the length of a struct buffer variable is supported.2736TEST_P(ComputeShaderTest, ShaderStorageBlocksStructLength)2737{2738const char kCSSource[] = R"(#version 310 es2739layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;27402741struct Particle2742{2743int len;2744};27452746layout(binding = 0, std430) readonly buffer Buf12747{2748Particle particlesRead[];2749};27502751layout(binding = 1, std430) buffer Buf22752{2753Particle particlesWrite[];2754};27552756void main()2757{2758int index = int(gl_GlobalInvocationID.x);2759particlesWrite[index].len = particlesRead.length();2760})";27612762ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2763EXPECT_GL_NO_ERROR();2764}27652766// Test that scalar buffer variables are supported.2767TEST_P(ComputeShaderTest, ShaderStorageBlocksScalar)2768{2769const char kCSSource[] = R"(#version 310 es2770layout(local_size_x=1) in;2771layout(std140, binding = 0) buffer blockA {2772uvec3 uv;2773float f;2774} instanceA;2775layout(std140, binding = 1) buffer blockB {2776vec2 v;2777uint u[3];2778float f;2779};2780void main()2781{2782f = instanceA.f;2783})";27842785ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2786EXPECT_GL_NO_ERROR();2787}27882789// Test that vector buffer variables are supported.2790TEST_P(ComputeShaderTest, ShaderStorageBlocksVector)2791{2792const char kCSSource[] = R"(#version 310 es2793layout(local_size_x=1) in;2794layout(std140, binding = 0) buffer blockA {2795vec2 f;2796} instanceA;2797layout(std140, binding = 1) buffer blockB {2798vec3 f;2799};2800void main()2801{2802f[1] = instanceA.f[0];2803})";28042805ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2806EXPECT_GL_NO_ERROR();2807}28082809// Test that matrix buffer variables are supported.2810TEST_P(ComputeShaderTest, ShaderStorageBlocksMatrix)2811{2812const char kCSSource[] = R"(#version 310 es2813layout(local_size_x=1) in;2814layout(std140, binding = 0) buffer blockA {2815mat3x4 m;2816} instanceA;2817layout(std140, binding = 1) buffer blockB {2818mat3x4 m;2819};2820void main()2821{2822m[0][1] = instanceA.m[0][1];2823})";28242825ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2826EXPECT_GL_NO_ERROR();2827}28282829// Test that scalar array buffer variables are supported.2830TEST_P(ComputeShaderTest, ShaderStorageBlocksScalarArray)2831{2832const char kCSSource[] = R"(#version 310 es2833layout(local_size_x=8) in;2834layout(std140, binding = 0) buffer blockA {2835float f[8];2836} instanceA;2837layout(std140, binding = 1) buffer blockB {2838float f[8];2839};2840void main()2841{2842f[gl_LocalInvocationIndex] = instanceA.f[gl_LocalInvocationIndex];2843})";28442845ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2846EXPECT_GL_NO_ERROR();2847}28482849// Test that vector array buffer variables are supported.2850TEST_P(ComputeShaderTest, ShaderStorageBlocksVectorArray)2851{2852const char kCSSource[] = R"(#version 310 es2853layout(local_size_x=4) in;2854layout(std140, binding = 0) buffer blockA {2855vec2 v[4];2856} instanceA;2857layout(std140, binding = 1) buffer blockB {2858vec4 v[4];2859};2860void main()2861{2862v[0][gl_LocalInvocationIndex] = instanceA.v[gl_LocalInvocationIndex][1];2863})";28642865ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2866EXPECT_GL_NO_ERROR();2867}28682869// Test that matrix array buffer variables are supported.2870TEST_P(ComputeShaderTest, ShaderStorageBlocksMatrixArray)2871{2872const char kCSSource[] = R"(#version 310 es2873layout(local_size_x=8) in;2874layout(std140, binding = 0) buffer blockA {2875float v1[5];2876mat4 m[8];2877} instanceA;2878layout(std140, binding = 1) buffer blockB {2879vec2 v1[3];2880mat4 m[8];2881};2882void main()2883{2884float data = instanceA.m[gl_LocalInvocationIndex][0][0];2885m[gl_LocalInvocationIndex][gl_LocalInvocationIndex][gl_LocalInvocationIndex] = data;2886})";28872888ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2889EXPECT_GL_NO_ERROR();2890}28912892// Test that shader storage blocks only in assignment right is supported.2893TEST_P(ComputeShaderTest, ShaderStorageBlocksInAssignmentRight)2894{2895const char kCSSource[] = R"(#version 310 es2896layout(local_size_x=8) in;2897layout(std140, binding = 0) buffer blockA {2898float data[8];2899} instanceA;2900layout(r32f, binding = 0) writeonly uniform highp image2D imageOut;29012902void main()2903{2904float data = 1.0;2905data = instanceA.data[gl_LocalInvocationIndex];2906imageStore(imageOut, ivec2(gl_LocalInvocationID.xy), vec4(data));2907})";29082909ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2910EXPECT_GL_NO_ERROR();2911}29122913// Test that shader storage blocks with unsized array are supported.2914TEST_P(ComputeShaderTest, ShaderStorageBlocksWithUnsizedArray)2915{2916const char kCSSource[] = R"(#version 310 es2917layout(local_size_x=8) in;2918layout(std140, binding = 0) buffer blockA {2919float v[];2920} instanceA;2921layout(std140, binding = 0) buffer blockB {2922float v[];2923} instanceB[1];29242925void main()2926{2927float data = instanceA.v[gl_LocalInvocationIndex];2928instanceB[0].v[gl_LocalInvocationIndex * 2u + 1u] = data;2929}2930)";29312932ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);2933EXPECT_GL_NO_ERROR();2934}29352936// Test that EOpIndexDirect/EOpIndexIndirect/EOpIndexDirectStruct nodes in ssbo EOpIndexInDirect2937// don't need to calculate the offset and should be translated by OutputHLSL directly.2938TEST_P(ComputeShaderTest, IndexAndDotOperatorsInSSBOIndexIndirectOperator)2939{2940constexpr char kComputeShaderSource[] = R"(#version 310 es2941layout(local_size_x=1) in;2942layout(std140, binding = 0) buffer blockA {2943float v[4];2944};2945layout(std140, binding = 1) buffer blockB {2946float v[4];2947} instanceB[1];2948struct S2949{2950uvec4 index[2];2951} s;2952void main()2953{2954s.index[0] = uvec4(0u, 1u, 2u, 3u);2955float data = v[s.index[0].y];2956instanceB[0].v[s.index[0].x] = data;2957})";29582959ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);2960EXPECT_GL_NO_ERROR();2961}29622963// Test that swizzle node in non-SSBO symbol works well.2964TEST_P(ComputeShaderTest, ShaderStorageBlocksWithNonSSBOSwizzle)2965{2966constexpr char kComputeShaderSource[] = R"(#version 310 es2967layout(local_size_x=8) in;2968layout(std140, binding = 0) buffer blockA {2969float v[8];2970};2971layout(std140, binding = 1) buffer blockB {2972float v[8];2973} instanceB[1];29742975void main()2976{2977float data = v[gl_GlobalInvocationID.x];2978instanceB[0].v[gl_GlobalInvocationID.x] = data;2979})";29802981ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);2982EXPECT_GL_NO_ERROR();2983}29842985// Test that swizzle node in SSBO symbol works well.2986TEST_P(ComputeShaderTest, ShaderStorageBlocksWithSSBOSwizzle)2987{2988constexpr char kComputeShaderSource[] = R"(#version 310 es2989layout(local_size_x=1) in;2990layout(std140, binding = 0) buffer blockA {2991vec2 v;2992};2993layout(std140, binding = 1) buffer blockB {2994float v;2995} instanceB[1];29962997void main()2998{2999instanceB[0].v = v.x;3000})";30013002ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);3003EXPECT_GL_NO_ERROR();3004}30053006// Test that a large struct array in std140 uniform block won't consume too much time.3007TEST_P(ComputeShaderTest, LargeStructArraySize)3008{3009constexpr char kComputeShaderSource[] = R"(#version 310 es3010layout(local_size_x=8) in;3011precision mediump float;30123013struct InstancingData3014{3015mat4 transformation;3016};30173018#define MAX_INSTANCE_COUNT 80030193020layout(std140) uniform InstanceBlock3021{3022InstancingData instances[MAX_INSTANCE_COUNT];3023};30243025layout(std140, binding = 1) buffer blockB {3026mat4 v[];3027} instanceB;30283029void main()3030{3031instanceB.v[gl_GlobalInvocationID.x] = instances[gl_GlobalInvocationID.x].transformation;3032})";30333034ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);3035EXPECT_GL_NO_ERROR();3036}30373038// Check that it is not possible to create a compute shader when the context does not support ES3039// 3.103040TEST_P(ComputeShaderTestES3, NotSupported)3041{3042GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);3043EXPECT_EQ(0u, computeShaderHandle);3044EXPECT_GL_ERROR(GL_INVALID_ENUM);3045}30463047// The contents of shared variables should be cleared to zero at the beginning of shader execution.3048TEST_P(WebGL2ComputeTest, sharedVariablesShouldBeZero)3049{3050// http://anglebug.com/32263051ANGLE_SKIP_TEST_IF(IsD3D11());30523053// Fails on Android, AMD/windows and Intel/windows. Probably works by chance on other3054// platforms, so suppressing on all platforms to avoid possible flakiness.3055// http://anglebug.com/38693056ANGLE_SKIP_TEST_IF(IsVulkan());30573058// http://anglebug.com/40923059ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());3060ANGLE_SKIP_TEST_IF(IsOpenGL() &&3061((getClientMajorVersion() == 3) && (getClientMinorVersion() >= 1)));30623063const char kCSShader[] = R"(#version 310 es3064layout (local_size_x = 4, local_size_y = 4, local_size_z = 1) in;3065layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;3066layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;3067struct S {3068float f;3069int i;3070uint u;3071bool b;3072vec4 v[64];3073};30743075shared S vars[16];3076void main()3077{3078S zeroS;3079zeroS.f = 0.0f;3080zeroS.i = 0;3081zeroS.u = 0u;3082zeroS.b = false;3083for (int i = 0; i < 64; i++)3084{3085zeroS.v[i] = vec4(0.0f);3086}30873088uint tid = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4u;3089uint value = (zeroS == vars[tid] ? 127u : 0u);3090imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(value));3091})";30923093const std::array<GLuint, 16> inputData = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};3094const std::array<GLuint, 16> expectedValues = {3095{127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127}};3096runSharedMemoryTest<GLuint, 4, 4>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,3097expectedValues);3098}30993100// Test uniform dirty in compute shader, and verify the contents.3101TEST_P(ComputeShaderTest, UniformDirty)3102{3103// http://anglebug.com/50723104ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());31053106// glReadPixels is getting the result of the first dispatch call. http://anglebug.com/38793107ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && (IsAMD() || IsNVIDIA()));31083109GLTexture texture[2];3110GLFramebuffer framebuffer;3111constexpr char kCS[] = R"(#version 310 es3112layout(local_size_x=1, local_size_y=1, local_size_z=1) in;3113layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;3114layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;3115uniform uint factor;3116void main()3117{3118uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));3119imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value * factor);3120})";31213122constexpr int kWidth = 1, kHeight = 1;3123constexpr GLuint kInputValues[2][1] = {{200}, {100}};31243125glBindTexture(GL_TEXTURE_2D, texture[0]);3126glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);3127glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,3128kInputValues[0]);3129EXPECT_GL_NO_ERROR();31303131glBindTexture(GL_TEXTURE_2D, texture[1]);3132glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);3133glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,3134kInputValues[1]);3135EXPECT_GL_NO_ERROR();31363137ANGLE_GL_COMPUTE_PROGRAM(program, kCS);3138glUseProgram(program);31393140glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);3141EXPECT_GL_NO_ERROR();31423143glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);3144EXPECT_GL_NO_ERROR();31453146glUniform1ui(glGetUniformLocation(program, "factor"), 2);3147EXPECT_GL_NO_ERROR();31483149glDispatchCompute(1, 1, 1);3150EXPECT_GL_NO_ERROR();31513152glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);31533154glUniform1ui(glGetUniformLocation(program, "factor"), 3);3155EXPECT_GL_NO_ERROR();31563157glDispatchCompute(1, 1, 1);3158EXPECT_GL_NO_ERROR();31593160glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);3161GLuint outputValues[kWidth * kHeight];3162GLuint expectedValue = 600;3163glUseProgram(0);3164glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);31653166glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);3167EXPECT_GL_NO_ERROR();3168glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);3169EXPECT_GL_NO_ERROR();31703171for (int i = 0; i < kWidth * kHeight; i++)3172{3173EXPECT_EQ(expectedValue, outputValues[i]) << " index " << i;3174}3175}31763177// Test storage buffer bound is unchanged, shader writes it, buffer content should be updated.3178TEST_P(ComputeShaderTest, StorageBufferBoundUnchanged)3179{3180// http://anglebug.com/40923181ANGLE_SKIP_TEST_IF(isSwiftshader());3182constexpr char kCS[] = R"(#version 310 es3183layout(local_size_x=16, local_size_y=16) in;3184precision highp usampler2D;3185uniform usampler2D tex;3186uniform uint factor;3187layout(std140, binding = 0) buffer buf {3188uint outData[16][16];3189};31903191void main()3192{3193uint x = gl_LocalInvocationID.x;3194uint y = gl_LocalInvocationID.y;3195float xCoord = float(x) / float(16);3196float yCoord = float(y) / float(16);3197outData[y][x] = texture(tex, vec2(xCoord, yCoord)).x + factor;3198})";31993200constexpr unsigned int kWidth = 16;3201constexpr unsigned int kHeight = 16;3202GLTexture tex;3203glBindTexture(GL_TEXTURE_2D, tex);3204glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);3205glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);3206glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);3207GLuint texels[kHeight][kWidth] = {{0}};3208for (unsigned int y = 0; y < kHeight; ++y)3209{3210for (unsigned int x = 0; x < kWidth; ++x)3211{3212texels[y][x] = x + y * kWidth;3213}3214}3215glPixelStorei(GL_UNPACK_ALIGNMENT, 1);3216glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,3217texels);3218glBindTexture(GL_TEXTURE_2D, 0);32193220// The array stride are rounded up to the base alignment of a vec4 for std140 layout.3221constexpr unsigned int kArrayStride = 16;3222GLBuffer ssbo;3223glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);3224glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,3225GL_STREAM_DRAW);3226glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);3227EXPECT_GL_NO_ERROR();32283229ANGLE_GL_COMPUTE_PROGRAM(program, kCS);3230glUseProgram(program);32313232glActiveTexture(GL_TEXTURE0);3233glBindTexture(GL_TEXTURE_2D, tex);3234glUniform1i(glGetUniformLocation(program, "tex"), 0);3235glUniform1ui(glGetUniformLocation(program, "factor"), 2);3236glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);3237glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);32383239glDispatchCompute(1, 1, 1);32403241const GLuint *ptr1 = reinterpret_cast<const GLuint *>(glMapBufferRange(3242GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));3243EXPECT_GL_NO_ERROR();3244for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)3245{3246EXPECT_EQ(idx + 2, *(ptr1 + idx * kArrayStride / 4));3247}3248glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);3249glUniform1ui(glGetUniformLocation(program, "factor"), 3);3250glDispatchCompute(1, 1, 1);32513252const GLuint *ptr2 = reinterpret_cast<const GLuint *>(glMapBufferRange(3253GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));3254EXPECT_GL_NO_ERROR();3255for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)3256{3257EXPECT_EQ(idx + 3, *(ptr2 + idx * kArrayStride / 4));3258}3259}32603261// Test imageSize to access mipmap slice.3262TEST_P(ComputeShaderTest, ImageSizeMipmapSlice)3263{3264// TODO([email protected]): http://anglebug.com/31013265ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());32663267// http://anglebug.com/43923268ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsD3D11());32693270GLTexture texture[2];3271GLFramebuffer framebuffer;3272const char kCS[] = R"(#version 310 es3273layout(local_size_x=1, local_size_y=1, local_size_z=1) in;3274layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;3275layout(rgba32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;3276void main()3277{3278ivec2 size = imageSize(uImage_1);3279imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), uvec4(size, 0, 0));3280})";32813282constexpr int kWidth1 = 8, kHeight1 = 4, kWidth2 = 1, kHeight2 = 1;3283constexpr GLuint kInputValues[] = {0, 0, 0, 0};32843285glBindTexture(GL_TEXTURE_2D, texture[0]);3286glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth1, kHeight1);3287EXPECT_GL_NO_ERROR();32883289glBindTexture(GL_TEXTURE_2D, texture[1]);3290glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth2, kHeight2);3291glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RGBA_INTEGER, GL_UNSIGNED_INT,3292kInputValues);3293EXPECT_GL_NO_ERROR();32943295ANGLE_GL_COMPUTE_PROGRAM(program, kCS);3296glUseProgram(program);32973298glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);3299glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);33003301glDispatchCompute(1, 1, 1);3302EXPECT_GL_NO_ERROR();33033304glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);3305GLuint outputValues[kWidth2 * kHeight2 * 4];3306constexpr GLuint expectedValue[] = {4, 2};3307glUseProgram(0);3308glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);33093310glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);3311EXPECT_GL_NO_ERROR();3312glReadPixels(0, 0, kWidth2, kHeight2, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);3313EXPECT_GL_NO_ERROR();33143315for (int i = 0; i < kWidth2 * kHeight2; i++)3316{3317EXPECT_EQ(expectedValue[i], outputValues[i]);3318EXPECT_EQ(expectedValue[i + 1], outputValues[i + 1]);3319}3320}33213322// Test imageLoad to access mipmap slice.3323TEST_P(ComputeShaderTest, ImageLoadMipmapSlice)3324{3325// TODO([email protected]): http://anglebug.com/31013326ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());33273328GLTexture texture[2];3329GLFramebuffer framebuffer;3330constexpr char kCS[] = R"(#version 310 es3331layout(local_size_x=1, local_size_y=1, local_size_z=1) in;3332layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;3333layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;3334void main()3335{3336uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));3337imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);3338})";33393340constexpr int kWidth1 = 2, kHeight1 = 2, kWidth2 = 1, kHeight2 = 1;3341constexpr GLuint kInputValues11[] = {3, 3, 3, 3};3342constexpr GLuint kInputValues12[] = {2};3343constexpr GLuint kInputValues2[] = {1};33443345glBindTexture(GL_TEXTURE_2D, texture[0]);3346glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth1, kHeight1);3347glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,3348kInputValues11);3349glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,3350kInputValues12);3351EXPECT_GL_NO_ERROR();33523353glBindTexture(GL_TEXTURE_2D, texture[1]);3354glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth2, kHeight2);3355glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,3356kInputValues2);3357EXPECT_GL_NO_ERROR();33583359ANGLE_GL_COMPUTE_PROGRAM(program, kCS);3360glUseProgram(program);33613362glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);3363glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);33643365glDispatchCompute(1, 1, 1);3366EXPECT_GL_NO_ERROR();33673368glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);3369GLuint outputValues;3370constexpr GLuint expectedValue = 2;3371glUseProgram(0);3372glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);33733374glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);3375EXPECT_GL_NO_ERROR();3376glReadPixels(0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValues);3377EXPECT_GL_NO_ERROR();3378EXPECT_EQ(expectedValue, outputValues);3379}33803381// Test imageStore to access mipmap slice.3382TEST_P(ComputeShaderTest, ImageStoreMipmapSlice)3383{3384// TODO([email protected]): http://anglebug.com/31013385ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());33863387GLTexture texture[2];3388GLFramebuffer framebuffer;3389constexpr char kCS[] = R"(#version 310 es3390layout(local_size_x=1, local_size_y=1, local_size_z=1) in;3391layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;3392layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;3393void main()3394{3395uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));3396imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);3397})";33983399constexpr int kWidth1 = 1, kHeight1 = 1, kWidth2 = 2, kHeight2 = 2;3400constexpr GLuint kInputValues1[] = {3};3401constexpr GLuint kInputValues21[] = {2, 2, 2, 2};3402constexpr GLuint kInputValues22[] = {1};34033404glBindTexture(GL_TEXTURE_2D, texture[0]);3405glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth1, kHeight1);3406glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,3407kInputValues1);3408EXPECT_GL_NO_ERROR();34093410glBindTexture(GL_TEXTURE_2D, texture[1]);3411glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth2, kHeight2);3412glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,3413kInputValues21);3414glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,3415kInputValues22);3416EXPECT_GL_NO_ERROR();34173418ANGLE_GL_COMPUTE_PROGRAM(program, kCS);3419glUseProgram(program);34203421glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);3422glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);34233424glDispatchCompute(1, 1, 1);3425EXPECT_GL_NO_ERROR();34263427glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);3428GLuint outputValues;3429constexpr GLuint expectedValue = 3;3430glUseProgram(0);3431glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);34323433glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);3434EXPECT_GL_NO_ERROR();3435glReadPixels(0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValues);3436EXPECT_GL_NO_ERROR();3437EXPECT_EQ(expectedValue, outputValues);3438}34393440// Test that a resource is bound on render pipeline output, and then it's bound as the compute3441// pipeline input. It works well. See http://anglebug.com/36583442TEST_P(ComputeShaderTest, DrawTexture1DispatchTexture2)3443{3444// http://anglebug.com/50723445ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());34463447ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float"));34483449const char kCSSource[] = R"(#version 310 es3450layout(local_size_x=1, local_size_y=1, local_size_z=1) in;3451precision highp sampler2D;3452uniform sampler2D tex;3453layout(rgba32f, binding = 0) writeonly uniform highp image2D image;3454void main()3455{3456vec4 value = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);3457imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(value.x - 1.0, 1.0, 0.0, value.w - 1.0));3458})";34593460const char kVSSource[] = R"(#version 310 es3461layout (location = 0) in vec2 pos;3462out vec2 texCoord;3463void main(void) {3464texCoord = 0.5*pos + 0.5;3465gl_Position = vec4(pos, 0.0, 1.0);3466})";34673468const char kFSSource[] = R"(#version 310 es3469precision highp float;3470uniform sampler2D tex;3471in vec2 texCoord;3472out vec4 fragColor;3473void main(void) {3474fragColor = texture(tex, texCoord);3475})";34763477GLuint aPosLoc = 0;3478ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);3479ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);3480glBindAttribLocation(program, aPosLoc, "pos");3481GLuint buffer;3482glGenBuffers(1, &buffer);3483glBindBuffer(GL_ARRAY_BUFFER, buffer);3484GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};3485glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);3486glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);3487glEnableVertexAttribArray(aPosLoc);34883489constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};3490constexpr GLfloat kZero[4] = {0.0, 0.0, 0.0, 0.0};3491GLFramebuffer framebuffer;3492GLTexture texture[3];3493glBindTexture(GL_TEXTURE_2D, texture[0]);3494glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);3495glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);3496glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);3497glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);34983499glBindTexture(GL_TEXTURE_2D, texture[1]);3500glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);3501glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kZero);3502glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);3503glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);35043505glBindTexture(GL_TEXTURE_2D, texture[2]);3506glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);3507glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kZero);3508glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);3509glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);35103511glUseProgram(program);3512glActiveTexture(GL_TEXTURE0);3513glBindTexture(GL_TEXTURE_2D, texture[0]);3514glUniform1i(glGetUniformLocation(program, "tex"), 0);3515glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);3516glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);3517glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3518EXPECT_GL_NO_ERROR();3519glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);3520GLfloat actual[4];3521glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, actual);3522EXPECT_GL_NO_ERROR();3523EXPECT_EQ(1.0, actual[0]);3524EXPECT_EQ(0.0, actual[1]);3525EXPECT_EQ(0.0, actual[2]);3526EXPECT_EQ(1.0, actual[3]);35273528glUseProgram(csProgram);3529glActiveTexture(GL_TEXTURE0);3530glBindTexture(GL_TEXTURE_2D, texture[1]);3531glUniform1i(glGetUniformLocation(program, "tex"), 0);3532glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);3533glDispatchCompute(1, 1, 1);3534glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);35353536glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);3537glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);3538glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, actual);3539EXPECT_GL_NO_ERROR();3540EXPECT_EQ(0.0, actual[0]);3541EXPECT_EQ(1.0, actual[1]);3542EXPECT_EQ(0.0, actual[2]);3543EXPECT_EQ(0.0, actual[3]);3544}35453546// Test that render pipeline and compute pipeline access to the same texture.3547// Steps:3548// 1. DispatchCompute.3549// 2. DrawArrays.3550TEST_P(ComputeShaderTest, DispatchDraw)3551{3552// http://anglebug.com/50723553ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());35543555const char kCSSource[] = R"(#version 310 es3556layout(local_size_x=1, local_size_y=1, local_size_z=1) in;3557layout(rgba32f, binding = 0) writeonly uniform highp image2D image;3558void main()3559{3560imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));3561})";35623563const char kVSSource[] = R"(#version 310 es3564layout (location = 0) in vec2 pos;3565out vec2 texCoord;3566void main(void) {3567texCoord = 0.5*pos + 0.5;3568gl_Position = vec4(pos, 0.0, 1.0);3569})";35703571const char kFSSource[] = R"(#version 310 es3572precision highp float;3573uniform sampler2D tex;3574in vec2 texCoord;3575out vec4 fragColor;3576void main(void) {3577fragColor = texture(tex, texCoord);3578})";35793580GLuint aPosLoc = 0;3581ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);3582glBindAttribLocation(program, aPosLoc, "pos");3583GLuint buffer;3584glGenBuffers(1, &buffer);3585glBindBuffer(GL_ARRAY_BUFFER, buffer);3586GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};3587glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);3588glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);3589glEnableVertexAttribArray(aPosLoc);35903591constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};3592GLTexture texture;3593glBindTexture(GL_TEXTURE_2D, texture);3594glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);3595glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);3596glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);3597glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);3598EXPECT_GL_NO_ERROR();35993600ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);3601glUseProgram(csProgram);36023603glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);36043605glDispatchCompute(1, 1, 1);3606EXPECT_GL_NO_ERROR();36073608glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);3609glUseProgram(program);3610glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3611EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);3612}36133614// Test that render pipeline and compute pipeline access to the same texture.3615// Steps:3616// 1. DrawArrays.3617// 2. DispatchCompute.3618// 3. DispatchCompute.3619// 4. DrawArrays.3620TEST_P(ComputeShaderTest, DrawDispatchDispatchDraw)3621{3622// http://anglebug.com/50723623ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());36243625// Fails on AMD windows drivers. http://anglebug.com/38713626ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());36273628const char kCSSource[] = R"(#version 310 es3629layout(local_size_x=1, local_size_y=1, local_size_z=1) in;3630layout(rgba32f, binding = 0) writeonly uniform highp image2D image;3631uniform float factor;3632void main()3633{3634imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(factor, 0.0, 1.0, 1.0));3635})";36363637const char kVSSource[] = R"(#version 310 es3638layout (location = 0) in vec2 pos;3639out vec2 texCoord;3640void main(void) {3641texCoord = 0.5*pos + 0.5;3642gl_Position = vec4(pos, 0.0, 1.0);3643})";36443645const char kFSSource[] = R"(#version 310 es3646precision highp float;3647uniform sampler2D tex;3648in vec2 texCoord;3649out vec4 fragColor;3650void main(void) {3651fragColor = texture(tex, texCoord);3652})";36533654GLuint aPosLoc = 0;3655ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);3656glBindAttribLocation(program, aPosLoc, "pos");3657GLuint buffer;3658glGenBuffers(1, &buffer);3659glBindBuffer(GL_ARRAY_BUFFER, buffer);3660GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};3661glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);3662glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);3663glEnableVertexAttribArray(aPosLoc);36643665constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};3666GLTexture texture;3667glBindTexture(GL_TEXTURE_2D, texture);3668glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);3669glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);3670glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);3671glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);3672glUseProgram(program);3673glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3674EXPECT_GL_NO_ERROR();36753676ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);3677glUseProgram(csProgram);3678glUniform1f(glGetUniformLocation(csProgram, "factor"), 0.0);3679glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);3680EXPECT_GL_NO_ERROR();36813682glDispatchCompute(1, 1, 1);3683glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);3684EXPECT_GL_NO_ERROR();36853686glUniform1f(glGetUniformLocation(csProgram, "factor"), 1.0);3687glDispatchCompute(1, 1, 1);3688glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);3689EXPECT_GL_NO_ERROR();36903691glUseProgram(program);3692glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3693EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::magenta);3694}36953696// Test that render pipeline and compute pipeline access to the same texture.3697// Steps:3698// 1. DispatchCompute.3699// 2. DrawArrays.3700// 3. DrawArrays.3701// 4. DispatchCompute.3702TEST_P(ComputeShaderTest, DispatchDrawDrawDispatch)3703{3704// http://anglebug.com/50723705ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());37063707const char kCSSource[] = R"(#version 310 es3708layout(local_size_x=1, local_size_y=1, local_size_z=1) in;3709layout(rgba32f, binding = 0) writeonly uniform highp image2D image;37103711void main()3712{3713imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));3714})";37153716const char kVSSource[] = R"(#version 310 es3717layout (location = 0) in vec2 pos;3718out vec2 texCoord;3719void main(void) {3720texCoord = 0.5*pos + 0.5;3721gl_Position = vec4(pos, 0.0, 1.0);3722})";37233724const char kFSSource[] = R"(#version 310 es3725precision highp float;3726uniform sampler2D tex;3727in vec2 texCoord;3728uniform float factor;3729out vec4 fragColor;3730void main(void) {3731fragColor = texture(tex, texCoord) + vec4(factor, 0.0, 0.0, 0.0);3732})";37333734GLuint aPosLoc = 0;3735ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);3736glBindAttribLocation(program, aPosLoc, "pos");3737GLuint buffer;3738glGenBuffers(1, &buffer);3739glBindBuffer(GL_ARRAY_BUFFER, buffer);3740GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};3741glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);3742glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);3743glEnableVertexAttribArray(aPosLoc);37443745constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};3746GLTexture texture;3747glBindTexture(GL_TEXTURE_2D, texture);3748glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);3749glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);3750glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);3751glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);37523753ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);3754glUseProgram(csProgram);3755glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);37563757glDispatchCompute(1, 1, 1);3758glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);3759EXPECT_GL_NO_ERROR();37603761glUseProgram(program);3762glUniform1f(glGetUniformLocation(program, "factor"), 0.0);3763glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3764EXPECT_GL_NO_ERROR();37653766glUniform1f(glGetUniformLocation(program, "factor"), 1.0);3767glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3768EXPECT_GL_NO_ERROR();37693770glUseProgram(csProgram);3771glDispatchCompute(1, 1, 1);3772glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);3773EXPECT_GL_NO_ERROR();37743775glUseProgram(program);3776glUniform1f(glGetUniformLocation(program, "factor"), 0.0);3777glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3778EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);3779}37803781// Test that invalid memory barrier will produce an error.3782TEST_P(ComputeShaderTest, InvalidMemoryBarrier)3783{3784GLbitfield barriers = 0;3785glMemoryBarrier(barriers);3786EXPECT_GL_ERROR(GL_INVALID_VALUE);3787}37883789// test atomic counter increment3790// http://anglebug.com/32463791TEST_P(ComputeShaderTest, AtomicCounterIncrement)3792{3793constexpr char kComputeShader[] = R"(#version 310 es3794layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;3795layout(binding = 1, std430) buffer Output {3796uint preGet[1];3797uint increment[1];3798uint postGet[1];3799} sb_in;3800layout(binding=0) uniform atomic_uint counter0;38013802void main(void)3803{3804uint id = (gl_GlobalInvocationID.x);3805sb_in.preGet[0u] = atomicCounter(counter0);3806sb_in.increment[0u] = atomicCounterIncrement(counter0);3807sb_in.postGet[0u] = atomicCounter(counter0);3808}3809)";3810ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);3811EXPECT_GL_NO_ERROR();38123813glUseProgram(program);38143815constexpr unsigned int kBytesPerComponent = sizeof(GLuint);38163817GLBuffer shaderStorageBuffer;3818glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);3819glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);3820glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);3821EXPECT_GL_NO_ERROR();38223823constexpr GLuint atomicBufferInitialData[] = {2u};3824GLuint atomicBuffer;3825glGenBuffers(1, &atomicBuffer);3826glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicBuffer);3827glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomicBufferInitialData), atomicBufferInitialData,3828GL_DYNAMIC_DRAW);3829glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicBuffer);3830EXPECT_GL_NO_ERROR();38313832glDispatchCompute(1, 1, 1);3833glFinish();3834EXPECT_GL_NO_ERROR();38353836// read back3837const GLuint *ptr = reinterpret_cast<const GLuint *>(3838glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT));3839EXPECT_EQ(2u, ptr[0]);3840EXPECT_EQ(2u, ptr[1]);3841EXPECT_EQ(3u, ptr[2]);38423843glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);3844}38453846// Create a 'very large' array inside of a function in a compute shader.3847TEST_P(ComputeShaderTest, VeryLargeArrayInsideFunction)3848{3849constexpr char kComputeShader[] = R"(#version 310 es3850layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;3851layout(binding = 0, std430) buffer Output {3852int value[1];3853} output_data;38543855void main()3856{3857int values[1000];3858for (int i = 0; i < values.length(); i++)3859{3860values[i] = 0;3861}38623863int total = 0;3864for (int i = 0; i < values.length(); i++)3865{3866total += i;3867values[i] = total;3868}3869output_data.value[0u] = values[1000-1];3870})";38713872ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);3873EXPECT_GL_NO_ERROR();38743875glUseProgram(program);38763877constexpr unsigned int kBytesPerComponent = sizeof(GLint);38783879GLBuffer shaderStorageBuffer;3880glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);3881glBufferData(GL_SHADER_STORAGE_BUFFER, 1 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);3882glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);3883EXPECT_GL_NO_ERROR();38843885glDispatchCompute(1, 1, 1);3886glFinish();3887EXPECT_GL_NO_ERROR();38883889// read back3890const GLint *ptr = reinterpret_cast<const GLint *>(3891glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 1 * kBytesPerComponent, GL_MAP_READ_BIT));3892EXPECT_EQ(499500, ptr[0]);38933894glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);3895}38963897// Test that render pipeline and compute pipeline access to the same texture.3898// Steps:3899// 1. Clear the texture and DrawArrays.3900// 2. DispatchCompute to set the image's first pixel to a specific color.3901// 3. DrawArrays and check data.3902TEST_P(ComputeShaderTest, DrawDispatchDrawPreserve)3903{3904// http://anglebug.com/50723905ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());39063907const char kCSSource[] = R"(#version 310 es3908layout(local_size_x=1, local_size_y=1) in;3909layout(rgba8, binding = 0) writeonly uniform highp image2D image;3910void main()3911{3912imageStore(image, ivec2(0, 0), vec4(0.0, 0.0, 1.0, 1.0));3913})";39143915const char kVSSource[] = R"(#version 310 es3916layout (location = 0) in vec2 pos;3917in vec4 inTex;3918out vec4 texCoord;3919void main(void) {3920texCoord = inTex;3921gl_Position = vec4(pos, 0.0, 1.0);3922})";39233924const char kFSSource[] = R"(#version 310 es3925precision highp float;3926uniform sampler2D tex;3927in vec4 texCoord;3928out vec4 fragColor;3929void main(void) {3930fragColor = texture(tex, texCoord.xy);3931})";3932GLuint aPosLoc = 0;3933ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);3934glBindAttribLocation(program, aPosLoc, "pos");39353936unsigned char *data = new unsigned char[4 * getWindowWidth() * getWindowHeight()];3937for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)3938{3939data[i * 4] = 0xff;3940data[i * 4 + 1] = 0;3941data[i * 4 + 2] = 0;3942data[i * 4 + 3] = 0xff;3943}3944GLTexture texture;3945glBindTexture(GL_TEXTURE_2D, texture);3946glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, getWindowWidth(), getWindowHeight());3947// Clear the texture level 0 to Red.3948glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA,3949GL_UNSIGNED_BYTE, data);3950for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)3951{3952data[i * 4] = 0;3953data[i * 4 + 1] = 0xff;3954data[i * 4 + 2] = 0;3955data[i * 4 + 3] = 0xff;3956}3957// Clear the texture level 1 to Green.3958glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,3959GL_UNSIGNED_BYTE, data);3960delete[] data;3961glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);3962glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);3963glUseProgram(program);3964GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};3965GLfloat texCoords[] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};3966GLint pos = glGetAttribLocation(program, "pos");3967glEnableVertexAttribArray(pos);3968glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);3969GLint posTex = glGetAttribLocation(program, "inTex");3970glEnableVertexAttribArray(posTex);3971glVertexAttribPointer(posTex, 2, GL_FLOAT, GL_FALSE, 0, texCoords);39723973// Draw with level 0, the whole framebuffer should be Red.3974glViewport(0, 0, getWindowWidth(), getWindowHeight());3975glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3976EXPECT_GL_NO_ERROR();3977EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);3978EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);3979EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);3980// Draw with level 1, a quarter of the framebuffer should be Green.3981glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);3982glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);3983EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);3984EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);3985EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);39863987// Clear the texture level 0's (0, 0) position to Blue.3988glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);3989ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);3990glUseProgram(csProgram);3991glDispatchCompute(1, 1, 1);3992glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);3993EXPECT_GL_NO_ERROR();3994glFinish();39953996glUseProgram(program);3997// Draw with level 0, the first position should be Blue.3998glViewport(0, 0, getWindowWidth(), getWindowHeight());3999glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);4000EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);4001EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);4002EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);4003// Draw with level 1, a quarter of the framebuffer should be Green.4004glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);4005glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);4006EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);4007EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);4008EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);4009}40104011// Test that maxComputeWorkGroupCount is valid number.4012TEST_P(ComputeShaderTest, ValidateMaxComputeWorkGroupCount)4013{4014constexpr char kCS[] = R"(#version 310 es4015layout(local_size_x=1) in;4016void main()4017{4018})";40194020GLuint program = glCreateProgram();4021GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);4022EXPECT_NE(0u, cs);40234024glAttachShader(program, cs);4025glDeleteShader(cs);40264027GLint x, y, z;4028glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &x);4029EXPECT_LE(65535, x);4030EXPECT_GE(std::numeric_limits<GLint>::max(), x);40314032glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &y);4033EXPECT_LE(65535, y);4034EXPECT_GE(std::numeric_limits<GLint>::max(), y);40354036glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &z);4037EXPECT_LE(65535, z);4038EXPECT_GE(std::numeric_limits<GLint>::max(), z);40394040glDeleteProgram(program);4041EXPECT_GL_NO_ERROR();4042}40434044// Validate that on Vulkan, compute pipeline driver uniforms descriptor set is updated after an4045// internal compute-based UtilsVk function is used. The latter is achieved through a draw with a4046// vertex buffer whose format is not natively supported. Atomic counters are used to make sure the4047// compute pipeline uses the driver uniforms descriptor set.4048TEST_P(ComputeShaderTest, DispatchConvertVertexDispatch)4049{4050ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_vertex_type_10_10_10_2"));40514052constexpr uint32_t kVertexCount = 6;40534054constexpr char kCS[] = R"(#version 310 es4055layout(local_size_x=6, local_size_y=1, local_size_z=1) in;40564057layout(binding = 0) uniform atomic_uint ac;40584059layout(binding=0, std140) buffer VertexData4060{4061uint data[];4062};40634064void main()4065{4066atomicCounterIncrement(ac);4067data[gl_GlobalInvocationID.x] = gl_GlobalInvocationID.x;4068})";40694070constexpr char kVS[] = R"(#version 310 es4071precision mediump float;40724073layout(location = 0) in vec4 position;4074layout(location = 1) in uvec4 data;40754076out vec4 color;40774078void main() {4079color = data.x < 6u && data.y == 0u && data.z == 0u && data.w == 0u4080? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);4081gl_Position = position;4082})";40834084constexpr char kFS[] = R"(#version 310 es4085precision mediump float;4086in vec4 color;4087out vec4 colorOut;4088void main() {4089colorOut = color;4090})";40914092ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);4093ANGLE_GL_PROGRAM(programVSFS, kVS, kFS);4094EXPECT_GL_NO_ERROR();40954096// Create atomic counter buffer4097GLBuffer atomicCounterBuffer;4098constexpr GLuint kInitialAcbData = 0;4099glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);4100glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kInitialAcbData), &kInitialAcbData,4101GL_STATIC_DRAW);4102glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);4103EXPECT_GL_NO_ERROR();41044105// Create vertex buffer4106constexpr unsigned kVertexBufferInitData[kVertexCount] = {};4107GLBuffer vertexBuffer;4108glBindBuffer(GL_SHADER_STORAGE_BUFFER, vertexBuffer);4109glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kVertexBufferInitData), kVertexBufferInitData,4110GL_STATIC_DRAW);4111glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vertexBuffer);4112EXPECT_GL_NO_ERROR();41134114// Create position buffer4115constexpr GLfloat positions[kVertexCount * 2] = {1.0, 1.0, -1.0, 1.0, -1.0, -1.0,41161.0, 1.0, -1.0, -1.0, 1.0, -1.0};4117GLBuffer positionBuffer;4118glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);4119glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);4120EXPECT_GL_NO_ERROR();41214122// Create vertex array4123GLVertexArray vao;4124glBindVertexArray(vao);41254126glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);4127glEnableVertexAttribArray(0);4128glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);41294130glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);4131glEnableVertexAttribArray(1);4132glVertexAttribPointer(1, 4, GL_UNSIGNED_INT_10_10_10_2_OES, false, 0, 0);4133EXPECT_GL_NO_ERROR();41344135// Fill the vertex buffer with a dispatch call4136glUseProgram(programCS);4137glDispatchCompute(1, 1, 1);4138EXPECT_GL_NO_ERROR();41394140glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);41414142// Draw using the vertex buffer, causing vertex format conversion in compute (in the Vulkan4143// backend)4144glUseProgram(programVSFS);4145glBindVertexArray(vao);4146glDrawArrays(GL_TRIANGLES, 0, kVertexCount);4147EXPECT_GL_NO_ERROR();41484149// Issue another dispatch call. The driver uniforms descriptor set must be rebound.4150glUseProgram(programCS);4151glDispatchCompute(1, 1, 1);4152EXPECT_GL_NO_ERROR();41534154glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);41554156// Verify that the atomic counter has the expected value.4157glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);4158GLuint *mappedBuffer = static_cast<GLuint *>(4159glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));4160EXPECT_EQ(kVertexCount * 2, mappedBuffer[0]);4161glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);4162}41634164// Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is4165// made. Blit stencil may issue a dispatch call.4166TEST_P(ComputeShaderTest, DispatchBlitStencilDispatch)4167{4168// http://anglebug.com/55334169ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());41704171// http://anglebug.com/50724172ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());41734174constexpr GLsizei kSize = 1;41754176constexpr char kCS[] = R"(#version 310 es4177layout(local_size_x=6, local_size_y=1, local_size_z=1) in;41784179uniform vec4 data;41804181layout(rgba8, binding = 0) writeonly uniform highp image2D image;41824183void main()4184{4185imageStore(image, ivec2(gl_LocalInvocationID.xy), data);4186})";41874188ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);4189EXPECT_GL_NO_ERROR();41904191// Create a framebuffer with stencil buffer. Use multisampled textures so the future blit4192// cannot use vkCmdBlitImage.4193GLTexture color;4194glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color);4195glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true);41964197GLTexture depthStencil;4198glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, depthStencil);4199glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_DEPTH24_STENCIL8, kSize, kSize,4200true);42014202GLFramebuffer fbo;4203glBindFramebuffer(GL_FRAMEBUFFER, fbo);4204glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color,42050);4206glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,4207depthStencil, 0);4208ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);4209ASSERT_GL_NO_ERROR();42104211// Clear the stencil and make sure it's done.4212glClearColor(1.0f, 1.0f, 1.0f, 1.0f);4213glClearStencil(0x55);4214glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);42154216glEnable(GL_STENCIL_TEST);4217glStencilFunc(GL_EQUAL, 0x55, 0xFF);4218glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);4219glStencilMask(0xFF);42204221ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());4222drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);4223ASSERT_GL_NO_ERROR();42244225GLTexture colorCopy;4226glBindTexture(GL_TEXTURE_2D, colorCopy);4227glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);42284229GLFramebuffer copyFbo;4230glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);4231glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorCopy, 0);4232ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);4233glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);4234ASSERT_GL_NO_ERROR();42354236glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFbo);4237EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);42384239glBindFramebuffer(GL_FRAMEBUFFER, fbo);42404241// Setup image for compute call4242GLTexture computeOut;4243glBindTexture(GL_TEXTURE_2D, computeOut);4244glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);4245glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);4246ASSERT_GL_NO_ERROR();42474248// Issue a dispatch call.4249glUseProgram(programCS);4250GLint uniformLoc = glGetUniformLocation(programCS, "data");4251ASSERT_NE(uniformLoc, -1);42524253glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);4254glDispatchCompute(1, 1, 1);4255glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);4256ASSERT_GL_NO_ERROR();42574258// Blit the stencil texture. This may use a compute shader internally.4259GLTexture depthStencilCopy;4260glBindTexture(GL_TEXTURE_2D, depthStencilCopy);4261glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);4262ASSERT_GL_NO_ERROR();42634264glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);4265glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,4266depthStencilCopy, 0);4267ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);4268ASSERT_GL_NO_ERROR();42694270glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_STENCIL_BUFFER_BIT, GL_NEAREST);4271ASSERT_GL_NO_ERROR();42724273// Issue another dispatch call.4274glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);4275glDispatchCompute(1, 1, 1);4276ASSERT_GL_NO_ERROR();42774278// Verify the results.4279glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);4280glBindFramebuffer(GL_FRAMEBUFFER, copyFbo);4281glBindTexture(GL_TEXTURE_2D, computeOut);4282glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);4283ASSERT_GL_NO_ERROR();42844285EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);42864287// Verify the blit copy results.4288drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);4289ASSERT_GL_NO_ERROR();42904291EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);4292}42934294// Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is4295// made. Generate mipmap may issue a dispatch call.4296TEST_P(ComputeShaderTest, DispatchGenerateMipmapDispatch)4297{4298constexpr GLsizei kSize = 8;42994300constexpr char kCS[] = R"(#version 310 es4301layout(local_size_x=6, local_size_y=1, local_size_z=1) in;43024303uniform vec4 data;43044305layout(rgba8, binding = 0) writeonly uniform highp image2D image;43064307void main()4308{4309imageStore(image, ivec2(gl_LocalInvocationID.xy), data);4310})";43114312ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);4313EXPECT_GL_NO_ERROR();43144315GLTexture color;4316glBindTexture(GL_TEXTURE_2D, color);4317glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, kSize, kSize);43184319const std::vector<GLColor> kInitialColor(kSize * kSize, GLColor::green);4320glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,4321kInitialColor.data());43224323// Setup image for compute call4324GLTexture computeOut;4325glBindTexture(GL_TEXTURE_2D, computeOut);4326glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);4327glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);4328ASSERT_GL_NO_ERROR();43294330// Issue a dispatch call.4331glUseProgram(programCS);4332GLint uniformLoc = glGetUniformLocation(programCS, "data");4333ASSERT_NE(uniformLoc, -1);43344335glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);4336glDispatchCompute(1, 1, 1);4337glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);4338ASSERT_GL_NO_ERROR();43394340// Generate mipmap on the texture. This may use a compute shader internally.4341glBindTexture(GL_TEXTURE_2D, color);4342glGenerateMipmap(GL_TEXTURE_2D);43434344// Issue another dispatch call.4345glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);4346glDispatchCompute(1, 1, 1);4347ASSERT_GL_NO_ERROR();43484349// Verify the results.4350GLFramebuffer fbo;4351glBindFramebuffer(GL_FRAMEBUFFER, fbo);4352glBindTexture(GL_TEXTURE_2D, computeOut);4353glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);4354ASSERT_GL_NO_ERROR();43554356glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);4357EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);4358}43594360// Write to image array with an aliasing format.4361TEST_P(ComputeShaderTest, AliasingFormatForImageArray)4362{4363// http://anglebug.com/53524364ANGLE_SKIP_TEST_IF(IsD3D11());43654366constexpr char kCS[] = R"(#version 310 es4367layout(local_size_x=1, local_size_y=1, local_size_z=2) in;4368layout(r32ui, binding = 0) writeonly uniform highp uimage2DArray image;4369void main()4370{4371uint yellow = 0xFF00FFFFu;4372imageStore(image, ivec3(gl_LocalInvocationID.xyz), uvec4(yellow, 0, 0, 0));4373})";43744375constexpr int kWidth = 1, kHeight = 1, kDepth = 2;43764377const std::vector<GLColor> kInitData(kWidth * kHeight * kDepth, GLColor::black);43784379GLTexture texture;4380glBindTexture(GL_TEXTURE_2D_ARRAY, texture);4381glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, kDepth);4382glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,4383GL_UNSIGNED_BYTE, kInitData.data());4384EXPECT_GL_NO_ERROR();43854386ANGLE_GL_COMPUTE_PROGRAM(program, kCS);4387glUseProgram(program);43884389// Output yellow to both layers.4390glBindImageTexture(0, texture, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);4391glDispatchCompute(1, 1, 1);4392EXPECT_GL_NO_ERROR();43934394// Verify results.4395glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);4396EXPECT_GL_NO_ERROR();43974398GLFramebuffer framebuffer;4399glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);4400glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0);4401glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture, 0, 1);4402EXPECT_GL_NO_ERROR();44034404glReadBuffer(GL_COLOR_ATTACHMENT0);4405EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);44064407glReadBuffer(GL_COLOR_ATTACHMENT1);4408EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);4409}44104411// Write to one layer of image array with an aliasing format.4412TEST_P(ComputeShaderTest, AliasingFormatForOneLayerOfImageArray)4413{4414// http://anglebug.com/53524415ANGLE_SKIP_TEST_IF(IsD3D11());44164417constexpr char kCS[] = R"(#version 310 es4418layout(local_size_x=1, local_size_y=1, local_size_z=1) in;4419layout(r32ui, binding = 0) writeonly uniform highp uimage2D image;4420void main()4421{4422uint yellow = 0xFF00FFFFu;4423imageStore(image, ivec2(gl_LocalInvocationID.xy), uvec4(yellow, 0, 0, 0));4424})";44254426constexpr int kWidth = 1, kHeight = 1, kDepth = 2;44274428const std::vector<GLColor> kInitData(kWidth * kHeight * kDepth, GLColor::black);44294430GLTexture texture;4431glBindTexture(GL_TEXTURE_2D_ARRAY, texture);4432glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, kDepth);4433glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,4434GL_UNSIGNED_BYTE, kInitData.data());4435EXPECT_GL_NO_ERROR();44364437GLFramebuffer framebuffer;4438glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);4439glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0);4440glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture, 0, 1);4441EXPECT_GL_NO_ERROR();44424443ANGLE_GL_COMPUTE_PROGRAM(program, kCS);4444glUseProgram(program);44454446// Output yellow to layer 0.4447glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);4448glDispatchCompute(1, 1, 1);4449EXPECT_GL_NO_ERROR();44504451// Verify that only layer 0 was changed.4452glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);4453EXPECT_GL_NO_ERROR();44544455glReadBuffer(GL_COLOR_ATTACHMENT0);4456EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);44574458glReadBuffer(GL_COLOR_ATTACHMENT1);4459EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);44604461// Reset texture back to black.4462glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,4463GL_UNSIGNED_BYTE, kInitData.data());44644465// Output yellow to layer 1.4466glBindImageTexture(0, texture, 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);4467glDispatchCompute(1, 1, 1);4468EXPECT_GL_NO_ERROR();44694470// Verify that only layer 1 was changed.4471glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);4472EXPECT_GL_NO_ERROR();44734474glReadBuffer(GL_COLOR_ATTACHMENT0);4475EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);44764477glReadBuffer(GL_COLOR_ATTACHMENT1);4478EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);4479}44804481// Test glMemoryBarrier(CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT) by writing to persistenly mapped4482// buffer from a compute shader.4483TEST_P(ComputeShaderTest, WriteToPersistentBuffer)4484{4485ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));44864487constexpr char kCS[] = R"(#version 310 es4488layout(local_size_x=1, local_size_y=1, local_size_z=1) in;4489layout(std140, binding = 0) buffer block {4490uvec4 data;4491} outBlock;4492void main()4493{4494outBlock.data += uvec4(1);4495})";44964497ANGLE_GL_COMPUTE_PROGRAM(program, kCS);4498glUseProgram(program);44994500constexpr std::array<uint32_t, 4> kInitData = {};45014502GLBuffer coherentBuffer;4503glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);4504glBufferStorageEXT(4505GL_SHADER_STORAGE_BUFFER, sizeof(kInitData), kInitData.data(),4506GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);45074508GLBuffer nonCoherentBuffer;4509glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);4510glBufferStorageEXT(GL_SHADER_STORAGE_BUFFER, sizeof(kInitData), kInitData.data(),4511GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);45124513// Map the buffers for read and write.4514glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);4515uint32_t *coherentMapped = reinterpret_cast<uint32_t *>(glMapBufferRange(4516GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitData),4517GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT));4518ASSERT_GL_NO_ERROR();45194520glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);4521uint32_t *nonCoherentMapped = reinterpret_cast<uint32_t *>(4522glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitData),4523GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT));4524ASSERT_GL_NO_ERROR();45254526constexpr std::array<uint32_t, 4> kCoherentExpectedData = {45270x12354678u,45280x2468ACE0u,45290x13579BDFu,45300x76543210u,4531};45324533constexpr std::array<uint32_t, 4> kNonCoherentExpectedData = {45340x9ABCDEF0u,45350xFDB97531u,45360x1F2E3D4Bu,45370x5A697887u,4538};45394540coherentMapped[0] = kCoherentExpectedData[0] - 1;4541coherentMapped[1] = kCoherentExpectedData[1] - 1;4542coherentMapped[2] = kCoherentExpectedData[2] - 1;4543coherentMapped[3] = kCoherentExpectedData[3] - 1;45444545nonCoherentMapped[0] = kNonCoherentExpectedData[0] - 1;4546nonCoherentMapped[1] = kNonCoherentExpectedData[1] - 1;4547nonCoherentMapped[2] = kNonCoherentExpectedData[2] - 1;4548nonCoherentMapped[3] = kNonCoherentExpectedData[3] - 1;45494550// Test coherent write4551glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, coherentBuffer);4552glDispatchCompute(1, 1, 1);4553EXPECT_GL_NO_ERROR();45544555glFinish();4556EXPECT_EQ(coherentMapped[0], kCoherentExpectedData[0]);4557EXPECT_EQ(coherentMapped[1], kCoherentExpectedData[1]);4558EXPECT_EQ(coherentMapped[2], kCoherentExpectedData[2]);4559EXPECT_EQ(coherentMapped[3], kCoherentExpectedData[3]);45604561// Test non-coherent write4562glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, nonCoherentBuffer);4563glDispatchCompute(1, 1, 1);45644565glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT);4566EXPECT_GL_NO_ERROR();45674568glFinish();4569EXPECT_EQ(nonCoherentMapped[0], kNonCoherentExpectedData[0]);4570EXPECT_EQ(nonCoherentMapped[1], kNonCoherentExpectedData[1]);4571EXPECT_EQ(nonCoherentMapped[2], kNonCoherentExpectedData[2]);4572EXPECT_EQ(nonCoherentMapped[3], kNonCoherentExpectedData[3]);45734574glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);4575glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);4576glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);4577glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);4578EXPECT_GL_NO_ERROR();4579}45804581GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTest);4582ANGLE_INSTANTIATE_TEST_ES31_AND(ComputeShaderTest, WithDirectSPIRVGeneration(ES31_VULKAN()));45834584GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTestES3);4585ANGLE_INSTANTIATE_TEST_ES3(ComputeShaderTestES3);45864587GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ComputeTest);4588ANGLE_INSTANTIATE_TEST_ES31(WebGL2ComputeTest);4589} // namespace459045914592