0
\$\begingroup\$

When trying to re-create my vertex buffers, my app crashes and I get this error:

D3D12 ERROR: ID3D12Resource2::: CORRUPTION: An ID3D12Resource object (0x000001DDEBA98FC0:'Vertex Buffer Default Resource Heap') is referenced by GPU operations in-flight on Command Queue (0x000001DDEB80E3A0:'Unnamed ID3D12CommandQueue Object'). It is not safe to final-release objects that may have GPU operations pending. This can result in application instability. [ EXECUTION ERROR #921: OBJECT_DELETED_WHILE_STILL_IN_USE]

Here is my function called create_vertex_buffers():

// a triangle
Vertex verts[] = {
    Vertex(0.0f, 0.5f, 0.5f),
    Vertex(0.5f, -0.5f, 0.5f),
    Vertex(-0.5f, -0.5f, 0.5f),
};

const UINT verts_size = sizeof(verts);

// create default heap
auto buffer = CD3DX12_RESOURCE_DESC::Buffer(verts_size);
auto heap_properties1 = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
device->CreateCommittedResource(
    &heap_properties1, // a default heap
    D3D12_HEAP_FLAG_NONE, // no flags
    &buffer, // resource description for a buffer
    D3D12_RESOURCE_STATE_COPY_DEST,
    nullptr,
    IID_PPV_ARGS(&vertex_buffer));

// create upload heap
// upload heaps are used to upload data to the GPU. CPU can write to it, GPU can read from it
// We will upload the vertex buffer using this heap to the default heap
auto heap_properties2 = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
auto buffer2 = CD3DX12_RESOURCE_DESC::Buffer(verts_size);
device->CreateCommittedResource(
    &heap_properties2, // upload heap
    D3D12_HEAP_FLAG_NONE, // no flags
    &buffer2, // resource description for a buffer
    D3D12_RESOURCE_STATE_GENERIC_READ,
    nullptr,
    IID_PPV_ARGS(&vertex_buffer_upload));

D3D12_SUBRESOURCE_DATA vertex_data = {};
vertex_data.pData = reinterpret_cast<BYTE*>(verts); // pointer to our vertex array
vertex_data.RowPitch = verts_size; // size of all our triangle vertex data
vertex_data.SlicePitch = verts_size; // also the size of our triangle vertex data

UpdateSubresources(command_list.Get(), vertex_buffer.Get(), vertex_buffer_upload.Get(), 0, 0, 1, &vertex_data);

auto transition = CD3DX12_RESOURCE_BARRIER::Transition(vertex_buffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
command_list->ResourceBarrier(1, &transition);

vertex_buffer_view.BufferLocation = vertex_buffer->GetGPUVirtualAddress();
vertex_buffer_view.StrideInBytes = sizeof(Vertex);
vertex_buffer_view.SizeInBytes = verts_size;

It is my function for creating the vertex upload and default buffers. I implement it into my command queue like this:

CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(render_targets[frame_index].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
command_list->ResourceBarrier(1, &barrier);

// -------------------------+
create_vertex_buffers(); // | <== This is where I'm calling it!!
// -------------------------+

CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(rtv_descriptor_heap->GetCPUDescriptorHandleForHeapStart(), frame_index, rtv_descriptor_size);
CD3DX12_CPU_DESCRIPTOR_HANDLE dsv_handle(depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart());

command_list->OMSetRenderTargets(1, &rtv_handle, FALSE, &dsv_handle);

command_list->ClearRenderTargetView(rtv_handle, color, 0, nullptr);
command_list->ClearDepthStencilView(depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);

command_list->SetPipelineState(pipeline_state_object.Get());
command_list->SetGraphicsRootSignature(root_signature.Get()); // set the root signature
command_list->RSSetViewports(1, &viewport); // set the viewports
command_list->RSSetScissorRects(1, &scissor_rect); // set the scissor rects
command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // set the primitive topology
command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view); // set the vertex buffer (using the vertex buffer view)
command_list->DrawInstanced(3, 1, 0, 0); // finally draw 3 vertices (draw the triangle)

barrier = CD3DX12_RESOURCE_BARRIER::Transition(render_targets[frame_index].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
command_list->ResourceBarrier(1, &barrier);

I have tried adding a fence after creating the resources and waiting for that fence before calling DrawInstanced(), in case it's still making them once it's started drawing. I tried moving where I call create_vertex_buffers().

I'm unsure of when I should be creating these buffers. I'm planning on later only creating them when necessary, which will be every so often, not every frame.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

You seem to be recreating the vertex buffer resources in every render frame. You should be calling create_vertex_buffers() only once, for example immediately after you have created your device, swapchain, PSOs and root signatures.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .