//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //===========================================================================// #ifndef ISHADERDEVICE_H #define ISHADERDEVICE_H #ifdef _WIN32 #pragma once #endif #include "appframework/IAppSystem.h" #include "bitmap/imageformat.h" #include "materialsystem/imaterial.h" #include "shaderapi/ishaderdynamic.h" #include "tier1/interface.h" #include "tier1/utlbuffer.h" //----------------------------------------------------------------------------- // forward declarations //----------------------------------------------------------------------------- struct MaterialAdapterInfo_t; class IMesh; class KeyValues; //----------------------------------------------------------------------------- // Describes how to set the mode //----------------------------------------------------------------------------- #define SHADER_DISPLAY_MODE_VERSION 1 struct ShaderDisplayMode_t { ShaderDisplayMode_t() { memset(this, 0, sizeof(ShaderDisplayMode_t)); m_nVersion = SHADER_DISPLAY_MODE_VERSION; } int m_nVersion; int m_nWidth; // 0 when running windowed means use desktop resolution int m_nHeight; ImageFormat m_Format; // use ImageFormats (ignored for windowed mode) int m_nRefreshRateNumerator; // Refresh rate. Use 0 in numerator + // denominator for a default setting. int m_nRefreshRateDenominator; // Refresh rate = numerator / denominator. }; //----------------------------------------------------------------------------- // Describes how to set the device //----------------------------------------------------------------------------- #define SHADER_DEVICE_INFO_VERSION 1 struct ShaderDeviceInfo_t { ShaderDeviceInfo_t() { memset(this, 0, sizeof(ShaderDeviceInfo_t)); m_nVersion = SHADER_DEVICE_INFO_VERSION; m_DisplayMode.m_nVersion = SHADER_DISPLAY_MODE_VERSION; } int m_nVersion; ShaderDisplayMode_t m_DisplayMode; int m_nBackBufferCount; // valid values are 1 or 2 [2 results in triple // buffering] int m_nAASamples; // Number of AA samples to use int m_nAAQuality; // AA quality level int m_nDXLevel; // 0 means use recommended DX level for this adapter int m_nWindowedSizeLimitWidth; // Used if m_bLimitWindowedSize is set, // defines max bounds for the back buffer int m_nWindowedSizeLimitHeight; bool m_bWindowed : 1; bool m_bResizing : 1; // Only is meaningful when using windowed mode; means // the window can be resized. bool m_bUseStencil : 1; bool m_bLimitWindowedSize : 1; // In windowed mode, should we prevent the // back buffer from getting too large? bool m_bWaitForVSync : 1; // Would we not present until vsync? bool m_bScaleToOutputResolution : 1; // 360 ONLY: sets up hardware scaling bool m_bProgressive : 1; // 360 ONLY: interlaced or progressive bool m_bUsingMultipleWindows : 1; // Forces D3DPresent to use _COPY instead }; //----------------------------------------------------------------------------- // Info for non-interactive mode //----------------------------------------------------------------------------- struct ShaderNonInteractiveInfo_t { ShaderAPITextureHandle_t m_hTempFullscreenTexture; int m_nPacifierCount; ShaderAPITextureHandle_t m_pPacifierTextures[64]; float m_flNormalizedX; float m_flNormalizedY; float m_flNormalizedSize; }; //----------------------------------------------------------------------------- // For vertex/index buffers. What type is it? // (NOTE: mirror this with a similarly named enum at the material system level // for backwards compatability.) //----------------------------------------------------------------------------- enum ShaderBufferType_t { SHADER_BUFFER_TYPE_STATIC = 0, SHADER_BUFFER_TYPE_DYNAMIC, SHADER_BUFFER_TYPE_STATIC_TEMP, SHADER_BUFFER_TYPE_DYNAMIC_TEMP, SHADER_BUFFER_TYPE_COUNT, }; inline bool IsDynamicBufferType(ShaderBufferType_t type) { return ((type == SHADER_BUFFER_TYPE_DYNAMIC) || (type == SHADER_BUFFER_TYPE_DYNAMIC_TEMP)); } //----------------------------------------------------------------------------- // Handle to a vertex, pixel, and geometry shader //----------------------------------------------------------------------------- DECLARE_POINTER_HANDLE(VertexShaderHandle_t); DECLARE_POINTER_HANDLE(GeometryShaderHandle_t); DECLARE_POINTER_HANDLE(PixelShaderHandle_t); #define VERTEX_SHADER_HANDLE_INVALID ((VertexShaderHandle_t)0) #define GEOMETRY_SHADER_HANDLE_INVALID ((GeometryShaderHandle_t)0) #define PIXEL_SHADER_HANDLE_INVALID ((PixelShaderHandle_t)0) //----------------------------------------------------------------------------- // A shader buffer returns a block of memory which must be released when done // with it //----------------------------------------------------------------------------- abstract_class IShaderBuffer { public: virtual size_t GetSize() const = 0; virtual const void *GetBits() const = 0; virtual void Release() = 0; }; //----------------------------------------------------------------------------- // Mode chance callback //----------------------------------------------------------------------------- typedef void (*ShaderModeChangeCallbackFunc_t)(void); //----------------------------------------------------------------------------- // Methods related to discovering and selecting devices //----------------------------------------------------------------------------- #define SHADER_DEVICE_MGR_INTERFACE_VERSION "ShaderDeviceMgr001" abstract_class IShaderDeviceMgr : public IAppSystem { public: // Gets the number of adapters... virtual int GetAdapterCount() const = 0; // Returns info about each adapter virtual void GetAdapterInfo(int nAdapter, MaterialAdapterInfo_t &info) const = 0; // Gets recommended congifuration for a particular adapter at a particular // dx level virtual bool GetRecommendedConfigurationInfo(int nAdapter, int nDXLevel, KeyValues *pConfiguration) = 0; // Returns the number of modes virtual int GetModeCount(int nAdapter) const = 0; // Returns mode information.. virtual void GetModeInfo(ShaderDisplayMode_t * pInfo, int nAdapter, int nMode) const = 0; // Returns the current mode info for the requested adapter virtual void GetCurrentModeInfo(ShaderDisplayMode_t * pInfo, int nAdapter) const = 0; // Initialization, shutdown virtual bool SetAdapter(int nAdapter, int nFlags) = 0; // Sets the mode // Use the returned factory to get at an IShaderDevice and an IShaderRender // and any other interfaces we decide to create. // A returned factory of NULL indicates the mode was not set properly. virtual CreateInterfaceFn SetMode(void *hWnd, int nAdapter, const ShaderDeviceInfo_t &mode) = 0; // Installs a callback to get called virtual void AddModeChangeCallback(ShaderModeChangeCallbackFunc_t func) = 0; virtual void RemoveModeChangeCallback( ShaderModeChangeCallbackFunc_t func) = 0; }; //----------------------------------------------------------------------------- // Methods related to control of the device //----------------------------------------------------------------------------- #define SHADER_DEVICE_INTERFACE_VERSION "ShaderDevice001" abstract_class IShaderDevice { public: // Releases/reloads resources when other apps want some memory virtual void ReleaseResources() = 0; virtual void ReacquireResources() = 0; // returns the backbuffer format and dimensions virtual ImageFormat GetBackBufferFormat() const = 0; virtual void GetBackBufferDimensions(int &width, int &height) const = 0; // Returns the current adapter in use virtual int GetCurrentAdapter() const = 0; // Are we using graphics? virtual bool IsUsingGraphics() const = 0; // Use this to spew information about the 3D layer virtual void SpewDriverInfo() const = 0; // What's the bit depth of the stencil buffer? virtual int StencilBufferBits() const = 0; // Are we using a mode that uses MSAA virtual bool IsAAEnabled() const = 0; // Does a page flip virtual void Present() = 0; // Returns the window size virtual void GetWindowSize(int &nWidth, int &nHeight) const = 0; // Gamma ramp control virtual void SetHardwareGammaRamp( float fGamma, float fGammaTVRangeMin, float fGammaTVRangeMax, float fGammaTVExponent, bool bTVEnabled) = 0; // Creates/ destroys a child window virtual bool AddView(void *hWnd) = 0; virtual void RemoveView(void *hWnd) = 0; // Activates a view virtual void SetView(void *hWnd) = 0; // Shader compilation virtual IShaderBuffer *CompileShader(const char *pProgram, size_t nBufLen, const char *pShaderVersion) = 0; // Shader creation, destruction virtual VertexShaderHandle_t CreateVertexShader(IShaderBuffer * pShaderBuffer) = 0; virtual void DestroyVertexShader(VertexShaderHandle_t hShader) = 0; virtual GeometryShaderHandle_t CreateGeometryShader(IShaderBuffer * pShaderBuffer) = 0; virtual void DestroyGeometryShader(GeometryShaderHandle_t hShader) = 0; virtual PixelShaderHandle_t CreatePixelShader(IShaderBuffer * pShaderBuffer) = 0; virtual void DestroyPixelShader(PixelShaderHandle_t hShader) = 0; // Utility methods to make shader creation simpler // NOTE: For the utlbuffer version, use a binary buffer for a compiled // shader and a text buffer for a source-code (.fxc) shader VertexShaderHandle_t CreateVertexShader( const char *pProgram, size_t nBufLen, const char *pShaderVersion); VertexShaderHandle_t CreateVertexShader(CUtlBuffer & buf, const char *pShaderVersion = NULL); GeometryShaderHandle_t CreateGeometryShader( const char *pProgram, size_t nBufLen, const char *pShaderVersion); GeometryShaderHandle_t CreateGeometryShader( CUtlBuffer & buf, const char *pShaderVersion = NULL); PixelShaderHandle_t CreatePixelShader(const char *pProgram, size_t nBufLen, const char *pShaderVersion); PixelShaderHandle_t CreatePixelShader(CUtlBuffer & buf, const char *pShaderVersion = NULL); // NOTE: Deprecated!! Use CreateVertexBuffer/CreateIndexBuffer instead // Creates/destroys Mesh virtual IMesh *CreateStaticMesh(VertexFormat_t vertexFormat, const char *pTextureBudgetGroup, IMaterial *pMaterial = NULL) = 0; virtual void DestroyStaticMesh(IMesh * mesh) = 0; // Creates/destroys static vertex + index buffers virtual IVertexBuffer *CreateVertexBuffer( ShaderBufferType_t type, VertexFormat_t fmt, int nVertexCount, const char *pBudgetGroup) = 0; virtual void DestroyVertexBuffer(IVertexBuffer * pVertexBuffer) = 0; virtual IIndexBuffer *CreateIndexBuffer( ShaderBufferType_t bufferType, MaterialIndexFormat_t fmt, int nIndexCount, const char *pBudgetGroup) = 0; virtual void DestroyIndexBuffer(IIndexBuffer * pIndexBuffer) = 0; // Do we need to specify the stream here in the case of locking multiple // dynamic VBs on different streams? virtual IVertexBuffer *GetDynamicVertexBuffer( int nStreamID, VertexFormat_t vertexFormat, bool bBuffered = true) = 0; virtual IIndexBuffer *GetDynamicIndexBuffer(MaterialIndexFormat_t fmt, bool bBuffered = true) = 0; // A special path used to tick the front buffer while loading on the 360 virtual void EnableNonInteractiveMode( MaterialNonInteractiveMode_t mode, ShaderNonInteractiveInfo_t *pInfo = NULL) = 0; virtual void RefreshFrontBufferNonInteractive() = 0; virtual void HandleThreadEvent(uint32 threadEvent) = 0; #ifdef DX_TO_GL_ABSTRACTION virtual void DoStartupShaderPreloading(void) = 0; #endif virtual char *GetDisplayDeviceName() = 0; }; //----------------------------------------------------------------------------- // Helper wrapper for IShaderBuffer for reading precompiled shader files // NOTE: This is meant to be instanced on the stack; so don't call Release! //----------------------------------------------------------------------------- class CUtlShaderBuffer : public IShaderBuffer { public: CUtlShaderBuffer(CUtlBuffer &buf) : m_pBuf(&buf) {} virtual size_t GetSize() const { return m_pBuf->TellMaxPut(); } virtual const void *GetBits() const { return m_pBuf->Base(); } virtual void Release() { Assert(0); } private: CUtlBuffer *m_pBuf; }; //----------------------------------------------------------------------------- // Inline methods of IShaderDevice //----------------------------------------------------------------------------- inline VertexShaderHandle_t IShaderDevice::CreateVertexShader( CUtlBuffer &buf, const char *pShaderVersion) { // NOTE: Text buffers are assumed to have source-code shader files // Binary buffers are assumed to have compiled shader files if (buf.IsText()) { Assert(pShaderVersion); return CreateVertexShader((const char *)buf.Base(), buf.TellMaxPut(), pShaderVersion); } CUtlShaderBuffer shaderBuffer(buf); return CreateVertexShader(&shaderBuffer); } inline VertexShaderHandle_t IShaderDevice::CreateVertexShader( const char *pProgram, size_t nBufLen, const char *pShaderVersion) { VertexShaderHandle_t hVertexShader = VERTEX_SHADER_HANDLE_INVALID; IShaderBuffer *pShaderBuffer = CompileShader(pProgram, nBufLen, pShaderVersion); if (pShaderBuffer) { hVertexShader = CreateVertexShader(pShaderBuffer); pShaderBuffer->Release(); } return hVertexShader; } inline GeometryShaderHandle_t IShaderDevice::CreateGeometryShader( CUtlBuffer &buf, const char *pShaderVersion) { // NOTE: Text buffers are assumed to have source-code shader files // Binary buffers are assumed to have compiled shader files if (buf.IsText()) { Assert(pShaderVersion); return CreateGeometryShader((const char *)buf.Base(), buf.TellMaxPut(), pShaderVersion); } CUtlShaderBuffer shaderBuffer(buf); return CreateGeometryShader(&shaderBuffer); } inline GeometryShaderHandle_t IShaderDevice::CreateGeometryShader( const char *pProgram, size_t nBufLen, const char *pShaderVersion) { GeometryShaderHandle_t hGeometryShader = GEOMETRY_SHADER_HANDLE_INVALID; IShaderBuffer *pShaderBuffer = CompileShader(pProgram, nBufLen, pShaderVersion); if (pShaderBuffer) { hGeometryShader = CreateGeometryShader(pShaderBuffer); pShaderBuffer->Release(); } return hGeometryShader; } inline PixelShaderHandle_t IShaderDevice::CreatePixelShader( CUtlBuffer &buf, const char *pShaderVersion) { // NOTE: Text buffers are assumed to have source-code shader files // Binary buffers are assumed to have compiled shader files if (buf.IsText()) { Assert(pShaderVersion); return CreatePixelShader((const char *)buf.Base(), buf.TellMaxPut(), pShaderVersion); } CUtlShaderBuffer shaderBuffer(buf); return CreatePixelShader(&shaderBuffer); } inline PixelShaderHandle_t IShaderDevice::CreatePixelShader( const char *pProgram, size_t nBufLen, const char *pShaderVersion) { PixelShaderHandle_t hPixelShader = PIXEL_SHADER_HANDLE_INVALID; IShaderBuffer *pShaderBuffer = CompileShader(pProgram, nBufLen, pShaderVersion); if (pShaderBuffer) { hPixelShader = CreatePixelShader(pShaderBuffer); pShaderBuffer->Release(); } return hPixelShader; } #endif // ISHADERDEVICE_H