Commit f1b47e89 by Jamie Madill

Fix ComputeGenericHash.

ANGLE's internal hash maps would run MurmurHash on c++ structs to come up with hash values. Since the hash ran on 4 byte words only, it would have no understanding that sometimes our structs would only have meaninful data in the first N bytes, and would include the garbage at the end in the hash calculation. This fixes the problem by forcing our structs to be aligned at compile-time. It also adds custom copy operators for a few classes to ensure that all bits are copied when the struct is initialized, including the padding. Bug: angleproject:1569 Bug: chromium:721648 Change-Id: I4d11f6e12d9a067b36e1416c7ed15586eff99aab Reviewed-on: https://chromium-review.googlesource.com/783990 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 89be29a5
......@@ -158,12 +158,16 @@ void TrimCache(size_t maxStates, size_t gcLimit, const char *name, T *cache)
}
}
// Computes a hash of struct "key". Any structs passed to this function must be multiples of
// 4 bytes, since the PMurhHas32 method can only operate increments of 4-byte words.
template <typename T>
std::size_t ComputeGenericHash(const T &key)
{
static const unsigned int seed = 0xABCDEF98;
return PMurHash32(seed, &key, sizeof(key));
// We can't support "odd" alignments.
static_assert(sizeof(key) % 4 == 0, "ComputeGenericHash requires aligned types");
return PMurHash32(seed, &key, sizeof(T));
}
} // namespace angle
......
......@@ -79,6 +79,11 @@ BlendState::BlendState()
dither = true;
}
BlendState::BlendState(const BlendState &other)
{
memcpy(this, &other, sizeof(BlendState));
}
bool operator==(const BlendState &a, const BlendState &b)
{
return memcmp(&a, &b, sizeof(BlendState)) == 0;
......@@ -111,6 +116,11 @@ DepthStencilState::DepthStencilState()
stencilBackPassDepthPass = GL_KEEP;
}
DepthStencilState::DepthStencilState(const DepthStencilState &other)
{
memcpy(this, &other, sizeof(DepthStencilState));
}
bool operator==(const DepthStencilState &a, const DepthStencilState &b)
{
return memcmp(&a, &b, sizeof(DepthStencilState)) == 0;
......
......@@ -144,6 +144,7 @@ struct BlendState final
{
// This will zero-initialize the struct, including padding.
BlendState();
BlendState(const BlendState &other);
bool blend;
GLenum sourceBlendRGB;
......@@ -170,6 +171,7 @@ struct DepthStencilState final
{
// This will zero-initialize the struct, including padding.
DepthStencilState();
DepthStencilState(const DepthStencilState &other);
bool depthTest;
GLenum depthFunc;
......
......@@ -306,8 +306,6 @@ gl::Error Clear11::ensureResourcesInitialized()
mBlendStateKey.blendState.blendEquationAlpha = GL_FUNC_ADD;
mBlendStateKey.blendState.sampleAlphaToCoverage = false;
mBlendStateKey.blendState.dither = true;
mBlendStateKey.mrt = false;
memset(mBlendStateKey.rtvMasks, 0, sizeof(mBlendStateKey.rtvMasks));
mResourcesInitialized = true;
return gl::NoError();
......@@ -691,7 +689,7 @@ gl::Error Clear11::clearFramebuffer(const gl::Context *context,
mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen;
mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue;
mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha;
mBlendStateKey.mrt = numRtvs > 1;
mBlendStateKey.rtvMax = numRtvs;
memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks));
// Get BlendState
......
......@@ -28,7 +28,28 @@
namespace rx
{
class DrawCallVertexParams;
struct PackedAttributeLayout;
struct PackedAttributeLayout
{
PackedAttributeLayout();
void addAttributeData(GLenum glType,
UINT semanticIndex,
gl::VertexFormatType vertexFormatType,
unsigned int divisor);
bool operator==(const PackedAttributeLayout &other) const;
enum Flags
{
FLAG_USES_INSTANCED_SPRITES = 0x1,
FLAG_INSTANCED_SPRITES_ACTIVE = 0x2,
FLAG_INSTANCED_RENDERING_ACTIVE = 0x4,
};
uint32_t numAttributes;
uint32_t flags;
std::array<uint32_t, gl::MAX_VERTEX_ATTRIBS> attributeData;
};
} // namespace rx
namespace std
......@@ -56,28 +77,6 @@ struct SourceIndexData;
class ProgramD3D;
class Renderer11;
struct PackedAttributeLayout
{
PackedAttributeLayout();
void addAttributeData(GLenum glType,
UINT semanticIndex,
gl::VertexFormatType vertexFormatType,
unsigned int divisor);
bool operator==(const PackedAttributeLayout &other) const;
enum Flags
{
FLAG_USES_INSTANCED_SPRITES = 0x1,
FLAG_INSTANCED_SPRITES_ACTIVE = 0x2,
FLAG_INSTANCED_RENDERING_ACTIVE = 0x4,
};
size_t numAttributes;
unsigned int flags;
std::array<uint32_t, gl::MAX_VERTEX_ATTRIBS> attributeData;
};
class InputLayoutCache : angle::NonCopyable
{
public:
......
......@@ -55,7 +55,6 @@ d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *conte
blendState.colorMaskBlue, blendState.colorMaskAlpha);
key.blendState = blendState;
key.mrt = false;
for (size_t i = 0; i < colorbuffers.size(); i++)
{
......@@ -63,23 +62,10 @@ d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *conte
if (attachment)
{
if (i > 0)
{
key.mrt = true;
}
key.rtvMax = static_cast<uint32_t>(i) + 1;
key.rtvMasks[i] =
(gl_d3d11::GetColorMask(*attachment->getFormat().info)) & blendStateMask;
}
else
{
key.rtvMasks[i] = 0;
}
}
for (size_t i = colorbuffers.size(); i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
key.rtvMasks[i] = 0;
}
return key;
......@@ -104,7 +90,7 @@ gl::Error RenderStateCache::getBlendState(Renderer11 *renderer,
const gl::BlendState &blendState = key.blendState;
blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
blendDesc.IndependentBlendEnable = key.mrt ? TRUE : FALSE;
blendDesc.IndependentBlendEnable = key.rtvMax > 1 ? TRUE : FALSE;
rtDesc0 = {};
......@@ -143,7 +129,7 @@ gl::Error RenderStateCache::getRasterizerState(Renderer11 *renderer,
{
d3d11::RasterizerStateKey key;
key.rasterizerState = rasterState;
key.scissorEnabled = scissorEnabled;
key.scissorEnabled = scissorEnabled ? 1 : 0;
auto keyIter = mRasterizerStateCache.Get(key);
if (keyIter != mRasterizerStateCache.end())
......
......@@ -128,7 +128,10 @@ struct BlendStateKey final
BlendStateKey();
gl::BlendState blendState;
bool mrt;
// An int so struct size rounds nicely.
uint32_t rtvMax;
uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
};
......@@ -141,7 +144,9 @@ struct RasterizerStateKey final
RasterizerStateKey();
gl::RasterizerState rasterizerState;
bool scissorEnabled;
// Use a 32-bit int to round the struct nicely.
uint32_t scissorEnabled;
};
bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b);
......
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