资源类型
Resource分为以下几类:
enum ResourceType
{
// Buffer
RT_VERTEXBUFFER = 0x010000,
RT_INDEXBUFFER = 0x020000,
RT_CONSTANTBUFFER = 0x030000,
RT_STRUCTUREDBUFFER = 0x040000,
RT_BYTEADDRESSBUFFER = 0x050000,
RT_INDIRECTARGSBUFFER = 0x060000,
// Texture
RT_TEXTURE1D = 0x070000,
RT_TEXTURE2D = 0x080000,
RT_TEXTURE3D = 0x090000,
}
模式
采用的是策略模式:
xxxConfigDX11:用于封装xxx资源的Desc,以便快速创建资源描述
xxxDX11 : 封装了xxx资源对象,并保存了相关联的Desc
如以Texture1d为例:
class Texture1dConfigDX11
{
public:
Texture1dConfigDX11();
virtual ~Texture1dConfigDX11();
// 默认设置
void SetDefaults();
void SetWidth( UINT state );
void SetMipLevels( UINT state );
void SetArraySize( UINT state );
void SetFormat( DXGI_FORMAT state );
void SetUsage( D3D11_USAGE state );
void SetBindFlags( UINT state );
void SetCPUAccessFlags( UINT state );
void SetMiscFlags( UINT state );
D3D11_TEXTURE1D_DESC GetTextureDesc();
protected:
D3D11_TEXTURE1D_DESC m_State;
friend RendererDX11;
};
class Texture1dDX11 : public ResourceDX11
{
public:
explicit Texture1dDX11( Microsoft::WRL::ComPtr<ID3D11Texture1D> pTex );
virtual ~Texture1dDX11();
D3D11_TEXTURE1D_DESC GetActualDescription();
D3D11_TEXTURE1D_DESC GetDesiredDescription();
void SetDesiredDescription( D3D11_TEXTURE1D_DESC description );
virtual ResourceType GetType();
virtual ID3D11Resource* GetResource();
virtual UINT GetEvictionPriority();
virtual void SetEvictionPriority( UINT EvictionPriority );
protected:
Microsoft::WRL::ComPtr<ID3D11Texture1D> m_pTexture;
D3D11_TEXTURE1D_DESC m_DesiredDesc;
D3D11_TEXTURE1D_DESC m_ActualDesc;
};
这里需要提一下的是ResourceDX11类,这是资源类的基类,其定义如下:
class ResourceDX11
{
public:
ResourceDX11();
virtual ~ResourceDX11();
virtual ResourceType GetResourceType() = 0;
virtual ID3D11Resource* GetResource() = 0;
virtual UINT GetEvictionPriority() = 0;
virtual void SetEvictionPriority() = 0;
unsigned int GetInnerID() = 0;
static unsigned short s_usResourceID;
unsigned short m_usInnerID;
};
基类声明了资源类的几个最基本功能
s_usResourceID是一个静态变量,每次创建一个ResourceDX11对象时,便自增1。使得每个资源对象具有唯一性
资源视图
资源视图也是采用了相同的模式,xxxConfigDX11封装了资源视图描述,用于快速创建视图描述,xxxDX11封装了视图对象,以ShaderResourceView为例:
class ShaderResourceViewConfigDX11
{
public:
ShaderResourceViewConfigDX11();
virtual ~ShaderResourceViewConfigDX11();
// 默认设置
void SetDefaults();
void SetFormat( DXGI_FORMAT Format );
void SetViewDimension( D3D11_SRV_DIMENSION ViewDimension );
void SetBuffer( D3D11_BUFFER_SRV Buffer );
void SetTexture1D( D3D11_TEX1D_SRV Texture1D );
void SetTexture1DArray( D3D11_TEX1D_ARRAY_SRV Texture1DArray );
void SetTexture2D( D3D11_TEX2D_SRV Texture2D );
void SetTexture2DArray( D3D11_TEX2D_ARRAY_SRV Texture2DArray );
void SetTexture2DMS( D3D11_TEX2DMS_SRV Texture2DMS );
void SetTexture2DMSArray( D3D11_TEX2DMS_ARRAY_SRV Texture2DMSArray );
void SetTexture3D( D3D11_TEX3D_SRV Texture3D );
void SetTextureCube( D3D11_TEXCUBE_SRV TextureCbue );
void SetTextureCubeArray( D3D11_TEXCUBE_ARRAY_SRV TextureCubeArray );
void SetBufferEx( D3D11_BUFFEREX_SRV BufferEx );
D3D11_SHADER_RESOURCE_VIEW_DESC& GetSRVDesc();
protected:
D3D11_SHADER_RESOURCE_VIEW_DESC m_State;
friend RendererDX11;
};
class ShaderResourceViewDX11
{
public:
ShaderResourceViewDX11();
virtual ~ShaderResourceViewDX11();
ID3D11ShaderResourceView* GetSRV();
protected:
Mircosoft::WRL::ComPtr<ID3D11ShaderResourceView*> m_ShaderResourceView;
friend PipelineManager;
friend Renderer;
};
状态对象
我们封装了状态描述对象,同样是为了快速创建状态描述对象,因为我们通常都是使用这些描述的默认值,改动也常常只需要更改其中某几项,因为这样可以极大的方便我们编程,以SamplerState为例:
class SamplerStateConfigDX11 : public D3D11_SAMPLER_DESC
{
public:
SamplerStateConfigDX11();
~SamplerStateConfigDX11();
void SetDefaults();
protected:
friend RendererDX11;
};
ResourceProxy
Resource与Resource View不分家,因此创建了一个ResourceProxy类用于将Resource,ResourceView关联在一起
先来看下代码:
class ResourceProxy
{
public:
ResourceProxy();
ResourceProxy(int ResourceID , BufferConfigDX11* pConfig ,
RendererDX11* pRenderer ,
ShaderResourceViewConfigDX11* pSRVConfig = NULL,
RenderTargetViewConfigDX11* pRTVConfig = NULL ,
UnorderedAccessViewConfigDX11* pUAVConfig = NULL);
...
virtual ~ResourceProxyDX11();
public:
int m_iResource;
int m_iResourceSRV;
int m_iResourceRTV;
int m_iResourceUAV;
int m_iResourceDSV;
BufferConfig* m_pBufferConfig;
Texture1dConfig* m_pTexture1dConfig;
Texture2dConfig* m_pTexture2dConfig;
Texture3dConfig* m_pTexture3dConfig;
ShaderResourceViewConfigDX11* m_pSRVConfig;
UnorderedAccessViewConfigDX11* m_UAVConfig;
RenderTargetViewConfigDX11* m_RTVConfig;
DepthStencilViewConfigDX11* m_DSVConfig;
friend RendererDX11;
protected:
void CommonConstructor(UINT BindFlags , int ResourceID ,
RendererDX11* pRenderer ,
ShaderResourceViewConfigDX11* pSRVConfig ,
RenderTargetViewConfigDX11* pRTVConfig ,
UnorderedAccessViewConfigDX11* pUAVConfig ,
DepthStencilViewConfigDX11* pDSVConfig = NULL);
}
该类中CommonConstructor用于为资源ID为ResourceID的资源根据BindFlags创建相应的Resource View
void CommonConstructor(UINT BindFlags , int ResourceID , RendererDX11* pRenderer , ShaderResourceViewConfigDX11* pSRVConfig , UnorderedAccessViewConfigDX11* pUAVConfig , DepthStencilViewConfigDX11* pDSVConfig = NULL)
{
// 保存资源ID
m_iResource = ResourceID;
m_iResourceSRV = 0;
m_iResourceRTV = 0;
m_iResourceSRV = 0;
m_iResourceUAV = 0;
m_iResourceDSV = 0;
m_pBufferConfig = nullptr;
m_pTexture1dConfig = nullptr;
m_pTexture2dConfig = nullptr;
m_pTexeture3dConfig = nullptr;
m_pSRVConfig = nullptr;
m_pUAVConfig = nullptr;
m_pRTVConfig = nullptr;
m_pDSVConfig = nullptr;
// 若Config不为空,则创建相应的View Config对象
if(pSRVConfig)
{
m_pSRVConfig = new ShaderResourceViewConfigDX11();
*m_pSRVConfig = *pSRVConfig;
}
...
// 根据BindFlags创建相应的视图对象,
// 保存返回的资源视图ID
if((BindFlags & D3D11_BIND_SAHDER_RESOURCE) == D3D11_BIND_SHADER_RESOURCE)
{
D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc = pSRVConfig ? &pSRVConfig->GetSRVDesc() : nullptr;
m_iResourceSRV = pRenderer->CreateShaderResourceView(m_iResource , pDesc);
}
...
}
正如上面所见到的,我们只是通过保存索引,对象是保存在Renderer中
如:
class Renderer
{
....
public:
std::vector<ShaderResourceViewDX11> m_vShaderResourceViews;
std::vector<RenderTargetViewDX11> m_vRenderTargetViews;
std::vector<UnorderedAccessViewDX11> m_vUnorderedAccessViews;
std::vector<DepthStencilViewDX11> m_vDepthStencilViews;
std::vector<ResourceDX11*> m_vResources;
}
这些容器保存了Resource View的实体,我们可以通过索引来存取。
ResourceProxy对象可以将Resource与ResourceView相关联起来,如果我们有一个ResourceProxy对象,则我们能够知道其资源ID,绑定到了哪些视图,并知道相应视图ID.
另外说明一下,m_iResource是由两部分组成的,高十六位是Inner ID(每创建一个Resource,Inner ID自增1,表示是第几个资源,低十六位是该资源保存在renderer的m_vResources中的位置),m_iResourceSRV等直接就等于保存在renderer的m_vShaderResourceViews等视图管理器中的位置