Commit 6dfdca83 by Xinghua Cao Committed by Commit Bot

ES31: support compute shader sampling on D3D backend

BUG=angleproject:2756 TEST=angle_end2end_tests.ComputeShaderTest.SamplingAndImageReadWrite/ES3_1_D3D11 Change-Id: I8f112227c5703fcaafffbd2262e6a039f869c483 Reviewed-on: https://chromium-review.googlesource.com/1161754 Commit-Queue: Xinghua Cao <xinghua.cao@intel.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 24507bc7
......@@ -560,8 +560,8 @@ ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
mUsesFlatInterpolation(false),
mUsedShaderSamplerRanges({}),
mDirtySamplerMapping(true),
mUsedComputeImageRange(0),
mUsedComputeReadonlyImageRange(0),
mUsedComputeImageRange(0, 0),
mUsedComputeReadonlyImageRange(0, 0),
mSerial(issueSerial())
{
mDynamicHLSL = new DynamicHLSL(renderer);
......@@ -640,7 +640,7 @@ gl::TextureType ProgramD3D::getSamplerTextureType(gl::ShaderType type,
return samplers[samplerIndex].textureType;
}
GLuint ProgramD3D::getUsedSamplerRange(gl::ShaderType type) const
gl::RangeUI ProgramD3D::getUsedSamplerRange(gl::ShaderType type) const
{
ASSERT(type != gl::ShaderType::InvalidEnum);
return mUsedShaderSamplerRanges[type];
......@@ -722,7 +722,7 @@ GLint ProgramD3D::getImageMapping(gl::ShaderType type,
return -1;
}
GLuint ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
gl::RangeUI ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
{
switch (type)
{
......@@ -731,7 +731,7 @@ GLuint ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
// TODO(xinghua.cao@intel.com): add image range of vertex shader and pixel shader.
default:
UNREACHABLE();
return 0u;
return {0, 0};
}
}
......@@ -778,7 +778,10 @@ gl::LinkResult ProgramD3D::load(const gl::Context *context,
mShaderSamplers[shaderType].push_back(sampler);
}
stream->readInt(&mUsedShaderSamplerRanges[shaderType]);
unsigned int samplerRangeLow, samplerRangeHigh;
stream->readInt(&samplerRangeLow);
stream->readInt(&samplerRangeHigh);
mUsedShaderSamplerRanges[shaderType] = gl::RangeUI(samplerRangeLow, samplerRangeHigh);
}
const unsigned int csImageCount = stream->readInt<unsigned int>();
......@@ -799,8 +802,15 @@ gl::LinkResult ProgramD3D::load(const gl::Context *context,
mReadonlyImagesCS.push_back(image);
}
stream->readInt(&mUsedComputeImageRange);
stream->readInt(&mUsedComputeReadonlyImageRange);
unsigned int computeImageRangeLow, computeImageRangeHigh, computeReadonlyImageRangeLow,
computeReadonlyImageRangeHigh;
stream->readInt(&computeImageRangeLow);
stream->readInt(&computeImageRangeHigh);
stream->readInt(&computeReadonlyImageRangeLow);
stream->readInt(&computeReadonlyImageRangeHigh);
mUsedComputeImageRange = gl::RangeUI(computeImageRangeLow, computeImageRangeHigh);
mUsedComputeReadonlyImageRange =
gl::RangeUI(computeReadonlyImageRangeLow, computeReadonlyImageRangeHigh);
const unsigned int uniformCount = stream->readInt<unsigned int>();
if (stream->error())
......@@ -1036,7 +1046,8 @@ void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream
stream->writeEnum(mShaderSamplers[shaderType][i].textureType);
}
stream->writeInt(mUsedShaderSamplerRanges[shaderType]);
stream->writeInt(mUsedShaderSamplerRanges[shaderType].low());
stream->writeInt(mUsedShaderSamplerRanges[shaderType].high());
}
stream->writeInt(mImagesCS.size());
......@@ -1053,8 +1064,10 @@ void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream
stream->writeInt(mReadonlyImagesCS[i].logicalImageUnit);
}
stream->writeInt(mUsedComputeImageRange);
stream->writeInt(mUsedComputeReadonlyImageRange);
stream->writeInt(mUsedComputeImageRange.low());
stream->writeInt(mUsedComputeImageRange.high());
stream->writeInt(mUsedComputeReadonlyImageRange.low());
stream->writeInt(mUsedComputeReadonlyImageRange.high());
stream->writeInt(mD3DUniforms.size());
for (const D3DUniform *uniform : mD3DUniforms)
......@@ -2028,6 +2041,11 @@ void ProgramD3D::defineUniformsAndAssignRegisters()
}
assignAllSamplerRegisters();
// Samplers and readonly images share shader input resource slot, adjust low value of
// readonly image range.
mUsedComputeReadonlyImageRange =
gl::RangeUI(mUsedShaderSamplerRanges[gl::ShaderType::Compute].high(),
mUsedShaderSamplerRanges[gl::ShaderType::Compute].high());
assignAllImageRegisters();
initializeUniformStorage(attachedShaders);
}
......@@ -2315,7 +2333,7 @@ void ProgramD3D::setUniformMatrixfvInternal(GLint location,
GLboolean transpose,
const GLfloat *value)
{
D3DUniform *targetUniform = getD3DUniformFromLocation(location);
D3DUniform *targetUniform = getD3DUniformFromLocation(location);
const gl::VariableLocation &uniformLocation = mState.getUniformLocations()[location];
unsigned int arrayElementOffset = uniformLocation.arrayIndex;
unsigned int elementCount = targetUniform->getArraySizeProduct();
......@@ -2390,9 +2408,11 @@ void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
const gl::UniformTypeInfo &typeInfo,
unsigned int samplerCount,
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange)
gl::RangeUI *outUsedRange)
{
unsigned int samplerIndex = startSamplerIndex;
unsigned int low = outUsedRange->low();
unsigned int high = outUsedRange->high();
do
{
......@@ -2401,9 +2421,13 @@ void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
sampler->active = true;
sampler->textureType = gl::FromGLenum<gl::TextureType>(typeInfo.textureType);
sampler->logicalTextureUnit = 0;
*outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
low = std::min(samplerIndex, low);
high = std::max(samplerIndex + 1, high);
samplerIndex++;
} while (samplerIndex < startSamplerIndex + samplerCount);
ASSERT(low < high);
*outUsedRange = gl::RangeUI(low, high);
}
void ProgramD3D::assignAllImageRegisters()
......@@ -2469,9 +2493,12 @@ void ProgramD3D::AssignImages(unsigned int startImageIndex,
int startLogicalImageUnit,
unsigned int imageCount,
std::vector<Image> &outImages,
GLuint *outUsedRange)
gl::RangeUI *outUsedRange)
{
unsigned int imageIndex = startImageIndex;
unsigned int low = outUsedRange->low();
unsigned int high = outUsedRange->high();
// If declare without a binding qualifier, any uniform image variable (include all elements of
// unbound image array) shoud be bound to unit zero.
if (startLogicalImageUnit == -1)
......@@ -2480,7 +2507,10 @@ void ProgramD3D::AssignImages(unsigned int startImageIndex,
Image *image = &outImages[imageIndex];
image->active = true;
image->logicalImageUnit = 0;
*outUsedRange = std::max(imageIndex + 1, *outUsedRange);
low = std::min(imageIndex, low);
high = std::max(imageIndex + 1, high);
ASSERT(low < high);
*outUsedRange = gl::RangeUI(low, high);
return;
}
......@@ -2491,10 +2521,14 @@ void ProgramD3D::AssignImages(unsigned int startImageIndex,
Image *image = &outImages[imageIndex];
image->active = true;
image->logicalImageUnit = logcalImageUnit;
*outUsedRange = std::max(imageIndex + 1, *outUsedRange);
low = std::min(imageIndex, low);
high = std::max(imageIndex + 1, high);
imageIndex++;
logcalImageUnit++;
} while (imageIndex < startImageIndex + imageCount);
ASSERT(low < high);
*outUsedRange = gl::RangeUI(low, high);
}
void ProgramD3D::reset()
......@@ -2534,10 +2568,10 @@ void ProgramD3D::reset()
mImagesCS.clear();
mReadonlyImagesCS.clear();
mUsedShaderSamplerRanges.fill(0);
mUsedShaderSamplerRanges.fill({0, 0});
mDirtySamplerMapping = true;
mUsedComputeImageRange = 0;
mUsedComputeReadonlyImageRange = 0;
mUsedComputeImageRange = {0, 0};
mUsedComputeReadonlyImageRange = {0, 0};
mAttribLocationToD3DSemantic.fill(-1);
......@@ -2684,9 +2718,9 @@ void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyi
for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
{
const auto &registerInfo = registerInfos[registerIndex];
const auto &varying = *registerInfo.packedVarying->varying;
GLenum transposedType = gl::TransposeMatrixType(varying.type);
int componentCount = gl::VariableColumnCount(transposedType);
const auto &varying = *registerInfo.packedVarying->varying;
GLenum transposedType = gl::TransposeMatrixType(varying.type);
int componentCount = gl::VariableColumnCount(transposedType);
ASSERT(!varying.isBuiltIn() && !varying.isStruct());
// There can be more than one register assigned to a particular varying, and each
......
......@@ -156,7 +156,7 @@ class ProgramD3D : public ProgramImpl
unsigned int samplerIndex,
const gl::Caps &caps) const;
gl::TextureType getSamplerTextureType(gl::ShaderType type, unsigned int samplerIndex) const;
GLuint getUsedSamplerRange(gl::ShaderType type) const;
gl::RangeUI getUsedSamplerRange(gl::ShaderType type) const;
enum SamplerMapping
{
......@@ -170,7 +170,7 @@ class ProgramD3D : public ProgramImpl
unsigned int imageIndex,
bool readonly,
const gl::Caps &caps) const;
GLuint getUsedImageRange(gl::ShaderType type, bool readonly) const;
gl::RangeUI getUsedImageRange(gl::ShaderType type, bool readonly) const;
bool usesPointSize() const { return mUsesPointSize; }
bool usesPointSpriteEmulation() const;
......@@ -421,7 +421,7 @@ class ProgramD3D : public ProgramImpl
const gl::UniformTypeInfo &typeInfo,
unsigned int samplerCount,
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange);
gl::RangeUI *outUsedRange);
void assignAllImageRegisters();
void assignImageRegisters(size_t uniformIndex);
......@@ -429,7 +429,7 @@ class ProgramD3D : public ProgramImpl
int startLogicalImageUnit,
unsigned int imageCount,
std::vector<Image> &outImages,
GLuint *outUsedRange);
gl::RangeUI *outUsedRange);
template <typename DestT>
void getUniformInternal(GLint location, DestT *dataOut) const;
......@@ -500,13 +500,13 @@ class ProgramD3D : public ProgramImpl
gl::ShaderMap<std::unique_ptr<UniformStorageD3D>> mShaderUniformStorages;
gl::ShaderMap<std::vector<Sampler>> mShaderSamplers;
gl::ShaderMap<GLuint> mUsedShaderSamplerRanges;
gl::ShaderMap<gl::RangeUI> mUsedShaderSamplerRanges;
bool mDirtySamplerMapping;
std::vector<Image> mImagesCS;
std::vector<Image> mReadonlyImagesCS;
GLuint mUsedComputeImageRange;
GLuint mUsedComputeReadonlyImageRange;
gl::RangeUI mUsedComputeImageRange;
gl::RangeUI mUsedComputeReadonlyImageRange;
// Cache for pixel shader output layout to save reallocations.
std::vector<GLenum> mPixelShaderOutputLayoutCache;
......
......@@ -289,7 +289,8 @@ class StateManager11 final : angle::NonCopyable
angle::Result syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode);
angle::Result syncTextures(const gl::Context *context);
angle::Result applyTextures(const gl::Context *context, gl::ShaderType shaderType);
angle::Result applyTexturesForSamplers(const gl::Context *context, gl::ShaderType shaderType);
angle::Result applyTexturesForImages(const gl::Context *context, gl::ShaderType shaderType);
angle::Result syncTexturesForCompute(const gl::Context *context);
angle::Result setSamplerState(const gl::Context *context,
......@@ -297,11 +298,11 @@ class StateManager11 final : angle::NonCopyable
int index,
gl::Texture *texture,
const gl::SamplerState &sampler);
angle::Result setTexture(const gl::Context *context,
gl::ShaderType type,
int index,
gl::Texture *texture,
const gl::SamplerState &sampler);
angle::Result setTextureForSampler(const gl::Context *context,
gl::ShaderType type,
int index,
gl::Texture *texture,
const gl::SamplerState &sampler);
angle::Result setTextureForImage(const gl::Context *context,
gl::ShaderType type,
int index,
......
......@@ -3098,8 +3098,9 @@ angle::Result Renderer9::applyTextures(const gl::Context *context, gl::ShaderTyp
// TODO(jmadill): Use the Program's sampler bindings.
const gl::ActiveTexturePointerArray &activeTextures = glState.getActiveTexturesCache();
unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
const gl::RangeUI samplerRange = programD3D->getUsedSamplerRange(shaderType);
for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
samplerIndex++)
{
GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
ASSERT(textureUnit != -1);
......@@ -3137,7 +3138,7 @@ angle::Result Renderer9::applyTextures(const gl::Context *context, gl::ShaderTyp
: caps.maxShaderTextureImageUnits[gl::ShaderType::Vertex];
// TODO(jmadill): faster way?
for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
for (size_t samplerIndex = samplerRange.high(); samplerIndex < samplerCount; samplerIndex++)
{
ANGLE_TRY(setTexture(context, shaderType, static_cast<int>(samplerIndex), nullptr));
}
......
......@@ -654,6 +654,76 @@ TEST_P(ComputeShaderTest, TextureSampling)
EXPECT_GL_NO_ERROR();
}
// Test mixed use of sampler and image.
TEST_P(ComputeShaderTest, SamplingAndImageReadWrite)
{
GLTexture texture[3];
GLFramebuffer framebuffer;
const std::string csSource =
R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
precision highp usampler2D;
uniform usampler2D tex;
void main()
{
uvec4 value_1 = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
uvec4 value_2 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value_1 + value_2);
})";
constexpr int kWidth = 1, kHeight = 1;
constexpr GLuint kInputValues[3][1] = {{50}, {100}, {20}};
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
kInputValues[0]);
glBindTexture(GL_TEXTURE_2D, texture[2]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
kInputValues[2]);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
kInputValues[1]);
EXPECT_GL_NO_ERROR();
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
glUseProgram(program.get());
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glDispatchCompute(1, 1, 1);
EXPECT_GL_NO_ERROR();
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
GLuint outputValues[kWidth * kHeight];
constexpr GLuint expectedValue = 150;
glUseProgram(0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
EXPECT_GL_NO_ERROR();
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
EXPECT_GL_NO_ERROR();
for (int i = 0; i < kWidth * kHeight; i++)
{
EXPECT_EQ(expectedValue, outputValues[i]);
}
}
// Use image uniform to read and write Texture2D in compute shader, and verify the contents.
TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment