Commit 155bfd11 by Qin Jiajia Committed by Commit Bot

Fix that same resource is bound on SRV and UAV simultaneously

This change makes sure that resource being set to UnorderedAccessView slot is not bound on ShaderResourceView and resource being set to shader resource slot is not bound on UnorderedAccessView. Bug: angleproject:2768 Change-Id: I52fc5bf5e76ccf8be61c59b2195459728f95e536 Reviewed-on: https://chromium-review.googlesource.com/1201324Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jiajia Qin <jiajia.qin@intel.com>
parent 73599543
......@@ -728,7 +728,10 @@ gl::RangeUI ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) co
{
case gl::ShaderType::Compute:
return readonly ? mUsedComputeReadonlyImageRange : mUsedComputeImageRange;
// TODO(xinghua.cao@intel.com): add image range of vertex shader and pixel shader.
// TODO(xinghua.cao@intel.com): add real image range of vertex shader and pixel shader.
case gl::ShaderType::Vertex:
case gl::ShaderType::Fragment:
return {0, 0};
default:
UNREACHABLE();
return {0, 0};
......
......@@ -665,6 +665,12 @@ void StateManager11::setUnorderedAccessViewInternal(gl::ShaderType shaderType,
{
auto deviceContext = mRenderer->getDeviceContext();
ID3D11UnorderedAccessView *uavPtr = uav ? uav->get() : nullptr;
// We need to make sure that resource being set to UnorderedAccessView slot |resourceSlot|
// is not bound on SRV.
if (uavPtr && unsetConflictingView(uavPtr))
{
mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
}
deviceContext->CSSetUnorderedAccessViews(resourceSlot, 1, &uavPtr, nullptr);
mCurComputeUAVs.update(resourceSlot, uavPtr);
......@@ -1661,7 +1667,8 @@ bool StateManager11::unsetConflictingView(ID3D11View *view)
{
uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
return unsetConflictingSRVs(gl::ShaderType::Vertex, resource, nullptr) ||
unsetConflictingSRVs(gl::ShaderType::Fragment, resource, nullptr);
unsetConflictingSRVs(gl::ShaderType::Fragment, resource, nullptr) ||
unsetConflictingSRVs(gl::ShaderType::Compute, resource, nullptr);
}
bool StateManager11::unsetConflictingSRVs(gl::ShaderType shaderType,
......@@ -2362,80 +2369,15 @@ void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect)
mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
}
// For each Direct3D sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive).
// Sampler mapping needs to be up-to-date on the program object before this is called.
angle::Result StateManager11::applyTexturesForSamplers(const gl::Context *context,
gl::ShaderType shaderType)
{
const auto &glState = context->getGLState();
const auto &caps = context->getCaps();
ASSERT(!mProgramD3D->isSamplerMappingDirty());
// TODO(jmadill): Use the Program's sampler bindings.
const gl::ActiveTexturePointerArray &completeTextures = glState.getActiveTexturesCache();
const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(shaderType);
for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
samplerIndex++)
{
GLint textureUnit = mProgramD3D->getSamplerMapping(shaderType, samplerIndex, caps);
ASSERT(textureUnit != -1);
gl::Texture *texture = completeTextures[textureUnit];
// A nullptr texture indicates incomplete.
if (texture)
{
gl::Sampler *samplerObject = glState.getSampler(textureUnit);
const gl::SamplerState &samplerState =
samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
ANGLE_TRY(
setTextureForSampler(context, shaderType, samplerIndex, texture, samplerState));
}
else
{
gl::TextureType textureType =
mProgramD3D->getSamplerTextureType(shaderType, samplerIndex);
// Texture is not sampler complete or it is in use by the framebuffer. Bind the
// incomplete texture.
gl::Texture *incompleteTexture = nullptr;
ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
incompleteTexture->getSamplerState()));
ANGLE_TRY(setTextureForSampler(context, shaderType, samplerIndex, incompleteTexture,
incompleteTexture->getSamplerState()));
}
}
return angle::Result::Continue();
}
angle::Result StateManager11::syncTextures(const gl::Context *context)
{
ANGLE_TRY(applyTexturesForSamplers(context, gl::ShaderType::Vertex));
ANGLE_TRY(applyTexturesForSamplers(context, gl::ShaderType::Fragment));
ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Vertex));
ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Fragment));
if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
{
ANGLE_TRY(applyTexturesForSamplers(context, gl::ShaderType::Geometry));
ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Geometry));
}
// Set all the remaining textures to NULL
const auto &caps = context->getCaps();
const gl::RangeUI vertexSamplerRange = mProgramD3D->getUsedSamplerRange(gl::ShaderType::Vertex);
const gl::RangeUI fragmentSamplerRange =
mProgramD3D->getUsedSamplerRange(gl::ShaderType::Fragment);
size_t vertexSamplerCount = caps.maxShaderTextureImageUnits[gl::ShaderType::Vertex];
size_t fragmentSamplerCount = caps.maxShaderTextureImageUnits[gl::ShaderType::Fragment];
ANGLE_TRY(clearSRVs(gl::ShaderType::Vertex, vertexSamplerRange.high(), vertexSamplerCount));
ANGLE_TRY(
clearSRVs(gl::ShaderType::Fragment, fragmentSamplerRange.high(), fragmentSamplerCount));
return angle::Result::Continue();
}
......@@ -2543,13 +2485,57 @@ angle::Result StateManager11::setTextureForSampler(const gl::Context *context,
return angle::Result::Continue();
}
angle::Result StateManager11::applyTexturesForImages(const gl::Context *context,
gl::ShaderType shaderType)
// For each Direct3D sampler of either the pixel or vertex stage,
// looks up the corresponding OpenGL texture image unit and texture type,
// and sets the texture and its addressing/filtering state (or NULL when inactive).
// Sampler mapping needs to be up-to-date on the program object before this is called.
angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context,
gl::ShaderType shaderType)
{
ASSERT(shaderType == gl::ShaderType::Compute);
const auto &glState = context->getGLState();
const auto &caps = context->getCaps();
ASSERT(!mProgramD3D->isSamplerMappingDirty());
// TODO(jmadill): Use the Program's sampler bindings.
const gl::ActiveTexturePointerArray &completeTextures = glState.getActiveTexturesCache();
const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(shaderType);
for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
samplerIndex++)
{
GLint textureUnit = mProgramD3D->getSamplerMapping(shaderType, samplerIndex, caps);
ASSERT(textureUnit != -1);
gl::Texture *texture = completeTextures[textureUnit];
// A nullptr texture indicates incomplete.
if (texture)
{
gl::Sampler *samplerObject = glState.getSampler(textureUnit);
const gl::SamplerState &samplerState =
samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
ANGLE_TRY(
setTextureForSampler(context, shaderType, samplerIndex, texture, samplerState));
}
else
{
gl::TextureType textureType =
mProgramD3D->getSamplerTextureType(shaderType, samplerIndex);
// Texture is not sampler complete or it is in use by the framebuffer. Bind the
// incomplete texture.
gl::Texture *incompleteTexture = nullptr;
ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
incompleteTexture->getSamplerState()));
ANGLE_TRY(setTextureForSampler(context, shaderType, samplerIndex, incompleteTexture,
incompleteTexture->getSamplerState()));
}
}
const gl::RangeUI readonlyImageRange = mProgramD3D->getUsedImageRange(shaderType, true);
for (unsigned int readonlyImageIndex = readonlyImageRange.low();
readonlyImageIndex < readonlyImageRange.high(); readonlyImageIndex++)
......@@ -2561,6 +2547,25 @@ angle::Result StateManager11::applyTexturesForImages(const gl::Context *context,
ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, true, imageUnit));
}
size_t samplerCount = caps.maxShaderTextureImageUnits[shaderType];
size_t readonlyImageCount =
context->getClientVersion() >= gl::Version(3, 1) ? caps.maxImageUnits : 0;
// Samplers and readonly images share the SRVs here, their range is
// [0, max(samplerRange.high(), readonlyImageRange.high()).
ANGLE_TRY(clearSRVs(shaderType, std::max(samplerRange.high(), readonlyImageRange.high()),
samplerCount + readonlyImageCount));
return angle::Result::Continue();
}
angle::Result StateManager11::applyTexturesForUAVs(const gl::Context *context,
gl::ShaderType shaderType)
{
ASSERT(shaderType == gl::ShaderType::Compute);
const auto &glState = context->getGLState();
const auto &caps = context->getCaps();
const gl::RangeUI imageRange = mProgramD3D->getUsedImageRange(shaderType, false);
for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++)
{
......@@ -2570,30 +2575,20 @@ angle::Result StateManager11::applyTexturesForImages(const gl::Context *context,
ANGLE_TRY(setTextureForImage(context, shaderType, imageIndex, false, imageUnit));
}
size_t imageCount = caps.maxImageUnits;
ANGLE_TRY(clearUAVs(shaderType, imageRange.high(), imageCount));
return angle::Result::Continue();
}
angle::Result StateManager11::syncTexturesForCompute(const gl::Context *context)
{
ANGLE_TRY(applyTexturesForSamplers(context, gl::ShaderType::Compute));
ANGLE_TRY(applyTexturesForImages(context, gl::ShaderType::Compute));
// Set all the remaining textures to NULL.
const auto &caps = context->getCaps();
const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(gl::ShaderType::Compute);
const gl::RangeUI readonlyImageRange =
mProgramD3D->getUsedImageRange(gl::ShaderType::Compute, true);
const gl::RangeUI imageRange = mProgramD3D->getUsedImageRange(gl::ShaderType::Compute, false);
size_t samplerCount = caps.maxShaderTextureImageUnits[gl::ShaderType::Compute];
size_t readonlyImageCount = caps.maxImageUnits;
size_t imageCount = caps.maxImageUnits;
// Samplers and readonly images share the SRVs here, their range is
// [0, max(samplerRange.high(), readonlyImageRange.high()).
ANGLE_TRY(clearSRVs(gl::ShaderType::Compute,
std::max(samplerRange.high(), readonlyImageRange.high()),
samplerCount + readonlyImageCount));
ANGLE_TRY(clearUAVs(gl::ShaderType::Compute, imageRange.high(), imageCount));
// applyTexturesForUAVs must be earlier than applyTexturesForSRVs since we need to do clearUVAs
// before set resources to SRVs. Otherwise, it will report the following error:
// ID3D11DeviceContext::CSSetShaderResources: Resource being set to CS shader resource slot 0 is
// still bound on output! Forcing to NULL.
ANGLE_TRY(applyTexturesForUAVs(context, gl::ShaderType::Compute));
ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Compute));
return angle::Result::Continue();
}
......
......@@ -289,8 +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 applyTexturesForSamplers(const gl::Context *context, gl::ShaderType shaderType);
angle::Result applyTexturesForImages(const gl::Context *context, gl::ShaderType shaderType);
angle::Result applyTexturesForSRVs(const gl::Context *context, gl::ShaderType shaderType);
angle::Result applyTexturesForUAVs(const gl::Context *context, gl::ShaderType shaderType);
angle::Result syncTexturesForCompute(const gl::Context *context);
angle::Result setSamplerState(const gl::Context *context,
......
......@@ -1687,6 +1687,122 @@ TEST_P(ComputeShaderTest, UniformBuffer)
}
}
// Test that storing data to image and then loading the same image data works correctly.
TEST_P(ComputeShaderTest, StoreImageThenLoad)
{
const char kCSSource[] =
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;
void main()
{
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
})";
constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
GLTexture texture[3];
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, texture[2]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
EXPECT_GL_NO_ERROR();
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
glUseProgram(program.get());
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
EXPECT_GL_NO_ERROR();
glBindImageTexture(0, texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
EXPECT_GL_NO_ERROR();
GLuint outputValue;
GLFramebuffer framebuffer;
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(300u, outputValue);
}
// Test that loading image data and then storing data to the same image works correctly.
TEST_P(ComputeShaderTest, LoadImageThenStore)
{
const char kCSSource[] =
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;
void main()
{
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
})";
constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
GLTexture texture[3];
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, texture[2]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
EXPECT_GL_NO_ERROR();
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
glUseProgram(program.get());
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
EXPECT_GL_NO_ERROR();
glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
glBindImageTexture(1, texture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
EXPECT_GL_NO_ERROR();
GLuint outputValue;
GLFramebuffer framebuffer;
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);
glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(100u, outputValue);
}
// Check that it is not possible to create a compute shader when the context does not support ES
// 3.10
TEST_P(ComputeShaderTestES3, NotSupported)
......
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