Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

290 lines
9.2 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // cglmprogram.h
  4. // GLMgr programs (ARBVP/ARBfp)
  5. //
  6. //===============================================================================
  7. #ifndef CGLMPROGRAM_H
  8. #define CGLMPROGRAM_H
  9. #include <sys/stat.h>
  10. #pragma once
  11. // good ARB program references
  12. // http://petewarden.com/notes/archives/2005/05/fragment_progra_2.html
  13. // http://petewarden.com/notes/archives/2005/06/fragment_progra_3.html
  14. // ext links
  15. // http://www.opengl.org/registry/specs/ARB/vertex_program.txt
  16. // http://www.opengl.org/registry/specs/ARB/fragment_program.txt
  17. // http://www.opengl.org/registry/specs/EXT/gpu_program_parameters.txt
  18. //===============================================================================
  19. // tokens not in the SDK headers
  20. //#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT
  21. // #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9
  22. //#endif
  23. //===============================================================================
  24. // forward declarations
  25. class GLMContext;
  26. class CGLMShaderPair;
  27. class CGLMShaderPairCache;
  28. // CGLMProgram can contain two flavors of the same program, one in assembler, one in GLSL.
  29. // these flavors are pretty different in terms of the API's that are used to activate them -
  30. // for example, assembler programs can just get bound to the context, whereas GLSL programs
  31. // have to be linked. To some extent we try to hide that detail inside GLM.
  32. // for now, make CGLMProgram a container, it does not set policy or hold a preference as to which
  33. // flavor you want to use. GLMContext has to handle that.
  34. enum EGLMProgramType
  35. {
  36. kGLMVertexProgram,
  37. kGLMFragmentProgram,
  38. kGLMNumProgramTypes
  39. };
  40. enum EGLMProgramLang
  41. {
  42. kGLMARB,
  43. kGLMGLSL,
  44. kGLMNumProgramLangs
  45. };
  46. struct GLMShaderDesc
  47. {
  48. union
  49. {
  50. GLuint arb; // ARB program object name
  51. GLhandleARB glsl; // GLSL shader object handle (void*)
  52. } m_object;
  53. // these can change if shader text is edited
  54. bool m_textPresent; // is this flavor(lang) of text present in the buffer?
  55. int m_textOffset; // where is it
  56. int m_textLength; // how big
  57. bool m_compiled; // has this text been through a compile attempt
  58. bool m_valid; // and if so, was the compile successful
  59. int m_slowMark; // has it been flagged during a non native draw batch before. increment every time it's slow.
  60. int m_highWater; // vount of vec4's in the major uniform array ("vc" on vs, "pc" on ps)
  61. // written by dxabstract.... gross!
  62. };
  63. GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target
  64. GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target
  65. class CGLMProgram
  66. {
  67. public:
  68. friend class CGLMShaderPairCache;
  69. friend class CGLMShaderPair;
  70. friend class GLMContext; // only GLMContext can make CGLMProgram objects
  71. friend class GLMTester;
  72. friend class IDirect3D9;
  73. friend class IDirect3DDevice9;
  74. //===============================
  75. // constructor is very light, it just makes one empty program object per flavor.
  76. CGLMProgram( GLMContext *ctx, EGLMProgramType type );
  77. ~CGLMProgram( );
  78. void SetProgramText ( char *text ); // import text to GLM object - invalidate any prev compiled program
  79. bool CompileActiveSources ( void ); // compile only the flavors that were provided.
  80. bool Compile ( EGLMProgramLang lang );
  81. bool CheckValidity ( EGLMProgramLang lang );
  82. void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that
  83. void GetLabelIndexCombo ( char *labelOut, int labelOutMaxChars, int *indexOut, int *comboOut );
  84. void GetComboIndexNameString ( char *stringOut, int stringOutMaxChars ); // mmmmmmmm-nnnnnnnn-filename
  85. #if GLMDEBUG
  86. bool PollForChanges( void ); // check mirror for changes.
  87. void ReloadStringFromEditable( void ); // populate m_string from editable item (react to change)
  88. bool SyncWithEditable( void );
  89. #endif
  90. //===============================
  91. // common stuff
  92. GLMContext *m_ctx; // link back to parent context
  93. EGLMProgramType m_type; // vertex or pixel
  94. uint m_serial; // serial number for hashing
  95. char *m_text; // copy of text passed into constructor. Can change if editable shaders is enabled.
  96. // note - it can contain multiple flavors, so use CGLMTextSectioner to scan it and locate them
  97. #if GLMDEBUG
  98. CGLMEditableTextItem *m_editable; // editable text item for debugging
  99. #endif
  100. GLMShaderDesc m_descs[ kGLMNumProgramLangs ];
  101. uint m_samplerMask; // (1<<n) mask of sampler active locs, if this is a fragment shader (dxabstract sets this field)
  102. };
  103. //===============================================================================
  104. struct GLMShaderPairInfo
  105. {
  106. int m_status; // -1 means req'd index was out of bounds (loop stop..) 0 means not present. 1 means present/active.
  107. char m_vsName[ 128 ];
  108. int m_vsStaticIndex;
  109. int m_vsDynamicIndex;
  110. char m_psName[ 128 ];
  111. int m_psStaticIndex;
  112. int m_psDynamicIndex;
  113. };
  114. class CGLMShaderPair // a container for a linked GLSL shader pair, and metadata obtained post-link
  115. {
  116. public:
  117. friend class CGLMProgram;
  118. friend class GLMContext;
  119. friend class CGLMShaderPairCache;
  120. //===============================
  121. // constructor just sets up a GLSL program object and leaves it empty.
  122. CGLMShaderPair( GLMContext *ctx );
  123. ~CGLMShaderPair( );
  124. bool SetProgramPair ( CGLMProgram *vp, CGLMProgram *fp );
  125. // true result means successful link and query
  126. bool RefreshProgramPair ( void );
  127. // re-link and re-query the uniforms
  128. //===============================
  129. // common stuff
  130. GLMContext *m_ctx; // link back to parent context
  131. CGLMProgram *m_vertexProg;
  132. CGLMProgram *m_fragmentProg;
  133. GLhandleARB m_program; // linked program object
  134. // need meta data for attribs / samplers / params
  135. // actually we only need it for samplers and params.
  136. // attributes are hardwired.
  137. // vertex stage uniforms
  138. GLint m_locVertexParams; // "vc" per dx9asmtogl2 convention
  139. GLint m_locVertexInteger0; // "i0"
  140. GLint m_locVertexBool0; // "b0"
  141. GLint m_locVertexBool1; // "b1"
  142. GLint m_locVertexBool2; // "b2"
  143. GLint m_locVertexBool3; // "b3"
  144. // fragment stage uniforms
  145. GLint m_locFragmentParams; // "pc" per dx9asmtogl2 convention
  146. GLint m_locFragmentFakeSRGBEnable; // "flSRGBWrite" - set to 1.0 to effect sRGB encoding on output
  147. float m_fakeSRGBEnableValue; // shadow to avoid redundant sets of the m_locFragmentFakeSRGBEnable uniform
  148. // init it to -1.0 at link or relink, so it will trip on any legit incoming value (0.0 or 1.0)
  149. GLint m_locSamplers[ 16 ]; // "sampler0 ... sampler1..."
  150. // other stuff
  151. bool m_valid; // true on successful link
  152. bool m_samplersFixed; // set on first draw (can't write the uniforms until the program is in use, and we don't want to mess with cur program inside cglmprogram)
  153. uint m_revision; // if this pair is relinked, bump this number.
  154. };
  155. //===============================================================================
  156. // N-row, M-way associative cache with LRU per row.
  157. // still needs some metric dump ability and some parameter tuning.
  158. // extra credit would be to make an auto-tuner.
  159. struct CGLMPairCacheEntry
  160. {
  161. long long m_lastMark; // a mark of zero means an empty entry
  162. CGLMProgram *m_vertexProg;
  163. CGLMProgram *m_fragmentProg;
  164. uint m_extraKeyBits;
  165. CGLMShaderPair *m_pair;
  166. };
  167. class CGLMShaderPairCache // cache for linked GLSL shader pairs
  168. {
  169. public:
  170. protected:
  171. friend class CGLMShaderPair;
  172. friend class CGLMProgram;
  173. friend class GLMContext;
  174. //===============================
  175. CGLMShaderPairCache( GLMContext *ctx );
  176. ~CGLMShaderPairCache( );
  177. CGLMShaderPair *SelectShaderPair ( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits );
  178. void QueryShaderPair ( int index, GLMShaderPairInfo *infoOut );
  179. // shoot down linked pairs that use the program in the arg
  180. // return true if any had to be skipped due to conflict with currently bound pair
  181. bool PurgePairsWithShader( CGLMProgram *prog );
  182. // purge everything (when would GLM know how to do this ? at context destroy time, but any other times?)
  183. // return true if any had to be skipped due to conflict with currently bound pair
  184. bool Purge ( void );
  185. // stats
  186. void DumpStats ( void );
  187. //===============================
  188. uint HashRowIndex ( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits );
  189. CGLMPairCacheEntry* HashRowPtr ( uint hashRowIndex );
  190. void HashRowProbe ( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int *hitwayOut, int *emptywayOut, int *oldestwayOut );
  191. //===============================
  192. // common stuff
  193. GLMContext *m_ctx; // link back to parent context
  194. long long m_mark;
  195. uint m_rowsLg2;
  196. uint m_rows;
  197. uint m_waysLg2;
  198. uint m_ways;
  199. uint m_entryCount;
  200. CGLMPairCacheEntry *m_entries; // array[ m_rows ][ m_ways ]
  201. uint *m_evictions; // array[ m_rows ];
  202. uint *m_hits; // array[ m_rows ];
  203. };
  204. #endif