Jump to content

  • Log In with Google      Sign In   
  • Create Account

Preventing releasing buffers in the pipeline queue

  • You cannot reply to this topic
5 replies to this topic

#1 ErnstH   Members   -  Reputation: 128

Like
0Likes
Like

Posted Yesterday, 03:02 AM

Most of my meshes are created before rendering starts and deleted afterwards.

 

Some have to be recreated every frame.

 

And some have to be recreated multiple times during a frame.

 

The last category flickers: meshes are invisible at random moments and sometimes even take over the appearance of other meshes!!!

 

When I say "mesh" I mean a class encapsulating a vertex and an index buffer, both using an ID3D11Buffer. When the mesh is deleted those bufers are released.

 

The loop looks like this:

 

for (i=0; i<10; i++){

 delete Mesh;

 Mesh=new Mesh(MyParameters);

 Mesh->Render();

}

 

The flickering can be fixed by adding a Sleep before deleting the mesh:

 

for (i=0; i<10; i++){

 Sleep(10);

 delete Mesh;

 Mesh=new Mesh(MyParameters);

 Mesh->Render();

}

 

So I have to wait for something before I can delete my mesh. But what?

 

My guess is that I have to wait for the mesh to be rendered:

 

for (i=0; i<10; i++){

 WaitForGPU2Finish();

 delete Mesh;

 Mesh=new Mesh(MyParameters)

 Mesh->Render();

}

 

This is my WaitForGPU2Finish function:

 


 
void MDirectX_Device::WaitForGPU2Finish() const{
 
 D3D11_QUERY_DESC d;

 ZeroMemory(&d, sizeof(d));

 d.Query = D3D11_QUERY_EVENT;
 
 ID3D11Query* Q = nullptr;

 HRESULT hr =mDevice->CreateQuery(&d, &Q);

 if (FAILED(hr)) return;
 
 mContext->End(Q);
 
 BOOL data = 0;

 while (true){

  hr =mContext->GetData(Q, &data, sizeof(data), 0);

  if (hr ==S_OK && data) break;

 }

 Q->Release();

}

 

This also works but since sleep works equally well, something totally different could be going on.

 

I worry there's something fundamental I do not understand about DirectX. I create and delete buffers all the time and wonder if I should be more careful.

 

The WaitForGPU2Finish is very cryptic and if it does what I hope it does also not very efficient because it waits for everything. I only want to wait for a specific buffer to be processed by the queue.

 

Does anyone know what's going on here?



Sponsor:

#2 Buckeye   Crossbones+   -  Reputation: 4927

Like
0Likes
Like

Posted Yesterday, 08:11 AM


My guess is that I have to wait for the mesh to be rendered:

 

That's correct. CPU and GPU work is taking place asynchronously. In particular, the device (creation/deletion of resources) can work in a multi-threaded fashion (thread-safe), but not the context (rendering resources). You're deleting resources before they've been properly used.

 

A better solution to the problem is to determine why you create/delete buffers during frame rendering. If you can describe the problem you've solving by creating/deleting resources that way, perhaps a better (safer, more efficient) method can be suggested.


Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.


#3 MJP   Moderators   -  Reputation: 11380

Like
2Likes
Like

Posted Yesterday, 12:38 PM

The driver and runtime is supposed to handle resource lifetime in cases like these. In theory you should be able to create and delete as much as you want, and the driver is supposed to make sure that the associated resources stay "alive" long enough for the GPU to consume them. However in practice what you're doing is extremely abnormal, and you're probably running afoul of driver bugs. In general the more you go off the beaten path, the more likely it is that you're going to find bugs (this true for almost all software).

I would strongly suggest that you re-architect things such that you're not constantly creating and destroying D3D resources. At the very least it's going to give you very poor performance. If you really need things to change from frame-to-frame, you should look into using dynamic buffers and filling them with new data as-needed.



#4 ErnstH   Members   -  Reputation: 128

Like
0Likes
Like

Posted Yesterday, 12:45 PM

I'm generating meshes during rendering for a lot of effects:
-lightning flashes
-extended silhouette edges for lightbeams en stencil shadows
-marching cube particle blobs
-voxel models (optimized for view and transparency bounds)

 

I guess some of them could be generated with geometry shaders, but others are too complex or need too much data.

 

And I run out of video memory when I keep every instance so I have to delete some during rendering. Question is when?



#5 ErnstH   Members   -  Reputation: 128

Like
0Likes
Like

Posted Yesterday, 01:06 PM

Thank you for your replies. I will look into using dynamic buffers.

 

Hope I no longer have to use the WaitForGPU2Finish() function when using its map method.


Edited by ErnstH, Yesterday, 01:25 PM.


#6 kauna   Crossbones+   -  Reputation: 2519

Like
1Likes
Like

Posted Today, 11:05 AM

All the effects you describe can be done using dynamic vertex buffers. Just create one dynamic vertex buffer and fill it without overwriting the old data, and when you arrive at the end, map it with discard so you can restart filling the buffer. You can do this as many times per frame as you need. 

 

Cheers!







PARTNERS