aboutsummaryrefslogtreecommitdiff
path: root/src/gpu/ganesh/GrGpuBuffer.h
blob: 1d5fc4fdd4ab635b7dcea6578496da0cce96c45c (plain)
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
/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrGpuBuffer_DEFINED
#define GrGpuBuffer_DEFINED

#include "src/gpu/ganesh/GrBuffer.h"
#include "src/gpu/ganesh/GrGpuResource.h"

class GrGpu;

class GrGpuBuffer : public GrGpuResource, public GrBuffer {
public:
    /**
     * Computes a scratch key for a GPU-side buffer with a "dynamic" access pattern. (Buffers with
     * "static" and "stream" patterns are disqualified by nature from being cached and reused.)
     */
    static void ComputeScratchKeyForDynamicBuffer(size_t size, GrGpuBufferType, skgpu::ScratchKey*);

    GrAccessPattern accessPattern() const { return fAccessPattern; }

    size_t size() const final { return fSizeInBytes; }

    void ref() const final { GrGpuResource::ref(); }

    void unref() const final { GrGpuResource::unref(); }

    /**
     * Maps the buffer to be read or written by the CPU.
     *
     * It is an error to draw from the buffer while it is mapped or transfer to/from the buffer. It
     * may fail if the backend doesn't support mapping the buffer. Once a buffer is mapped,
     * subsequent calls to map() trivially succeed. No matter how many times map() is called,
     * umap() will unmap the buffer on the first call if it is mapped.
     *
     * If the buffer is of type GrGpuBufferType::kXferGpuToCpu then it is mapped for reading only.
     * Otherwise it is mapped writing only. Writing to a buffer that is mapped for reading or vice
     * versa produces undefined results. If the buffer is mapped for writing then the buffer's
     * previous contents are invalidated.
     *
     * @return a pointer to the data or nullptr if the map fails.
     */
    void* map();

    /**
     * Unmaps the buffer if it is mapped.
     *
     * The pointer returned by the previous map call will no longer be valid.
     */
    void unmap();

    /**
     * Queries whether the buffer has been mapped.
     *
     * @return true if the buffer is mapped, false otherwise.
     */
    bool isMapped() const;

    bool isCpuBuffer() const final { return false; }

    /**
     * Overwrites the buffer with zero bytes. Always fails for GrGpuBufferType::kXferGpuToCpu
     * buffers. The buffer must not currently be mapped.
     */
    bool clearToZero();

    /**
     * Updates the buffer data.
     *
     * The size of the buffer will be preserved. The src data will be
     * placed at offset. If preserve is false then any remaining content
     * before/after the range [offset, offset+size) becomes undefined.
     * Preserving updates will fail if the size and offset are not aligned
     * to GrCaps::bufferUpdateDataPreserveAlignment().
     *
     * The buffer must not be mapped.
     *
     * Fails for GrGpuBufferType::kXferGpuToCpu.
     *
     * Note that buffer updates do not go through GrContext and therefore are
     * not serialized with other operations.
     *
     * @return returns true if the update succeeds, false otherwise.
     */
    bool updateData(const void* src, size_t offset, size_t size, bool preserve);

    GrGpuBufferType intendedType() const { return fIntendedType; }

protected:
    GrGpuBuffer(GrGpu*,
                size_t sizeInBytes,
                GrGpuBufferType,
                GrAccessPattern,
                std::string_view label);

    enum class MapType {
        /** Maps for reading. The effect of writes is undefined. */
        kRead,
        /**
         * Maps for writing. The existing contents are discarded and the initial contents of the
         * buffer. Reads (even after overwriting initial contents) should be avoided for performance
         * reasons as the memory may not be cached.
         */
        kWriteDiscard,
    };

    void* fMapPtr;

private:
    /** Currently MapType is determined entirely by the buffer type, as documented in map(). */
    MapType mapType() const {
        return this->intendedType() == GrGpuBufferType::kXferGpuToCpu ? MapType::kRead
                                                                      : MapType::kWriteDiscard;
    }

    virtual void onMap(MapType) = 0;
    virtual void onUnmap(MapType) = 0;
    virtual bool onClearToZero() = 0;
    virtual bool onUpdateData(const void* src, size_t offset, size_t size, bool preserve) = 0;

    size_t onGpuMemorySize() const override { return fSizeInBytes; }
    void onSetLabel() override{}
    const char* getResourceType() const override { return "Buffer Object"; }
    void computeScratchKey(skgpu::ScratchKey* key) const override;

    size_t            fSizeInBytes;
    GrAccessPattern   fAccessPattern;
    GrGpuBufferType   fIntendedType;
};

#endif