Fix IOSurface synchronization issues
It appears that not only render targets, but also samplers that use
IOSurfaces require SwiftShader to perform synchronized draws,
otherwise it seems like using a shared IOSurface's CPU memory is
unsafe and can cause crashes in Layout Tests.
Bug chromium:846693
Change-Id: I0ce24700d34c657ac2447ceb2f6f837bfa3a9a58
Reviewed-on: https://swiftshader-review.googlesource.com/19288
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/common/Image.cpp b/src/OpenGL/common/Image.cpp
index 447222c..988b532 100644
--- a/src/OpenGL/common/Image.cpp
+++ b/src/OpenGL/common/Image.cpp
@@ -1332,7 +1332,7 @@
#endif
}
- bool ClientBuffer::targetRequiresSync() const
+ bool ClientBuffer::requiresSync() const
{
#if defined(__APPLE__)
return true;
@@ -1431,9 +1431,9 @@
sw::Surface::unlockExternal();
}
- bool targetRequiresSync() const override
+ bool requiresSync() const override
{
- return clientBuffer.targetRequiresSync();
+ return clientBuffer.requiresSync();
}
void release() override
diff --git a/src/OpenGL/common/Image.hpp b/src/OpenGL/common/Image.hpp
index d7117c5..a744763 100644
--- a/src/OpenGL/common/Image.hpp
+++ b/src/OpenGL/common/Image.hpp
@@ -79,7 +79,7 @@
void release();
void* lock(int x, int y, int z);
void unlock();
- bool targetRequiresSync() const;
+ bool requiresSync() const;
private:
int width;
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 7bd9fea..a479f18 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3180,6 +3180,7 @@
device->setMipmapFilter(samplerType, samplerIndex, es2sw::ConvertMipMapFilter(minFilter));
device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy);
device->setHighPrecisionFiltering(samplerType, samplerIndex, mState.textureFilteringHint == GL_NICEST);
+ device->setSyncRequired(samplerType, samplerIndex, texture->requiresSync());
applyTexture(samplerType, samplerIndex, texture);
}
diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index ca28ed9..a218cd3 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -528,6 +528,19 @@
return level - 1;
}
+bool Texture2D::requiresSync() const
+{
+ for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ if(image[level] && image[level]->requiresSync())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLint internalformat, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels)
{
if(image[level])
@@ -1019,6 +1032,22 @@
return level - 1;
}
+bool TextureCubeMap::requiresSync() const
+{
+ for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for(int face = 0; face < 6; face++)
+ {
+ if(image[face][level] && image[face][level]->requiresSync())
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
int face = CubeFaceIndex(target);
@@ -1531,6 +1560,19 @@
return level - 1;
}
+bool Texture3D::requiresSync() const
+{
+ for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ if(image[level] && image[level]->requiresSync())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLint internalformat, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels)
{
if(image[level])
diff --git a/src/OpenGL/libGLESv2/Texture.h b/src/OpenGL/libGLESv2/Texture.h
index 3b4bfc5..ddd915e 100644
--- a/src/OpenGL/libGLESv2/Texture.h
+++ b/src/OpenGL/libGLESv2/Texture.h
@@ -97,6 +97,7 @@
virtual GLsizei getDepth(GLenum target, GLint level) const;
virtual GLint getFormat(GLenum target, GLint level) const = 0;
virtual int getTopLevel() const = 0;
+ virtual bool requiresSync() const = 0;
virtual bool isSamplerComplete() const = 0;
virtual bool isCompressed(GLenum target, GLint level) const = 0;
@@ -159,6 +160,7 @@
GLsizei getHeight(GLenum target, GLint level) const override;
GLint getFormat(GLenum target, GLint level) const override;
int getTopLevel() const override;
+ bool requiresSync() const override;
void setImage(GLint level, GLsizei width, GLsizei height, GLint internalformat, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels);
void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
@@ -226,6 +228,7 @@
GLsizei getHeight(GLenum target, GLint level) const override;
GLint getFormat(GLenum target, GLint level) const override;
int getTopLevel() const override;
+ bool requiresSync() const override;
void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLint internalformat, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels);
void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
@@ -287,6 +290,7 @@
GLsizei getDepth(GLenum target, GLint level) const override;
GLint getFormat(GLenum target, GLint level) const override;
int getTopLevel() const override;
+ bool requiresSync() const override;
void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLint internalformat, GLenum format, GLenum type, const gl::PixelStorageModes &unpackParameters, const void *pixels);
void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
diff --git a/src/Renderer/PixelProcessor.cpp b/src/Renderer/PixelProcessor.cpp
index 7ae45e9..3903701 100644
--- a/src/Renderer/PixelProcessor.cpp
+++ b/src/Renderer/PixelProcessor.cpp
@@ -537,6 +537,15 @@
else ASSERT(false);
}
+ void PixelProcessor::setSyncRequired(unsigned int sampler, bool isSincRequired)
+ {
+ if(sampler < TEXTURE_IMAGE_UNITS)
+ {
+ context->sampler[sampler].setSyncRequired(isSincRequired);
+ }
+ else ASSERT(false);
+ }
+
void PixelProcessor::setWriteSRGB(bool sRGB)
{
context->setWriteSRGB(sRGB);
diff --git a/src/Renderer/PixelProcessor.hpp b/src/Renderer/PixelProcessor.hpp
index 1954610..cea417d 100644
--- a/src/Renderer/PixelProcessor.hpp
+++ b/src/Renderer/PixelProcessor.hpp
@@ -242,6 +242,7 @@
void setMaxLevel(unsigned int sampler, int maxLevel);
void setMinLod(unsigned int sampler, float minLod);
void setMaxLod(unsigned int sampler, float maxLod);
+ void setSyncRequired(unsigned int sampler, bool isSincRequired);
void setWriteSRGB(bool sRGB);
void setDepthBufferEnable(bool depthBufferEnable);
diff --git a/src/Renderer/Renderer.cpp b/src/Renderer/Renderer.cpp
index 1334e70..b560f41 100644
--- a/src/Renderer/Renderer.cpp
+++ b/src/Renderer/Renderer.cpp
@@ -224,7 +224,7 @@
int ss = context->getSuperSampleCount();
int ms = context->getMultiSampleCount();
- bool targetRequiresSync = false;
+ bool requiresSync = false;
for(int q = 0; q < ss; q++)
{
@@ -368,6 +368,8 @@
draw->texture[sampler]->lock(PUBLIC, isReadWriteTexture(sampler) ? MANAGED : PRIVATE); // If the texure is both read and written, use the same read/write lock as render targets
data->mipmap[sampler] = context->sampler[sampler].getTextureData();
+
+ requiresSync |= context->sampler[sampler].requiresSync();
}
}
@@ -426,6 +428,8 @@
draw->texture[TEXTURE_IMAGE_UNITS + sampler]->lock(PUBLIC, PRIVATE);
data->mipmap[TEXTURE_IMAGE_UNITS + sampler] = context->sampler[TEXTURE_IMAGE_UNITS + sampler].getTextureData();
+
+ requiresSync |= context->sampler[TEXTURE_IMAGE_UNITS + sampler].requiresSync();
}
}
}
@@ -608,7 +612,7 @@
if(draw->renderTarget[index])
{
unsigned int layer = context->renderTargetLayer[index];
- targetRequiresSync |= context->renderTarget[index]->targetRequiresSync();
+ requiresSync |= context->renderTarget[index]->requiresSync();
data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
data->colorBuffer[index] += q * ms * context->renderTarget[index]->getSliceB(true);
data->colorPitchB[index] = context->renderTarget[index]->getInternalPitchB();
@@ -622,7 +626,7 @@
if(draw->depthBuffer)
{
unsigned int layer = context->depthBufferLayer;
- targetRequiresSync |= context->depthBuffer->targetRequiresSync();
+ requiresSync |= context->depthBuffer->requiresSync();
data->depthBuffer = (float*)context->depthBuffer->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
data->depthBuffer += q * ms * context->depthBuffer->getSliceB(true);
data->depthPitchB = context->depthBuffer->getInternalPitchB();
@@ -632,7 +636,7 @@
if(draw->stencilBuffer)
{
unsigned int layer = context->stencilBufferLayer;
- targetRequiresSync |= context->stencilBuffer->targetRequiresSync();
+ requiresSync |= context->stencilBuffer->requiresSync();
data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(0, 0, layer, MANAGED);
data->stencilBuffer += q * ms * context->stencilBuffer->getSliceB(true);
data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
@@ -681,7 +685,7 @@
}
// TODO(sugoi): This is a temporary brute-force workaround to ensure IOSurface synchronization.
- if(targetRequiresSync)
+ if(requiresSync)
{
synchronize();
}
@@ -2469,6 +2473,18 @@
}
}
+ void Renderer::setSyncRequired(SamplerType type, int sampler, bool syncRequired)
+ {
+ if(type == SAMPLER_PIXEL)
+ {
+ PixelProcessor::setSyncRequired(sampler, syncRequired);
+ }
+ else
+ {
+ VertexProcessor::setSyncRequired(sampler, syncRequired);
+ }
+ }
+
void Renderer::setPointSpriteEnable(bool pointSpriteEnable)
{
context->setPointSpriteEnable(pointSpriteEnable);
diff --git a/src/Renderer/Renderer.hpp b/src/Renderer/Renderer.hpp
index b37da5f..ce22866 100644
--- a/src/Renderer/Renderer.hpp
+++ b/src/Renderer/Renderer.hpp
@@ -304,6 +304,7 @@
void setMaxLevel(SamplerType type, int sampler, int maxLevel);
void setMinLod(SamplerType type, int sampler, float minLod);
void setMaxLod(SamplerType type, int sampler, float maxLod);
+ void setSyncRequired(SamplerType type, int sampler, bool syncRequired);
void setPointSpriteEnable(bool pointSpriteEnable);
void setPointScaleEnable(bool pointScaleEnable);
diff --git a/src/Renderer/Sampler.cpp b/src/Renderer/Sampler.cpp
index 748fb4e..efac4c6 100644
--- a/src/Renderer/Sampler.cpp
+++ b/src/Renderer/Sampler.cpp
@@ -401,6 +401,16 @@
return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY;
}
+ void Sampler::setSyncRequired(bool isSyncRequired)
+ {
+ syncRequired = isSyncRequired;
+ }
+
+ bool Sampler::requiresSync() const
+ {
+ return syncRequired;
+ }
+
const Texture &Sampler::getTextureData()
{
return texture;
diff --git a/src/Renderer/Sampler.hpp b/src/Renderer/Sampler.hpp
index c73721d..af225c5 100644
--- a/src/Renderer/Sampler.hpp
+++ b/src/Renderer/Sampler.hpp
@@ -193,6 +193,7 @@
void setMaxLevel(int maxLevel);
void setMinLod(float minLod);
void setMaxLod(float maxLod);
+ void setSyncRequired(bool isSincRequired);
static void setFilterQuality(FilterType maximumFilterQuality);
static void setMipmapQuality(MipmapType maximumFilterQuality);
@@ -202,6 +203,7 @@
bool hasUnsignedTexture() const;
bool hasCubeTexture() const;
bool hasVolumeTexture() const;
+ bool requiresSync() const;
const Texture &getTextureData();
@@ -226,6 +228,7 @@
bool sRGB;
bool gather;
bool highPrecisionFiltering;
+ bool syncRequired;
int border;
SwizzleType swizzleR;
diff --git a/src/Renderer/Surface.hpp b/src/Renderer/Surface.hpp
index 2b1b906..a6ef15b 100644
--- a/src/Renderer/Surface.hpp
+++ b/src/Renderer/Surface.hpp
@@ -321,7 +321,7 @@
inline int getStencilSliceB() const;
void sync(); // Wait for lock(s) to be released.
- virtual bool targetRequiresSync() const { return false; }
+ virtual bool requiresSync() const { return false; }
inline bool isUnlocked() const; // Only reliable after sync().
inline int getSamples() const;
diff --git a/src/Renderer/VertexProcessor.cpp b/src/Renderer/VertexProcessor.cpp
index cc9bd25..976ea2b 100644
--- a/src/Renderer/VertexProcessor.cpp
+++ b/src/Renderer/VertexProcessor.cpp
@@ -692,6 +692,15 @@
else ASSERT(false);
}
+ void VertexProcessor::setSyncRequired(unsigned int sampler, bool isSincRequired)
+ {
+ if(sampler < TEXTURE_IMAGE_UNITS)
+ {
+ context->sampler[sampler].setSyncRequired(isSincRequired);
+ }
+ else ASSERT(false);
+ }
+
void VertexProcessor::setPointSize(float pointSize)
{
point.pointSize = replicate(pointSize);
diff --git a/src/Renderer/VertexProcessor.hpp b/src/Renderer/VertexProcessor.hpp
index cd3849a..277a155 100644
--- a/src/Renderer/VertexProcessor.hpp
+++ b/src/Renderer/VertexProcessor.hpp
@@ -268,6 +268,7 @@
void setMaxLevel(unsigned int sampler, int maxLevel);
void setMinLod(unsigned int sampler, float minLod);
void setMaxLod(unsigned int sampler, float maxLod);
+ void setSyncRequired(unsigned int sampler, bool isSincRequired);
void setPointSize(float pointSize);
void setPointSizeMin(float pointSizeMin);