La gestió de memòria és un aspecte crucial en el desenvolupament de qualsevol aplicació gràfica, especialment quan es treballa amb DirectX. Una gestió de memòria eficient pot millorar significativament el rendiment de la teva aplicació i evitar problemes com fuites de memòria i errors de segmentació. En aquest tema, explorarem les tècniques i les millors pràctiques per gestionar la memòria en aplicacions DirectX.

Conceptes Clau

  1. Memòria de Vídeo vs. Memòria del Sistema:

    • Memòria de Vídeo (VRAM): Utilitzada per emmagatzemar textures, buffers de vèrtexs, i altres dades gràfiques.
    • Memòria del Sistema (RAM): Utilitzada per emmagatzemar dades de l'aplicació, incloent estructures de dades i codi.
  2. Buffers de Vèrtexs i Índexs:

    • Buffers de Vèrtexs: Emmagatzemen les coordenades dels vèrtexs.
    • Buffers d'Índexs: Emmagatzemen els índexs que defineixen com es connecten els vèrtexs per formar primitives (com triangles).
  3. Textures:

    • Emmagatzemen imatges que es poden aplicar a superfícies 3D per donar-los aparença detallada.
  4. Gestió de Recursos:

    • Creació i Destrucció: Com crear i destruir recursos de manera eficient.
    • Mapatge i Desmapatge: Com accedir i modificar dades en buffers i textures.

Creació i Destrucció de Recursos

Creació de Buffers

Per crear un buffer de vèrtexs en DirectX, utilitzem la funció CreateBuffer. Aquí tens un exemple:

// Estructura de dades per a un vèrtex
struct Vertex {
    float x, y, z; // Coordenades del vèrtex
    float r, g, b; // Color del vèrtex
};

// Dades dels vèrtexs
Vertex vertices[] = {
    {0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f},
    {0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f},
    {-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f}
};

// Descripció del buffer
D3D11_BUFFER_DESC bufferDesc = {};
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(vertices);
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;

// Dades inicials del buffer
D3D11_SUBRESOURCE_DATA initData = {};
initData.pSysMem = vertices;

// Creació del buffer
ID3D11Buffer* vertexBuffer;
HRESULT hr = device->CreateBuffer(&bufferDesc, &initData, &vertexBuffer);
if (FAILED(hr)) {
    // Manejar l'error
}

Destrucció de Buffers

Per destruir un buffer, simplement alliberem la memòria associada:

if (vertexBuffer) {
    vertexBuffer->Release();
    vertexBuffer = nullptr;
}

Mapeig i Desmapeig de Recursos

Mapeig de Buffers

El mapeig permet accedir directament a la memòria del buffer per modificar les seves dades. Aquí tens un exemple de com mapar un buffer de vèrtexs:

D3D11_MAPPED_SUBRESOURCE mappedResource;
hr = context->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (SUCCEEDED(hr)) {
    // Accedir a les dades del buffer
    Vertex* vertices = (Vertex*)mappedResource.pData;
    vertices[0].x = 0.1f; // Modificar les dades del vèrtex

    // Desmapar el buffer
    context->Unmap(vertexBuffer, 0);
}

Gestió de Textures

Creació de Textures

Per crear una textura, utilitzem la funció CreateTexture2D. Aquí tens un exemple:

// Descripció de la textura
D3D11_TEXTURE2D_DESC textureDesc = {};
textureDesc.Width = 256;
textureDesc.Height = 256;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;

// Dades inicials de la textura
D3D11_SUBRESOURCE_DATA initData = {};
initData.pSysMem = imageData; // Punter a les dades de la imatge
initData.SysMemPitch = 256 * 4; // Amplada de la imatge en bytes

// Creació de la textura
ID3D11Texture2D* texture;
hr = device->CreateTexture2D(&textureDesc, &initData, &texture);
if (FAILED(hr)) {
    // Manejar l'error
}

Destrucció de Textures

Per destruir una textura, alliberem la memòria associada:

if (texture) {
    texture->Release();
    texture = nullptr;
}

Exercicis Pràctics

