Hash :
113c5e29
Author :
Date :
2020-05-11T22:49:03
Metal: deferred render command encoder creation. MTLRenderCommandEncoder creation will be deferred until a render pass ends. Commands will be stored into a back-end owned buffer during render pass. At the end of the render pass, those commands will be re-encoded into an actual MTLRenderCommandEncoder. Benefits: - Useful for future implementation of occlusion query buffer where it could be allocated right before the end of a render pass to be big enough to store all queries within the render pass. - It's possible to change load option (deferred clear) as long as there is no draw call issued yet. This is not implemented yet. - Possibility of commands' re-ordering. Bug: angleproject:2634 Change-Id: I1348716aa882c0540d9120bf175d8dac13fb58bd Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2193196 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>
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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
//
// 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.
//
// mtl_resources.h:
// Declares wrapper classes for Metal's MTLTexture and MTLBuffer.
//
#ifndef LIBANGLE_RENDERER_METAL_MTL_RESOURCES_H_
#define LIBANGLE_RENDERER_METAL_MTL_RESOURCES_H_
#import <Metal/Metal.h>
#include <atomic>
#include <memory>
#include "common/FastVector.h"
#include "common/MemoryBuffer.h"
#include "common/angleutils.h"
#include "libANGLE/Error.h"
#include "libANGLE/ImageIndex.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/metal/mtl_common.h"
#include "libANGLE/renderer/metal/mtl_format_utils.h"
namespace rx
{
class ContextMtl;
namespace mtl
{
class CommandQueue;
class BlitCommandEncoder;
class Resource;
class Texture;
class Buffer;
using ResourceRef = std::shared_ptr<Resource>;
using TextureRef = std::shared_ptr<Texture>;
using TextureWeakRef = std::weak_ptr<Texture>;
using BufferRef = std::shared_ptr<Buffer>;
using BufferWeakRef = std::weak_ptr<Buffer>;
class Resource : angle::NonCopyable
{
public:
virtual ~Resource() {}
// Check whether the resource still being used by GPU
bool isBeingUsedByGPU(Context *context) const;
// Checks whether the last command buffer that uses the given resource has been committed or not
bool hasPendingWorks(Context *context) const;
void setUsedByCommandBufferWithQueueSerial(uint64_t serial, bool writing);
uint64_t getCommandBufferQueueSerial() const { return mUsageRef->cmdBufferQueueSerial; }
// Flag indicate whether we should synchronize the content to CPU after GPU changed this
// resource's content.
bool isCPUReadMemNeedSync() const { return mUsageRef->cpuReadMemNeedSync; }
void resetCPUReadMemNeedSync() { mUsageRef->cpuReadMemNeedSync = false; }
protected:
Resource();
// Share the GPU usage ref with other resource
Resource(Resource *other);
void reset();
private:
struct UsageRef
{
// The id of the last command buffer that is using this resource.
uint64_t cmdBufferQueueSerial = 0;
// This flag means the resource was issued to be modified by GPU, if CPU wants to read
// its content, explicit synchronization call must be invoked.
bool cpuReadMemNeedSync = false;
};
// One resource object might just be a view of another resource. For example, a texture 2d
// object might be a view of one face of a cube texture object. Another example is one texture
// object of size 2x2 might be a mipmap view of a texture object size 4x4. Thus, if one object
// is being used by a command buffer, it means the other object is being used also. In this
// case, the two objects must share the same UsageRef property.
std::shared_ptr<UsageRef> mUsageRef;
};
class Texture final : public Resource,
public WrappedObject<id<MTLTexture>>,
public std::enable_shared_from_this<Texture>
{
public:
static angle::Result Make2DTexture(ContextMtl *context,
const Format &format,
uint32_t width,
uint32_t height,
uint32_t mips /** use zero to create full mipmaps chain */,
bool renderTargetOnly,
bool allowTextureView,
TextureRef *refOut);
static angle::Result MakeCubeTexture(ContextMtl *context,
const Format &format,
uint32_t size,
uint32_t mips /** use zero to create full mipmaps chain */,
bool renderTargetOnly,
bool allowTextureView,
TextureRef *refOut);
static TextureRef MakeFromMetal(id<MTLTexture> metalTexture);
// Allow CPU to read & write data directly to this texture?
bool isCPUAccessible() const;
void replaceRegion(ContextMtl *context,
MTLRegion region,
uint32_t mipmapLevel,
uint32_t slice,
const uint8_t *data,
size_t bytesPerRow);
// read pixel data from slice 0
void getBytes(ContextMtl *context,
size_t bytesPerRow,
MTLRegion region,
uint32_t mipmapLevel,
uint8_t *dataOut);
// Create 2d view of a cube face which full range of mip levels.
TextureRef createCubeFaceView(uint32_t face);
// Create a view of one slice at a level.
TextureRef createSliceMipView(uint32_t slice, uint32_t level);
// Create a view with different format
TextureRef createViewWithDifferentFormat(MTLPixelFormat format);
MTLTextureType textureType() const;
MTLPixelFormat pixelFormat() const;
uint32_t mipmapLevels() const;
uint32_t width(uint32_t level = 0) const;
uint32_t height(uint32_t level = 0) const;
gl::Extents size(uint32_t level = 0) const;
gl::Extents size(const gl::ImageIndex &index) const;
// For render target
MTLColorWriteMask getColorWritableMask() const { return *mColorWritableMask; }
void setColorWritableMask(MTLColorWriteMask mask) { *mColorWritableMask = mask; }
// Change the wrapped metal object. Special case for swapchain image
void set(id<MTLTexture> metalTexture);
// sync content between CPU and GPU
void syncContent(ContextMtl *context, mtl::BlitCommandEncoder *encoder);
private:
using ParentClass = WrappedObject<id<MTLTexture>>;
Texture(id<MTLTexture> metalTexture);
Texture(ContextMtl *context,
MTLTextureDescriptor *desc,
uint32_t mips,
bool renderTargetOnly,
bool supportTextureView);
// Create a texture view
Texture(Texture *original, MTLPixelFormat format);
Texture(Texture *original, MTLTextureType type, NSRange mipmapLevelRange, uint32_t slice);
void syncContent(ContextMtl *context);
// This property is shared between this object and its views:
std::shared_ptr<MTLColorWriteMask> mColorWritableMask;
};
class Buffer final : public Resource, public WrappedObject<id<MTLBuffer>>
{
public:
static angle::Result MakeBuffer(ContextMtl *context,
size_t size,
const uint8_t *data,
BufferRef *bufferOut);
angle::Result reset(ContextMtl *context, size_t size, const uint8_t *data);
uint8_t *map(ContextMtl *context);
void unmap(ContextMtl *context);
size_t size() const;
private:
Buffer(ContextMtl *context, size_t size, const uint8_t *data);
};
} // namespace mtl
} // namespace rx
#endif /* LIBANGLE_RENDERER_METAL_MTL_RESOURCES_H_ */