Overte C++ Documentation
State.h
1 //
2 // State
3 // libraries/gpu/src/gpu
4 //
5 // Created by Sam Gateau on 3/8/2015.
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 #ifndef hifi_gpu_State_h
12 #define hifi_gpu_State_h
13 
14 #include "Format.h"
15 
16 #include <memory>
17 #include <sstream>
18 #include <vector>
19 #include <unordered_map>
20 #include <bitset>
21 #include <QString>
22 
23 #include "Sampler.h"
24 
25 template <typename T>
26 static std::string bytesToAscii(T t) {
27  std::string hexString;
28  const auto bytes = reinterpret_cast<uint8_t*>(&t);
29  hexString.resize(sizeof(T) * 2);
30  auto stringData = hexString.data();
31  constexpr int8_t charOffset = 'A';
32  for (size_t i = 0; i < sizeof(t); i++) {
33  stringData[i * 2] = static_cast<int8_t>(charOffset + (bytes[i] >> 4));
34  stringData[i * 2 + 1] = static_cast<int8_t>(charOffset + (bytes[i] & 0x0F));
35  }
36  return hexString;
37 }
38 
39 // Why a macro and not a fancy template you will ask me ?
40 // Because some of the fields are bool packed tightly in the State::Cache class
41 // and it s just not good anymore for template T& variable manipulation...
42 #define SET_FIELD(FIELD, PATH, value) \
43  { \
44  _values.PATH = value; \
45  if (value == DEFAULT.PATH) { \
46  _signature.reset(FIELD); \
47  } else { \
48  _signature.set(FIELD); \
49  } \
50  _stamp++; \
51  }
52 
53 namespace gpu {
54 
55 class GPUObject;
56 
58 class State {
59 public:
60  State();
61  State(const State& state) : _values(state._values), _signature(state._signature), _stamp(state._stamp) {}
62  virtual ~State();
63 
70  Stamp getStamp() const { return _stamp; }
71 
72  enum FillMode
73  {
74  FILL_POINT = 0,
75  FILL_LINE,
76  FILL_FACE,
77 
78  NUM_FILL_MODES,
79  };
80 
81  enum CullMode
82  {
83  CULL_NONE = 0,
84  CULL_FRONT,
85  CULL_BACK,
86 
87  NUM_CULL_MODES,
88  };
89 
90  enum StencilOp
91  {
92  STENCIL_OP_KEEP = 0,
93  STENCIL_OP_ZERO,
94  STENCIL_OP_REPLACE,
95  STENCIL_OP_INCR_SAT,
96  STENCIL_OP_DECR_SAT,
97  STENCIL_OP_INVERT,
98  STENCIL_OP_INCR,
99  STENCIL_OP_DECR,
100 
101  NUM_STENCIL_OPS,
102  };
103 
104  enum BlendArg
105  {
106  ZERO = 0,
107  ONE,
108  SRC_COLOR,
109  INV_SRC_COLOR,
110  SRC_ALPHA,
111  INV_SRC_ALPHA,
112  DEST_ALPHA,
113  INV_DEST_ALPHA,
114  DEST_COLOR,
115  INV_DEST_COLOR,
116  SRC_ALPHA_SAT,
117  FACTOR_COLOR,
118  INV_FACTOR_COLOR,
119  FACTOR_ALPHA,
120  INV_FACTOR_ALPHA,
121 
122  NUM_BLEND_ARGS,
123  };
124 
125  enum BlendOp
126  {
127  BLEND_OP_ADD = 0,
128  BLEND_OP_SUBTRACT,
129  BLEND_OP_REV_SUBTRACT,
130  BLEND_OP_MIN,
131  BLEND_OP_MAX,
132 
133  NUM_BLEND_OPS,
134  };
135 
136  enum ColorMask
137  {
138  WRITE_NONE = 0,
139  WRITE_RED = 1,
140  WRITE_GREEN = 2,
141  WRITE_BLUE = 4,
142  WRITE_ALPHA = 8,
143  WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA),
144  };
145 
147  class DepthTest {
148  public:
150  uint8 writeMask{ true };
151 
153  uint8 enabled{ false };
154 
155  ComparisonFunction function{ ComparisonFunction::LESS };
156 
157  public:
164  DepthTest(bool enabled = false, bool writeMask = true, ComparisonFunction func = ComparisonFunction::LESS) :
165  writeMask(writeMask), enabled(enabled), function(func) {}
166 
170  bool isEnabled() const { return enabled != 0; }
171 
175  ComparisonFunction getFunction() const { return function; }
176 
180  uint8 getWriteMask() const { return writeMask; }
181 
182  bool operator==(const DepthTest& right) const {
183  return
184  writeMask == right.writeMask &&
185  enabled == right.enabled &&
186  function == right.function;
187  }
188 
189  bool operator!=(const DepthTest& right) const {
190  return !(*this == right);
191  }
192 
193  operator QString() const {
194  return QString("{ writeMask = %1, enabled = %2, function = %3 }").arg(writeMask).arg(enabled).arg((uint8_t)function);
195  }
196  };
197 
199  struct StencilTest {
200  ComparisonFunction function;
201  StencilOp failOp;
202  StencilOp depthFailOp;
203  StencilOp passOp;
204  int8 reference{ 0 };
205  uint8 readMask{ 0xff };
206 
207  public:
216  StencilTest(int8 reference = 0,
217  uint8 readMask = 0xFF,
218  ComparisonFunction func = ComparisonFunction::ALWAYS,
219  StencilOp failOp = STENCIL_OP_KEEP,
220  StencilOp depthFailOp = STENCIL_OP_KEEP,
221  StencilOp passOp = STENCIL_OP_KEEP) :
222  function(func),
223  failOp(failOp), depthFailOp(depthFailOp), passOp(passOp), reference(reference), readMask(readMask) {}
224 
228  ComparisonFunction getFunction() const { return function; }
229 
233  StencilOp getFailOp() const { return failOp; }
234 
238  StencilOp getDepthFailOp() const { return depthFailOp; }
239 
243  StencilOp getPassOp() const { return passOp; }
244 
248  int8 getReference() const { return reference; }
249 
253  uint8 getReadMask() const { return readMask; }
254 
255  bool operator==(const StencilTest& right) const {
256  return
257  function == right.function &&
258  failOp == right.failOp &&
259  depthFailOp == right.depthFailOp &&
260  passOp == right.passOp &&
261  reference == right.reference &&
262  readMask == right.readMask;
263 
264  }
265 
266  bool operator!=(const StencilTest &right) const { return !(right==*this); }
267  };
268 
270  struct StencilActivation {
271  uint8 frontWriteMask = 0xFF;
272  uint8 backWriteMask = 0xFF;
273  bool enabled;
274 
275  public:
281  StencilActivation(bool enabled = false, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) :
282  frontWriteMask(frontWriteMask), backWriteMask(backWriteMask), enabled(enabled) {}
283 
287  bool isEnabled() const { return enabled; }
288 
292  uint8 getWriteMaskFront() const { return frontWriteMask; }
293 
297  uint8 getWriteMaskBack() const { return backWriteMask; }
298 
299  bool operator==(const StencilActivation& right) const {
300  return
301  frontWriteMask == right.frontWriteMask &&
302  backWriteMask == right.backWriteMask &&
303  enabled == right.enabled;
304  }
305 
306  bool operator!=(const StencilActivation& right) const {
307  return !(*this == right);
308  }
309  };
310 
312  struct BlendFunction {
313  // Using uint8 here will make the structure as a whole not align to 32 bits
315  uint16 enabled;
316 
318  BlendArg sourceColor;
319 
321  BlendArg sourceAlpha;
322 
324  BlendArg destColor;
325 
327  BlendArg destAlpha;
328 
330  BlendOp opColor;
331 
333  BlendOp opAlpha;
334 
335  public:
347  BlendArg sourceColor,
348  BlendOp operationColor,
349  BlendArg destinationColor,
350  BlendArg sourceAlpha,
351  BlendOp operationAlpha,
352  BlendArg destinationAlpha) :
353  enabled(enabled),
355  destColor(destinationColor), destAlpha(destinationAlpha),
356  opColor(operationColor), opAlpha(operationAlpha) {}
357 
364  BlendFunction(bool enabled = false, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) :
365  BlendFunction(enabled, source, operation, destination, source, operation, destination) {}
366 
370  bool isEnabled() const { return (enabled != 0); }
371 
375  BlendArg getSourceColor() const { return sourceColor; }
376 
380  BlendArg getDestinationColor() const { return destColor; }
381 
385  BlendOp getOperationColor() const { return opColor; }
386 
390  BlendArg getSourceAlpha() const { return sourceAlpha; }
391 
395  BlendArg getDestinationAlpha() const { return destAlpha; }
396 
400  BlendOp getOperationAlpha() const { return opAlpha; }
401 
402  bool operator==(const BlendFunction& right) const {
403  return
404  enabled == right.enabled &&
405  sourceColor == right.sourceColor &&
406  sourceAlpha == right.sourceAlpha &&
407  destColor == right.destColor &&
408  destAlpha == right.destAlpha &&
409  opColor == right.opColor &&
410  opAlpha == right.opAlpha;
411 
412  }
413 
414  bool operator!=(const BlendFunction& right) const {
415  return !(*this == right);
416  }
417  };
418 
420  struct Flags {
421  Flags() :
422  frontFaceClockwise(false), depthClampEnable(false), scissorEnable(false), multisampleEnable(false),
423  antialisedLineEnable(true), alphaToCoverageEnable(false) {}
424  bool frontFaceClockwise;
425  bool depthClampEnable;
426  bool scissorEnable;
427  bool multisampleEnable;
428  bool antialisedLineEnable;
429  bool alphaToCoverageEnable;
430 
431 
432  bool operator==(const Flags& right) const {
433  return
434  frontFaceClockwise == right.frontFaceClockwise &&
435  depthClampEnable == right.depthClampEnable &&
436  scissorEnable == right.scissorEnable &&
437  multisampleEnable == right.multisampleEnable &&
438  antialisedLineEnable == right.antialisedLineEnable &&
439  alphaToCoverageEnable == right.alphaToCoverageEnable;
440 
441  }
442 
443  bool operator!=(const Flags& right) const {
444  return !(*this == right);
445  }
446  };
447 
453  class Data {
454  public:
455  float depthBias = 0.0f;
456  float depthBiasSlopeScale = 0.0f;
457 
458  DepthTest depthTest;
459  StencilActivation stencilActivation;
460  StencilTest stencilTestFront;
461  StencilTest stencilTestBack;
462  uint32 sampleMask = 0xFFFFFFFF;
463  BlendFunction blendFunction;
464  FillMode fillMode{ FILL_FACE };
465  CullMode cullMode{ CULL_NONE };
466  ColorMask colorWriteMask{ WRITE_ALL };
467 
468  Flags flags;
469  };
470 
474  std::string getKey() const;
475 
477  static const Data DEFAULT;
478  void setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, fillMode, fill); }
479  FillMode getFillMode() const { return _values.fillMode; }
480 
481  void setCullMode(CullMode cull) { SET_FIELD(CULL_MODE, cullMode, cull); }
482  CullMode getCullMode() const { return _values.cullMode; }
483 
487  const Flags& getFlags() const { return _values.flags; }
488 
489  void setFrontFaceClockwise(bool isClockwise) { SET_FIELD(FRONT_FACE_CLOCKWISE, flags.frontFaceClockwise, isClockwise); }
490  bool isFrontFaceClockwise() const { return _values.flags.frontFaceClockwise; }
491 
492  void setDepthClampEnable(bool enable) { SET_FIELD(DEPTH_CLAMP_ENABLE, flags.depthClampEnable, enable); }
493  bool isDepthClampEnable() const { return _values.flags.depthClampEnable; }
494 
495  void setScissorEnable(bool enable) { SET_FIELD(SCISSOR_ENABLE, flags.scissorEnable, enable); }
496  bool isScissorEnable() const { return _values.flags.scissorEnable; }
497 
498  void setMultisampleEnable(bool enable) { SET_FIELD(MULTISAMPLE_ENABLE, flags.multisampleEnable, enable); }
499  bool isMultisampleEnable() const { return _values.flags.multisampleEnable; }
500 
501  void setAntialiasedLineEnable(bool enable) { SET_FIELD(ANTIALISED_LINE_ENABLE, flags.antialisedLineEnable, enable); }
502  bool isAntialiasedLineEnable() const { return _values.flags.antialisedLineEnable; }
503 
504  // Depth Bias
505  void setDepthBias(float bias) { SET_FIELD(DEPTH_BIAS, depthBias, bias); }
506  float getDepthBias() const { return _values.depthBias; }
507 
508  void setDepthBiasSlopeScale(float scale) { SET_FIELD(DEPTH_BIAS_SLOPE_SCALE, depthBiasSlopeScale, scale); }
509  float getDepthBiasSlopeScale() const { return _values.depthBiasSlopeScale; }
510 
511  // Depth Test
512  void setDepthTest(DepthTest newDepthTest) { SET_FIELD(DEPTH_TEST, depthTest, newDepthTest); }
513  void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) {
514  setDepthTest(DepthTest(enable, writeMask, func));
515  }
516  DepthTest getDepthTest() const { return _values.depthTest; }
517 
518  bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); }
519  uint8 getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); }
520  ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); }
521 
522  // Stencil test
530  void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) {
531  SET_FIELD(STENCIL_ACTIVATION, stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask));
532  SET_FIELD(STENCIL_TEST_FRONT, stencilTestFront, frontTest);
533  SET_FIELD(STENCIL_TEST_BACK, stencilTestBack, backTest);
534  }
535 
541  void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) {
542  setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest);
543  }
544 
545  StencilActivation getStencilActivation() const { return _values.stencilActivation; }
546  StencilTest getStencilTestFront() const { return _values.stencilTestFront; }
547  StencilTest getStencilTestBack() const { return _values.stencilTestBack; }
548 
549  bool isStencilEnabled() const { return getStencilActivation().isEnabled(); }
550  uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); }
551  uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); }
552 
553  // Alpha to coverage
554  void setAlphaToCoverageEnable(bool enable) { SET_FIELD(ALPHA_TO_COVERAGE_ENABLE, flags.alphaToCoverageEnable, enable); }
555  bool isAlphaToCoverageEnabled() const { return _values.flags.alphaToCoverageEnable; }
556 
557  // Sample mask
564  void setSampleMask(uint32 mask) { SET_FIELD(SAMPLE_MASK, sampleMask, mask); }
565 
572  uint32 getSampleMask() const { return _values.sampleMask; }
573 
574  // Blend Function
575  void setBlendFunction(BlendFunction function) { SET_FIELD(BLEND_FUNCTION, blendFunction, function); }
576  const BlendFunction& getBlendFunction() const { return _values.blendFunction; }
577 
587  void setBlendFunction(bool enabled,
588  BlendArg sourceColor,
589  BlendOp operationColor,
590  BlendArg destinationColor,
591  BlendArg sourceAlpha,
592  BlendOp operationAlpha,
593  BlendArg destinationAlpha) {
594  setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha,
595  destinationAlpha));
596  }
597 
604  void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) {
605  setBlendFunction(BlendFunction(enabled, source, operation, destination));
606  }
607 
608  bool isBlendEnabled() const { return getBlendFunction().isEnabled(); }
609 
610  // Color write mask
614  void setColorWriteMask(ColorMask mask) { SET_FIELD(COLOR_WRITE_MASK, colorWriteMask, mask); }
615 
624  void setColorWriteMask(bool red, bool green, bool blue, bool alpha) {
625  ColorMask value = (ColorMask)((WRITE_RED * red) | (WRITE_GREEN * green) | (WRITE_BLUE * blue) | (WRITE_ALPHA * alpha));
626  SET_FIELD(COLOR_WRITE_MASK, colorWriteMask, value);
627  }
628  ColorMask getColorWriteMask() const { return _values.colorWriteMask; }
629 
632  enum Field
633  {
634  FILL_MODE,
635  CULL_MODE,
636  FRONT_FACE_CLOCKWISE,
637  DEPTH_CLAMP_ENABLE,
638  SCISSOR_ENABLE,
639  MULTISAMPLE_ENABLE,
640  ANTIALISED_LINE_ENABLE,
641 
642  DEPTH_BIAS,
643  DEPTH_BIAS_SLOPE_SCALE,
644 
645  DEPTH_TEST,
646 
647  STENCIL_ACTIVATION,
648  STENCIL_TEST_FRONT,
649  STENCIL_TEST_BACK,
650 
651  SAMPLE_MASK,
652 
653  ALPHA_TO_COVERAGE_ENABLE,
654 
655  BLEND_FUNCTION,
656 
657  COLOR_WRITE_MASK,
658 
659  NUM_FIELDS, // not a valid field, just the count
660  };
661 
664  typedef std::bitset<NUM_FIELDS> Signature;
665 
669  Signature getSignature() const { return _signature; }
670 
675  static Signature evalSignature(const Data& state);
676 
678  State(const Data& values);
679 
683  const Data& getValues() const { return _values; }
684 
687 
688 protected:
689  State& operator=(const State& state);
690 
693 
696 
698  Stamp _stamp{ 0 };
699 };
700 
701 typedef std::shared_ptr<State> StatePointer;
702 typedef std::vector<StatePointer> States;
703 
704 }; // namespace gpu
705 
706 #endif
Definition: gpu/src/gpu/Forward.h:134
The Data class is the full explicit description of the State class fields value.
Definition: State.h:453
Represents setting for depth testing and writing.
Definition: State.h:147
uint8 enabled
Enable depth test.
Definition: State.h:153
uint8 getWriteMask() const
Definition: State.h:180
bool isEnabled() const
Definition: State.h:170
ComparisonFunction getFunction() const
Definition: State.h:175
DepthTest(bool enabled=false, bool writeMask=true, ComparisonFunction func=ComparisonFunction::LESS)
Definition: State.h:164
uint8 writeMask
Enable writing to the depth buffer.
Definition: State.h:150
Describes pipeline state.
Definition: State.h:58
void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest)
Definition: State.h:541
static Signature evalSignature(const Data &state)
Definition: State.cpp:27
uint32 getSampleMask() const
Definition: State.h:572
Stamp _stamp
Incremented on changes and used to determine if API-specific backend object needs updating.
Definition: State.h:698
static const Data DEFAULT
The unique default values for all the fields.
Definition: State.h:477
void setColorWriteMask(bool red, bool green, bool blue, bool alpha)
Sets which color channels can be written to.
Definition: State.h:624
const GPUObjectPointer gpuObject
Object representing state on the API-specific backend side.
Definition: State.h:686
void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination)
Definition: State.h:604
const Data & getValues() const
Definition: State.h:683
const Flags & getFlags() const
Definition: State.h:487
Field
Definition: State.h:633
void setColorWriteMask(ColorMask mask)
Definition: State.h:614
Signature _signature
Used to tell which fields have default values and which are changed.
Definition: State.h:695
Data _values
Full description of the state.
Definition: State.h:692
void setSampleMask(uint32 mask)
Definition: State.h:564
void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest)
Definition: State.h:530
std::string getKey() const
Definition: State.cpp:90
Signature getSignature() const
Definition: State.h:669
std::bitset< NUM_FIELDS > Signature
Definition: State.h:664
Stamp getStamp() const
Get the current stamp.
Definition: State.h:70
void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha)
Definition: State.h:587
Represents blending state.
Definition: State.h:312
BlendArg sourceColor
Determines how source color will be used.
Definition: State.h:318
BlendArg getDestinationAlpha() const
Definition: State.h:395
BlendOp getOperationAlpha() const
Definition: State.h:400
BlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha)
Definition: State.h:346
uint16 enabled
true if blending is enabled.
Definition: State.h:315
BlendArg getDestinationColor() const
Definition: State.h:380
BlendOp getOperationColor() const
Definition: State.h:385
BlendFunction(bool enabled=false, BlendArg source=ONE, BlendOp operation=BLEND_OP_ADD, BlendArg destination=ZERO)
Definition: State.h:364
BlendArg getSourceAlpha() const
Definition: State.h:390
BlendOp opColor
Type of operation that will be performed on color if blending is enabled.
Definition: State.h:330
BlendArg getSourceColor() const
Definition: State.h:375
BlendArg destColor
Determines how destination color will be used.
Definition: State.h:324
BlendArg destAlpha
Determines how destination alpha will be used.
Definition: State.h:327
BlendOp opAlpha
Type of operation that will be performed on alpha if blending is enabled.
Definition: State.h:333
bool isEnabled() const
Definition: State.h:370
BlendArg sourceAlpha
Determines how source alpha will be used.
Definition: State.h:321
Flags for enabling or disabling various settings for the pipeline.
Definition: State.h:420