Creazione di risorse trama (Direct3D 10)

Una risorsa trama è una raccolta strutturata di dati. In genere, i valori di colore vengono archiviati in trame e accessibili durante il rendering dalla pipeline in varie fasi per input e output. La creazione di trame e la definizione di come verranno usate è una parte importante del rendering di scene interessanti in Direct3D 10.

Anche se le trame in genere contengono informazioni sul colore, la creazione di trame usando DXGI_FORMAT diverse consente loro di archiviare diversi tipi di dati. Questi dati possono quindi essere sfruttati dalla pipeline Direct3D 10 in modi non tradizionali.

Tutte le trame hanno limiti sulla quantità di memoria utilizzata e sul numero di texel che contengono. Questi limiti vengono specificati dalle costanti delle risorse.

Creare una trama da un file

Nota

La libreria di utilità D3DX è deprecata per Windows 8 e non è supportata per le app di Windows Store.

 

Quando si crea una trama in Direct3D 10, è anche necessario creare una visualizzazione. Una visualizzazione è un oggetto che indica al dispositivo come deve essere accessibile una trama durante il rendering. Il modo più comune per accedere a una trama consiste nel leggerlo usando uno shader. Una visualizzazione shader-resource indicherà a uno shader come leggere da una trama durante il rendering. Il tipo di visualizzazione che verrà usata da una trama deve essere specificato quando lo si crea.

La creazione di una trama e il caricamento dei dati iniziali possono essere eseguite in due modi diversi: creare una trama e una visualizzazione separatamente oppure creare sia la trama che la visualizzazione contemporaneamente. L'API fornisce entrambe le tecniche in modo da poter scegliere quali sono le esigenze migliori.

Creare trama e visualizzazione separatamente

Il modo più semplice per creare una trama consiste nel caricarlo da un file di immagine. Per creare la trama, compilare una struttura e specificare il nome della trama a D3DX10CreateTextureFromFile.

ID3D10Device *pDevice = NULL;
// Initialize D3D10 device...

D3DX10_IMAGE_LOAD_INFO loadInfo;
ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) );
loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;

ID3D10Resource *pTexture = NULL;
D3DX10CreateTextureFromFile( pDevice, L"sample.bmp", &loadInfo, NULL, &pTexture, NULL );

La funzione D3DX D3DX10CreateTextureFromFile esegue tre operazioni: per prima cosa, crea un oggetto trama Direct3D 10; secondo, legge il file di immagine di input; terzo, archivia i dati dell'immagine nell'oggetto trama. Nell'esempio precedente viene caricato un file BMP, ma la funzione può caricare un'ampia gamma di tipi di file.

Il flag di associazione indica che la trama verrà creata come risorsa shader che consente a una fase shader di leggere dalla trama durante il rendering.

L'esempio precedente non specifica tutti i parametri di caricamento. In effetti, è spesso utile zero sui parametri di caricamento, in quanto consente a D3DX di scegliere valori appropriati in base all'immagine di input. Se si vuole che l'immagine di input determini tutti i parametri con cui viene creata la trama, è sufficiente specificare NULL per il parametro loadInfo come indicato di seguito:

D3DX10CreateTextureFromFile( pDevice, L"sample.bmp", NULL, NULL, &pTexture, NULL );

La specifica di NULL per le informazioni di caricamento è una semplice scelta rapida ma potente.

Dopo aver creato una trama, è necessario creare una visualizzazione shader-resource in modo che la trama possa essere associata come input a uno shader. Poiché D3DX10CreateTextureFromFile restituisce un puntatore a una risorsa e non un puntatore a una trama, è necessario determinare il tipo esatto di risorsa caricato e quindi è possibile creare una visualizzazione shader-resource usando CreateShaderResourceView.

D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
D3D10_RESOURCE_DIMENSION type;
pTexture->GetType( &type );
switch( type )
{
    case D3D10_RESOURCE_DIMENSION_BUFFER:
    //...
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
    //...
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
    {
        D3D10_TEXTURE2D_DESC desc;
        ID3D10Texture2D *pTexture2D = (ID3D10Texture2D*)pTexture;
        pTexture2D->GetDesc( &desc );
        
        srvDesc.Format = desc.Format;
        srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
        srvDesc.Texture2D.MipLevels = desc.MipLevels;
        srvDesc.Texture2D.MostDetailedMip = desc.MipLevels -1;

    }
    break;
    case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
    //...
    break;
    default:
    //...
    break;
}

ID3D10ShaderResourceView *pSRView = NULL;
pDevice->CreateShaderResourceView( pTexture, &srvDesc, &pSRView );

