summaryrefslogtreecommitdiff
path: root/Runtime/GfxDevice/GfxDevice.h
blob: 07d3906aa2353cd945ee25ce8396cb3c91591a6d (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
#pragma once

#include "Configuration/UnityConfigure.h"
#include "GfxDeviceConfigure.h"
#include "GfxDeviceTypes.h"
#include "GfxDeviceObjects.h"
#include "GfxDeviceStats.h"
#include "Runtime/Math/Matrix4x4.h"
#include "Runtime/Math/Color.h"
#include "Runtime/Shaders/GraphicsCaps.h"
#include "Runtime/Shaders/MaterialProperties.h"
#include "Runtime/Threads/Thread.h"
#include "BuiltinShaderParams.h"
#include "Runtime/Modules/ExportModules.h"

#if UNITY_EDITOR && UNITY_WIN
#include "GfxDeviceWindow.h"
#endif

#if ENABLE_TEXTUREID_MAP
	#include "TextureIdMap.h"
#endif


// On some platforms we choose renderer at runtime; on others there's always a single
// renderer. On those that have only one, GFX_DEVICE_VIRTUAL is defined to zero, and
// the actual implementation is named GfxDevice, and uses no virtual functions.

#if UNITY_PS3
//#	define CELL_GCM_DEBUG
#	include <cell/gcm.h>
#endif

#if UNITY_WIN || UNITY_OSX || UNITY_LINUX || UNITY_PS3 || UNITY_IPHONE || UNITY_ANDROID || UNITY_PEPPER || UNITY_XENON || UNITY_BB10 || UNITY_WEBGL || UNITY_TIZEN
#define GFX_DEVICE_VIRTUAL 1
#else
#define GFX_DEVICE_VIRTUAL 0
#endif

#if (UNITY_OSX && WEBPLUG) || UNITY_LINUX && !UNITY_PEPPER
#define GFX_USES_VIEWPORT_OFFSET 1
#else
#define GFX_USES_VIEWPORT_OFFSET 0
#endif



#if GFX_DEVICE_VIRTUAL

#define GFX_API virtual
#define GFX_PURE = 0
#define GFX_GL_IMPL GfxDeviceGL

#else

#define GFX_API
#define GFX_PURE
#define GFX_GL_IMPL GfxDevice
struct GfxDeviceImpl;

#endif

#define GFX_DEVICE_VERIFY_ENABLE (!UNITY_RELEASE)

class VBO;
class RawVBO;
class VBOList;
class DynamicVBO;
class RenderTexture;
class ImageReference;
class Matrix4x4f;
class GpuProgram;
class GpuProgramParameters;
class GfxTimerQuery;
class GfxDisplayList;
class MaterialPropertyBlock;
class ShaderErrors;
class ChannelAssigns;
class CreateGpuProgramOutput;
struct SkinMeshInfo;
struct MemExportInfo;
struct VertexBufferData;
struct IndexBufferData;
struct PropertyNamesSet;
#if ENABLE_SPRITES
struct SpriteRenderData;
#endif
struct BoneInfluence;
namespace ShaderLab {
	class IntShader;
	struct ParserShader;
	struct TextureBinding;
	class PropertySheet;
	class SubProgram;
}
namespace xenon {
	class IVideoPlayer;
}

class GPUSkinningInfo;

class GfxDevice {
public:

	enum PresentMode
	{
		kPresentBeforeUpdate,
		kPresentAfterDraw
	};

	enum SurfaceFlags
	{
		kSurfaceDefault = 0,

		// Bits 0 and 1 are used to control render target restores. There flags are mutually exclusive.
		kSurfaceNeverRestore  = (1<<0), // Xbox 360: SetRenderTarget will never restore contents to EDRAM.
		kSurfaceAlwaysRestore = (1<<1), // Xbox 360: SetRenderTarget will always restore contents to EDRAM.
		kSurfaceRestoreMask   = kSurfaceNeverRestore | kSurfaceAlwaysRestore,
		// Xbox 360: SetRenderTarget by default will only restore contents to EDRAM if render target was previously used that frame.

		// next flag (1<<2)
	};

	enum ReloadResourcesFlags {
		kReleaseRenderTextures = (1<<0),
		kReloadShaders = (1<<1),
		kReloadTextures = (1<<2),
	};

	enum RenderTargetFlags {
		kFlagDontRestoreColor = (1<<0),	// Xbox 360 specific: do not restore old contents to EDRAM
		kFlagDontRestoreDepth = (1<<1),	// Xbox 360 specific: do not restore old contents to EDRAM
		kFlagDontRestore      = kFlagDontRestoreColor | kFlagDontRestoreDepth,
		kFlagForceResolve     = (1<<3), // Xbox 360 specific: force a resolve to system RAM
	};

	enum ImmediateShapeType {
		kShapeCube = 0,			// Quads
		kShapeDodecahedron		// Triangles
	};

	enum GfxProfileControl {
		kGfxProfBeginFrame = 0,
		kGfxProfEndFrame,
		kGfxProfDisableSampling,
		kGfxProfSetActive,
	};

	GfxDevice();
	GFX_API ~GfxDevice();

	GFX_API void	InvalidateState() GFX_PURE;
	#if GFX_DEVICE_VERIFY_ENABLE
	GFX_API void	VerifyState() GFX_PURE;
	#endif

	GfxDeviceRenderer GetRenderer() const { return m_Renderer; }
	// OpenGL: texture V coordinate is 0 at the bottom; 1 at the top
	// otherwise: texture V coordinate is 0 at the top; 1 at the bottom
	bool UsesOpenGLTextureCoords() const { return m_UsesOpenGLTextureCoords; }
	// Should half-texel offset be applied for pixel-correct rendering (true on D3D9)?
	bool UsesHalfTexelOffset() const { return m_UsesHalfTexelOffset; }

	GFX_API void SetMaxBufferedFrames (int bufferSize) { m_MaxBufferedFrames = bufferSize; }
	int GetMaxBufferedFrames () const { return m_MaxBufferedFrames; }

	const GfxDeviceStats& GetFrameStats() const { return m_Stats; }
	GfxDeviceStats& GetFrameStats() { return m_Stats; }

	RenderTexture* GetActiveRenderTexture() const
	{
#if !UNITY_EDITOR // TODO: this needs fixing in the editor
		ASSERT_RUNNING_ON_MAIN_THREAD;
#endif
		return m_ActiveRenderTexture;
	}
	void SetActiveRenderTexture(RenderTexture* rt)
	{
#if !UNITY_EDITOR // TODO: this needs fixing in the editor
		ASSERT_RUNNING_ON_MAIN_THREAD;
#endif
		m_ActiveRenderTexture = rt;
	}

	const BuiltinShaderParamValues& GetBuiltinParamValues() const { return m_BuiltinParamValues; }
	BuiltinShaderParamValues& GetBuiltinParamValues() { return m_BuiltinParamValues; }
	const GfxFogParams& GetFogParams() const { return m_FogParams; }

	static inline ColorRGBA32 ConvertToDeviceVertexColor(const ColorRGBA32& color)
	{
		#if GFX_OPENGLESxx_ONLY || UNITY_PS3 || UNITY_WII
			// Optimization: we know that we never have to swizzle vertex color here
			DebugAssert(gGraphicsCaps.needsToSwizzleVertexColors == false);
			return color;
		#elif UNITY_XENON
			// Optimization: we know that we always have to swizzle vertex color on Xbox360 platform
			DebugAssert(gGraphicsCaps.needsToSwizzleVertexColors == true);
			return color.SwizzleToARGB();
		#else
			return gGraphicsCaps.needsToSwizzleVertexColors ? color.SwizzleToBGRA() : color;
		#endif
	};

	int			GetTotalVBOCount() const;
	int			GetTotalVBOBytes() const;

	void		RecreateAllVBOs();

	#if GFX_SUPPORTS_D3D9
		void		ResetDynamicVBs();
	#endif
	#if GFX_SUPPORTS_OPENGLES20
		void		MarkAllVBOsLost();
	#endif


	GFX_API void	Clear (UInt32 clearFlags, const float color[4], float depth, int stencil) GFX_PURE;
	GFX_API void	SetInvertProjectionMatrix( bool enable ) GFX_PURE;
	GFX_API bool	GetInvertProjectionMatrix() const GFX_PURE;
	#if GFX_USES_VIEWPORT_OFFSET
	GFX_API void	SetViewportOffset( float x, float y ) GFX_PURE;
	GFX_API void	GetViewportOffset( float &x, float &y ) const GFX_PURE;
	#endif

	GFX_API DeviceBlendState* CreateBlendState(const GfxBlendState& state) GFX_PURE;
	GFX_API DeviceDepthState* CreateDepthState(const GfxDepthState& state) GFX_PURE;
	GFX_API DeviceStencilState* CreateStencilState(const GfxStencilState& state) GFX_PURE;
	GFX_API DeviceRasterState* CreateRasterState(const GfxRasterState& state) GFX_PURE;

	GFX_API void RecordSetBlendState(const DeviceBlendState* state, const ShaderLab::FloatVal& alphaRef, const ShaderLab::PropertySheet* props );
	GFX_API void SetBlendState(const DeviceBlendState* state, float alphaRef) GFX_PURE;
	GFX_API void SetRasterState(const DeviceRasterState* state) GFX_PURE;
	GFX_API void SetDepthState(const DeviceDepthState* state) GFX_PURE;
	GFX_API void SetStencilState(const DeviceStencilState* state, int stencilRef) GFX_PURE;
	GFX_API void SetSRGBWrite (const bool) GFX_PURE;
	GFX_API bool GetSRGBWrite () GFX_PURE;

	GFX_API void SetUserBackfaceMode(bool enable) GFX_PURE;
	GFX_API void SetWireframe(bool wire) GFX_PURE;
	GFX_API bool GetWireframe() const GFX_PURE;

	GFX_API void	SetWorldMatrixAndType( const float matrix[16], TransformType type );
	GFX_API void	SetWorldMatrix( const float matrix[16] ) GFX_PURE;
	GFX_API void	SetViewMatrix( const float matrix[16] ) GFX_PURE;
	GFX_API void	SetProjectionMatrix (const Matrix4x4f& matrix) GFX_PURE;

	GFX_API void	GetMatrix( float outMatrix[16] ) const GFX_PURE;


	GFX_API	const float* GetWorldMatrix() const GFX_PURE;
	GFX_API	const float* GetViewMatrix() const GFX_PURE;
	GFX_API	const float* GetProjectionMatrix() const GFX_PURE; // get projection matrix as passed from Unity (OpenGL projection conventions)
	GFX_API const float* GetDeviceProjectionMatrix() const GFX_PURE; // get projection matrix that will be actually used

	GFX_API void	SetInverseScale (float invScale);

	GFX_API void	SetNormalizationBackface( NormalizationMode mode, bool backface ) GFX_PURE;

	GFX_API void	SetFFLighting( bool on, bool separateSpecular, ColorMaterialMode colorMaterial ) GFX_PURE;
	GFX_API void	RecordSetMaterial( const ShaderLab::VectorVal& ambient, const ShaderLab::VectorVal& diffuse, const ShaderLab::VectorVal& specular, const ShaderLab::VectorVal& emissive, const ShaderLab::FloatVal& shininess, const ShaderLab::PropertySheet* props );
	GFX_API void	SetMaterial( const float ambient[4], const float diffuse[4], const float specular[4], const float emissive[4], const float shininess ) GFX_PURE;
	GFX_API void	RecordSetColor( const ShaderLab::VectorVal& color, const ShaderLab::PropertySheet* props );
	GFX_API void	SetColor( const float color[4] ) GFX_PURE;
	GFX_API void	SetViewport( int x, int y, int width, int height ) GFX_PURE;
	GFX_API void	GetViewport( int* values ) const GFX_PURE;

	GFX_API void	SetScissorRect( int x, int y, int width, int height ) GFX_PURE;
	GFX_API void	DisableScissor() GFX_PURE;
	GFX_API bool	IsScissorEnabled() const GFX_PURE;
	GFX_API void	GetScissorRect( int values[4] ) const GFX_PURE;

	GFX_API TextureCombinersHandle CreateTextureCombiners( int count, const ShaderLab::TextureBinding* texEnvs, const ShaderLab::PropertySheet* props, bool hasVertexColorOrLighting, bool usesAddSpecular ) GFX_PURE;
	GFX_API void	DeleteTextureCombiners( TextureCombinersHandle& textureCombiners ) GFX_PURE;
	GFX_API void	SetTextureCombiners( TextureCombinersHandle textureCombiners, const ShaderLab::PropertySheet* props ) GFX_PURE;

	GFX_API void	SetTexture (ShaderType shaderType, int unit, int samplerUnit, TextureID texture, TextureDimension dim, float bias) GFX_PURE;
	GFX_API void	SetTextureParams( TextureID texture, TextureDimension texDim, TextureFilterMode filter, TextureWrapMode wrap, int anisoLevel, bool hasMipMap, TextureColorSpace colorSpace ) GFX_PURE;
	GFX_API void	SetTextureTransform( int unit, TextureDimension dim, TexGenMode texGen, bool identity, const float matrix[16]) GFX_PURE;
	GFX_API void	SetTextureName( TextureID texture, char const* name ) GFX_PURE;

	GFX_API void	SetMaterialProperties(const MaterialPropertyBlock& block);

	GFX_API GpuProgram* CreateGpuProgram( const std::string& source, CreateGpuProgramOutput& output );
	GFX_API void	SetShadersMainThread( ShaderLab::SubProgram* programs[kShaderTypeCount], const ShaderLab::PropertySheet* props ) GFX_PURE;

	GFX_API bool	IsShaderActive( ShaderType type ) const GFX_PURE;
	GFX_API void	DestroySubProgram( ShaderLab::SubProgram* subprogram ) GFX_PURE;
	GFX_API void	SetConstantBufferInfo (int /*id*/, int /*size*/) { }

	GFX_API void	DisableLights( int startLight ) GFX_PURE;
	GFX_API void	SetLight( int light, const GfxVertexLight& data) GFX_PURE;
	GFX_API void	SetAmbient( const float ambient[4] ) GFX_PURE;

	GFX_API void	RecordEnableFog( FogMode fogMode, const ShaderLab::FloatVal& fogStart, const ShaderLab::FloatVal& fogEnd, const ShaderLab::FloatVal& fogDensity, const ShaderLab::VectorVal& fogColor, const ShaderLab::PropertySheet* props );
	GFX_API void	EnableFog( const GfxFogParams& fog ) GFX_PURE;
	GFX_API void	DisableFog() GFX_PURE;

	GFX_API VBO*	CreateVBO() GFX_PURE;
	GFX_API void	DeleteVBO( VBO* vbo ) GFX_PURE;
	GFX_API DynamicVBO&	GetDynamicVBO() GFX_PURE;

	GFX_API void	BeginSkinning( int maxSkinCount );
	GFX_API bool	SkinMesh( const SkinMeshInfo& skin, VBO* vbo );
	GFX_API void	EndSkinning();

#if GFX_ENABLE_DRAW_CALL_BATCHING
	static	int		GetMaxStaticBatchIndices();
	GFX_API	void	BeginStaticBatching(const ChannelAssigns& channels, GfxPrimitiveType topology);
	GFX_API	void	StaticBatchMesh( UInt32 firstVertex, UInt32 vertexCount, const IndexBufferData& indices, UInt32 firstIndexByte, UInt32 indexCount );
	GFX_API	void	EndStaticBatching( VBO& vbo, const Matrix4x4f& matrix, TransformType transformType, int sourceChannels );

	GFX_API	void	BeginDynamicBatching( const ChannelAssigns& shaderChannels, UInt32 availableChannels, size_t maxVertices, size_t maxIndices, GfxPrimitiveType topology);
	GFX_API	void	DynamicBatchMesh( const Matrix4x4f& matrix, const VertexBufferData& vertices, UInt32 firstVertex, UInt32 vertexCount, const IndexBufferData& indices, UInt32 firstIndexByte, UInt32 indexCount );
	GFX_API	void	EndDynamicBatching( TransformType transformType );
#if ENABLE_SPRITES
	GFX_API	void    DynamicBatchSprite(const Matrix4x4f* matrix, const SpriteRenderData* rd, ColorRGBA32 color);
#endif
#endif

	GFX_API	void	AddBatchingStats( int batchedTris, int batchedVerts, int batchedCalls );

	/**
	* CreateGPUSkinningInfo - Create a GPU-assisted skinning object.
	*
	* GPU-assisted skinning is limited to platforms that support GPU
	* writing the skinned output mesh into a VBO (StreamOut, MemExport, Transform Feedback).
	*
	* The returned object should be used against a single Skinned Mesh instance, and deleted once no longer needed.
	*
	* @return GFX_API GPUSkinningInfo* New GPU skinning object, or NULL if GPU skinning is not supported on this GfxDevice.
	*/
	GFX_API GPUSkinningInfo* CreateGPUSkinningInfo() GFX_PURE;

	/**
	* DeleteGPUSkinningInfo - Release a GPUSkinningInfo object.
	*
	* @param info GPUSkinningInfo object to delete
	*/
	GFX_API void DeleteGPUSkinningInfo(GPUSkinningInfo *info) GFX_PURE;

	/**
	* SkinOnGPU - Perform GPU-assisted skinning into the destination VBO.
	*
	* @param info GPUSkinningInfo object filled with valid data and set up using UpdateSkinData and UpdateSkinBones
	* @param lastThisFrame True if this is the last GPU-skinned mesh in this frame, false otherwise.
	*/
	GFX_API void	SkinOnGPU( GPUSkinningInfo* info, bool lastThisFrame ) GFX_PURE;

	/**
	* UpdateSkinSourceData - Pass the Vertex and skin data to the GPU.
	*
	* Assumes channel map, vertex count and stride has been previously set.
	* If dirty is true, the vertex or skin data has changed since the last call, and the implementation should refresh the content.
	* Otherwise, the implementation should just check that it has set up its internal buffers correctly and return.
	*
	* @param info GPUSkinningInfo object, expected to be properly set up with calls to setVertexCount, setChannelMap and setStride
	* @param vertData Vertex data, array size defined by previous calls to setVertexCount(), setChannelMap() and setStride
	* @param skinData Bone influence data, array size defined by setVertexCount
	* @param dirty Dirty flag, see above
	*/
	GFX_API void UpdateSkinSourceData(GPUSkinningInfo *info, const void *vertData, const BoneInfluence *skinData, bool dirty) GFX_PURE;

	/**
	* UpdateSkinBonePoses - Update bone pose matrices for a GPU-assisted skin.
	*
	* Note that the array is not guaranteed to stay alive after the call, so unless
	* the data can be uploaded immediately, a local copy is required.
	*
	* @param boneCount Number of bones
	* @param poses Array of bone matrices
	*/
	GFX_API void UpdateSkinBonePoses(GPUSkinningInfo *info, const int boneCount, const Matrix4x4f* poses) GFX_PURE;


#if UNITY_XENON
	GFX_API RawVBO*	CreateRawVBO( UInt32 size, UInt32 flags ) GFX_PURE;
	GFX_API void	DeleteRawVBO( RawVBO* vbo ) GFX_PURE;
	GFX_API void    EnablePersistDisplayOnQuit( bool enabled ) GFX_PURE;

	GFX_API void    RegisterTexture2D( TextureID tid, IDirect3DBaseTexture9* texture ) GFX_PURE;
	GFX_API void    PatchTexture2D( TextureID tid, IDirect3DBaseTexture9* texture ) GFX_PURE;
	GFX_API void    DeleteTextureEntryOnly( TextureID textureID ) GFX_PURE;
	GFX_API void    UnbindAndDelayReleaseTexture( IDirect3DBaseTexture9* texture ) GFX_PURE;
	GFX_API void    SetTextureWrapModes( TextureID textureID, TextureWrapMode wrapU, TextureWrapMode wrapV, TextureWrapMode wrapW ) GFX_PURE;

	GFX_API void    OnLastFrameCallback() GFX_PURE;

	GFX_API xenon::IVideoPlayer* CreateVideoPlayer( bool fullscreen ) GFX_PURE;
	GFX_API void                 DeleteVideoPlayer( xenon::IVideoPlayer* player ) GFX_PURE;
	GFX_API void SetNullPixelShader() GFX_PURE;
	GFX_API void SetHiZEnable( const HiZstate hiz_enable ) GFX_PURE;
	GFX_API void SetHiStencilState( const bool hiStencilEnable, const bool hiStencilWriteEnable, const int hiStencilRef, const CompareFunction cmpFunc ) GFX_PURE;
	GFX_API void HiStencilFlush( const HiSflush flushtype ) GFX_PURE;
#endif

	GFX_API RenderSurfaceHandle CreateRenderColorSurface (TextureID textureID, int width, int height, int samples, int depth, TextureDimension dim, RenderTextureFormat format, UInt32 createFlags) GFX_PURE;
	GFX_API RenderSurfaceHandle CreateRenderDepthSurface (TextureID textureID, int width, int height, int samples, TextureDimension dim, DepthBufferFormat depthFormat, UInt32 createFlags) GFX_PURE;
	GFX_API void DestroyRenderSurface (RenderSurfaceHandle& rs) GFX_PURE;
	GFX_API void SetRenderTargets (int count, RenderSurfaceHandle* colorHandles, RenderSurfaceHandle depthHandle, int mipLevel = 0, CubemapFace face = kCubeFaceUnknown) GFX_PURE;
	GFX_API void SetRenderTargets (int count, RenderSurfaceHandle* colorHandles, RenderSurfaceHandle depthHandle, int mipLevel, CubemapFace face, UInt32 flags)
#if !UNITY_XENON
	{ SetRenderTargets(count, colorHandles, depthHandle, mipLevel, face); }
#else
	GFX_PURE
#endif
	;

	GFX_API void ResolveColorSurface (RenderSurfaceHandle srcHandle, RenderSurfaceHandle dstHandle) GFX_PURE;

	GFX_API void DiscardContents (RenderSurfaceHandle& rs) GFX_PURE;
	// Do not produce a warning for next unresolve of current RT; it is expected and there's nothing we can do about it
	GFX_API void IgnoreNextUnresolveOnCurrentRenderTarget() { }
	GFX_API void IgnoreNextUnresolveOnRS(RenderSurfaceHandle rs) { }

	GFX_API void ResolveDepthIntoTexture (RenderSurfaceHandle /*colorHandle*/, RenderSurfaceHandle /*depthHandle*/) { }

	GFX_API RenderSurfaceHandle GetActiveRenderColorSurface (int index) GFX_PURE;
	GFX_API RenderSurfaceHandle GetActiveRenderDepthSurface () GFX_PURE;

	// TODO: we might need to extend it in the future, e.g. for multi-display
	GFX_API RenderSurfaceHandle GetBackBufferColorSurface () 	{ return m_BackBufferColor; }
	GFX_API RenderSurfaceHandle GetBackBufferDepthSurface () 	{ return m_BackBufferDepth; }

	GFX_API void SetBackBufferColorSurface(RenderSurfaceBase* color)	{ m_BackBufferColor=RenderSurfaceHandle(color); }
	GFX_API void SetBackBufferDepthSurface(RenderSurfaceBase* depth)	{ m_BackBufferDepth=RenderSurfaceHandle(depth); }

	GFX_API bool IsRenderTargetConfigValid(UInt32 width, UInt32 height, RenderTextureFormat /*colorFormat*/, DepthBufferFormat /*depthFormat*/)
#if !UNITY_XENON
	{ return width <= gGraphicsCaps.maxRenderTextureSize && height <= gGraphicsCaps.maxRenderTextureSize; }
#else
	GFX_PURE
#endif
	;

	GFX_API void SetSurfaceFlags(RenderSurfaceHandle surf, UInt32 flags, UInt32 keepFlags = 0) GFX_PURE;

	GFX_API TextureID	CreateTextureID();
	GFX_API void		FreeTextureID( TextureID texture );

#if ENABLE_TEXTUREID_MAP
	GFX_API intptr_t	CreateExternalTextureFromNative(intptr_t nativeTex) 				{ return nativeTex; }
	GFX_API void		UpdateExternalTextureFromNative(TextureID tex, intptr_t nativeTex)	{ TextureIdMap::UpdateTexture(tex, nativeTex); }
#endif

	enum kUploadTextureFlags
	{
		kUploadTextureDefault = 0,
		kUploadTextureDontUseSubImage = 1<<0, // texture might not be created yet, or is being resized
		kUploadTextureOSDrawingCompatible = 1<<1, // create an OS-drawing compatible one (e.g. for GDI on Windows)
		// NOTE: Richard S added these on another Xbox360 branch, uncomment/merge when that branch comes back
		//kUploadTextureTiled = 1<<2,
		//kUploadTextureMemoryReady = 1<<3,
	};

	GFX_API void UploadTexture2D( TextureID texture, TextureDimension dimension, UInt8* srcData, int srcSize, int width, int height, TextureFormat format, int mipCount, UInt32 uploadFlags, int skipMipLevels, TextureUsageMode usageMode,  TextureColorSpace colorSpace ) GFX_PURE;
	GFX_API void UploadTextureSubData2D( TextureID texture, UInt8* srcData, int srcSize, int mipLevel, int x, int y, int width, int height, TextureFormat format, TextureColorSpace colorSpace ) GFX_PURE;
	GFX_API void UploadTextureCube( TextureID texture, UInt8* srcData, int srcSize, int faceDataSize, int size, TextureFormat format, int mipCount, UInt32 uploadFlags, TextureColorSpace colorSpace ) GFX_PURE;
	GFX_API void UploadTexture3D( TextureID texture, UInt8* srcData, int srcSize, int width, int height, int depth, TextureFormat format, int mipCount, UInt32 uploadFlags ) GFX_PURE;
	GFX_API void DeleteTexture( TextureID texture ) GFX_PURE;

	GFX_API PresentMode	GetPresentMode() GFX_PURE;

	GFX_API void	BeginFrame() GFX_PURE;
	GFX_API void	EndFrame() GFX_PURE;
	inline bool		IsInsideFrame() const { return m_InsideFrame; }
	inline void		SetInsideFrame(bool v) { m_InsideFrame = v; }
	GFX_API void	PresentFrame() GFX_PURE;
	// Check if device is in valid state. E.g. lost device on D3D9; in this case all rendering
	// should be skipped.
	GFX_API bool	IsValidState() GFX_PURE;
	GFX_API bool	HandleInvalidState() { return true; }
	GFX_API void	ResetDynamicResources() {}
	GFX_API bool	IsReadyToBeginFrame() { return true; }

	// Fully finish any queued-up rendering (including on the GPU)
	GFX_API void	FinishRendering() GFX_PURE;
	// Insert CPU fence into command queue (if threaded)
	GFX_API UInt32	InsertCPUFence() { return 0; }
	// Get next CPU fence that will be inserted
	GFX_API UInt32	GetNextCPUFence() { return 0; }
	// Finish any threaded commands before CPU fence
	GFX_API void	WaitOnCPUFence(UInt32 /*fence*/) {}

	// Are we recording graphics commands?
	inline bool		IsRecording() const { return m_IsRecording; }

	// Does this device derive from GfxThreadableDevice?
	inline bool		IsThreadable() const { return m_IsThreadable; }

	// Acquire thread ownership on the calling thread. Worker releases ownership.
	GFX_API void	AcquireThreadOwnership() {}
	// Release thread ownership on the calling thread. Worker acquires ownership.
	GFX_API void	ReleaseThreadOwnership() {}

	// Immediate mode rendering
	GFX_API void	ImmediateShape( float x, float y, float z, float scale, ImmediateShapeType shape );
	GFX_API void	ImmediateVertex( float x, float y, float z ) GFX_PURE;
	GFX_API void	ImmediateNormal( float x, float y, float z ) GFX_PURE;
	GFX_API void	ImmediateColor( float r, float g, float b, float a ) GFX_PURE;
	GFX_API void	ImmediateTexCoordAll( float x, float y, float z ) GFX_PURE;
	GFX_API void	ImmediateTexCoord( int unit, float x, float y, float z ) GFX_PURE;
	GFX_API void	ImmediateBegin( GfxPrimitiveType type ) GFX_PURE;
	GFX_API	void	ImmediateEnd() GFX_PURE;

	// Recording display lists
#if GFX_SUPPORTS_DISPLAY_LISTS
	GFX_API bool	BeginRecording() { return false; }
	GFX_API bool	EndRecording( GfxDisplayList** outDisplayList ) { return false; }
#endif

	// Capturing screen shots / blits
	GFX_API bool	CaptureScreenshot( int left, int bottom, int width, int height, UInt8* rgba32 ) GFX_PURE;
	GFX_API bool	ReadbackImage( ImageReference& image, int left, int bottom, int width, int height, int destX, int destY ) GFX_PURE;
	GFX_API void	GrabIntoRenderTexture (RenderSurfaceHandle rs, RenderSurfaceHandle rd, int x, int y, int width, int height) GFX_PURE;

	// Any housekeeping around draw calls
	GFX_API void	BeforeDrawCall( bool immediateMode ) GFX_PURE;
	GFX_API void	AfterDrawCall() {};

	GFX_API bool	IsPositionRequiredForTexGen (int texStageIndex) const GFX_PURE;
	GFX_API bool	IsNormalRequiredForTexGen (int texStageIndex) const GFX_PURE;
	GFX_API bool	IsPositionRequiredForTexGen() const GFX_PURE;
	GFX_API bool	IsNormalRequiredForTexGen() const GFX_PURE;

	GFX_API void	SetActiveContext (void* /*ctx*/) {};

	GFX_API void	ResetFrameStats();
	GFX_API void	BeginFrameStats();
	GFX_API void	EndFrameStats();
	GFX_API void	SaveDrawStats();
	GFX_API void	RestoreDrawStats();
	GFX_API void	SynchronizeStats();

	#if ENABLE_PROFILER
	GFX_API void	BeginProfileEvent (const char* /*name*/) {}
	GFX_API void	EndProfileEvent () {}
	GFX_API void	ProfileControl (GfxProfileControl /*ctrl*/, unsigned /*param*/) {}

	GFX_API GfxTimerQuery*		CreateTimerQuery() GFX_PURE;
	GFX_API void				DeleteTimerQuery(GfxTimerQuery* query) GFX_PURE;
	GFX_API void				BeginTimerQueries() GFX_PURE;
	GFX_API void				EndTimerQueries() GFX_PURE;
	GFX_API bool				TimerQueriesIsActive() { return false; }
	#endif

	// Editor-only stuff
	#if UNITY_EDITOR
	GFX_API void	SetColorBytes (const UInt8 color[4]);
	GFX_API void				SetAntiAliasFlag( bool aa ) GFX_PURE;
	GFX_API void				DrawUserPrimitives( GfxPrimitiveType type, int vertexCount, UInt32 vertexChannels, const void* data, int stride ) GFX_PURE;
	GFX_API int					GetCurrentTargetAA() const GFX_PURE;

	#if UNITY_WIN
		//ToDo: This is windows specific code, we should replace HWND window with something more abstract
		GFX_API GfxDeviceWindow*	CreateGfxWindow( HWND window, int width, int height, DepthBufferFormat depthFormat, int antiAlias ) GFX_PURE;

	#endif
	#endif

	#if UNITY_WIN
		GFX_API int	GetCurrentTargetWidth() const { return 0; }
		GFX_API int	GetCurrentTargetHeight() const { return 0; }
		GFX_API void SetCurrentTargetSize(int /*width*/, int /*height*/) { }
		GFX_API void SetCurrentWindowSize(int /*width*/, int /*height*/) { }
	#endif

	static void CommonReloadResources( UInt32 flags );

	#if GFX_SUPPORTS_OPENGL
	GFX_API void UnbindObjects () {}
	#endif

	#if GFX_OPENGLESxx_ONLY || GFX_SUPPORTS_MOLEHILL
	GFX_API void ReloadResources() GFX_PURE;
	#endif

	#if !GFX_DEVICE_VIRTUAL
	GfxDeviceImpl*	GetImpl() { return impl; }
	#endif

#if GFX_DEVICE_VIRTUAL
	GFX_API RenderTextureFormat	GetDefaultRTFormat() const	{ return kRTFormatARGB32; }
#else
	GFX_API RenderTextureFormat	GetDefaultRTFormat() const;
#endif

#if GFX_DEVICE_VIRTUAL
	GFX_API RenderTextureFormat GetDefaultHDRRTFormat() const	{ return kRTFormatARGBHalf; }
#else
	GFX_API RenderTextureFormat	GetDefaultHDRRTFormat() const;
#endif

	GFX_API void* GetNativeGfxDevice() { return NULL; }
	GFX_API void* GetNativeTexturePointer(TextureID /*id*/) { return NULL; }
	GFX_API UInt32 GetNativeTextureID(TextureID id);
	GFX_API void InsertCustomMarker (int marker);

	GFX_API ComputeBufferID CreateComputeBufferID();
	GFX_API void FreeComputeBufferID(ComputeBufferID id);

	GFX_API void SetComputeBufferData (ComputeBufferID /*bufferHandle*/, const void* /*data*/, size_t /*size*/) { }
	GFX_API void GetComputeBufferData (ComputeBufferID /*bufferHandle*/, void* /*dest*/, size_t /*destSize*/) { }
	GFX_API void CopyComputeBufferCount (ComputeBufferID /*srcBuffer*/, ComputeBufferID /*dstBuffer*/, UInt32 /*dstOffset*/) { }

	GFX_API void SetRandomWriteTargetTexture (int /*index*/, TextureID /*tid*/) { }
	GFX_API void SetRandomWriteTargetBuffer (int /*index*/, ComputeBufferID /*bufferHandle*/) { }
	GFX_API void ClearRandomWriteTargets () { }

	GFX_API ComputeProgramHandle CreateComputeProgram (const UInt8* /*code*/, size_t /*codeSize*/) { ComputeProgramHandle cp; return cp; }
	GFX_API void DestroyComputeProgram (ComputeProgramHandle& /*cpHandle*/) { }
	GFX_API void CreateComputeConstantBuffers (unsigned /*count*/, const UInt32* /*sizes*/, ConstantBufferHandle* /*outCBs*/) { }
	GFX_API void DestroyComputeConstantBuffers (unsigned /*count*/, ConstantBufferHandle* /*cbs*/) { }
	GFX_API void CreateComputeBuffer (ComputeBufferID /*id*/, size_t /*count*/, size_t /*stride*/, UInt32 /*flags*/) { }
	GFX_API void DestroyComputeBuffer (ComputeBufferID /*handle*/) { }
	GFX_API void UpdateComputeConstantBuffers (unsigned /*count*/, ConstantBufferHandle* /*cbs*/, UInt32 /*cbDirty*/, size_t /*dataSize*/, const UInt8* /*data*/, const UInt32* /*cbSizes*/, const UInt32* /*cbOffsets*/, const int* /*bindPoints*/) { }
	GFX_API void UpdateComputeResources (
		unsigned /*texCount*/, const TextureID* /*textures*/, const int* /*texBindPoints*/,
		unsigned /*samplerCount*/, const unsigned* /*samplers*/,
		unsigned /*inBufferCount*/, const ComputeBufferID* /*inBuffers*/, const int* /*inBufferBindPoints*/,
		unsigned /*outBufferCount*/, const ComputeBufferID* /*outBuffers*/, const TextureID* /*outTextures*/, const UInt32* /*outBufferBindPoints*/) { }
	GFX_API void DispatchComputeProgram (ComputeProgramHandle /*cpHandle*/, unsigned /*threadsX*/, unsigned /*threadsY*/, unsigned /*threadsZ*/) { }

	GFX_API void DrawNullGeometry (GfxPrimitiveType /*topology*/, int /*vertexCount*/, int /*instanceCount*/) { };
	GFX_API void DrawNullGeometryIndirect (GfxPrimitiveType /*topology*/, ComputeBufferID /*bufferHandle*/, UInt32 /*bufferOffset*/) { };
	DepthBufferFormat GetFramebufferDepthFormat() const { return m_FramebufferDepthFormat; }
	void SetFramebufferDepthFormat(DepthBufferFormat depthFormat) { m_FramebufferDepthFormat = depthFormat; }

protected:
	void SetupVertexLightParams(int light, const GfxVertexLight& data);

private:

	#if !GFX_DEVICE_VIRTUAL
	GfxDeviceImpl*	impl;
	#endif

protected:
	void OnCreate();
	void OnDelete();
	void OnCreateVBO(VBO* vbo);
	void OnDeleteVBO(VBO* vbo);

	// Mutable state
	BuiltinShaderParamValues	m_BuiltinParamValues;
	GfxFogParams		m_FogParams;
	GfxDeviceStats		m_Stats;
	GfxDeviceStats		m_SavedStats;
	bool				m_InsideFrame;
	bool				m_IsRecording;
	bool				m_IsThreadable;
	RenderTexture*		m_ActiveRenderTexture;
	const BuiltinShaderParamIndices*	m_BuiltinParamIndices[kShaderTypeCount];
	BuiltinShaderParamIndices	m_NullParamIndices;
	MaterialPropertyBlock	m_MaterialProperties;

	// Immutable data
	GfxDeviceRenderer	m_Renderer;
	bool				m_UsesOpenGLTextureCoords;
	bool				m_UsesHalfTexelOffset;
	int					m_MaxBufferedFrames;
	DepthBufferFormat	m_FramebufferDepthFormat;


	RenderSurfaceHandle	m_BackBufferColor;
	RenderSurfaceHandle	m_BackBufferDepth;


private:

	VBOList*			m_VBOList;
	static volatile int	ms_TextureIDGenerator;
	static volatile int	ms_ComputeBufferIDGenerator;

	typedef std::map<TextureID, size_t> TextureIDToSizeMap;
	TextureIDToSizeMap m_TextureSizes;
};

class GfxThreadableDevice : public GfxDevice
{
public:
	//! Called by the worker thread on thread startup
	GFX_API void	OnDeviceCreated (bool /*callingFromRenderThread*/) { }

	//! IsCombineModeSupported() exists because we want CreateTextureCombiners() failure to happen
	//! on the main thread, not the render thread where we can't do anything about it.
	//! When it returns true then creating combiners *should* succeed
	GFX_API bool	IsCombineModeSupported( unsigned int combiner ) GFX_PURE;

	GFX_API void	SetTextureCombinersThreadable( TextureCombinersHandle textureCombiners, const TexEnvData* texEnvData, const Vector4f* texColors ) GFX_PURE;
	GFX_API void	SetShadersMainThread (ShaderLab::SubProgram* programs[kShaderTypeCount], const ShaderLab::PropertySheet* props);
	GFX_API void	SetShadersThreadable (GpuProgram* programs[kShaderTypeCount], const GpuProgramParameters* params[kShaderTypeCount], UInt8 const * const paramsBuffer[kShaderTypeCount]) { };

	//! CreateShaderParameters() exists because the main thread needs to know which parameters a shader takes, and on
	//! GL-like platforms it can vary with different fog modes because we recompile shaders when the mode was changed.
	GFX_API void	CreateShaderParameters( ShaderLab::SubProgram* /*program*/, FogMode /*fogMode*/ ) { }
};

bool				IsGfxDevice();
EXPORT_COREMODULE GfxDevice& GetGfxDevice();
GfxDevice&			GetUncheckedGfxDevice();
void				SetGfxDevice(GfxDevice* device);
void				DestroyGfxDevice();

GfxDevice&			GetRealGfxDevice();
bool				IsRealGfxDeviceThreadOwner();
#if ENABLE_MULTITHREADED_CODE
void				SetRealGfxDevice(GfxDevice* device);
void				SetRealGfxDeviceThreadOwnership();
void				DestroyRealGfxDevice();
void				SetGfxThreadingMode(GfxThreadingMode mode);
GfxThreadingMode	GetGfxThreadingMode();
#endif

class AutoGfxDeviceAcquireThreadOwnership
{
public:
	AutoGfxDeviceAcquireThreadOwnership();
	~AutoGfxDeviceAcquireThreadOwnership();

private:
	bool m_WasOwner;
};

class AutoGfxDeviceBeginEndFrame
{
public:
	AutoGfxDeviceBeginEndFrame();
	~AutoGfxDeviceBeginEndFrame();

	void End();
	bool GetSuccess() const { return m_Success; }

private:
	bool m_Success;
	bool m_NeedsEndFrame;
};

void CalculateDeviceProjectionMatrix (Matrix4x4f& m, bool usesOpenGLTextureCoords, bool invertY);

inline AutoGfxDeviceAcquireThreadOwnership::AutoGfxDeviceAcquireThreadOwnership()
{
	m_WasOwner = IsRealGfxDeviceThreadOwner();
	if (!m_WasOwner)
		GetGfxDevice().AcquireThreadOwnership();
}

inline AutoGfxDeviceAcquireThreadOwnership::~AutoGfxDeviceAcquireThreadOwnership()
{
	if (!m_WasOwner)
		GetGfxDevice().ReleaseThreadOwnership();
}

inline AutoGfxDeviceBeginEndFrame::AutoGfxDeviceBeginEndFrame() :
m_Success(true), m_NeedsEndFrame(false)
{
	GfxDevice& device = GetGfxDevice();
	if (!device.IsInsideFrame())
	{
		device.BeginFrame();
		m_Success = device.IsValidState();
		m_NeedsEndFrame = true;
	}
}

inline AutoGfxDeviceBeginEndFrame::~AutoGfxDeviceBeginEndFrame()
{
	End();
}

inline void AutoGfxDeviceBeginEndFrame::End()
{
	if (m_NeedsEndFrame)
		GetGfxDevice().EndFrame();
	m_NeedsEndFrame = false;
}


inline DepthBufferFormat DepthBufferFormatFromBits(int bits)
{
	if( bits <= 0 )
		return kDepthFormatNone;
	else if( bits <= 16 )
		return kDepthFormat16;
	else
		return kDepthFormat24;
}

#if UNITY_EDITOR
extern VertexComponent kSuitableVertexComponentForChannel[];
#endif


class SetAndRestoreWireframeMode {
public:
	SetAndRestoreWireframeMode() {
		GfxDevice& device = GetGfxDevice();
		m_SavedWireframe = device.GetWireframe();
	}
	SetAndRestoreWireframeMode(bool wireframe) {
		GfxDevice& device = GetGfxDevice();
		m_SavedWireframe = device.GetWireframe();
		device.SetWireframe(wireframe);
	}
	~SetAndRestoreWireframeMode() {
		GfxDevice& device = GetGfxDevice();
		device.SetWireframe(m_SavedWireframe);
	}
private:
	bool m_SavedWireframe;
};

void ApplyTexEnvData (unsigned int texUnit, unsigned int samplerUnit, const TexEnvData& data);