プログラミング インスタンシング導入したらメモリリークした・・・
あいさつ
どうも、はかせです。
今回は前回複数テクスチャ使ったインスタンシングができるようになったので
以前作った弾幕に入れてみた話です。
実装
今回実装は極めて単純に
描画データをまとめた構造体を定義し、
その構造体を管理クラスに投げて描画します。
//テクスチャ情報を保持 struct TEXTURE_DATA { std::wstring fileName; ComPtr<ID3D11Resource> texture; ComPtr<ID3D11ShaderResourceView> shaderView; }; struct RENDER_TEXTURE_DATA { TEXTURE_DATA* textureData = nullptr; int drawNumber = 0; DirectX::XMMATRIX renderMatrix; DirectX::XMVECTOR renderColor; ComPtr<ID3D11VertexShader> vertexShader = nullptr; ComPtr<ID3D11PixelShader> pixelShader = nullptr; ComPtr<ID3D11Buffer> vertexBuffer = nullptr; ComPtr<ID3D11Buffer> indexBuffer = nullptr; ComPtr<ID3D11InputLayout> inputLayout = nullptr; ID3D11DepthStencilState* depthStencilState = nullptr; ComPtr<ID3D11SamplerState> samplerState = nullptr; ComPtr<ID3D11RasterizerState> rasterizeState = nullptr; D3D11_PRIMITIVE_TOPOLOGY topology; bool isAlphaBlend = false; UINT stride = 0; UINT offset = 0; ~RENDER_TEXTURE_DATA() { vertexBuffer.Reset(); vertexShader.Reset(); pixelShader.Reset(); indexBuffer.Reset(); inputLayout.Reset(); depthStencilState = nullptr; samplerState.Reset(); rasterizeState.Reset(); }; };
void MyDirectX::DXRenderManager::Render() { //インスタンスデータ用バッファの設定 D3D11_BUFFER_DESC bd_instance; bd_instance.Usage = D3D11_USAGE_DYNAMIC; bd_instance.ByteWidth = sizeof(PerInstanceData) * mRenderDatas.capacity(); bd_instance.BindFlags = D3D11_BIND_SHADER_RESOURCE; bd_instance.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; bd_instance.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; bd_instance.StructureByteStride = sizeof(PerInstanceData); mDevice->CreateBuffer(&bd_instance, NULL, &mPerInstanceBuffer); //インスタンス用のリソースビューを作成 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; srvDesc.BufferEx.FirstElement = 0; srvDesc.Format = DXGI_FORMAT_UNKNOWN; srvDesc.BufferEx.NumElements = mRenderDatas.capacity(); mDevice->CreateShaderResourceView(mPerInstanceBuffer.Get(), &srvDesc, &mShaderResourceView); // パラメータの受け渡し D3D11_MAPPED_SUBRESOURCE pdata; PerInstanceData* instanceData = nullptr; std::set<std::wstring> fileNames; std::map <std::wstring, std::vector<RENDER_TEXTURE_DATA*>> splitData; //各テクスチャ毎に描画データをまとめる for (auto render : mRenderDatas) { splitData[render->textureData->fileName].push_back(render); fileNames.insert(render->textureData->fileName); } for(auto fileName:fileNames) { //各テクスチャ毎に描画する for(auto render:splitData[fileName]) { mDeviceContext->IASetVertexBuffers(0, 1, render->vertexBuffer.GetAddressOf(), &render->stride, &render->offset); //インデックスバッファーの設定 mDeviceContext->IASetIndexBuffer(render->indexBuffer.Get(), DXGI_FORMAT_R32_UINT, render->offset); //入力レイアウト設定 mDeviceContext->IASetInputLayout(render->inputLayout.Get()); //頂点情報の解釈の仕方を設定 mDeviceContext->IASetPrimitiveTopology(render->topology); int instanceCount = splitData[fileName].capacity(); mDeviceContext->VSSetShader(render->vertexShader.Get(), NULL, 0); mDeviceContext->PSSetShader(render->pixelShader.Get(), NULL, 0); mDeviceContext->PSSetSamplers(0, 1, render->samplerState.GetAddressOf()); mDeviceContext->Map(mPerInstanceBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &pdata); instanceData = (PerInstanceData*)(pdata.pData); for (int i = 0; i < instanceCount; i++) { //行列情報をセット instanceData[i].renderMatrix = render->renderMatrix; //色情報をセット instanceData[i].renderColor = render->renderColor; } mDeviceContext->Unmap(mPerInstanceBuffer.Get(), 0); mDeviceContext->VSSetShaderResources(0, 1, mShaderResourceView.GetAddressOf()); ID3D11ShaderResourceView* srv[] = { mShaderResourceView.Get() ,render->textureData->shaderView.Get() }; mDeviceContext->PSSetShaderResources(0, 2, srv); mDeviceContext->OMSetDepthStencilState(render->depthStencilState, 0); mManager->OMSetBlendState(render->isAlphaBlend); // 描画実行 mDeviceContext->DrawIndexedInstanced(render->drawNumber, instanceCount, 0, 0, 0); } } std::vector<RENDER_TEXTURE_DATA*> swapVector; mRenderDatas.swap(swapVector); splitData.clear(); fileNames.clear(); mRenderDatas.clear(); } void MyDirectX::DXRenderManager::PushRenderData(RENDER_TEXTURE_DATA* renderData) { mRenderDatas.push_back(renderData); }
これでデータをまとめて一括で描画することに成功しました。
全部うまくいくことなんてありえない
ぎゃー!!!
_(:3 」∠)_瀕死
な、なんでだ・・・?
今回各種ポインタはComPtrにして管理を自動化しているのに・・・
しかも軒並みRefcount0だし・・・・