Merge pull request #6289 from aliaspider/master

(D3D11/12) prevent double-free when resizing framebuffers.
This commit is contained in:
Twinaphex 2018-02-11 23:03:04 +01:00 committed by GitHub
commit 327e2237d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 116 additions and 80 deletions

View File

@ -202,9 +202,6 @@ bool d3d11_init_shader(
} }
else /* char array */ else /* char array */
{ {
if (!size)
size = strlen(src);
if (vs_entry && !d3d_compile(src, size, (LPCSTR)src_name, vs_entry, "vs_5_0", &vs_code)) if (vs_entry && !d3d_compile(src, size, (LPCSTR)src_name, vs_entry, "vs_5_0", &vs_code))
success = false; success = false;
if (ps_entry && !d3d_compile(src, size, (LPCSTR)src_name, ps_entry, "ps_5_0", &ps_code)) if (ps_entry && !d3d_compile(src, size, (LPCSTR)src_name, ps_entry, "ps_5_0", &ps_code))

View File

@ -2549,7 +2549,6 @@ typedef struct
struct struct
{ {
d3d11_shader_t shader; d3d11_shader_t shader;
D3D11SamplerStateRef sampler;
D3D11Buffer buffers[SLANG_CBUFFER_MAX]; D3D11Buffer buffers[SLANG_CBUFFER_MAX];
d3d11_texture_t rt; d3d11_texture_t rt;
d3d11_texture_t feedback; d3d11_texture_t feedback;

View File

@ -201,6 +201,8 @@ bool d3d12_init_queue(d3d12_video_t* d3d12)
d3d12->queue.fenceValue = 1; d3d12->queue.fenceValue = 1;
d3d12->queue.fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL); d3d12->queue.fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
D3D12SignalCommandQueue(d3d12->queue.handle, d3d12->queue.fence, d3d12->queue.fenceValue);
return true; return true;
} }

View File

@ -183,33 +183,27 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const
{ {
/* Original */ /* Original */
{ &d3d11->frame.texture[0].view, 0, { &d3d11->frame.texture[0].view, 0,
&d3d11->frame.texture[0].size_data, 0, &d3d11->frame.texture[0].size_data, 0},
&d3d11->pass[i].sampler, 0 },
/* Source */ /* Source */
{ &source->view, 0, { &source->view, 0,
&source->size_data, 0, &source->size_data, 0},
&d3d11->pass[i].sampler, 0 },
/* OriginalHistory */ /* OriginalHistory */
{ &d3d11->frame.texture[0].view, sizeof(*d3d11->frame.texture), { &d3d11->frame.texture[0].view, sizeof(*d3d11->frame.texture),
&d3d11->frame.texture[0].size_data, sizeof(*d3d11->frame.texture), &d3d11->frame.texture[0].size_data, sizeof(*d3d11->frame.texture)},
&d3d11->pass[i].sampler, 0 },
/* PassOutput */ /* PassOutput */
{ &d3d11->pass[0].rt.view, sizeof(*d3d11->pass), { &d3d11->pass[0].rt.view, sizeof(*d3d11->pass),
&d3d11->pass[0].rt.size_data, sizeof(*d3d11->pass), &d3d11->pass[0].rt.size_data, sizeof(*d3d11->pass)},
&d3d11->pass[i].sampler, 0 },
/* PassFeedback */ /* PassFeedback */
{ &d3d11->pass[0].feedback.view, sizeof(*d3d11->pass), { &d3d11->pass[0].feedback.view, sizeof(*d3d11->pass),
&d3d11->pass[0].feedback.size_data, sizeof(*d3d11->pass), &d3d11->pass[0].feedback.size_data, sizeof(*d3d11->pass)},
&d3d11->pass[i].sampler, 0 },
/* User */ /* User */
{ &d3d11->luts[0].view, sizeof(*d3d11->luts), { &d3d11->luts[0].view, sizeof(*d3d11->luts),
&d3d11->luts[0].size_data, sizeof(*d3d11->luts), &d3d11->luts[0].size_data, sizeof(*d3d11->luts)},
&d3d11->luts[0].sampler, sizeof(*d3d11->luts) },
}, },
{ {
&d3d11->mvp, /* MVP */ &d3d11->mvp, /* MVP */
@ -324,9 +318,6 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const
&d3d11->luts[i]); &d3d11->luts[i]);
image_texture_free(&image); image_texture_free(&image);
d3d11->luts[i].sampler =
d3d11->samplers[d3d11->shader_preset->lut[i].filter][d3d11->shader_preset->lut[i].wrap];
} }
video_shader_resolve_current_parameters(conf, d3d11->shader_preset); video_shader_resolve_current_parameters(conf, d3d11->shader_preset);
@ -852,8 +843,6 @@ static void d3d11_init_render_targets(d3d11_video_t* d3d11, unsigned width, unsi
d3d11->pass[i].rt.size_data.z = 1.0f / width; d3d11->pass[i].rt.size_data.z = 1.0f / width;
d3d11->pass[i].rt.size_data.w = 1.0f / height; d3d11->pass[i].rt.size_data.w = 1.0f / height;
} }
d3d11->pass[i].sampler = d3d11->samplers[pass->filter][pass->wrap];
} }
d3d11->resize_render_targets = false; d3d11->resize_render_targets = false;
@ -926,7 +915,12 @@ static bool d3d11_gfx_frame(
{ {
/* release all render targets first to avoid memory fragmentation */ /* release all render targets first to avoid memory fragmentation */
for (i = 0; i < d3d11->shader_preset->passes; i++) for (i = 0; i < d3d11->shader_preset->passes; i++)
{
d3d11_release_texture(&d3d11->pass[i].rt); d3d11_release_texture(&d3d11->pass[i].rt);
d3d11_release_texture(&d3d11->pass[i].feedback);
memset(&d3d11->pass[i].rt, 0, sizeof(d3d11->pass[i].rt));
memset(&d3d11->pass[i].feedback, 0, sizeof(d3d11->pass[i].feedback));
}
} }
if (d3d11->shader_preset->history_size) if (d3d11->shader_preset->history_size)
@ -1032,7 +1026,7 @@ static bool d3d11_gfx_frame(
{ {
int binding = texture_sem->binding; int binding = texture_sem->binding;
textures[binding] = *(D3D11ShaderResourceView*)texture_sem->texture_data; textures[binding] = *(D3D11ShaderResourceView*)texture_sem->texture_data;
samplers[binding] = *(D3D11SamplerState*)texture_sem->sampler_data; samplers[binding] = d3d11->samplers[texture_sem->filter][texture_sem->wrap];
texture_sem++; texture_sem++;
} }
@ -1043,7 +1037,9 @@ static bool d3d11_gfx_frame(
if (d3d11->pass[i].rt.handle) if (d3d11->pass[i].rt.handle)
{ {
D3D11SetRenderTargets(context, 1, &d3d11->pass[i].rt.rt_view, NULL); D3D11SetRenderTargets(context, 1, &d3d11->pass[i].rt.rt_view, NULL);
#if 0
D3D11ClearRenderTargetView(context, d3d11->pass[i].rt.rt_view, d3d11->clearcolor); D3D11ClearRenderTargetView(context, d3d11->pass[i].rt.rt_view, d3d11->clearcolor);
#endif
D3D11SetViewports(context, 1, &d3d11->pass[i].viewport); D3D11SetViewports(context, 1, &d3d11->pass[i].viewport);
D3D11Draw(context, 4, 0); D3D11Draw(context, 4, 0);

View File

@ -34,6 +34,16 @@
#include "wiiu/wiiu_dbg.h" #include "wiiu/wiiu_dbg.h"
static void d3d12_gfx_sync(d3d12_video_t* d3d12)
{
if (D3D12GetCompletedValue(d3d12->queue.fence) < d3d12->queue.fenceValue)
{
D3D12SetEventOnCompletion(
d3d12->queue.fence, d3d12->queue.fenceValue, d3d12->queue.fenceEvent);
WaitForSingleObject(d3d12->queue.fenceEvent, INFINITE);
}
}
static void d3d12_set_filtering(void* data, unsigned index, bool smooth) static void d3d12_set_filtering(void* data, unsigned index, bool smooth)
{ {
int i; int i;
@ -58,6 +68,7 @@ static void d3d12_gfx_set_rotation(void* data, unsigned rotation)
if (!d3d12) if (!d3d12)
return; return;
d3d12_gfx_sync(d3d12);
d3d12->frame.rotation = rotation; d3d12->frame.rotation = rotation;
matrix_4x4_rotate_z(rot, d3d12->frame.rotation * (M_PI / 2.0f)); matrix_4x4_rotate_z(rot, d3d12->frame.rotation * (M_PI / 2.0f));
@ -155,6 +166,8 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
if (!d3d12) if (!d3d12)
return false; return false;
d3d12_gfx_sync(d3d12);
d3d12_free_shader_preset(d3d12); d3d12_free_shader_preset(d3d12);
if (!path) if (!path)
@ -187,33 +200,27 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
{ {
/* Original */ /* Original */
{ &d3d12->frame.texture[0], 0, { &d3d12->frame.texture[0], 0,
&d3d12->frame.texture[0].size_data, 0, &d3d12->frame.texture[0].size_data, 0},
&d3d12->pass[i].sampler, 0 },
/* Source */ /* Source */
{ source, 0, { source, 0,
&source->size_data, 0, &source->size_data, 0},
&d3d12->pass[i].sampler, 0 },
/* OriginalHistory */ /* OriginalHistory */
{ &d3d12->frame.texture[0], sizeof(*d3d12->frame.texture), { &d3d12->frame.texture[0], sizeof(*d3d12->frame.texture),
&d3d12->frame.texture[0].size_data, sizeof(*d3d12->frame.texture), &d3d12->frame.texture[0].size_data, sizeof(*d3d12->frame.texture)},
&d3d12->pass[i].sampler, 0 },
/* PassOutput */ /* PassOutput */
{ &d3d12->pass[0].rt, sizeof(*d3d12->pass), { &d3d12->pass[0].rt, sizeof(*d3d12->pass),
&d3d12->pass[0].rt.size_data, sizeof(*d3d12->pass), &d3d12->pass[0].rt.size_data, sizeof(*d3d12->pass)},
&d3d12->pass[i].sampler, 0 },
/* PassFeedback */ /* PassFeedback */
{ &d3d12->pass[0].feedback, sizeof(*d3d12->pass), { &d3d12->pass[0].feedback, sizeof(*d3d12->pass),
&d3d12->pass[0].feedback.size_data, sizeof(*d3d12->pass), &d3d12->pass[0].feedback.size_data, sizeof(*d3d12->pass)},
&d3d12->pass[i].sampler, 0 },
/* User */ /* User */
{ &d3d12->luts[0], sizeof(*d3d12->luts), { &d3d12->luts[0], sizeof(*d3d12->luts),
&d3d12->luts[0].size_data, sizeof(*d3d12->luts), &d3d12->luts[0].size_data, sizeof(*d3d12->luts)},
&d3d12->luts[0].sampler, sizeof(*d3d12->luts) },
}, },
{ {
&d3d12->mvp, /* MVP */ &d3d12->mvp, /* MVP */
@ -267,8 +274,12 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
if (!d3d_compile(ps_src, 0, ps_path, "main", "ps_5_0", &ps_code)) if (!d3d_compile(ps_src, 0, ps_path, "main", "ps_5_0", &ps_code))
save_hlsl = true; save_hlsl = true;
desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc; desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
if (i == d3d12->shader_preset->passes - 1)
desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
else
desc.RTVFormats[0] = glslang_format_to_dxgi(d3d12->pass[i].semantics.format); desc.RTVFormats[0] = glslang_format_to_dxgi(d3d12->pass[i].semantics.format);
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
desc.InputLayout.pInputElementDescs = inputElementDesc; desc.InputLayout.pInputElementDescs = inputElementDesc;
desc.InputLayout.NumElements = countof(inputElementDesc); desc.InputLayout.NumElements = countof(inputElementDesc);
@ -345,9 +356,6 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
&d3d12->luts[i]); &d3d12->luts[i]);
image_texture_free(&image); image_texture_free(&image);
d3d12->luts[i].sampler =
d3d12->samplers[d3d12->shader_preset->lut[i].filter][d3d12->shader_preset->lut[i].wrap];
} }
video_shader_resolve_current_parameters(conf, d3d12->shader_preset); video_shader_resolve_current_parameters(conf, d3d12->shader_preset);
@ -633,6 +641,8 @@ static void d3d12_gfx_free(void* data)
if (!d3d12) if (!d3d12)
return; return;
d3d12_gfx_sync(d3d12);
d3d12_free_shader_preset(d3d12); d3d12_free_shader_preset(d3d12);
font_driver_free_osd(); font_driver_free_osd();
@ -941,6 +951,10 @@ static bool d3d12_gfx_frame(
d3d12_texture_t* texture = NULL; d3d12_texture_t* texture = NULL;
d3d12_video_t* d3d12 = (d3d12_video_t*)data; d3d12_video_t* d3d12 = (d3d12_video_t*)data;
PERF_START();
d3d12_gfx_sync(d3d12);
if (d3d12->resize_chain) if (d3d12->resize_chain)
{ {
unsigned i; unsigned i;
@ -957,8 +971,6 @@ static bool d3d12_gfx_frame(
d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]); d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]);
} }
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
d3d12->chain.viewport.Width = video_info->width; d3d12->chain.viewport.Width = video_info->width;
d3d12->chain.viewport.Height = video_info->height; d3d12->chain.viewport.Height = video_info->height;
d3d12->chain.scissorRect.right = video_info->width; d3d12->chain.scissorRect.right = video_info->width;
@ -972,7 +984,6 @@ static bool d3d12_gfx_frame(
video_driver_set_size(&video_info->width, &video_info->height); video_driver_set_size(&video_info->width, &video_info->height);
} }
PERF_START();
D3D12ResetCommandAllocator(d3d12->queue.allocator); D3D12ResetCommandAllocator(d3d12->queue.allocator);
D3D12ResetGraphicsCommandList( D3D12ResetGraphicsCommandList(
@ -995,6 +1006,10 @@ static bool d3d12_gfx_frame(
{ {
if (d3d12->shader_preset) if (d3d12->shader_preset)
{ {
if (d3d12->shader_preset->luts && d3d12->luts[0].dirty)
for (i = 0; i < d3d12->shader_preset->luts; i++)
d3d12_upload_texture(d3d12->queue.cmd, &d3d12->luts[i]);
if (d3d12->frame.texture[0].desc.Width != width || if (d3d12->frame.texture[0].desc.Width != width ||
d3d12->frame.texture[0].desc.Height != height) d3d12->frame.texture[0].desc.Height != height)
d3d12->resize_render_targets = true; d3d12->resize_render_targets = true;
@ -1003,7 +1018,12 @@ static bool d3d12_gfx_frame(
{ {
/* release all render targets first to avoid memory fragmentation */ /* release all render targets first to avoid memory fragmentation */
for (i = 0; i < d3d12->shader_preset->passes; i++) for (i = 0; i < d3d12->shader_preset->passes; i++)
{
d3d12_release_texture(&d3d12->pass[i].rt); d3d12_release_texture(&d3d12->pass[i].rt);
d3d12->pass[i].rt.handle = NULL;
d3d12_release_texture(&d3d12->pass[i].feedback);
d3d12->pass[i].feedback.handle = NULL;
}
} }
if (d3d12->shader_preset->history_size) if (d3d12->shader_preset->history_size)
@ -1124,15 +1144,36 @@ static bool d3d12_gfx_frame(
d3d12->desc.sampler_heap.cpu.ptr + d3d12->desc.sampler_heap.cpu.ptr +
texture_sem->binding * d3d12->desc.sampler_heap.stride texture_sem->binding * d3d12->desc.sampler_heap.stride
}; };
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_POINT }; D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_LINEAR };
if (texture_sem->filter == RARCH_FILTER_NEAREST)
desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
switch (texture_sem->wrap)
{
case RARCH_WRAP_BORDER:
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
break;
case RARCH_WRAP_EDGE:
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
break;
case RARCH_WRAP_REPEAT:
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
break;
case RARCH_WRAP_MIRRORED_REPEAT:
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
break;
}
desc.AddressV = desc.AddressU;
desc.AddressW = desc.AddressU;
desc.MaxAnisotropy = 1; desc.MaxAnisotropy = 1;
desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
desc.MinLOD = -D3D12_FLOAT32_MAX; desc.MinLOD = -D3D12_FLOAT32_MAX;
desc.MaxLOD = D3D12_FLOAT32_MAX; desc.MaxLOD = D3D12_FLOAT32_MAX;
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
desc.AddressV = desc.AddressU;
desc.AddressW = desc.AddressU;
desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
D3D12CreateSampler(d3d12->device, &desc, handle); D3D12CreateSampler(d3d12->device, &desc, handle);
} }
@ -1185,6 +1226,7 @@ static bool d3d12_gfx_frame(
d3d12->queue.cmd, ROOT_ID_UBO, d3d12->frame.ubo_view.BufferLocation); d3d12->queue.cmd, ROOT_ID_UBO, d3d12->frame.ubo_view.BufferLocation);
} }
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
d3d12_resource_transition( d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index], d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
@ -1246,7 +1288,9 @@ static bool d3d12_gfx_frame(
d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index], d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
D3D12CloseGraphicsCommandList(d3d12->queue.cmd); D3D12CloseGraphicsCommandList(d3d12->queue.cmd);
D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1, &d3d12->queue.cmd); D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1, &d3d12->queue.cmd);
D3D12SignalCommandQueue(d3d12->queue.handle, d3d12->queue.fence, ++d3d12->queue.fenceValue);
#if 1 #if 1
DXGIPresent(d3d12->chain.handle, !!d3d12->chain.vsync, 0); DXGIPresent(d3d12->chain.handle, !!d3d12->chain.vsync, 0);
@ -1255,18 +1299,6 @@ static bool d3d12_gfx_frame(
DXGIPresent1(d3d12->swapchain, 0, 0, &pp); DXGIPresent1(d3d12->swapchain, 0, 0, &pp);
#endif #endif
/* wait_for_previous_frame */
D3D12SignalCommandQueue(d3d12->queue.handle, d3d12->queue.fence, d3d12->queue.fenceValue);
if (D3D12GetCompletedValue(d3d12->queue.fence) < d3d12->queue.fenceValue)
{
D3D12SetEventOnCompletion(
d3d12->queue.fence, d3d12->queue.fenceValue, d3d12->queue.fenceEvent);
WaitForSingleObject(d3d12->queue.fenceEvent, INFINITE);
}
d3d12->queue.fenceValue++;
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
PERF_STOP(); PERF_STOP();
if (msg && *msg) if (msg && *msg)
@ -1460,6 +1492,7 @@ static void d3d12_gfx_unload_texture(void* data, uintptr_t handle)
if (!texture) if (!texture)
return; return;
d3d12_gfx_sync((d3d12_video_t*)data);
d3d12_release_texture(texture); d3d12_release_texture(texture);
free(texture); free(texture);
} }