Exercici 1: Crear i Destruir un Buffer de Vèrtexs

  1. Crea un buffer de vèrtexs que emmagatzemi les coordenades i els colors de tres vèrtexs.
  2. Destrueix el buffer de vèrtexs alliberant la memòria associada.

Exercici 2: Mapejar i Modificar un Buffer de Vèrtexs

  1. Crea un buffer de vèrtexs amb tres vèrtexs.
  2. Mapa el buffer i modifica les coordenades del primer vèrtex.
  3. Desmapa el buffer.

Exercici 3: Crear i Destruir una Textura

  1. Crea una textura 2D de 256x256 píxels amb format DXGI_FORMAT_R8G8B8A8_UNORM.
  2. Destrueix la textura alliberant la memòria associada.

Solucions

Solució a l'Exercici 1

// Estructura de dades per a un vèrtex
struct Vertex {
    float x, y, z;
    float r, g, b;
};

// Dades dels vèrtexs
Vertex vertices[] = {
    {0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f},
    {0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f},
    {-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f}
};

// Descripció del buffer
D3D11_BUFFER_DESC bufferDesc = {};
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(vertices);
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;

// Dades inicials del buffer
D3D11_SUBRESOURCE_DATA initData = {};
initData.pSysMem = vertices;

// Creació del buffer
ID3D11Buffer* vertexBuffer;
HRESULT hr = device->CreateBuffer(&bufferDesc, &initData, &vertexBuffer);
if (FAILED(hr)) {
    // Manejar l'error
}

// Destrucció del buffer
if (vertexBuffer) {
    vertexBuffer->Release();
    vertexBuffer = nullptr;
}

Solució a l'Exercici 2

// Estructura de dades per a un vèrtex
struct Vertex {
    float x, y, z;
    float r, g, b;
};

// Dades dels vèrtexs
Vertex vertices[] = {
    {0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f},
    {0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f},
    {-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f}
};

// Descripció del buffer
D3D11_BUFFER_DESC bufferDesc = {};
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
bufferDesc.ByteWidth = sizeof(vertices);
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

// Dades inicials del buffer
D3D11_SUBRESOURCE_DATA initData = {};
initData.pSysMem = vertices;

// Creació del buffer
ID3D11Buffer* vertexBuffer;
HRESULT hr = device->CreateBuffer(&bufferDesc, &initData, &vertexBuffer);
if (FAILED(hr)) {
    // Manejar l'error
}

// Mapeig del buffer
D3D11_MAPPED_SUBRESOURCE mappedResource;
hr = context->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (SUCCEEDED(hr)) {
    // Accedir a les dades del buffer
    Vertex* vertices = (Vertex*)mappedResource.pData;
    vertices[0].x = 0.1f; // Modificar les dades del vèrtex

    // Desmapar el buffer
    context->Unmap(vertexBuffer, 0);
}

// Destrucció del buffer
if (vertexBuffer) {
    vertexBuffer->Release();
    vertexBuffer = nullptr;
}

Solució a l'Exercici 3

// Descripció de la textura
D3D11_TEXTURE2D_DESC textureDesc = {};
textureDesc.Width = 256;
textureDesc.Height = 256;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;

// Dades inicials de la textura
D3D11_SUBRESOURCE_DATA initData = {};
initData.pSysMem = imageData; // Punter a les dades de la imatge
initData.SysMemPitch = 256 * 4; // Amplada de la imatge en bytes

// Creació de la textura
ID3D11Texture2D* texture;
HRESULT hr = device->CreateTexture2D(&textureDesc, &initData, &texture);
if (FAILED(hr)) {
    // Manejar l'error
}

// Destrucció de la textura
if (texture) {
    texture->Release();
    texture = nullptr;
}

Conclusió

La gestió de memòria és essencial per assegurar que les aplicacions DirectX funcionin de manera eficient i sense problemes. Hem cobert els conceptes bàsics de la creació, destrucció, mapeig i desmapeig de recursos com buffers i textures. A més, hem proporcionat exercicis pràctics per reforçar aquests conceptes. Amb una bona comprensió d'aquests temes, estaràs millor preparat per optimitzar el rendiment de les teves aplicacions DirectX.

© Copyright 2024. Tots els drets reservats