Commit d7149f2a by Le Hoang Quyen Committed by Commit Bot

Metal: Disable unused attribute slots.

If an attribute slot is unused and user enables it but doesn't bind any buffer, Metal validation layer will complain that a buffer slot is missing (even though the slot is not used inside shader). Fix: if shader program doesn't use an attribute slot or there is no buffer bound to it, then disable that attribute. Bug: angleproject:2634 Change-Id: Ib56e0bf64bab13efce8b2972bfe386e26f45e50e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2392171 Commit-Queue: Le Hoang Quyen <le.hoang.q@gmail.com> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent f39e0f01
...@@ -139,7 +139,7 @@ inline size_t GetIndexCount(BufferMtl *srcBuffer, size_t offset, gl::DrawElement ...@@ -139,7 +139,7 @@ inline size_t GetIndexCount(BufferMtl *srcBuffer, size_t offset, gl::DrawElement
inline void SetDefaultVertexBufferLayout(mtl::VertexBufferLayoutDesc *layout) inline void SetDefaultVertexBufferLayout(mtl::VertexBufferLayoutDesc *layout)
{ {
layout->stepFunction = MTLVertexStepFunctionConstant; layout->stepFunction = mtl::kVertexStepFunctionInvalid;
layout->stepRate = 0; layout->stepRate = 0;
layout->stride = 0; layout->stride = 0;
} }
...@@ -264,6 +264,9 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext, ...@@ -264,6 +264,9 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
{ {
mVertexArrayDirty = false; mVertexArrayDirty = false;
const gl::AttributesMask &programActiveAttribsMask =
glContext->getState().getProgram()->getExecutable().getActiveAttribLocationsMask();
const std::vector<gl::VertexAttribute> &attribs = mState.getVertexAttributes(); const std::vector<gl::VertexAttribute> &attribs = mState.getVertexAttributes();
const std::vector<gl::VertexBinding> &bindings = mState.getVertexBindings(); const std::vector<gl::VertexBinding> &bindings = mState.getVertexBindings();
...@@ -280,6 +283,14 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext, ...@@ -280,6 +283,14 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
for (uint32_t v = 0; v < mtl::kMaxVertexAttribs; ++v) for (uint32_t v = 0; v < mtl::kMaxVertexAttribs; ++v)
{ {
if (!programActiveAttribsMask.test(v))
{
desc.attributes[v].format = MTLVertexFormatInvalid;
desc.attributes[v].bufferIndex = 0;
desc.attributes[v].offset = 0;
continue;
}
const auto &attrib = attribs[v]; const auto &attrib = attribs[v];
const gl::VertexBinding &binding = bindings[attrib.bindingIndex]; const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
...@@ -287,7 +298,8 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext, ...@@ -287,7 +298,8 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
desc.attributes[v].format = mCurrentArrayBufferFormats[v]->metalFormat; desc.attributes[v].format = mCurrentArrayBufferFormats[v]->metalFormat;
bool attribEnabled = attrib.enabled; bool attribEnabled = attrib.enabled;
if (attribEnabled && !mCurrentArrayBuffers[v]) if (attribEnabled &&
(!mCurrentArrayBuffers[v] || !mCurrentArrayBuffers[v]->getCurrentBuffer()))
{ {
// Disable it to avoid crash. // Disable it to avoid crash.
attribEnabled = false; attribEnabled = false;
......
...@@ -132,6 +132,11 @@ constexpr uint32_t kDefaultUniformsBindingIndex = kDefaultAttribsBindingIndex + ...@@ -132,6 +132,11 @@ constexpr uint32_t kDefaultUniformsBindingIndex = kDefaultAttribsBindingIndex +
constexpr uint32_t kStencilMaskAll = 0xff; // Only 8 bits stencil is supported constexpr uint32_t kStencilMaskAll = 0xff; // Only 8 bits stencil is supported
// This special constant is used to indicate that a particular vertex descriptor's buffer layout
// index is unused.
constexpr MTLVertexStepFunction kVertexStepFunctionInvalid =
static_cast<MTLVertexStepFunction>(0xff);
constexpr float kEmulatedAlphaValue = 1.0f; constexpr float kEmulatedAlphaValue = 1.0f;
constexpr size_t kOcclusionQueryResultSize = sizeof(uint64_t); constexpr size_t kOcclusionQueryResultSize = sizeof(uint64_t);
......
...@@ -114,7 +114,12 @@ MTLVertexDescriptor *ToObjC(const VertexDesc &desc) ...@@ -114,7 +114,12 @@ MTLVertexDescriptor *ToObjC(const VertexDesc &desc)
for (uint8_t i = 0; i < desc.numBufferLayouts; ++i) for (uint8_t i = 0; i < desc.numBufferLayouts; ++i)
{ {
[objCDesc.layouts setObject:ToObjC(desc.layouts[i]) atIndexedSubscript:i]; // Ignore if stepFunction is kVertexStepFunctionInvalid.
// If we don't set this slot, it will apparently be disabled by metal runtime.
if (desc.layouts[i].stepFunction != kVertexStepFunctionInvalid)
{
[objCDesc.layouts setObject:ToObjC(desc.layouts[i]) atIndexedSubscript:i];
}
} }
return [objCDesc ANGLE_MTL_AUTORELEASE]; return [objCDesc ANGLE_MTL_AUTORELEASE];
......
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