Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2017 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef GrDeferredUpload_DEFINED
      9 #define GrDeferredUpload_DEFINED
     10 
     11 #include <functional>
     12 #include "GrTypes.h"
     13 
     14 class GrTextureProxy;
     15 
     16 /**
     17  * A word about deferred uploads and tokens: Ops should usually schedule their uploads to occur at
     18  * the beginning of a frame whenever possible. These are called ASAP uploads. Of course, this
     19  * requires that there are no draws that have yet to be flushed that rely on the old texture
     20  * contents. In that case the ASAP upload would happen prior to the draw and therefore the draw
     21  * would read the new (wrong) texture data. When this read-before-write data hazard exists they
     22  * should schedule an inline upload.
     23  *
     24  * Ops, in conjunction with helpers such as GrDrawOpAtlas, use upload tokens to know what the most
     25  * recent draw was that referenced a resource (or portion of a resource). Each draw is assigned a
     26  * token. A resource (or portion thereof) can be tagged with the most recent reading draw's token.
     27  * The deferred uploads target provides a facility for testing whether the draw corresponding to the
     28  * token has been flushed. If it has not been flushed then the op must perform an inline upload
     29  * instead so that the upload occurs after the draw depending on the old contents and before the
     30  * draw depending on the updated contents. When scheduling an inline upload the op provides the
     31  * token of the draw that the upload must occur before.
     32  */
     33 
     34 /**
     35  * GrDeferredUploadToken is used to sequence the uploads relative to each other and to draws.
     36  */
     37 class GrDeferredUploadToken {
     38 public:
     39     static GrDeferredUploadToken AlreadyFlushedToken() { return GrDeferredUploadToken(0); }
     40 
     41     GrDeferredUploadToken(const GrDeferredUploadToken&) = default;
     42     GrDeferredUploadToken& operator=(const GrDeferredUploadToken&) = default;
     43 
     44     bool operator==(const GrDeferredUploadToken& that) const {
     45         return fSequenceNumber == that.fSequenceNumber;
     46     }
     47     bool operator!=(const GrDeferredUploadToken& that) const { return !(*this == that); }
     48     bool operator<(const GrDeferredUploadToken that) const {
     49         return fSequenceNumber < that.fSequenceNumber;
     50     }
     51     bool operator<=(const GrDeferredUploadToken that) const {
     52         return fSequenceNumber <= that.fSequenceNumber;
     53     }
     54     bool operator>(const GrDeferredUploadToken that) const {
     55         return fSequenceNumber > that.fSequenceNumber;
     56     }
     57     bool operator>=(const GrDeferredUploadToken that) const {
     58         return fSequenceNumber >= that.fSequenceNumber;
     59     }
     60 
     61     GrDeferredUploadToken& operator++() {
     62         ++fSequenceNumber;
     63         return *this;
     64     }
     65     GrDeferredUploadToken operator++(int) {
     66         auto old = fSequenceNumber;
     67         ++fSequenceNumber;
     68         return GrDeferredUploadToken(old);
     69     }
     70 
     71     GrDeferredUploadToken next() const { return GrDeferredUploadToken(fSequenceNumber + 1); }
     72 
     73     /** Is this token in the [start, end] inclusive interval? */
     74     bool inInterval(const GrDeferredUploadToken& start, const GrDeferredUploadToken& end) {
     75         return *this >= start && *this <= end;
     76     }
     77 
     78 private:
     79     GrDeferredUploadToken() = delete;
     80     explicit GrDeferredUploadToken(uint64_t sequenceNumber) : fSequenceNumber(sequenceNumber) {}
     81     uint64_t fSequenceNumber;
     82 };
     83 
     84 /*
     85  * The GrTokenTracker encapsulates the incrementing and distribution of tokens.
     86  */
     87 class GrTokenTracker {
     88 public:
     89     /** Gets the token one beyond the last token that has been flushed. */
     90     GrDeferredUploadToken nextTokenToFlush() const { return fLastFlushedToken.next(); }
     91 
     92     /** Gets the next draw token that will be issued by this target. This can be used by an op
     93         to record that the next draw it issues will use a resource (e.g. texture) while preparing
     94         that draw. */
     95     GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); }
     96 
     97 private:
     98     // Only these two classes get to increment the token counters
     99     friend class SkInternalAtlasTextContext;
    100     friend class GrOpFlushState;
    101 
    102     /** Issues the next token for a draw. */
    103     GrDeferredUploadToken issueDrawToken() { return ++fLastIssuedToken; }
    104 
    105     /** Advances the last flushed token by one. */
    106     GrDeferredUploadToken flushToken() { return ++fLastFlushedToken; }
    107 
    108     GrDeferredUploadToken fLastIssuedToken = GrDeferredUploadToken::AlreadyFlushedToken();
    109     GrDeferredUploadToken fLastFlushedToken = GrDeferredUploadToken::AlreadyFlushedToken();
    110 };
    111 
    112 /**
    113  * Passed to a deferred upload when it is executed, this method allows the deferred upload to
    114  * actually write its pixel data into a texture.
    115  */
    116 using GrDeferredTextureUploadWritePixelsFn =
    117         std::function<bool(GrTextureProxy*, int left, int top, int width, int height,
    118                            GrPixelConfig config, const void* buffer, size_t rowBytes)>;
    119 
    120 /**
    121  * A deferred texture upload is simply a std::function that takes a
    122  * GrDeferredTextureUploadWritePixelsFn as a parameter. It is called when it should perform its
    123  * upload as the draw/upload sequence is executed.
    124  */
    125 using GrDeferredTextureUploadFn = std::function<void(GrDeferredTextureUploadWritePixelsFn&)>;
    126 
    127 /**
    128  * An interface for scheduling deferred uploads. It accepts asap and deferred inline uploads.
    129  */
    130 class GrDeferredUploadTarget {
    131 public:
    132     virtual ~GrDeferredUploadTarget() {}
    133 
    134     virtual const GrTokenTracker* tokenTracker() = 0;
    135 
    136     /** Returns the token of the draw that this upload will occur before. */
    137     virtual GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) = 0;
    138 
    139     /** Returns the token of the draw that this upload will occur before. Since ASAP uploads
    140         are done first during a flush, this will be the first token since the most recent
    141         flush. */
    142     virtual GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) = 0;
    143 };
    144 
    145 #endif
    146