Hash :
ab42afa6
Author :
Date :
2019-11-21T10:13:44
Metal: fix vertex attribute's conversion lost after changing buffer binding. After vertex buffer's attribute is converted and stored in conversion buffer. Binding the same attribute to another buffer, then binding it back to previous buffer will result in previous conversion information lost. The conversion method would skip the conversion due to buffer's content hadn't been changed, however it didn't reuse the old conversion result. This CL also changed the way binding offset is used in Metal backend. - Previous, the offset would be assigned to the offset field of MTLVertexAttributeDescriptor, then the buffer would simply be bound to the command encoder with offset=0 i.e. setVertexBuffer(buffer, index, 0) - However this approach has several disadvantages. Since Metal doesn't allow MTLVertexAttributeDescriptor's offset to be larger than the vertex attribute's stride, the old approach would force the back-end to convert the attribute and store in conversion buffer. New approach: - MTLVertexAttributeDescriptor's offset will be zero. The offset will be used to bind the buffer itself to the render command encoder. i.e. setVertexBuffer(buffer, index, offset) This way the "offset <= stride" restriction no longer exists. The only restriction is the offset must be multiple of attribute's size. Added 3 new tests: - SimpleStateChangeTest.RebindTranslatedAttribute - VertexAttributeTest.DrawWithLargeBufferOffset - VertexAttributeTest.DrawWithLargeBufferOffsetAndLessComponents Bug: angleproject:2634 Change-Id: I6c2fa8091436e4a24405d791f86d17d97df02d64 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1940009 Commit-Queue: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VertexArrayMtl.h:
// Defines the class interface for VertexArrayMtl, implementing VertexArrayImpl.
//
#ifndef LIBANGLE_RENDERER_METAL_VERTEXARRAYMTL_H_
#define LIBANGLE_RENDERER_METAL_VERTEXARRAYMTL_H_
#include "libANGLE/renderer/VertexArrayImpl.h"
#include "libANGLE/renderer/metal/BufferMtl.h"
#include "libANGLE/renderer/metal/mtl_buffer_pool.h"
#include "libANGLE/renderer/metal/mtl_command_buffer.h"
#include "libANGLE/renderer/metal/mtl_format_utils.h"
#include "libANGLE/renderer/metal/mtl_resources.h"
namespace rx
{
class ContextMtl;
class VertexArrayMtl : public VertexArrayImpl
{
public:
VertexArrayMtl(const gl::VertexArrayState &state, ContextMtl *context);
~VertexArrayMtl() override;
void destroy(const gl::Context *context) override;
angle::Result syncState(const gl::Context *context,
const gl::VertexArray::DirtyBits &dirtyBits,
gl::VertexArray::DirtyAttribBitsArray *attribBits,
gl::VertexArray::DirtyBindingBitsArray *bindingBits) override;
// Feed client side's vertex/index data
angle::Result updateClientAttribs(const gl::Context *context,
GLint firstVertex,
GLsizei vertexOrIndexCount,
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices);
// vertexDescChanged is both input and output, the input value if is true, will force new
// mtl::VertexDesc to be returned via vertexDescOut. Otherwise, it is only returned when the
// vertex array is dirty
angle::Result setupDraw(const gl::Context *glContext,
mtl::RenderCommandEncoder *cmdEncoder,
bool *vertexDescChanged,
mtl::VertexDesc *vertexDescOut);
angle::Result getIndexBuffer(const gl::Context *glContext,
gl::DrawElementsType indexType,
size_t indexCount,
const void *sourcePointer,
mtl::BufferRef *idxBufferOut,
size_t *idxBufferOffsetOut,
gl::DrawElementsType *indexTypeOut);
private:
void reset(ContextMtl *context);
angle::Result syncDirtyAttrib(const gl::Context *glContext,
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
size_t attribIndex);
angle::Result convertIndexBuffer(const gl::Context *glContext,
gl::DrawElementsType indexType,
size_t offset,
mtl::BufferRef *idxBufferOut,
size_t *idxBufferOffsetOut);
angle::Result streamIndexBufferFromClient(const gl::Context *glContext,
gl::DrawElementsType indexType,
size_t indexCount,
const void *sourcePointer,
mtl::BufferRef *idxBufferOut,
size_t *idxBufferOffsetOut);
angle::Result convertIndexBufferGPU(const gl::Context *glContext,
gl::DrawElementsType indexType,
BufferMtl *idxBuffer,
size_t offset,
size_t indexCount,
IndexConversionBufferMtl *conversion);
angle::Result convertVertexBuffer(const gl::Context *glContext,
BufferMtl *srcBuffer,
const gl::VertexBinding &binding,
size_t attribIndex,
const mtl::VertexFormat &vertexFormat);
angle::Result convertVertexBufferCPU(const gl::Context *glContext,
BufferMtl *srcBuffer,
const gl::VertexBinding &binding,
size_t attribIndex,
const mtl::VertexFormat &vertexFormat,
ConversionBufferMtl *conversion);
// These can point to real BufferMtl or converted buffer in mConvertedArrayBufferHolders
gl::AttribArray<BufferHolderMtl *> mCurrentArrayBuffers;
gl::AttribArray<SimpleWeakBufferHolderMtl> mConvertedArrayBufferHolders;
gl::AttribArray<size_t> mCurrentArrayBufferOffsets;
gl::AttribArray<GLuint> mCurrentArrayBufferStrides;
gl::AttribArray<const mtl::VertexFormat *> mCurrentArrayBufferFormats;
mtl::BufferPool mDynamicVertexData;
mtl::BufferPool mDynamicIndexData;
bool mVertexArrayDirty = true;
};
} // namespace rx
#endif /* LIBANGLE_RENDERER_METAL_VERTEXARRAYMTL_H_ */