Anche se l'esempio precedente crea una visualizzazione risorsa shader 2D, il codice per creare altri tipi di visualizzazione shader-resource è molto simile. Qualsiasi fase shader può ora usare questa trama come input.

L'uso di D3DX10CreateTextureFromFile e CreateShaderResourceView per creare una trama e la visualizzazione associata è un modo per preparare una trama da associare a una fase shader. Un altro modo per eseguire questa operazione consiste nel creare sia la trama che la relativa visualizzazione contemporaneamente, che viene illustrata nella sezione successiva.

Creare trama e visualizzazione simultaneamente

Direct3D 10 richiede sia una trama che una visualizzazione risorsa shader per leggere da una trama durante il runtime. Poiché la creazione di una trama e una visualizzazione delle risorse shader è un'attività comune, D3DX fornisce d3DX10CreateShaderResourceViewFromFile per farlo.

D3DX10_IMAGE_LOAD_INFO loadInfo;
ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) );
loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;
loadInfo.Format = DXGI_FORMAT_BC1_UNORM;

ID3D10ShaderResourceView *pSRView = NULL;
D3DX10CreateShaderResourceViewFromFile( pDevice, L"sample.bmp", &loadInfo, NULL, &pSRView, NULL );

Con una singola chiamata D3DX, vengono create sia la trama che la visualizzazione delle risorse shader. La funzionalità del parametro loadInfo è invariata; è possibile usarlo per personalizzare la modalità di creazione della trama o derivare i parametri necessari dal file di input specificando NULL per il parametro loadInfo .

L'oggetto ID3D10ShaderResourceView restituito dalla funzione D3DX10CreateShaderResourceViewFromFile può essere usato in un secondo momento per recuperare l'interfaccia ID3D10Resource originale se necessario. Questa operazione può essere eseguita chiamando il metodo GetResource .

D3DX fornisce una singola funzione per creare una visualizzazione trama e risorsa shader come convienienza; è consigliabile decidere quale metodo creare una trama e visualizzare meglio le esigenze dell'applicazione.

Ora che si sa come creare una trama e la relativa visualizzazione delle risorse shader, la sezione successiva mostrerà come è possibile eseguire un esempio (lettura) da tale trama usando uno shader.

Creazione di trame vuote

A volte le applicazioni vogliono creare una trama e calcolare i dati da archiviare nella trama o usare la pipeline grafica per eseguire il rendering in questa trama e usare in seguito i risultati in altre elaborazioni. Queste trame possono essere aggiornate dalla pipeline grafica o dall'applicazione stessa, a seconda del tipo di utilizzo specificato per la trama quando è stata creata.

Rendering in una trama

Il caso più comune della creazione di una trama vuota da riempire con i dati durante il runtime è il caso in cui un'applicazione vuole eseguire il rendering in una trama e quindi usare i risultati dell'operazione di rendering in un passaggio successivo. Le trame create con questo scopo devono specificare l'utilizzo predefinito.

L'esempio di codice seguente crea una trama vuota in cui la pipeline può eseguire il rendering e successivamente viene usata come input per uno shader.

// Create the render target texture
D3D10_TEXTURE2D_DESC desc;
ZeroMemory( &desc, sizeof(desc) );
desc.Width = 256;
desc.Height = 256;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;

ID3D10Texture2D *pRenderTarget = NULL;
pDevice->CreateTexture2D( &desc, NULL, &pRenderTarget );

La creazione della trama richiede all'applicazione di specificare alcune informazioni sulle proprietà che la trama avrà. La larghezza e l'altezza della trama in texels è impostata su 256. Per questa destinazione di rendering, è necessario un singolo livello mipmap. È necessaria una sola destinazione di rendering in modo che le dimensioni della matrice siano impostate su 1. Ogni texel contiene quattro valori a virgola mobile a 32 bit, che possono essere usati per archiviare informazioni molto precise (vedere DXGI_FORMAT). Un esempio per pixel è tutto ciò che sarà necessario. L'utilizzo è impostato su impostazione predefinita perché consente la posizione più efficiente della destinazione di rendering in memoria. Infine, il fatto che la trama verrà associata come destinazione di rendering e viene specificata una risorsa shader in punti diversi in tempo.

Le trame non possono essere associate per il rendering direttamente alla pipeline; usare una vista di destinazione di rendering, come illustrato nell'esempio di codice seguente.

D3D10_RENDER_TARGET_VIEW_DESC rtDesc;
rtDesc.Format = desc.Format;
rtDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
rtDesc.Texture2D.MipSlice = 0;

ID3D10RenderTargetView *pRenderTargetView = NULL;
pDevice->CreateRenderTargetView( pRenderTarget, &rtDesc, &pRenderTargetView );

