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) ...@@ -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> template <typename T>
std::size_t ComputeGenericHash(const T &key) std::size_t ComputeGenericHash(const T &key)
{ {
static const unsigned int seed = 0xABCDEF98; 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 } // namespace angle
......
...@@ -79,6 +79,11 @@ BlendState::BlendState() ...@@ -79,6 +79,11 @@ BlendState::BlendState()
dither = true; dither = true;
} }
BlendState::BlendState(const BlendState &other)
{
memcpy(this, &other, sizeof(BlendState));
}
bool operator==(const BlendState &a, const BlendState &b) bool operator==(const BlendState &a, const BlendState &b)
{ {
return memcmp(&a, &b, sizeof(BlendState)) == 0; return memcmp(&a, &b, sizeof(BlendState)) == 0;
...@@ -111,6 +116,11 @@ DepthStencilState::DepthStencilState() ...@@ -111,6 +116,11 @@ DepthStencilState::DepthStencilState()
stencilBackPassDepthPass = GL_KEEP; stencilBackPassDepthPass = GL_KEEP;
} }
DepthStencilState::DepthStencilState(const DepthStencilState &other)
{
memcpy(this, &other, sizeof(DepthStencilState));
}
bool operator==(const DepthStencilState &a, const DepthStencilState &b) bool operator==(const DepthStencilState &a, const DepthStencilState &b)
{ {
return memcmp(&a, &b, sizeof(DepthStencilState)) == 0; return memcmp(&a, &b, sizeof(DepthStencilState)) == 0;
......
...@@ -144,6 +144,7 @@ struct BlendState final ...@@ -144,6 +144,7 @@ struct BlendState final
{ {
// This will zero-initialize the struct, including padding. // This will zero-initialize the struct, including padding.
BlendState(); BlendState();
BlendState(const BlendState &other);
bool blend; bool blend;
GLenum sourceBlendRGB; GLenum sourceBlendRGB;
...@@ -170,6 +171,7 @@ struct DepthStencilState final ...@@ -170,6 +171,7 @@ struct DepthStencilState final
{ {
// This will zero-initialize the struct, including padding. // This will zero-initialize the struct, including padding.
DepthStencilState(); DepthStencilState();
DepthStencilState(const DepthStencilState &other);
bool depthTest; bool depthTest;
GLenum depthFunc; GLenum depthFunc;
......
...@@ -306,8 +306,6 @@ gl::Error Clear11::ensureResourcesInitialized() ...@@ -306,8 +306,6 @@ gl::Error Clear11::ensureResourcesInitialized()
mBlendStateKey.blendState.blendEquationAlpha = GL_FUNC_ADD; mBlendStateKey.blendState.blendEquationAlpha = GL_FUNC_ADD;
mBlendStateKey.blendState.sampleAlphaToCoverage = false; mBlendStateKey.blendState.sampleAlphaToCoverage = false;
mBlendStateKey.blendState.dither = true; mBlendStateKey.blendState.dither = true;
mBlendStateKey.mrt = false;
memset(mBlendStateKey.rtvMasks, 0, sizeof(mBlendStateKey.rtvMasks));
mResourcesInitialized = true; mResourcesInitialized = true;
return gl::NoError(); return gl::NoError();
...@@ -691,7 +689,7 @@ gl::Error Clear11::clearFramebuffer(const gl::Context *context, ...@@ -691,7 +689,7 @@ gl::Error Clear11::clearFramebuffer(const gl::Context *context,
mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen; mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen;
mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue; mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue;
mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha; mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha;
mBlendStateKey.mrt = numRtvs > 1; mBlendStateKey.rtvMax = numRtvs;
memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks)); memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks));
// Get BlendState // Get BlendState
......
...@@ -28,7 +28,28 @@ ...@@ -28,7 +28,28 @@
namespace rx namespace rx
{ {
class DrawCallVertexParams; 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 rx
namespace std namespace std
...@@ -56,28 +77,6 @@ struct SourceIndexData; ...@@ -56,28 +77,6 @@ struct SourceIndexData;
class ProgramD3D; class ProgramD3D;
class Renderer11; 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 class InputLayoutCache : angle::NonCopyable
{ {
public: public:
......
...@@ -55,7 +55,6 @@ d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *conte ...@@ -55,7 +55,6 @@ d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *conte
blendState.colorMaskBlue, blendState.colorMaskAlpha); blendState.colorMaskBlue, blendState.colorMaskAlpha);
key.blendState = blendState; key.blendState = blendState;
key.mrt = false;
for (size_t i = 0; i < colorbuffers.size(); i++) for (size_t i = 0; i < colorbuffers.size(); i++)
{ {
...@@ -63,23 +62,10 @@ d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *conte ...@@ -63,23 +62,10 @@ d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *conte
if (attachment) if (attachment)
{ {
if (i > 0) key.rtvMax = static_cast<uint32_t>(i) + 1;
{
key.mrt = true;
}
key.rtvMasks[i] = key.rtvMasks[i] =
(gl_d3d11::GetColorMask(*attachment->getFormat().info)) & blendStateMask; (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; return key;
...@@ -104,7 +90,7 @@ gl::Error RenderStateCache::getBlendState(Renderer11 *renderer, ...@@ -104,7 +90,7 @@ gl::Error RenderStateCache::getBlendState(Renderer11 *renderer,
const gl::BlendState &blendState = key.blendState; const gl::BlendState &blendState = key.blendState;
blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
blendDesc.IndependentBlendEnable = key.mrt ? TRUE : FALSE; blendDesc.IndependentBlendEnable = key.rtvMax > 1 ? TRUE : FALSE;
rtDesc0 = {}; rtDesc0 = {};
...@@ -143,7 +129,7 @@ gl::Error RenderStateCache::getRasterizerState(Renderer11 *renderer, ...@@ -143,7 +129,7 @@ gl::Error RenderStateCache::getRasterizerState(Renderer11 *renderer,
{ {
d3d11::RasterizerStateKey key; d3d11::RasterizerStateKey key;
key.rasterizerState = rasterState; key.rasterizerState = rasterState;
key.scissorEnabled = scissorEnabled; key.scissorEnabled = scissorEnabled ? 1 : 0;
auto keyIter = mRasterizerStateCache.Get(key); auto keyIter = mRasterizerStateCache.Get(key);
if (keyIter != mRasterizerStateCache.end()) if (keyIter != mRasterizerStateCache.end())
......
...@@ -128,7 +128,10 @@ struct BlendStateKey final ...@@ -128,7 +128,10 @@ struct BlendStateKey final
BlendStateKey(); BlendStateKey();
gl::BlendState blendState; gl::BlendState blendState;
bool mrt;
// An int so struct size rounds nicely.
uint32_t rtvMax;
uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
}; };
...@@ -141,7 +144,9 @@ struct RasterizerStateKey final ...@@ -141,7 +144,9 @@ struct RasterizerStateKey final
RasterizerStateKey(); RasterizerStateKey();
gl::RasterizerState rasterizerState; 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); 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