Commit 77b2436e by Jamie Madill Committed by Commit Bot

Vulkan: Reduce PipelineDesc size.

This packs the desc into 288 bytes. Down from over 400. The hashing and memcmp functions are sped up considerably. Improves performance in the VulkanPipelineCachePerf test by 50% and also improves performance in the state changing draw call test by 20%. Bug: angleproject:2522 Change-Id: I72ed191a93721b875684f647f806c09be4e66821 Reviewed-on: https://chromium-review.googlesource.com/c/1308460Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 3d86e89b
...@@ -75,6 +75,8 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend ...@@ -75,6 +75,8 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend
mCurrentElementArrayBufferHandle(VK_NULL_HANDLE), mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
mCurrentElementArrayBufferOffset(0), mCurrentElementArrayBufferOffset(0),
mCurrentElementArrayBufferResource(nullptr), mCurrentElementArrayBufferResource(nullptr),
mPackedInputBindings{},
mPackedInputAttributes{},
mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize), mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize), mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
mTranslatedByteIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize), mTranslatedByteIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
...@@ -85,9 +87,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend ...@@ -85,9 +87,6 @@ VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state, RendererVk *rend
mCurrentArrayBufferOffsets.fill(0); mCurrentArrayBufferOffsets.fill(0);
mCurrentArrayBufferResources.fill(nullptr); mCurrentArrayBufferResources.fill(nullptr);
mPackedInputBindings.fill({0, 0});
mPackedInputAttributes.fill({0, 0, 0});
for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion) for (vk::DynamicBuffer &buffer : mCurrentArrayBufferConversion)
{ {
buffer.init(kMaxVertexFormatAlignment, renderer); buffer.init(kMaxVertexFormatAlignment, renderer);
...@@ -397,10 +396,9 @@ void VertexArrayVk::updatePackedInputDescriptions() ...@@ -397,10 +396,9 @@ void VertexArrayVk::updatePackedInputDescriptions()
bindingDesc.stride = 0; bindingDesc.stride = 0;
bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex]; mPackedInputAttributes.formats[attribIndex] =
attribDesc.format = static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT); static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
attribDesc.location = static_cast<uint16_t>(attribIndex); mPackedInputAttributes.offsets[attribIndex] = 0;
attribDesc.offset = 0;
} }
} }
...@@ -424,10 +422,8 @@ void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex, ...@@ -424,10 +422,8 @@ void VertexArrayVk::updatePackedInputInfo(uint32_t attribIndex,
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex]; mPackedInputAttributes.formats[attribIndex] = static_cast<uint8_t>(vkFormat);
attribDesc.format = static_cast<uint16_t>(vkFormat); mPackedInputAttributes.offsets[attribIndex] = static_cast<uint16_t>(attrib.relativeOffset);
attribDesc.location = static_cast<uint16_t>(attribIndex);
attribDesc.offset = static_cast<uint32_t>(attrib.relativeOffset);
} }
angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context, angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include "libANGLE/renderer/vulkan/vk_format_utils.h" #include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
#include <type_traits>
namespace rx namespace rx
{ {
namespace vk namespace vk
...@@ -152,7 +154,9 @@ void UnpackAttachmentDesc(VkAttachmentDescription *desc, ...@@ -152,7 +154,9 @@ void UnpackAttachmentDesc(VkAttachmentDescription *desc,
desc->finalLayout = static_cast<VkImageLayout>(ops.finalLayout); desc->finalLayout = static_cast<VkImageLayout>(ops.finalLayout);
} }
void UnpackStencilState(const vk::PackedStencilOpState &packedState, VkStencilOpState *stateOut) void UnpackStencilState(const vk::PackedStencilOpState &packedState,
uint8_t stencilReference,
VkStencilOpState *stateOut)
{ {
stateOut->failOp = static_cast<VkStencilOp>(packedState.failOp); stateOut->failOp = static_cast<VkStencilOp>(packedState.failOp);
stateOut->passOp = static_cast<VkStencilOp>(packedState.passOp); stateOut->passOp = static_cast<VkStencilOp>(packedState.passOp);
...@@ -160,20 +164,18 @@ void UnpackStencilState(const vk::PackedStencilOpState &packedState, VkStencilOp ...@@ -160,20 +164,18 @@ void UnpackStencilState(const vk::PackedStencilOpState &packedState, VkStencilOp
stateOut->compareOp = static_cast<VkCompareOp>(packedState.compareOp); stateOut->compareOp = static_cast<VkCompareOp>(packedState.compareOp);
stateOut->compareMask = packedState.compareMask; stateOut->compareMask = packedState.compareMask;
stateOut->writeMask = packedState.writeMask; stateOut->writeMask = packedState.writeMask;
stateOut->reference = packedState.reference; stateOut->reference = stencilReference;
} }
void UnpackBlendAttachmentState(const vk::PackedColorBlendAttachmentState &packedState, void UnpackBlendAttachmentState(const vk::PackedColorBlendAttachmentState &packedState,
VkPipelineColorBlendAttachmentState *stateOut) VkPipelineColorBlendAttachmentState *stateOut)
{ {
stateOut->blendEnable = static_cast<VkBool32>(packedState.blendEnable);
stateOut->srcColorBlendFactor = static_cast<VkBlendFactor>(packedState.srcColorBlendFactor); stateOut->srcColorBlendFactor = static_cast<VkBlendFactor>(packedState.srcColorBlendFactor);
stateOut->dstColorBlendFactor = static_cast<VkBlendFactor>(packedState.dstColorBlendFactor); stateOut->dstColorBlendFactor = static_cast<VkBlendFactor>(packedState.dstColorBlendFactor);
stateOut->colorBlendOp = static_cast<VkBlendOp>(packedState.colorBlendOp); stateOut->colorBlendOp = static_cast<VkBlendOp>(packedState.colorBlendOp);
stateOut->srcAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.srcAlphaBlendFactor); stateOut->srcAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.srcAlphaBlendFactor);
stateOut->dstAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.dstAlphaBlendFactor); stateOut->dstAlphaBlendFactor = static_cast<VkBlendFactor>(packedState.dstAlphaBlendFactor);
stateOut->alphaBlendOp = static_cast<VkBlendOp>(packedState.alphaBlendOp); stateOut->alphaBlendOp = static_cast<VkBlendOp>(packedState.alphaBlendOp);
stateOut->colorWriteMask = static_cast<VkColorComponentFlags>(packedState.colorWriteMask);
} }
angle::Result InitializeRenderPassFromDesc(vk::Context *context, angle::Result InitializeRenderPassFromDesc(vk::Context *context,
...@@ -240,6 +242,45 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context, ...@@ -240,6 +242,45 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context,
return angle::Result::Continue(); return angle::Result::Continue();
} }
// Utility for setting a value on a packed 4-bit integer array.
template <typename SrcT>
void Int4Array_Set(uint8_t *arrayBytes, uint32_t arrayIndex, SrcT value)
{
uint32_t byteIndex = arrayIndex >> 1;
ASSERT(value < 16);
if ((arrayIndex & 1) == 0)
{
arrayBytes[byteIndex] &= 0xF0;
arrayBytes[byteIndex] |= static_cast<uint8_t>(value);
}
else
{
arrayBytes[byteIndex] &= 0x0F;
arrayBytes[byteIndex] |= static_cast<uint8_t>(value) << 4;
}
}
// Utility for getting a value from a packed 4-bit integer array.
template <typename DestT>
DestT Int4Array_Get(const uint8_t *arrayBytes, uint32_t arrayIndex)
{
uint32_t byteIndex = arrayIndex >> 1;
if ((arrayIndex & 1) == 0)
{
return static_cast<DestT>(arrayBytes[byteIndex] & 0xF);
}
else
{
return static_cast<DestT>(arrayBytes[byteIndex] >> 4);
}
}
// Helper macro that casts to a bitfield type then verifies no bits were dropped.
#define SetBitField(lhs, rhs) \
lhs = static_cast<typename std::decay<decltype(lhs)>::type>(rhs); \
ASSERT(static_cast<decltype(rhs)>(lhs) == rhs);
} // anonymous namespace } // anonymous namespace
// RenderPassDesc implementation. // RenderPassDesc implementation.
...@@ -255,9 +296,14 @@ RenderPassDesc::RenderPassDesc(const RenderPassDesc &other) ...@@ -255,9 +296,14 @@ RenderPassDesc::RenderPassDesc(const RenderPassDesc &other)
memcpy(this, &other, sizeof(RenderPassDesc)); memcpy(this, &other, sizeof(RenderPassDesc));
} }
size_t RenderPassDesc::colorAttachmentCount() const
{
return mColorAttachmentCount;
}
size_t RenderPassDesc::attachmentCount() const size_t RenderPassDesc::attachmentCount() const
{ {
return mAttachmentCount; return mColorAttachmentCount + mDepthStencilAttachmentCount;
} }
void RenderPassDesc::setSamples(GLint samples) void RenderPassDesc::setSamples(GLint samples)
...@@ -268,10 +314,21 @@ void RenderPassDesc::setSamples(GLint samples) ...@@ -268,10 +314,21 @@ void RenderPassDesc::setSamples(GLint samples)
void RenderPassDesc::packAttachment(const Format &format) void RenderPassDesc::packAttachment(const Format &format)
{ {
ASSERT(mAttachmentCount < mAttachmentFormats.size() - 1); ASSERT(attachmentCount() < mAttachmentFormats.size() - 1);
static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(), static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
"Too many ANGLE formats to fit in uint8_t"); "Too many ANGLE formats to fit in uint8_t");
mAttachmentFormats[mAttachmentCount++] = static_cast<uint8_t>(format.angleFormatID); uint8_t &packedFormat = mAttachmentFormats[attachmentCount()];
SetBitField(packedFormat, format.angleFormatID);
if (format.angleFormat().hasDepthOrStencilBits())
{
mDepthStencilAttachmentCount++;
}
else
{
// Force the user to pack the depth/stencil attachment last.
ASSERT(mDepthStencilAttachmentCount == 0);
mColorAttachmentCount++;
}
} }
RenderPassDesc &RenderPassDesc::operator=(const RenderPassDesc &other) RenderPassDesc &RenderPassDesc::operator=(const RenderPassDesc &other)
...@@ -304,7 +361,6 @@ void PipelineDesc::operator delete(void *ptr) ...@@ -304,7 +361,6 @@ void PipelineDesc::operator delete(void *ptr)
PipelineDesc::PipelineDesc() PipelineDesc::PipelineDesc()
{ {
ANGLE_UNUSED_VARIABLE(mPadding);
memset(this, 0, sizeof(PipelineDesc)); memset(this, 0, sizeof(PipelineDesc));
} }
...@@ -331,78 +387,85 @@ bool PipelineDesc::operator==(const PipelineDesc &other) const ...@@ -331,78 +387,85 @@ bool PipelineDesc::operator==(const PipelineDesc &other) const
return (memcmp(this, &other, sizeof(PipelineDesc)) == 0); return (memcmp(this, &other, sizeof(PipelineDesc)) == 0);
} }
// TODO(jmadill): We should prefer using Packed GLenums. http://anglebug.com/2169
void PipelineDesc::initDefaults() void PipelineDesc::initDefaults()
{ {
mInputAssemblyInfo.topology = static_cast<uint32_t>(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); mRasterizationAndMultisampleStateInfo.depthClampEnable = 0;
mInputAssemblyInfo.primitiveRestartEnable = 0; mRasterizationAndMultisampleStateInfo.rasterizationDiscardEnable = 0;
SetBitField(mRasterizationAndMultisampleStateInfo.polygonMode, VK_POLYGON_MODE_FILL);
mRasterizationStateInfo.depthClampEnable = 0; SetBitField(mRasterizationAndMultisampleStateInfo.cullMode, VK_CULL_MODE_NONE);
mRasterizationStateInfo.rasterizationDiscardEnable = 0; SetBitField(mRasterizationAndMultisampleStateInfo.frontFace, VK_FRONT_FACE_CLOCKWISE);
mRasterizationStateInfo.polygonMode = static_cast<uint16_t>(VK_POLYGON_MODE_FILL); mRasterizationAndMultisampleStateInfo.depthBiasEnable = 0;
mRasterizationStateInfo.cullMode = static_cast<uint16_t>(VK_CULL_MODE_NONE); mRasterizationAndMultisampleStateInfo.depthBiasConstantFactor = 0.0f;
mRasterizationStateInfo.frontFace = static_cast<uint16_t>(VK_FRONT_FACE_CLOCKWISE); mRasterizationAndMultisampleStateInfo.depthBiasClamp = 0.0f;
mRasterizationStateInfo.depthBiasEnable = 0; mRasterizationAndMultisampleStateInfo.depthBiasSlopeFactor = 0.0f;
mRasterizationStateInfo.depthBiasConstantFactor = 0.0f; mRasterizationAndMultisampleStateInfo.lineWidth = 1.0f;
mRasterizationStateInfo.depthBiasClamp = 0.0f;
mRasterizationStateInfo.depthBiasSlopeFactor = 0.0f; mRasterizationAndMultisampleStateInfo.rasterizationSamples = 1;
mRasterizationStateInfo.lineWidth = 1.0f; mRasterizationAndMultisampleStateInfo.sampleShadingEnable = 0;
mRasterizationAndMultisampleStateInfo.minSampleShading = 0.0f;
mMultisampleStateInfo.rasterizationSamples = 1; for (uint32_t &sampleMask : mRasterizationAndMultisampleStateInfo.sampleMask)
mMultisampleStateInfo.sampleShadingEnable = 0;
mMultisampleStateInfo.minSampleShading = 0.0f;
for (uint32_t &sampleMask : mMultisampleStateInfo.sampleMask)
{ {
sampleMask = 0; sampleMask = 0;
} }
mMultisampleStateInfo.alphaToCoverageEnable = 0; mRasterizationAndMultisampleStateInfo.alphaToCoverageEnable = 0;
mMultisampleStateInfo.alphaToOneEnable = 0; mRasterizationAndMultisampleStateInfo.alphaToOneEnable = 0;
mDepthStencilStateInfo.depthTestEnable = 0; mDepthStencilStateInfo.depthTestEnable = 0;
mDepthStencilStateInfo.depthWriteEnable = 1; mDepthStencilStateInfo.depthWriteEnable = 1;
mDepthStencilStateInfo.depthCompareOp = static_cast<uint8_t>(VK_COMPARE_OP_LESS); SetBitField(mDepthStencilStateInfo.depthCompareOp, VK_COMPARE_OP_LESS);
mDepthStencilStateInfo.depthBoundsTestEnable = 0; mDepthStencilStateInfo.depthBoundsTestEnable = 0;
mDepthStencilStateInfo.stencilTestEnable = 0; mDepthStencilStateInfo.stencilTestEnable = 0;
mDepthStencilStateInfo.minDepthBounds = 0.0f; mDepthStencilStateInfo.minDepthBounds = 0.0f;
mDepthStencilStateInfo.maxDepthBounds = 0.0f; mDepthStencilStateInfo.maxDepthBounds = 0.0f;
mDepthStencilStateInfo.front.failOp = static_cast<uint8_t>(VK_STENCIL_OP_KEEP); SetBitField(mDepthStencilStateInfo.front.failOp, VK_STENCIL_OP_KEEP);
mDepthStencilStateInfo.front.passOp = static_cast<uint8_t>(VK_STENCIL_OP_KEEP); SetBitField(mDepthStencilStateInfo.front.passOp, VK_STENCIL_OP_KEEP);
mDepthStencilStateInfo.front.depthFailOp = static_cast<uint8_t>(VK_STENCIL_OP_KEEP); SetBitField(mDepthStencilStateInfo.front.depthFailOp, VK_STENCIL_OP_KEEP);
mDepthStencilStateInfo.front.compareOp = static_cast<uint8_t>(VK_COMPARE_OP_ALWAYS); SetBitField(mDepthStencilStateInfo.front.compareOp, VK_COMPARE_OP_ALWAYS);
mDepthStencilStateInfo.front.compareMask = static_cast<uint32_t>(-1); SetBitField(mDepthStencilStateInfo.front.compareMask, 0xFF);
mDepthStencilStateInfo.front.writeMask = static_cast<uint32_t>(-1); SetBitField(mDepthStencilStateInfo.front.writeMask, 0xFF);
mDepthStencilStateInfo.front.reference = 0; mDepthStencilStateInfo.frontStencilReference = 0;
mDepthStencilStateInfo.back.failOp = static_cast<uint8_t>(VK_STENCIL_OP_KEEP); SetBitField(mDepthStencilStateInfo.back.failOp, VK_STENCIL_OP_KEEP);
mDepthStencilStateInfo.back.passOp = static_cast<uint8_t>(VK_STENCIL_OP_KEEP); SetBitField(mDepthStencilStateInfo.back.passOp, VK_STENCIL_OP_KEEP);
mDepthStencilStateInfo.back.depthFailOp = static_cast<uint8_t>(VK_STENCIL_OP_KEEP); SetBitField(mDepthStencilStateInfo.back.depthFailOp, VK_STENCIL_OP_KEEP);
mDepthStencilStateInfo.back.compareOp = static_cast<uint8_t>(VK_COMPARE_OP_ALWAYS); SetBitField(mDepthStencilStateInfo.back.compareOp, VK_COMPARE_OP_ALWAYS);
mDepthStencilStateInfo.back.compareMask = static_cast<uint32_t>(-1); SetBitField(mDepthStencilStateInfo.back.compareMask, 0xFF);
mDepthStencilStateInfo.back.writeMask = static_cast<uint32_t>(-1); SetBitField(mDepthStencilStateInfo.back.writeMask, 0xFF);
mDepthStencilStateInfo.back.reference = 0; mDepthStencilStateInfo.backStencilReference = 0;
// TODO(jmadill): Blend state/MRT. PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend =
mInputAssembltyAndColorBlendStateInfo;
inputAndBlend.logicOpEnable = 0;
inputAndBlend.logicOp = static_cast<uint32_t>(VK_LOGIC_OP_CLEAR);
inputAndBlend.blendEnableMask = 0;
inputAndBlend.blendConstants[0] = 0.0f;
inputAndBlend.blendConstants[1] = 0.0f;
inputAndBlend.blendConstants[2] = 0.0f;
inputAndBlend.blendConstants[3] = 0.0f;
VkFlags allColorBits = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
for (uint32_t colorIndex = 0; colorIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorIndex)
{
Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndex, allColorBits);
}
PackedColorBlendAttachmentState blendAttachmentState; PackedColorBlendAttachmentState blendAttachmentState;
blendAttachmentState.blendEnable = 0; SetBitField(blendAttachmentState.srcColorBlendFactor, VK_BLEND_FACTOR_ONE);
blendAttachmentState.srcColorBlendFactor = static_cast<uint8_t>(VK_BLEND_FACTOR_ONE); SetBitField(blendAttachmentState.dstColorBlendFactor, VK_BLEND_FACTOR_ONE);
blendAttachmentState.dstColorBlendFactor = static_cast<uint8_t>(VK_BLEND_FACTOR_ONE); SetBitField(blendAttachmentState.colorBlendOp, VK_BLEND_OP_ADD);
blendAttachmentState.colorBlendOp = static_cast<uint8_t>(VK_BLEND_OP_ADD); SetBitField(blendAttachmentState.srcAlphaBlendFactor, VK_BLEND_FACTOR_ONE);
blendAttachmentState.srcAlphaBlendFactor = static_cast<uint8_t>(VK_BLEND_FACTOR_ONE); SetBitField(blendAttachmentState.dstAlphaBlendFactor, VK_BLEND_FACTOR_ONE);
blendAttachmentState.dstAlphaBlendFactor = static_cast<uint8_t>(VK_BLEND_FACTOR_ONE); SetBitField(blendAttachmentState.alphaBlendOp, VK_BLEND_OP_ADD);
blendAttachmentState.alphaBlendOp = static_cast<uint8_t>(VK_BLEND_OP_ADD);
blendAttachmentState.colorWriteMask = std::fill(&inputAndBlend.attachments[0],
static_cast<uint8_t>(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | &inputAndBlend.attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS],
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
mColorBlendStateInfo.logicOpEnable = 0;
mColorBlendStateInfo.logicOp = static_cast<uint32_t>(VK_LOGIC_OP_CLEAR);
mColorBlendStateInfo.attachmentCount = 1;
mColorBlendStateInfo.blendConstants[0] = 0.0f;
mColorBlendStateInfo.blendConstants[1] = 0.0f;
mColorBlendStateInfo.blendConstants[2] = 0.0f;
mColorBlendStateInfo.blendConstants[3] = 0.0f;
std::fill(&mColorBlendStateInfo.attachments[0],
&mColorBlendStateInfo.attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS],
blendAttachmentState); blendAttachmentState);
inputAndBlend.topology = static_cast<uint16_t>(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
inputAndBlend.primitiveRestartEnable = 0;
} }
angle::Result PipelineDesc::initializePipeline(vk::Context *context, angle::Result PipelineDesc::initializePipeline(vk::Context *context,
...@@ -446,23 +509,30 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context, ...@@ -446,23 +509,30 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context,
uint32_t vertexAttribCount = 0; uint32_t vertexAttribCount = 0;
size_t unpackedSize = sizeof(shaderStages) + sizeof(vertexInputState) +
sizeof(inputAssemblyState) + sizeof(viewportState) + sizeof(rasterState) +
sizeof(multisampleState) + sizeof(depthStencilState) +
sizeof(blendAttachmentState) + sizeof(blendState) + sizeof(bindingDescs) +
sizeof(attributeDescs);
ANGLE_UNUSED_VARIABLE(unpackedSize);
for (size_t attribIndexSizeT : activeAttribLocationsMask) for (size_t attribIndexSizeT : activeAttribLocationsMask)
{ {
const auto attribIndex = static_cast<uint32_t>(attribIndexSizeT); const uint32_t attribIndex = static_cast<uint32_t>(attribIndexSizeT);
VkVertexInputBindingDescription &bindingDesc = bindingDescs[vertexAttribCount]; VkVertexInputBindingDescription &bindingDesc = bindingDescs[vertexAttribCount];
VkVertexInputAttributeDescription &attribDesc = attributeDescs[vertexAttribCount]; VkVertexInputAttributeDescription &attribDesc = attributeDescs[vertexAttribCount];
const PackedVertexInputBindingDesc &packedBinding = mVertexInputBindings[attribIndex]; const PackedVertexInputBindingDesc &packedBinding = mVertexInputBindings[attribIndex];
const PackedVertexInputAttributeDesc &packedAttrib = mVertexInputAttribs[attribIndex];
bindingDesc.binding = attribIndex; bindingDesc.binding = attribIndex;
bindingDesc.inputRate = static_cast<VkVertexInputRate>(packedBinding.inputRate); bindingDesc.inputRate = static_cast<VkVertexInputRate>(packedBinding.inputRate);
bindingDesc.stride = static_cast<uint32_t>(packedBinding.stride); bindingDesc.stride = static_cast<uint32_t>(packedBinding.stride);
// The binding or location might change in future ES versions.
attribDesc.binding = attribIndex; attribDesc.binding = attribIndex;
attribDesc.format = static_cast<VkFormat>(packedAttrib.format); attribDesc.format = static_cast<VkFormat>(mVertexInputAttribs.formats[attribIndex]);
attribDesc.location = static_cast<uint32_t>(packedAttrib.location); attribDesc.location = static_cast<uint32_t>(attribIndex);
attribDesc.offset = packedAttrib.offset; attribDesc.offset = mVertexInputAttribs.offsets[attribIndex];
vertexAttribCount++; vertexAttribCount++;
} }
...@@ -478,9 +548,10 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context, ...@@ -478,9 +548,10 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context,
// Primitive topology is filled in at draw time. // Primitive topology is filled in at draw time.
inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssemblyState.flags = 0; inputAssemblyState.flags = 0;
inputAssemblyState.topology = static_cast<VkPrimitiveTopology>(mInputAssemblyInfo.topology); inputAssemblyState.topology =
static_cast<VkPrimitiveTopology>(mInputAssembltyAndColorBlendStateInfo.topology);
inputAssemblyState.primitiveRestartEnable = inputAssemblyState.primitiveRestartEnable =
static_cast<VkBool32>(mInputAssemblyInfo.primitiveRestartEnable); static_cast<VkBool32>(mInputAssembltyAndColorBlendStateInfo.primitiveRestartEnable);
// Set initial viewport and scissor state. // Set initial viewport and scissor state.
...@@ -491,35 +562,35 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context, ...@@ -491,35 +562,35 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context,
viewportState.scissorCount = 1; viewportState.scissorCount = 1;
viewportState.pScissors = &mScissor; viewportState.pScissors = &mScissor;
const PackedRasterizationAndMultisampleStateInfo &rasterAndMS =
mRasterizationAndMultisampleStateInfo;
// Rasterizer state. // Rasterizer state.
rasterState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rasterState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterState.flags = 0; rasterState.flags = 0;
rasterState.depthClampEnable = static_cast<VkBool32>(mRasterizationStateInfo.depthClampEnable); rasterState.depthClampEnable = static_cast<VkBool32>(rasterAndMS.depthClampEnable);
rasterState.rasterizerDiscardEnable = rasterState.rasterizerDiscardEnable =
static_cast<VkBool32>(mRasterizationStateInfo.rasterizationDiscardEnable); static_cast<VkBool32>(rasterAndMS.rasterizationDiscardEnable);
rasterState.polygonMode = static_cast<VkPolygonMode>(mRasterizationStateInfo.polygonMode); rasterState.polygonMode = static_cast<VkPolygonMode>(rasterAndMS.polygonMode);
rasterState.cullMode = static_cast<VkCullModeFlags>(mRasterizationStateInfo.cullMode); rasterState.cullMode = static_cast<VkCullModeFlags>(rasterAndMS.cullMode);
rasterState.frontFace = static_cast<VkFrontFace>(mRasterizationStateInfo.frontFace); rasterState.frontFace = static_cast<VkFrontFace>(rasterAndMS.frontFace);
rasterState.depthBiasEnable = static_cast<VkBool32>(mRasterizationStateInfo.depthBiasEnable); rasterState.depthBiasEnable = static_cast<VkBool32>(rasterAndMS.depthBiasEnable);
rasterState.depthBiasConstantFactor = mRasterizationStateInfo.depthBiasConstantFactor; rasterState.depthBiasConstantFactor = rasterAndMS.depthBiasConstantFactor;
rasterState.depthBiasClamp = mRasterizationStateInfo.depthBiasClamp; rasterState.depthBiasClamp = rasterAndMS.depthBiasClamp;
rasterState.depthBiasSlopeFactor = mRasterizationStateInfo.depthBiasSlopeFactor; rasterState.depthBiasSlopeFactor = rasterAndMS.depthBiasSlopeFactor;
rasterState.lineWidth = mRasterizationStateInfo.lineWidth; rasterState.lineWidth = rasterAndMS.lineWidth;
// Multisample state. // Multisample state.
multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampleState.flags = 0; multisampleState.flags = 0;
multisampleState.rasterizationSamples = multisampleState.rasterizationSamples = gl_vk::GetSamples(rasterAndMS.rasterizationSamples);
gl_vk::GetSamples(mMultisampleStateInfo.rasterizationSamples); multisampleState.sampleShadingEnable = static_cast<VkBool32>(rasterAndMS.sampleShadingEnable);
multisampleState.sampleShadingEnable = multisampleState.minSampleShading = rasterAndMS.minSampleShading;
static_cast<VkBool32>(mMultisampleStateInfo.sampleShadingEnable);
multisampleState.minSampleShading = mMultisampleStateInfo.minSampleShading;
// TODO(jmadill): sample masks // TODO(jmadill): sample masks
multisampleState.pSampleMask = nullptr; multisampleState.pSampleMask = nullptr;
multisampleState.alphaToCoverageEnable = multisampleState.alphaToCoverageEnable =
static_cast<VkBool32>(mMultisampleStateInfo.alphaToCoverageEnable); static_cast<VkBool32>(rasterAndMS.alphaToCoverageEnable);
multisampleState.alphaToOneEnable = multisampleState.alphaToOneEnable = static_cast<VkBool32>(rasterAndMS.alphaToOneEnable);
static_cast<VkBool32>(mMultisampleStateInfo.alphaToOneEnable);
// Depth/stencil state. // Depth/stencil state.
depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
...@@ -534,27 +605,38 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context, ...@@ -534,27 +605,38 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context,
static_cast<VkBool32>(mDepthStencilStateInfo.depthBoundsTestEnable); static_cast<VkBool32>(mDepthStencilStateInfo.depthBoundsTestEnable);
depthStencilState.stencilTestEnable = depthStencilState.stencilTestEnable =
static_cast<VkBool32>(mDepthStencilStateInfo.stencilTestEnable); static_cast<VkBool32>(mDepthStencilStateInfo.stencilTestEnable);
UnpackStencilState(mDepthStencilStateInfo.front, &depthStencilState.front); UnpackStencilState(mDepthStencilStateInfo.front, mDepthStencilStateInfo.frontStencilReference,
UnpackStencilState(mDepthStencilStateInfo.back, &depthStencilState.back); &depthStencilState.front);
UnpackStencilState(mDepthStencilStateInfo.back, mDepthStencilStateInfo.backStencilReference,
&depthStencilState.back);
depthStencilState.minDepthBounds = mDepthStencilStateInfo.minDepthBounds; depthStencilState.minDepthBounds = mDepthStencilStateInfo.minDepthBounds;
depthStencilState.maxDepthBounds = mDepthStencilStateInfo.maxDepthBounds; depthStencilState.maxDepthBounds = mDepthStencilStateInfo.maxDepthBounds;
const PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend =
mInputAssembltyAndColorBlendStateInfo;
blendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; blendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
blendState.flags = 0; blendState.flags = 0;
blendState.logicOpEnable = static_cast<VkBool32>(mColorBlendStateInfo.logicOpEnable); blendState.logicOpEnable = static_cast<VkBool32>(inputAndBlend.logicOpEnable);
blendState.logicOp = static_cast<VkLogicOp>(mColorBlendStateInfo.logicOp); blendState.logicOp = static_cast<VkLogicOp>(inputAndBlend.logicOp);
blendState.attachmentCount = mColorBlendStateInfo.attachmentCount; blendState.attachmentCount = mRenderPassDesc.colorAttachmentCount();
blendState.pAttachments = blendAttachmentState.data(); blendState.pAttachments = blendAttachmentState.data();
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
blendState.blendConstants[i] = mColorBlendStateInfo.blendConstants[i]; blendState.blendConstants[i] = inputAndBlend.blendConstants[i];
} }
const gl::DrawBufferMask blendEnableMask(inputAndBlend.blendEnableMask);
for (uint32_t colorIndex = 0; colorIndex < blendState.attachmentCount; ++colorIndex) for (uint32_t colorIndex = 0; colorIndex < blendState.attachmentCount; ++colorIndex)
{ {
UnpackBlendAttachmentState(mColorBlendStateInfo.attachments[colorIndex], VkPipelineColorBlendAttachmentState &state = blendAttachmentState[colorIndex];
&blendAttachmentState[colorIndex]);
state.blendEnable = blendEnableMask[colorIndex] ? VK_TRUE : VK_FALSE;
state.colorWriteMask =
Int4Array_Get<VkColorComponentFlags>(inputAndBlend.colorWriteMaskBits, colorIndex);
UnpackBlendAttachmentState(inputAndBlend.attachments[colorIndex], &state);
} }
// TODO(jmadill): Dynamic state. // TODO(jmadill): Dynamic state.
...@@ -636,23 +718,25 @@ void PipelineDesc::updateVertexInputInfo(const VertexInputBindings &bindings, ...@@ -636,23 +718,25 @@ void PipelineDesc::updateVertexInputInfo(const VertexInputBindings &bindings,
void PipelineDesc::updateTopology(gl::PrimitiveMode drawMode) void PipelineDesc::updateTopology(gl::PrimitiveMode drawMode)
{ {
mInputAssemblyInfo.topology = static_cast<uint32_t>(gl_vk::GetPrimitiveTopology(drawMode)); mInputAssembltyAndColorBlendStateInfo.topology =
static_cast<uint32_t>(gl_vk::GetPrimitiveTopology(drawMode));
} }
void PipelineDesc::updateCullMode(const gl::RasterizerState &rasterState) void PipelineDesc::updateCullMode(const gl::RasterizerState &rasterState)
{ {
mRasterizationStateInfo.cullMode = static_cast<uint16_t>(gl_vk::GetCullMode(rasterState)); mRasterizationAndMultisampleStateInfo.cullMode =
static_cast<uint16_t>(gl_vk::GetCullMode(rasterState));
} }
void PipelineDesc::updateFrontFace(const gl::RasterizerState &rasterState, bool invertFrontFace) void PipelineDesc::updateFrontFace(const gl::RasterizerState &rasterState, bool invertFrontFace)
{ {
mRasterizationStateInfo.frontFace = mRasterizationAndMultisampleStateInfo.frontFace =
static_cast<uint16_t>(gl_vk::GetFrontFace(rasterState.frontFace, invertFrontFace)); static_cast<uint16_t>(gl_vk::GetFrontFace(rasterState.frontFace, invertFrontFace));
} }
void PipelineDesc::updateLineWidth(float lineWidth) void PipelineDesc::updateLineWidth(float lineWidth)
{ {
mRasterizationStateInfo.lineWidth = lineWidth; mRasterizationAndMultisampleStateInfo.lineWidth = lineWidth;
} }
const RenderPassDesc &PipelineDesc::getRenderPassDesc() const const RenderPassDesc &PipelineDesc::getRenderPassDesc() const
...@@ -662,23 +746,25 @@ const RenderPassDesc &PipelineDesc::getRenderPassDesc() const ...@@ -662,23 +746,25 @@ const RenderPassDesc &PipelineDesc::getRenderPassDesc() const
void PipelineDesc::updateBlendColor(const gl::ColorF &color) void PipelineDesc::updateBlendColor(const gl::ColorF &color)
{ {
mColorBlendStateInfo.blendConstants[0] = color.red; mInputAssembltyAndColorBlendStateInfo.blendConstants[0] = color.red;
mColorBlendStateInfo.blendConstants[1] = color.green; mInputAssembltyAndColorBlendStateInfo.blendConstants[1] = color.green;
mColorBlendStateInfo.blendConstants[2] = color.blue; mInputAssembltyAndColorBlendStateInfo.blendConstants[2] = color.blue;
mColorBlendStateInfo.blendConstants[3] = color.alpha; mInputAssembltyAndColorBlendStateInfo.blendConstants[3] = color.alpha;
} }
void PipelineDesc::updateBlendEnabled(bool isBlendEnabled) void PipelineDesc::updateBlendEnabled(bool isBlendEnabled)
{ {
for (auto &blendAttachmentState : mColorBlendStateInfo.attachments) gl::DrawBufferMask blendEnabled;
{ if (isBlendEnabled)
blendAttachmentState.blendEnable = isBlendEnabled; blendEnabled.set();
} mInputAssembltyAndColorBlendStateInfo.blendEnableMask =
static_cast<uint8_t>(blendEnabled.bits());
} }
void PipelineDesc::updateBlendEquations(const gl::BlendState &blendState) void PipelineDesc::updateBlendEquations(const gl::BlendState &blendState)
{ {
for (auto &blendAttachmentState : mColorBlendStateInfo.attachments) for (PackedColorBlendAttachmentState &blendAttachmentState :
mInputAssembltyAndColorBlendStateInfo.attachments)
{ {
blendAttachmentState.colorBlendOp = PackGLBlendOp(blendState.blendEquationRGB); blendAttachmentState.colorBlendOp = PackGLBlendOp(blendState.blendEquationRGB);
blendAttachmentState.alphaBlendOp = PackGLBlendOp(blendState.blendEquationAlpha); blendAttachmentState.alphaBlendOp = PackGLBlendOp(blendState.blendEquationAlpha);
...@@ -687,7 +773,8 @@ void PipelineDesc::updateBlendEquations(const gl::BlendState &blendState) ...@@ -687,7 +773,8 @@ void PipelineDesc::updateBlendEquations(const gl::BlendState &blendState)
void PipelineDesc::updateBlendFuncs(const gl::BlendState &blendState) void PipelineDesc::updateBlendFuncs(const gl::BlendState &blendState)
{ {
for (auto &blendAttachmentState : mColorBlendStateInfo.attachments) for (PackedColorBlendAttachmentState &blendAttachmentState :
mInputAssembltyAndColorBlendStateInfo.attachments)
{ {
blendAttachmentState.srcColorBlendFactor = PackGLBlendFactor(blendState.sourceBlendRGB); blendAttachmentState.srcColorBlendFactor = PackGLBlendFactor(blendState.sourceBlendRGB);
blendAttachmentState.dstColorBlendFactor = PackGLBlendFactor(blendState.destBlendRGB); blendAttachmentState.dstColorBlendFactor = PackGLBlendFactor(blendState.destBlendRGB);
...@@ -699,12 +786,14 @@ void PipelineDesc::updateBlendFuncs(const gl::BlendState &blendState) ...@@ -699,12 +786,14 @@ void PipelineDesc::updateBlendFuncs(const gl::BlendState &blendState)
void PipelineDesc::updateColorWriteMask(VkColorComponentFlags colorComponentFlags, void PipelineDesc::updateColorWriteMask(VkColorComponentFlags colorComponentFlags,
const gl::DrawBufferMask &alphaMask) const gl::DrawBufferMask &alphaMask)
{ {
PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend =
mInputAssembltyAndColorBlendStateInfo;
uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags); uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
for (size_t colorIndex = 0; colorIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorIndex++) for (size_t colorIndex = 0; colorIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorIndex++)
{ {
mColorBlendStateInfo.attachments[colorIndex].colorWriteMask = uint8_t mask = alphaMask[colorIndex] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask;
alphaMask[colorIndex] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask; Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndex, mask);
} }
} }
...@@ -742,17 +831,17 @@ void PipelineDesc::updateStencilTestEnabled(const gl::DepthStencilState &depthSt ...@@ -742,17 +831,17 @@ void PipelineDesc::updateStencilTestEnabled(const gl::DepthStencilState &depthSt
void PipelineDesc::updateStencilFrontFuncs(GLint ref, void PipelineDesc::updateStencilFrontFuncs(GLint ref,
const gl::DepthStencilState &depthStencilState) const gl::DepthStencilState &depthStencilState)
{ {
mDepthStencilStateInfo.front.reference = ref; mDepthStencilStateInfo.frontStencilReference = static_cast<uint8_t>(ref);
mDepthStencilStateInfo.front.compareOp = PackGLCompareFunc(depthStencilState.stencilFunc); mDepthStencilStateInfo.front.compareOp = PackGLCompareFunc(depthStencilState.stencilFunc);
mDepthStencilStateInfo.front.compareMask = static_cast<uint32_t>(depthStencilState.stencilMask); mDepthStencilStateInfo.front.compareMask = static_cast<uint8_t>(depthStencilState.stencilMask);
} }
void PipelineDesc::updateStencilBackFuncs(GLint ref, const gl::DepthStencilState &depthStencilState) void PipelineDesc::updateStencilBackFuncs(GLint ref, const gl::DepthStencilState &depthStencilState)
{ {
mDepthStencilStateInfo.back.reference = ref; mDepthStencilStateInfo.backStencilReference = static_cast<uint8_t>(ref);
mDepthStencilStateInfo.back.compareOp = PackGLCompareFunc(depthStencilState.stencilBackFunc); mDepthStencilStateInfo.back.compareOp = PackGLCompareFunc(depthStencilState.stencilBackFunc);
mDepthStencilStateInfo.back.compareMask = mDepthStencilStateInfo.back.compareMask =
static_cast<uint32_t>(depthStencilState.stencilBackMask); static_cast<uint8_t>(depthStencilState.stencilBackMask);
} }
void PipelineDesc::updateStencilFrontOps(const gl::DepthStencilState &depthStencilState) void PipelineDesc::updateStencilFrontOps(const gl::DepthStencilState &depthStencilState)
...@@ -776,7 +865,7 @@ void PipelineDesc::updateStencilFrontWriteMask(const gl::DepthStencilState &dept ...@@ -776,7 +865,7 @@ void PipelineDesc::updateStencilFrontWriteMask(const gl::DepthStencilState &dept
const gl::Framebuffer *drawFramebuffer) const gl::Framebuffer *drawFramebuffer)
{ {
// Don't write to stencil buffers that should not exist // Don't write to stencil buffers that should not exist
mDepthStencilStateInfo.front.writeMask = static_cast<uint32_t>( mDepthStencilStateInfo.front.writeMask = static_cast<uint8_t>(
drawFramebuffer->hasStencil() ? depthStencilState.stencilWritemask : 0); drawFramebuffer->hasStencil() ? depthStencilState.stencilWritemask : 0);
} }
...@@ -784,19 +873,19 @@ void PipelineDesc::updateStencilBackWriteMask(const gl::DepthStencilState &depth ...@@ -784,19 +873,19 @@ void PipelineDesc::updateStencilBackWriteMask(const gl::DepthStencilState &depth
const gl::Framebuffer *drawFramebuffer) const gl::Framebuffer *drawFramebuffer)
{ {
// Don't write to stencil buffers that should not exist // Don't write to stencil buffers that should not exist
mDepthStencilStateInfo.back.writeMask = static_cast<uint32_t>( mDepthStencilStateInfo.back.writeMask = static_cast<uint8_t>(
drawFramebuffer->hasStencil() ? depthStencilState.stencilBackWritemask : 0); drawFramebuffer->hasStencil() ? depthStencilState.stencilBackWritemask : 0);
} }
void PipelineDesc::updatePolygonOffsetFillEnabled(bool enabled) void PipelineDesc::updatePolygonOffsetFillEnabled(bool enabled)
{ {
mRasterizationStateInfo.depthBiasEnable = enabled; mRasterizationAndMultisampleStateInfo.depthBiasEnable = enabled;
} }
void PipelineDesc::updatePolygonOffset(const gl::RasterizerState &rasterState) void PipelineDesc::updatePolygonOffset(const gl::RasterizerState &rasterState)
{ {
mRasterizationStateInfo.depthBiasSlopeFactor = rasterState.polygonOffsetFactor; mRasterizationAndMultisampleStateInfo.depthBiasSlopeFactor = rasterState.polygonOffsetFactor;
mRasterizationStateInfo.depthBiasConstantFactor = rasterState.polygonOffsetUnits; mRasterizationAndMultisampleStateInfo.depthBiasConstantFactor = rasterState.polygonOffsetUnits;
} }
void PipelineDesc::updateRenderPassDesc(const RenderPassDesc &renderPassDesc) void PipelineDesc::updateRenderPassDesc(const RenderPassDesc &renderPassDesc)
......
...@@ -56,10 +56,12 @@ class alignas(4) RenderPassDesc final ...@@ -56,10 +56,12 @@ class alignas(4) RenderPassDesc final
RenderPassDesc(const RenderPassDesc &other); RenderPassDesc(const RenderPassDesc &other);
RenderPassDesc &operator=(const RenderPassDesc &other); RenderPassDesc &operator=(const RenderPassDesc &other);
// The caller must pack the depth/stencil attachment last.
void packAttachment(const Format &format); void packAttachment(const Format &format);
size_t hash() const; size_t hash() const;
size_t colorAttachmentCount() const;
size_t attachmentCount() const; size_t attachmentCount() const;
void setSamples(GLint samples); void setSamples(GLint samples);
...@@ -68,19 +70,21 @@ class alignas(4) RenderPassDesc final ...@@ -68,19 +70,21 @@ class alignas(4) RenderPassDesc final
angle::FormatID operator[](size_t index) const angle::FormatID operator[](size_t index) const
{ {
ASSERT(index < mAttachmentFormats.size()); ASSERT(index < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1);
return static_cast<angle::FormatID>(mAttachmentFormats[index]); return static_cast<angle::FormatID>(mAttachmentFormats[index]);
} }
private: private:
uint8_t mSamples; uint8_t mSamples;
uint8_t mAttachmentCount; uint8_t mColorAttachmentCount : 4;
uint8_t mDepthStencilAttachmentCount : 4;
gl::AttachmentArray<uint8_t> mAttachmentFormats; gl::AttachmentArray<uint8_t> mAttachmentFormats;
}; };
bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs); bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs);
static_assert(sizeof(RenderPassDesc) == 12, "Size check failed"); constexpr size_t kRenderPassDescSize = sizeof(RenderPassDesc);
static_assert(kRenderPassDescSize == 12, "Size check failed");
struct alignas(8) PackedAttachmentOpsDesc final struct alignas(8) PackedAttachmentOpsDesc final
{ {
...@@ -120,7 +124,7 @@ bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs); ...@@ -120,7 +124,7 @@ bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs);
static_assert(sizeof(AttachmentOpsArray) == 80, "Size check failed"); static_assert(sizeof(AttachmentOpsArray) == 80, "Size check failed");
struct alignas(8) PackedShaderStageInfo final struct PackedShaderStageInfo final
{ {
uint32_t stage; uint32_t stage;
uint32_t moduleSerial; uint32_t moduleSerial;
...@@ -129,7 +133,7 @@ struct alignas(8) PackedShaderStageInfo final ...@@ -129,7 +133,7 @@ struct alignas(8) PackedShaderStageInfo final
static_assert(sizeof(PackedShaderStageInfo) == 8, "Size check failed"); static_assert(sizeof(PackedShaderStageInfo) == 8, "Size check failed");
struct alignas(4) PackedVertexInputBindingDesc final struct PackedVertexInputBindingDesc final
{ {
// Although techncially stride can be any value in ES 2.0, in practice supporting stride // Although techncially stride can be any value in ES 2.0, in practice supporting stride
// greater than MAX_USHORT should not be that helpful. Note that stride limits are // greater than MAX_USHORT should not be that helpful. Note that stride limits are
...@@ -140,32 +144,21 @@ struct alignas(4) PackedVertexInputBindingDesc final ...@@ -140,32 +144,21 @@ struct alignas(4) PackedVertexInputBindingDesc final
static_assert(sizeof(PackedVertexInputBindingDesc) == 4, "Size check failed"); static_assert(sizeof(PackedVertexInputBindingDesc) == 4, "Size check failed");
struct alignas(8) PackedVertexInputAttributeDesc final struct PackedRasterizationAndMultisampleStateInfo final
{
uint16_t location;
uint16_t format;
uint32_t offset;
};
static_assert(sizeof(PackedVertexInputAttributeDesc) == 8, "Size check failed");
struct alignas(8) PackedInputAssemblyInfo
{
uint32_t topology;
uint32_t primitiveRestartEnable;
};
static_assert(sizeof(PackedInputAssemblyInfo) == 8, "Size check failed");
struct alignas(32) PackedRasterizationStateInfo
{ {
// Padded to ensure there's no gaps in this structure or those that use it. // Padded to ensure there's no gaps in this structure or those that use it.
uint32_t depthClampEnable; uint32_t depthClampEnable : 4;
uint32_t rasterizationDiscardEnable; uint32_t rasterizationDiscardEnable : 4;
uint16_t polygonMode; uint32_t polygonMode : 4;
uint16_t cullMode; uint32_t cullMode : 4;
uint16_t frontFace; uint32_t frontFace : 4;
uint16_t depthBiasEnable; uint32_t depthBiasEnable : 4;
uint32_t rasterizationSamples : 4;
uint32_t sampleShadingEnable : 1;
uint32_t alphaToCoverageEnable : 1;
uint32_t alphaToOneEnable : 2;
float minSampleShading;
uint32_t sampleMask[gl::MAX_SAMPLE_MASK_WORDS];
float depthBiasConstantFactor; float depthBiasConstantFactor;
// Note: depth bias clamp is only exposed in a 3.1 extension, but left here for completeness. // Note: depth bias clamp is only exposed in a 3.1 extension, but left here for completeness.
float depthBiasClamp; float depthBiasClamp;
...@@ -173,79 +166,82 @@ struct alignas(32) PackedRasterizationStateInfo ...@@ -173,79 +166,82 @@ struct alignas(32) PackedRasterizationStateInfo
float lineWidth; float lineWidth;
}; };
static_assert(sizeof(PackedRasterizationStateInfo) == 32, "Size check failed"); static constexpr size_t kPackedRasterizationAndMultisampleStateSize =
sizeof(PackedRasterizationAndMultisampleStateInfo);
static_assert(kPackedRasterizationAndMultisampleStateSize == 32, "Size check failed");
struct alignas(16) PackedMultisampleStateInfo final struct PackedStencilOpState final
{ {
uint8_t rasterizationSamples; uint8_t failOp : 4;
uint8_t sampleShadingEnable; uint8_t passOp : 4;
uint8_t alphaToCoverageEnable; uint8_t depthFailOp : 4;
uint8_t alphaToOneEnable; uint8_t compareOp : 4;
float minSampleShading; uint8_t compareMask;
uint32_t sampleMask[gl::MAX_SAMPLE_MASK_WORDS]; uint8_t writeMask;
}; };
static_assert(sizeof(PackedMultisampleStateInfo) == 16, "Size check failed"); static constexpr size_t kPackedStencilOpSize = sizeof(PackedStencilOpState);
static_assert(sizeof(PackedStencilOpState) == 4, "Size check failed");
struct alignas(16) PackedStencilOpState final
{
uint8_t failOp;
uint8_t passOp;
uint8_t depthFailOp;
uint8_t compareOp;
uint32_t compareMask;
uint32_t writeMask;
uint32_t reference;
};
static_assert(sizeof(PackedStencilOpState) == 16, "Size check failed");
struct PackedDepthStencilStateInfo final struct PackedDepthStencilStateInfo final
{ {
uint8_t depthTestEnable; uint8_t depthTestEnable : 1;
uint8_t depthWriteEnable; uint8_t depthWriteEnable : 1;
uint8_t depthCompareOp; uint8_t depthCompareOp : 4;
uint8_t depthBoundsTestEnable; uint8_t depthBoundsTestEnable : 1;
// 32-bits to pad the alignments. uint8_t stencilTestEnable : 1;
uint32_t stencilTestEnable; uint8_t frontStencilReference;
uint8_t backStencilReference;
uint8_t padding;
float minDepthBounds; float minDepthBounds;
float maxDepthBounds; float maxDepthBounds;
PackedStencilOpState front; PackedStencilOpState front;
PackedStencilOpState back; PackedStencilOpState back;
}; };
static_assert(sizeof(PackedDepthStencilStateInfo) == 48, "Size check failed"); constexpr size_t kPackedDepthStencilStateSize = sizeof(PackedDepthStencilStateInfo);
static_assert(kPackedDepthStencilStateSize == 20, "Size check failed");
struct alignas(8) PackedColorBlendAttachmentState final struct PackedColorBlendAttachmentState final
{ {
uint8_t blendEnable; uint16_t srcColorBlendFactor : 5;
uint8_t srcColorBlendFactor; uint16_t dstColorBlendFactor : 5;
uint8_t dstColorBlendFactor; uint16_t colorBlendOp : 6;
uint8_t colorBlendOp; uint16_t srcAlphaBlendFactor : 5;
uint8_t srcAlphaBlendFactor; uint16_t dstAlphaBlendFactor : 5;
uint8_t dstAlphaBlendFactor; uint16_t alphaBlendOp : 6;
uint8_t alphaBlendOp;
uint8_t colorWriteMask;
}; };
static_assert(sizeof(PackedColorBlendAttachmentState) == 8, "Size check failed"); static_assert(sizeof(PackedColorBlendAttachmentState) == 4, "Size check failed");
struct PackedColorBlendStateInfo final struct PackedInputAssemblyAndColorBlendStateInfo final
{ {
// Padded to round the struct size. uint8_t logicOpEnable : 1;
uint32_t logicOpEnable; uint8_t logicOp : 7;
uint32_t logicOp; uint8_t blendEnableMask;
uint32_t attachmentCount; uint8_t colorWriteMaskBits[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS / 2];
uint32_t padding;
float blendConstants[4];
PackedColorBlendAttachmentState attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; PackedColorBlendAttachmentState attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
uint16_t topology : 15;
uint16_t primitiveRestartEnable : 1;
float blendConstants[4];
}; };
static_assert(sizeof(PackedColorBlendStateInfo) == 96, "Size check failed"); constexpr size_t kPackedInputAssemblyAndColorBlendStateSize =
sizeof(PackedInputAssemblyAndColorBlendStateInfo);
static_assert(kPackedInputAssemblyAndColorBlendStateSize == 56, "Size check failed");
using ShaderStageInfo = vk::ShaderMap<PackedShaderStageInfo>; using ShaderStageInfo = vk::ShaderMap<PackedShaderStageInfo>;
using VertexInputBindings = gl::AttribArray<PackedVertexInputBindingDesc>; using VertexInputBindings = gl::AttribArray<PackedVertexInputBindingDesc>;
using VertexInputAttributes = gl::AttribArray<PackedVertexInputAttributeDesc>;
struct VertexInputAttributes final
{
uint8_t formats[gl::MAX_VERTEX_ATTRIBS];
uint16_t offsets[gl::MAX_VERTEX_ATTRIBS]; // can only take 11 bits on NV
};
constexpr size_t kShaderStageInfoSize = sizeof(ShaderStageInfo);
constexpr size_t kVertexInputBindingsSize = sizeof(VertexInputBindings);
constexpr size_t kVertexInputAttributesSize = sizeof(VertexInputAttributes);
class PipelineDesc final class PipelineDesc final
{ {
...@@ -340,18 +336,15 @@ class PipelineDesc final ...@@ -340,18 +336,15 @@ class PipelineDesc final
ShaderStageInfo mShaderStageInfo; ShaderStageInfo mShaderStageInfo;
VertexInputBindings mVertexInputBindings; VertexInputBindings mVertexInputBindings;
VertexInputAttributes mVertexInputAttribs; VertexInputAttributes mVertexInputAttribs;
PackedInputAssemblyInfo mInputAssemblyInfo; RenderPassDesc mRenderPassDesc;
PackedRasterizationAndMultisampleStateInfo mRasterizationAndMultisampleStateInfo;
PackedDepthStencilStateInfo mDepthStencilStateInfo;
PackedInputAssemblyAndColorBlendStateInfo mInputAssembltyAndColorBlendStateInfo;
// TODO(jmadill): Consider using dynamic state for viewport/scissor. // TODO(jmadill): Consider using dynamic state for viewport/scissor.
VkViewport mViewport; VkViewport mViewport;
VkRect2D mScissor; VkRect2D mScissor;
PackedRasterizationStateInfo mRasterizationStateInfo;
PackedMultisampleStateInfo mMultisampleStateInfo;
PackedDepthStencilStateInfo mDepthStencilStateInfo;
PackedColorBlendStateInfo mColorBlendStateInfo;
// TODO(jmadill): Dynamic state. // TODO(jmadill): Dynamic state.
// TODO(jmadill): Pipeline layout // TODO(jmadill): Pipeline layout
RenderPassDesc mRenderPassDesc;
uint8_t mPadding[20];
}; };
// Verify the packed pipeline description has no gaps in the packing. // Verify the packed pipeline description has no gaps in the packing.
...@@ -359,11 +352,10 @@ class PipelineDesc final ...@@ -359,11 +352,10 @@ class PipelineDesc final
// No gaps or padding at the end ensures that hashing and memcmp checks will not run // No gaps or padding at the end ensures that hashing and memcmp checks will not run
// into uninitialized memory regions. // into uninitialized memory regions.
constexpr size_t kPipelineDescSumOfSizes = constexpr size_t kPipelineDescSumOfSizes =
sizeof(ShaderStageInfo) + sizeof(VertexInputBindings) + sizeof(VertexInputAttributes) + kShaderStageInfoSize + kVertexInputBindingsSize + kVertexInputAttributesSize +
sizeof(PackedInputAssemblyInfo) + sizeof(VkViewport) + sizeof(VkRect2D) + kPackedInputAssemblyAndColorBlendStateSize + sizeof(VkViewport) + sizeof(VkRect2D) +
sizeof(PackedRasterizationStateInfo) + sizeof(PackedMultisampleStateInfo) + kPackedRasterizationAndMultisampleStateSize + kPackedDepthStencilStateSize +
sizeof(PackedDepthStencilStateInfo) + sizeof(PackedColorBlendStateInfo) + kRenderPassDescSize;
sizeof(RenderPassDesc) + 20;
static constexpr size_t kPipelineDescSize = sizeof(PipelineDesc); static constexpr size_t kPipelineDescSize = sizeof(PipelineDesc);
static_assert(kPipelineDescSize == kPipelineDescSumOfSizes, "Size mismatch"); static_assert(kPipelineDescSize == kPipelineDescSumOfSizes, "Size mismatch");
......
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