View File

@ -228,9 +228,19 @@ static bool slang_process_reflection(
if (src.stage_mask) if (src.stage_mask)
{ {
texture_sem_t texture = { texture_sem_t texture = {
(void*)((uintptr_t)map->textures[semantic].image + index * map->textures[semantic].image_stride), (void*)((uintptr_t)map->textures[semantic].image + index * map->textures[semantic].image_stride)
(void*)((uintptr_t)map->textures[semantic].sampler + index * map->textures[semantic].sampler_stride),
}; };
if (semantic == SLANG_TEXTURE_SEMANTIC_USER)
{
texture.wrap = shader_info->lut[index].wrap;
texture.filter = shader_info->lut[index].filter;
}
else
{
texture.wrap = shader_info->pass[pass_number].wrap;
texture.filter = shader_info->pass[pass_number].filter;
}
texture.stage_mask = src.stage_mask; texture.stage_mask = src.stage_mask;
texture.binding = src.binding; texture.binding = src.binding;
string id = get_semantic_name(sl_reflection, (slang_texture_semantic)semantic, index); string id = get_semantic_name(sl_reflection, (slang_texture_semantic)semantic, index);

View File

@ -36,8 +36,6 @@ typedef struct
size_t image_stride; size_t image_stride;
void* size; void* size;
size_t size_stride; size_t size_stride;
void* sampler;
size_t sampler_stride;
} texture_map_t; } texture_map_t;
typedef struct typedef struct
@ -57,7 +55,8 @@ typedef struct
typedef struct typedef struct
{ {
void* texture_data; void* texture_data;
void* sampler_data; enum gfx_wrap_type wrap;
unsigned filter;
unsigned stage_mask; unsigned stage_mask;
unsigned binding; unsigned binding;
char id[64]; char id[64];