[D3D12] Immdraw texture upload leak fix + cleanup
This commit is contained in:
parent
c218d6dc10
commit
18031a8f6d
|
@ -198,20 +198,12 @@ bool D3D12ImmediateDrawer::Initialize() {
|
||||||
sampler_heap_gpu_start_ = sampler_heap_->GetGPUDescriptorHandleForHeapStart();
|
sampler_heap_gpu_start_ = sampler_heap_->GetGPUDescriptorHandleForHeapStart();
|
||||||
uint32_t sampler_size = provider.GetSamplerDescriptorSize();
|
uint32_t sampler_size = provider.GetSamplerDescriptorSize();
|
||||||
// Nearest neighbor, clamp.
|
// Nearest neighbor, clamp.
|
||||||
D3D12_SAMPLER_DESC sampler_desc;
|
D3D12_SAMPLER_DESC sampler_desc = {};
|
||||||
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||||
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
sampler_desc.MipLODBias = 0.0f;
|
|
||||||
sampler_desc.MaxAnisotropy = 1;
|
sampler_desc.MaxAnisotropy = 1;
|
||||||
sampler_desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
|
|
||||||
sampler_desc.BorderColor[0] = 0.0f;
|
|
||||||
sampler_desc.BorderColor[1] = 0.0f;
|
|
||||||
sampler_desc.BorderColor[2] = 0.0f;
|
|
||||||
sampler_desc.BorderColor[3] = 0.0f;
|
|
||||||
sampler_desc.MinLOD = 0.0f;
|
|
||||||
sampler_desc.MaxLOD = 0.0f;
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle;
|
D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle;
|
||||||
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
|
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
|
||||||
uint32_t(SamplerIndex::kNearestClamp) * sampler_size;
|
uint32_t(SamplerIndex::kNearestClamp) * sampler_size;
|
||||||
|
@ -221,19 +213,18 @@ bool D3D12ImmediateDrawer::Initialize() {
|
||||||
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
|
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
|
||||||
uint32_t(SamplerIndex::kLinearClamp) * sampler_size;
|
uint32_t(SamplerIndex::kLinearClamp) * sampler_size;
|
||||||
device->CreateSampler(&sampler_desc, sampler_handle);
|
device->CreateSampler(&sampler_desc, sampler_handle);
|
||||||
// Nearest neighbor, repeat.
|
// Bilinear, repeat.
|
||||||
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
|
||||||
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
|
|
||||||
uint32_t(SamplerIndex::kNearestRepeat) * sampler_size;
|
|
||||||
device->CreateSampler(&sampler_desc, sampler_handle);
|
|
||||||
// Bilinear, repeat.
|
|
||||||
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
|
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
|
||||||
uint32_t(SamplerIndex::kLinearRepeat) * sampler_size;
|
uint32_t(SamplerIndex::kLinearRepeat) * sampler_size;
|
||||||
device->CreateSampler(&sampler_desc, sampler_handle);
|
device->CreateSampler(&sampler_desc, sampler_handle);
|
||||||
|
// Nearest neighbor, repeat.
|
||||||
|
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||||
|
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
|
||||||
|
uint32_t(SamplerIndex::kNearestRepeat) * sampler_size;
|
||||||
|
device->CreateSampler(&sampler_desc, sampler_handle);
|
||||||
|
|
||||||
// Create pools for draws.
|
// Create pools for draws.
|
||||||
vertex_buffer_pool_ = std::make_unique<D3D12UploadBufferPool>(provider);
|
vertex_buffer_pool_ = std::make_unique<D3D12UploadBufferPool>(provider);
|
||||||
|
@ -315,25 +306,30 @@ std::unique_ptr<ImmediateTexture> D3D12ImmediateDrawer::CreateTexture(
|
||||||
void* upload_buffer_mapping;
|
void* upload_buffer_mapping;
|
||||||
if (SUCCEEDED(upload_buffer->Map(0, &upload_buffer_read_range,
|
if (SUCCEEDED(upload_buffer->Map(0, &upload_buffer_read_range,
|
||||||
&upload_buffer_mapping))) {
|
&upload_buffer_mapping))) {
|
||||||
uint8_t* upload_buffer_row =
|
size_t data_row_length = sizeof(uint32_t) * width;
|
||||||
reinterpret_cast<uint8_t*>(upload_buffer_mapping) +
|
if (data_row_length == upload_footprint.Footprint.RowPitch) {
|
||||||
upload_footprint.Offset;
|
std::memcpy(upload_buffer_mapping, data, data_row_length * height);
|
||||||
const uint8_t* data_row = data;
|
} else {
|
||||||
for (uint32_t i = 0; i < height; ++i) {
|
uint8_t* upload_buffer_row =
|
||||||
std::memcpy(upload_buffer_row, data_row, width * 4);
|
reinterpret_cast<uint8_t*>(upload_buffer_mapping) +
|
||||||
data_row += width * 4;
|
upload_footprint.Offset;
|
||||||
upload_buffer_row += upload_footprint.Footprint.RowPitch;
|
const uint8_t* data_row = data;
|
||||||
|
for (uint32_t i = 0; i < height; ++i) {
|
||||||
|
std::memcpy(upload_buffer_row, data_row, data_row_length);
|
||||||
|
data_row += data_row_length;
|
||||||
|
upload_buffer_row += upload_footprint.Footprint.RowPitch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
upload_buffer->Unmap(0, nullptr);
|
upload_buffer->Unmap(0, nullptr);
|
||||||
// Defer uploading and transition to the next draw.
|
// Defer uploading and transition to the next draw.
|
||||||
PendingTextureUpload pending_upload;
|
PendingTextureUpload& pending_upload =
|
||||||
|
texture_uploads_pending_.emplace_back();
|
||||||
// While the upload has not been yet completed, keep a reference to the
|
// While the upload has not been yet completed, keep a reference to the
|
||||||
// resource because its lifetime is not tied to that of the
|
// resource because its lifetime is not tied to that of the
|
||||||
// ImmediateTexture (and thus to context's submissions) now.
|
// ImmediateTexture (and thus to context's submissions) now.
|
||||||
resource->AddRef();
|
resource->AddRef();
|
||||||
pending_upload.texture = resource;
|
pending_upload.texture = resource;
|
||||||
pending_upload.buffer = upload_buffer;
|
pending_upload.buffer = upload_buffer;
|
||||||
texture_uploads_pending_.push_back(pending_upload);
|
|
||||||
} else {
|
} else {
|
||||||
XELOGE(
|
XELOGE(
|
||||||
"Failed to map a Direct3D 12 upload buffer for a {}x{} texture for "
|
"Failed to map a Direct3D 12 upload buffer for a {}x{} texture for "
|
||||||
|
@ -383,9 +379,7 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
|
||||||
// Release upload buffers for completed texture uploads.
|
// Release upload buffers for completed texture uploads.
|
||||||
auto erase_uploads_end = texture_uploads_submitted_.begin();
|
auto erase_uploads_end = texture_uploads_submitted_.begin();
|
||||||
while (erase_uploads_end != texture_uploads_submitted_.end()) {
|
while (erase_uploads_end != texture_uploads_submitted_.end()) {
|
||||||
uint64_t upload_fence_value = erase_uploads_end->fence_value;
|
if (erase_uploads_end->fence_value > completed_fence_value) {
|
||||||
if (upload_fence_value > completed_fence_value) {
|
|
||||||
++erase_uploads_end;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
erase_uploads_end->buffer->Release();
|
erase_uploads_end->buffer->Release();
|
||||||
|
@ -650,9 +644,7 @@ void D3D12ImmediateDrawer::UploadTextures() {
|
||||||
// pipeline barriers).
|
// pipeline barriers).
|
||||||
std::vector<D3D12_RESOURCE_BARRIER> barriers;
|
std::vector<D3D12_RESOURCE_BARRIER> barriers;
|
||||||
barriers.reserve(texture_uploads_pending_.size());
|
barriers.reserve(texture_uploads_pending_.size());
|
||||||
while (!texture_uploads_pending_.empty()) {
|
for (const PendingTextureUpload& pending_upload : texture_uploads_pending_) {
|
||||||
const PendingTextureUpload& pending_upload =
|
|
||||||
texture_uploads_pending_.back();
|
|
||||||
ID3D12Resource* texture = pending_upload.texture;
|
ID3D12Resource* texture = pending_upload.texture;
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC texture_desc = texture->GetDesc();
|
D3D12_RESOURCE_DESC texture_desc = texture->GetDesc();
|
||||||
|
@ -676,15 +668,15 @@ void D3D12ImmediateDrawer::UploadTextures() {
|
||||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||||
|
|
||||||
SubmittedTextureUpload submitted_upload;
|
SubmittedTextureUpload& submitted_upload =
|
||||||
|
texture_uploads_submitted_.emplace_back();
|
||||||
// Transfer the reference to the texture - need to keep it until the upload
|
// Transfer the reference to the texture - need to keep it until the upload
|
||||||
// is completed.
|
// is completed.
|
||||||
submitted_upload.texture = texture;
|
submitted_upload.texture = texture;
|
||||||
submitted_upload.buffer = pending_upload.buffer;
|
submitted_upload.buffer = pending_upload.buffer;
|
||||||
submitted_upload.fence_value = current_fence_value;
|
submitted_upload.fence_value = current_fence_value;
|
||||||
texture_uploads_submitted_.push_back(submitted_upload);
|
|
||||||
texture_uploads_pending_.pop_back();
|
|
||||||
}
|
}
|
||||||
|
texture_uploads_pending_.clear();
|
||||||
assert_false(barriers.empty());
|
assert_false(barriers.empty());
|
||||||
current_command_list_->ResourceBarrier(UINT(barriers.size()),
|
current_command_list_->ResourceBarrier(UINT(barriers.size()),
|
||||||
barriers.data());
|
barriers.data());
|
||||||
|
|
Loading…
Reference in New Issue