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
-
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.
-
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).
-
Textures:
- Emmagatzemen imatges que es poden aplicar a superfícies 3D per donar-los aparença detallada.
-
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:
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:
Exercicis Pràctics
Exercici 1: Crear i Destruir un Buffer de Vèrtexs
- Crea un buffer de vèrtexs que emmagatzemi les coordenades i els colors de tres vèrtexs.
- Destrueix el buffer de vèrtexs alliberant la memòria associada.
Exercici 2: Mapejar i Modificar un Buffer de Vèrtexs
- Crea un buffer de vèrtexs amb tres vèrtexs.
- Mapa el buffer i modifica les coordenades del primer vèrtex.
- Desmapa el buffer.
Exercici 3: Crear i Destruir una Textura
- Crea una textura 2D de 256x256 píxels amb format
DXGI_FORMAT_R8G8B8A8_UNORM
. - 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.
Curs de Programació DirectX
Mòdul 1: Introducció a DirectX
- Què és DirectX?
- Configuració de l'Entorn de Desenvolupament
- Comprendre l'API de DirectX
- Crear la Teva Primera Aplicació DirectX
Mòdul 2: Conceptes Bàsics de Direct3D
- Introducció a Direct3D
- Inicialitzar Direct3D
- Renderitzar un Triangle
- Gestionar el Bucle de Renderització
Mòdul 3: Treballar amb Shaders
Mòdul 4: Tècniques Avançades de Renderització
Mòdul 5: Models 3D i Animació
Mòdul 6: Optimització del Rendiment
- Perfilat i Depuració
- Optimitzar el Rendiment de la Renderització
- Gestió de Memòria
- Multifil en DirectX