Skip to content

Commit

Permalink
Vulkan: use a dummy buffer for missing attributes.
Browse files Browse the repository at this point in the history
To prevent an excess of variants, sometimes our vertex shaders declare
inputs that they never read from. For example, our skin-and-morph
variant might never read from the skinning attribute, but still declares
the input.

This PR is a sister to #1663, which is a fix for #1525.

See also #1279.
  • Loading branch information
prideout committed Sep 19, 2019
1 parent 8fc94f1 commit 48b73ad
Showing 1 changed file with 23 additions and 3 deletions.
26 changes: 23 additions & 3 deletions filament/backend/src/vulkan/VulkanHandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,20 +583,40 @@ void VulkanRenderPrimitive::setBuffers(VulkanVertexBuffer* vertexBuffer,
memset(varray.attributes, 0, sizeof(varray.attributes));
memset(varray.buffers, 0, sizeof(varray.buffers));

// Position should always be present.
assert(enabledAttributes & 1);

// For each enabled attribute, append to each of the above lists. Note that a single VkBuffer
// handle might be appended more than once, which is perfectly fine.
uint32_t bufferIndex = 0;
for (uint32_t attribIndex = 0; attribIndex < nattrs; attribIndex++) {
Attribute attrib = vertexBuffer->attributes[attribIndex];
VkFormat vkformat = getVkFormat(attrib.type, attrib.flags & Attribute::FLAG_NORMALIZED);

// We re-use the positions buffer as a dummy buffer for any disabled attribute that might
// be consumed by the shader.
VkBuffer vkbuffer = 0;
if (!(enabledAttributes & (1U << attribIndex))) {
continue;

// TODO: all vertex attributes are floats, except for mesh_bone_indices, which are
// unsigned integers. Ideally the Vulkan backend would not need to know about this.
const uint32_t kBoneIndicesLocation = 5; // VertexAttribute::BONE_INDICES
vkformat = attribIndex == kBoneIndicesLocation ? VK_FORMAT_R8G8B8A8_UINT : vkformat;

// TODO: avoid using dummy buffers by adding the concept of frozen renderables.
if (UTILS_LIKELY(enabledAttributes & 1)) {
attrib = vertexBuffer->attributes[0];
} else {
continue;
}
}
const Attribute& attrib = vertexBuffer->attributes[attribIndex];

buffers.push_back(vertexBuffer->buffers[attrib.buffer]->getGpuBuffer());
offsets.push_back(attrib.offset);
varray.attributes[bufferIndex] = {
.location = attribIndex, // matches the GLSL layout specifier
.binding = bufferIndex, // matches the position within vkCmdBindVertexBuffers
.format = getVkFormat(attrib.type, attrib.flags & Attribute::FLAG_NORMALIZED),
.format = vkformat,
.offset = 0
};
varray.buffers[bufferIndex] = {
Expand Down

0 comments on commit 48b73ad

Please sign in to comment.