blob: 1576fac9bad2417da4e2796badba44ed19c6ed29 [file] [log] [blame]
//
// 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.
//
// BufferMtl.h:
// Defines the class interface for BufferMtl, implementing BufferImpl.
//
#ifndef LIBANGLE_RENDERER_METAL_BUFFERMTL_H_
#define LIBANGLE_RENDERER_METAL_BUFFERMTL_H_
#import <Metal/Metal.h>
#include <utility>
#include "libANGLE/Buffer.h"
#include "libANGLE/Observer.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/Format.h"
#include "libANGLE/renderer/metal/mtl_buffer_pool.h"
#include "libANGLE/renderer/metal/mtl_resources.h"
namespace rx
{
// Conversion buffers hold translated index and vertex data.
struct ConversionBufferMtl
{
ConversionBufferMtl(const gl::Context *context, size_t initialSize, size_t alignment);
~ConversionBufferMtl();
// One state value determines if we need to re-stream vertex data.
bool dirty;
// The conversion is stored in a dynamic buffer.
mtl::BufferPool data;
};
struct IndexConversionBufferMtl : public ConversionBufferMtl
{
IndexConversionBufferMtl(const gl::Context *context,
gl::DrawElementsType type,
size_t offsetIn);
const gl::DrawElementsType type;
const size_t offset;
// These properties are to be filled by user of this buffer conversion
mtl::BufferRef convertedBuffer;
size_t convertedOffset;
};
class BufferHolderMtl
{
public:
virtual ~BufferHolderMtl() = default;
// Due to the complication of synchronizing accesses between CPU and GPU,
// a mtl::Buffer might be under used by GPU but CPU wants to modify its content through
// map() method, this could lead to GPU stalling. The more efficient method is maintain
// a queue of mtl::Buffer and only let CPU modifies a free mtl::Buffer.
// So, in order to let GPU use the most recent modified content, one must call this method
// right before the draw call to retrieved the most up-to-date mtl::Buffer.
mtl::BufferRef getCurrentBuffer(const gl::Context *context)
{
return mIsWeak ? mBufferWeakRef.lock() : mBuffer;
}
protected:
mtl::BufferRef mBuffer;
mtl::BufferWeakRef mBufferWeakRef;
bool mIsWeak = false;
};
class BufferMtl : public BufferImpl, public BufferHolderMtl
{
public:
BufferMtl(const gl::BufferState &state);
~BufferMtl() override;
void destroy(const gl::Context *context) override;
angle::Result setData(const gl::Context *context,
gl::BufferBinding target,
const void *data,
size_t size,
gl::BufferUsage usage) override;
angle::Result setSubData(const gl::Context *context,
gl::BufferBinding target,
const void *data,
size_t size,
size_t offset) override;
angle::Result copySubData(const gl::Context *context,
BufferImpl *source,
GLintptr sourceOffset,
GLintptr destOffset,
GLsizeiptr size) override;
angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
angle::Result mapRange(const gl::Context *context,
size_t offset,
size_t length,
GLbitfield access,
void **mapPtr) override;
angle::Result unmap(const gl::Context *context, GLboolean *result) override;
angle::Result getIndexRange(const gl::Context *context,
gl::DrawElementsType type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange) override;
angle::Result getFirstLastIndices(const gl::Context *context,
gl::DrawElementsType type,
size_t offset,
size_t count,
std::pair<uint32_t, uint32_t> *outIndices) const;
const uint8_t *getClientShadowCopyData(const gl::Context *context);
ConversionBufferMtl *getVertexConversionBuffer(const gl::Context *context,
angle::FormatID formatID,
GLuint stride,
size_t offset);
IndexConversionBufferMtl *getIndexConversionBuffer(const gl::Context *context,
gl::DrawElementsType type,
size_t offset);
size_t size() const { return mState.getSize(); }
private:
angle::Result setSubDataImpl(const gl::Context *context,
const void *data,
size_t size,
size_t offset);
angle::Result commitShadowCopy(const gl::Context *context);
void markConversionBuffersDirty();
// Client side shadow buffer
angle::MemoryBuffer mShadowCopy;
// GPU side buffers pool
mtl::BufferPool mBufferPool;
struct VertexConversionBuffer : public ConversionBufferMtl
{
VertexConversionBuffer(const gl::Context *context,
angle::FormatID formatIDIn,
GLuint strideIn,
size_t offsetIn);
// The conversion is identified by the triple of {format, stride, offset}.
angle::FormatID formatID;
GLuint stride;
size_t offset;
};
// A cache of converted vertex data.
std::vector<VertexConversionBuffer> mVertexConversionBuffers;
std::vector<IndexConversionBufferMtl> mIndexConversionBuffers;
};
class SimpleWeakBufferHolderMtl : public BufferHolderMtl
{
public:
SimpleWeakBufferHolderMtl();
void set(const mtl::BufferRef &buffer) { mBufferWeakRef = buffer; }
};
} // namespace rx
#endif /* LIBANGLE_RENDERER_METAL_BUFFERMTL_H_ */