Il formato della visualizzazione di destinazione di rendering è semplicemente impostato sul formato della trama originale. Le informazioni nella risorsa devono essere interpretate come trama 2D e si vuole usare solo il primo livello di mipmap della destinazione di rendering.

Analogamente a come deve essere creata una visualizzazione di destinazione di rendering in modo che la destinazione di rendering possa essere associata all'output della pipeline, è necessario creare una visualizzazione risorsa shader in modo che la destinazione di rendering possa essere associata alla pipeline come input. L'esempio di codice seguente illustra questa operazione.

// Create the shader-resource view
D3D10_SHADER_RESOURCE_VIEW_DESC srDesc;
srDesc.Format = desc.Format;
srDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MostDetailedMip = 0;
srDesc.Texture2D.MipLevels = 1;

ID3D10ShaderResourceView *pShaderResView = NULL;
pDevice->CreateShaderResourceView( pRenderTarget, &srDesc, &pShaderResView );

I parametri delle descrizioni delle visualizzazioni delle risorse shader sono molto simili a quelli delle descrizioni della visualizzazione di destinazione di rendering e sono stati scelti per gli stessi motivi.

Riempimento di trame manualmente

A volte le applicazioni vogliono calcolare i valori in fase di esecuzione, inserirle manualmente in una trama e quindi usare questa trama nelle operazioni di rendering successive. A tale scopo, l'applicazione deve creare una trama vuota in modo da consentire alla CPU di accedere alla memoria sottostante. Questa operazione viene eseguita creando una trama dinamica e ottenendo l'accesso alla memoria sottostante chiamando un determinato metodo. Nell'esempio di codice seguente viene illustrato come eseguire questa procedura.

D3D10_TEXTURE2D_DESC desc;
desc.Width = 256;
desc.Height = 256;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DYNAMIC;
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
ID3D10Texture2D *pTexture = NULL;
pd3dDevice->CreateTexture2D( &desc, NULL, &pTexture );

Si noti che il formato è impostato su un bit a 32 bit per pixel in cui ogni componente è definito da 8 bit. Il parametro di utilizzo è impostato su dinamico mentre i flag di associazione vengono impostati per specificare che la trama verrà accessibile da uno shader. Il resto della descrizione della trama è simile alla creazione di una destinazione di rendering.

La chiamata a Mappa consente all'applicazione di accedere alla memoria sottostante della trama. Il puntatore recuperato viene quindi usato per riempire la trama con i dati. Questo esempio di codice può essere visualizzato nell'esempio di codice seguente.

D3D10_MAPPED_TEXTURE2D mappedTex;
pTexture->Map( D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedTex );

UCHAR* pTexels = (UCHAR*)mappedTex.pData;
for( UINT row = 0; row < desc.Height; row++ )
{
    UINT rowStart = row * mappedTex.RowPitch;
    for( UINT col = 0; col < desc.Width; col++ )
    {
        UINT colStart = col * 4;
        pTexels[rowStart + colStart + 0] = 255; // Red
        pTexels[rowStart + colStart + 1] = 128; // Green
        pTexels[rowStart + colStart + 2] = 64;  // Blue
        pTexels[rowStart + colStart + 3] = 32;  // Alpha
    }
}

pTexture->Unmap( D3D10CalcSubresource(0, 0, 1) );

Più renderingtarget

Fino a otto visualizzazioni di destinazione di rendering possono essere associate alla pipeline alla volta (con OMSetRenderTargets). Per ogni pixel (o ogni esempio se è abilitato il multicampionamento), la fusione viene eseguita in modo indipendente per ogni visualizzazione di destinazione di rendering. Due delle variabili di stato di blend - BlendEnable e RenderTargetWriteMask - sono matrici di otto, ogni membro della matrice corrisponde a una visualizzazione di destinazione di rendering. Quando si usano più destinazioni di rendering, ogni destinazione di rendering deve essere lo stesso tipo di risorsa (buffer, trama 1D, matrice trama 2D e così via) e deve avere la stessa dimensione (larghezza, altezza, profondità per trame 3D e dimensioni della matrice per le matrici di trama). Se le destinazioni di rendering sono multicampionate, devono avere tutti lo stesso numero di campioni per pixel.

Può essere attivo solo uno stencil di profondità, indipendentemente dal numero di destinazioni di rendering attive. Quando si usano matrici di trama come destinazioni di rendering, tutte le dimensioni di visualizzazione devono corrispondere. Le destinazioni di rendering non devono avere lo stesso formato di trama.

Risorse (Direct3D 10)