Commit be6a1d87 by Manh Nguyen Committed by Commit Bot

Add texture serialization capability

Serializes textures' states stored on CPU. Gets textures' contents at every mipmap level from GPU then serialize them. Adds texture serialization to serializeContext method so that capture replay regresssion testing now compares the states of texture too. Bug: angleproject:4817 Change-Id: I87670fdc744f96d4ff244462dee1a065de44f9b7 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2325029 Commit-Queue: Manh Nguyen <nguyenmh@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 69ca1025
......@@ -125,7 +125,9 @@ class TextureState final : private angle::NonCopyable
// Returns true if base level changed.
bool setBaseLevel(GLuint baseLevel);
GLuint getBaseLevel() const { return mBaseLevel; }
bool setMaxLevel(GLuint maxLevel);
GLuint getMaxLevel() const { return mMaxLevel; }
bool isCubeComplete() const;
......@@ -177,6 +179,15 @@ class TextureState final : private angle::NonCopyable
// Return the enabled mipmap level count.
GLuint getEnabledLevelCount() const;
const std::vector<ContextBindingCount> &getBindingCounts() const { return mBindingCounts; }
bool getImmutableFormat() const { return mImmutableFormat; }
GLuint getImmutableLevels() const { return mImmutableLevels; }
const std::vector<ImageDesc> &getImageDescs() const { return mImageDescs; }
InitState getInitState() const { return mInitState; }
private:
// Texture needs access to the ImageDesc functions.
friend class Texture;
......@@ -343,6 +354,8 @@ class Texture final : public RefCountObject<TextureID>,
void setUsage(const Context *context, GLenum usage);
GLenum getUsage() const;
const TextureState &getState() const { return mState; }
void setBorderColor(const Context *context, const ColorGeneric &color);
const ColorGeneric &getBorderColor() const;
......
......@@ -118,6 +118,11 @@ Result SerializeFramebufferAttachment(const gl::Context *context,
gl::Framebuffer *framebuffer,
const gl::FramebufferAttachment &framebufferAttachment)
{
if (framebufferAttachment.type() == GL_TEXTURE ||
framebufferAttachment.type() == GL_RENDERBUFFER)
{
bos->writeInt(framebufferAttachment.id());
}
bos->writeInt(framebufferAttachment.type());
// serialize target variable
bos->writeInt(framebufferAttachment.getBinding());
......@@ -130,20 +135,24 @@ Result SerializeFramebufferAttachment(const gl::Context *context,
bos->writeInt(framebufferAttachment.getBaseViewIndex());
bos->writeInt(framebufferAttachment.getRenderToTextureSamples());
GLenum prevReadBufferState = framebuffer->getReadBufferState();
GLenum binding = framebufferAttachment.getBinding();
if (IsValidColorAttachmentBinding(binding,
framebuffer->getState().getColorAttachments().size()))
if (framebufferAttachment.type() != GL_TEXTURE &&
framebufferAttachment.type() != GL_RENDERBUFFER)
{
framebuffer->setReadBuffer(framebufferAttachment.getBinding());
ANGLE_TRY(framebuffer->syncState(context, GL_FRAMEBUFFER));
GLenum prevReadBufferState = framebuffer->getReadBufferState();
GLenum binding = framebufferAttachment.getBinding();
if (IsValidColorAttachmentBinding(binding,
framebuffer->getState().getColorAttachments().size()))
{
framebuffer->setReadBuffer(framebufferAttachment.getBinding());
ANGLE_TRY(framebuffer->syncState(context, GL_FRAMEBUFFER));
}
MemoryBuffer *pixelsPtr = nullptr;
ANGLE_TRY(ReadPixelsFromAttachment(context, framebuffer, framebufferAttachment,
scratchBuffer, &pixelsPtr));
bos->writeBytes(pixelsPtr->data(), pixelsPtr->size());
// Reset framebuffer state
framebuffer->setReadBuffer(prevReadBufferState);
}
MemoryBuffer *pixelsPtr = nullptr;
ANGLE_TRY(ReadPixelsFromAttachment(context, framebuffer, framebufferAttachment, scratchBuffer,
&pixelsPtr));
bos->writeBytes(pixelsPtr->data(), pixelsPtr->size());
// Reset framebuffer state
framebuffer->setReadBuffer(prevReadBufferState);
return Result::Continue;
}
......@@ -509,6 +518,21 @@ void SerializeSampler(gl::BinaryOutputStream *bos, gl::Sampler *sampler)
SerializeSamplerState(bos, sampler->getSamplerState());
}
void SerializeSwizzleState(gl::BinaryOutputStream *bos, const gl::SwizzleState &swizzleState)
{
bos->writeInt(swizzleState.swizzleRed);
bos->writeInt(swizzleState.swizzleGreen);
bos->writeInt(swizzleState.swizzleBlue);
bos->writeInt(swizzleState.swizzleAlpha);
}
void SerializeExtents(gl::BinaryOutputStream *bos, const gl::Extents &extents)
{
bos->writeInt(extents.width);
bos->writeInt(extents.height);
bos->writeInt(extents.depth);
}
void SerializeInternalFormat(gl::BinaryOutputStream *bos, const gl::InternalFormat *internalFormat)
{
bos->writeInt(internalFormat->internalFormat);
......@@ -777,6 +801,112 @@ void SerializeProgram(gl::BinaryOutputStream *bos, gl::Program *program)
bos->writeInt(program->getRefCount());
bos->writeInt(program->id().value);
}
void SerializeImageDesc(gl::BinaryOutputStream *bos, const gl::ImageDesc &imageDesc)
{
SerializeExtents(bos, imageDesc.size);
SerializeFormat(bos, imageDesc.format);
bos->writeInt(imageDesc.samples);
bos->writeInt(imageDesc.fixedSampleLocations);
bos->writeEnum(imageDesc.initState);
}
void SerializeContextBindingCount(gl::BinaryOutputStream *bos,
const gl::ContextBindingCount &contextBindingCount)
{
bos->writeInt(contextBindingCount.contextID);
bos->writeInt(contextBindingCount.imageBindingCount);
bos->writeInt(contextBindingCount.samplerBindingCount);
}
void SerializeTextureState(gl::BinaryOutputStream *bos, const gl::TextureState &textureState)
{
bos->writeEnum(textureState.getType());
SerializeSwizzleState(bos, textureState.getSwizzleState());
SerializeSamplerState(bos, textureState.getSamplerState());
bos->writeEnum(textureState.getSRGBOverride());
bos->writeInt(textureState.getBaseLevel());
bos->writeInt(textureState.getMaxLevel());
bos->writeInt(textureState.getDepthStencilTextureMode());
const std::vector<gl::ContextBindingCount> &contextBindingCounts =
textureState.getBindingCounts();
for (const gl::ContextBindingCount &contextBindingCount : contextBindingCounts)
{
SerializeContextBindingCount(bos, contextBindingCount);
}
bos->writeInt(textureState.getImmutableFormat());
bos->writeInt(textureState.getImmutableLevels());
bos->writeInt(textureState.getUsage());
const std::vector<gl::ImageDesc> &imageDescs = textureState.getImageDescs();
for (const gl::ImageDesc &imageDesc : imageDescs)
{
SerializeImageDesc(bos, imageDesc);
}
SerializeRectangle(bos, textureState.getCrop());
bos->writeInt(textureState.getGenerateMipmapHint());
bos->writeEnum(textureState.getInitState());
}
Result SerializeTextureData(gl::BinaryOutputStream *bos,
const gl::Context *context,
gl::Texture *texture,
ScratchBuffer *scratchBuffer)
{
gl::ImageIndexIterator imageIter = gl::ImageIndexIterator::MakeGeneric(
texture->getType(), 0, texture->getMipmapMaxLevel() + 1, gl::ImageIndex::kEntireLevel,
gl::ImageIndex::kEntireLevel);
while (imageIter.hasNext())
{
gl::ImageIndex index = imageIter.next();
const gl::ImageDesc &desc = texture->getTextureState().getImageDesc(index);
if (desc.size.empty())
continue;
const gl::InternalFormat &format = *desc.format.info;
// Check for supported textures
ASSERT(index.getType() == gl::TextureType::_2D || index.getType() == gl::TextureType::_3D ||
index.getType() == gl::TextureType::_2DArray ||
index.getType() == gl::TextureType::CubeMap);
GLenum getFormat = format.format;
GLenum getType = format.type;
const gl::Extents size(desc.size.width, desc.size.height, desc.size.depth);
const gl::PixelUnpackState &unpack = context->getState().getUnpackState();
GLuint endByte = 0;
bool unpackSize = format.computePackUnpackEndByte(getType, size, unpack, true, &endByte);
ASSERT(unpackSize);
MemoryBuffer *texelsPtr = nullptr;
ANGLE_CHECK_GL_ALLOC(const_cast<gl::Context *>(context),
scratchBuffer->getInitialized(endByte, &texelsPtr, 0));
gl::PixelPackState packState;
packState.alignment = 1;
ANGLE_TRY(texture->getTexImage(context, packState, nullptr, index.getTarget(),
index.getLevelIndex(), getFormat, getType,
texelsPtr->data()));
bos->writeBytes(texelsPtr->data(), texelsPtr->size());
}
return Result::Continue;
}
Result SerializeTexture(const gl::Context *context,
gl::BinaryOutputStream *bos,
ScratchBuffer *scratchBuffer,
gl::Texture *texture)
{
SerializeTextureState(bos, texture->getState());
bos->writeString(texture->getLabel());
// FrameCapture can not serialize mBoundSurface and mBoundStream
// because they are likely to change with each run
ANGLE_TRY(SerializeTextureData(bos, context, texture, scratchBuffer));
return Result::Continue;
}
} // namespace
......@@ -826,6 +956,12 @@ Result SerializeContext(gl::BinaryOutputStream *bos, const gl::Context *context)
gl::Program *programPtr = program.second;
SerializeProgram(bos, programPtr);
}
const gl::TextureManager &textureManager = context->getState().getTextureManagerForCapture();
for (const auto &texture : textureManager)
{
gl::Texture *texturePtr = texture.second;
ANGLE_TRY(SerializeTexture(context, bos, &scratchBuffer, texturePtr));
}
scratchBuffer.clear();
return Result::Continue;
......
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