1/* 2 * Copyright 2014 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 GrProgramDesc_DEFINED 9#define GrProgramDesc_DEFINED 10 11#include "GrColor.h" 12#include "GrTypesPriv.h" 13#include "SkOpts.h" 14#include "SkTArray.h" 15#include "glsl/GrGLSLFragmentShaderBuilder.h" 16 17class GrShaderCaps; 18class GrPipeline; 19class GrPrimitiveProcessor; 20 21/** This class describes a program to generate. It also serves as a program cache key */ 22class GrProgramDesc { 23public: 24 // Creates an uninitialized key that must be populated by GrGpu::buildProgramDesc() 25 GrProgramDesc() {} 26 27 /** 28 * Builds a program descriptor. Before the descriptor can be used, the client must call finalize 29 * on the returned GrProgramDesc. 30 * 31 * @param GrPrimitiveProcessor The geometry 32 * @param hasPointSize Controls whether the shader will output a point size. 33 * @param GrPipeline The optimized drawstate. The descriptor will represent a program 34 * which this optstate can use to draw with. The optstate contains 35 * general draw information, as well as the specific color, geometry, 36 * and coverage stages which will be used to generate the GL Program for 37 * this optstate. 38 * @param GrShaderCaps Capabilities of the shading language. 39 * @param GrProgramDesc The built and finalized descriptor 40 **/ 41 static bool Build(GrProgramDesc*, 42 const GrPrimitiveProcessor&, 43 bool hasPointSize, 44 const GrPipeline&, 45 const GrShaderCaps&); 46 47 // Returns this as a uint32_t array to be used as a key in the program cache. 48 const uint32_t* asKey() const { 49 return reinterpret_cast<const uint32_t*>(fKey.begin()); 50 } 51 52 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two 53 // keys the size of either key can be used with memcmp() since the lengths themselves begin the 54 // keys and thus the memcmp will exit early if the keys are of different lengths. 55 uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>(); } 56 57 // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache. 58 uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); } 59 60 GrProgramDesc& operator= (const GrProgramDesc& other) { 61 uint32_t keyLength = other.keyLength(); 62 fKey.reset(SkToInt(keyLength)); 63 memcpy(fKey.begin(), other.fKey.begin(), keyLength); 64 return *this; 65 } 66 67 bool operator== (const GrProgramDesc& that) const { 68 SkASSERT(SkIsAlign4(this->keyLength())); 69 int l = this->keyLength() >> 2; 70 const uint32_t* aKey = this->asKey(); 71 const uint32_t* bKey = that.asKey(); 72 for (int i = 0; i < l; ++i) { 73 if (aKey[i] != bKey[i]) { 74 return false; 75 } 76 } 77 return true; 78 } 79 80 bool operator!= (const GrProgramDesc& other) const { 81 return !(*this == other); 82 } 83 84 void setSurfaceOriginKey(int key) { 85 KeyHeader* header = this->atOffset<KeyHeader, kHeaderOffset>(); 86 header->fSurfaceOriginKey = key; 87 } 88 89 static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) { 90 SkASSERT(SkIsAlign4(a.keyLength())); 91 int l = a.keyLength() >> 2; 92 const uint32_t* aKey = a.asKey(); 93 const uint32_t* bKey = b.asKey(); 94 for (int i = 0; i < l; ++i) { 95 if (aKey[i] != bKey[i]) { 96 return aKey[i] < bKey[i] ? true : false; 97 } 98 } 99 return false; 100 } 101 102 struct KeyHeader { 103 // Set to uniquely idenitify any swizzling of the shader's output color(s). 104 uint8_t fOutputSwizzle; 105 uint8_t fColorFragmentProcessorCnt; // Can be packed into 4 bits if required. 106 uint8_t fCoverageFragmentProcessorCnt; 107 // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info. 108 uint8_t fSurfaceOriginKey : 2; 109 bool fSnapVerticesToPixelCenters : 1; 110 bool fHasPointSize : 1; 111 uint8_t fPad : 4; 112 }; 113 GR_STATIC_ASSERT(sizeof(KeyHeader) == 4); 114 115 // This should really only be used internally, base classes should return their own headers 116 const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); } 117 118 void finalize() { 119 int keyLength = fKey.count(); 120 SkASSERT(0 == (keyLength % 4)); 121 *(this->atOffset<uint32_t, GrProgramDesc::kLengthOffset>()) = SkToU32(keyLength); 122 123 uint32_t* checksum = this->atOffset<uint32_t, GrProgramDesc::kChecksumOffset>(); 124 *checksum = 0; // We'll hash through these bytes, so make sure they're initialized. 125 *checksum = SkOpts::hash(fKey.begin(), keyLength); 126 } 127 128protected: 129 template<typename T, size_t OFFSET> T* atOffset() { 130 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET); 131 } 132 133 template<typename T, size_t OFFSET> const T* atOffset() const { 134 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET); 135 } 136 137 // The key, stored in fKey, is composed of four parts: 138 // 1. uint32_t for total key length. 139 // 2. uint32_t for a checksum. 140 // 3. Header struct defined above. 141 // 4. A Backend specific payload which includes the per-processor keys. 142 enum KeyOffsets { 143 // Part 1. 144 kLengthOffset = 0, 145 // Part 2. 146 kChecksumOffset = kLengthOffset + sizeof(uint32_t), 147 // Part 3. 148 kHeaderOffset = kChecksumOffset + sizeof(uint32_t), 149 kHeaderSize = SkAlign4(sizeof(KeyHeader)), 150 // Part 4. 151 // This is the offset into the backenend specific part of the key, which includes 152 // per-processor keys. 153 kProcessorKeysOffset = kHeaderOffset + kHeaderSize, 154 }; 155 156 enum { 157 kMaxPreallocProcessors = 8, 158 kIntsPerProcessor = 4, // This is an overestimate of the average effect key size. 159 kPreAllocSize = kHeaderOffset + kHeaderSize + 160 kMaxPreallocProcessors * sizeof(uint32_t) * kIntsPerProcessor, 161 }; 162 163 SkSTArray<kPreAllocSize, uint8_t, true>& key() { return fKey; } 164 const SkSTArray<kPreAllocSize, uint8_t, true>& key() const { return fKey; } 165 166private: 167 SkSTArray<kPreAllocSize, uint8_t, true> fKey; 168}; 169 170#endif 171