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 */
{
if (!size)
size = strlen(src);
if (vs_entry && !d3d_compile(src, size, (LPCSTR)src_name, vs_entry, "vs_5_0", &vs_code))
success = false;
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
{
d3d11_shader_t shader;
D3D11SamplerStateRef sampler;
D3D11Buffer buffers[SLANG_CBUFFER_MAX];
d3d11_texture_t rt;
d3d11_texture_t feedback;

View File

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

View File

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

View File

@ -34,6 +34,16 @@
#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)
{
int i;
@ -58,6 +68,7 @@ static void d3d12_gfx_set_rotation(void* data, unsigned rotation)
if (!d3d12)
return;
d3d12_gfx_sync(d3d12);
d3d12->frame.rotation = rotation;
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)
return false;
d3d12_gfx_sync(d3d12);
d3d12_free_shader_preset(d3d12);
if (!path)
@ -187,33 +200,27 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const
{
/* Original */
{ &d3d12->frame.texture[0], 0,
&d3d12->frame.texture[0].size_data, 0,
&d3d12->pass[i].sampler, 0 },
&d3d12->frame.texture[0].size_data, 0},
/* Source */
{ source, 0,
&source->size_data, 0,
&d3d12->pass[i].sampler, 0 },
&source->size_data, 0},
/* OriginalHistory */
{ &d3d12->frame.texture[0], sizeof(*d3d12->frame.texture),
&d3d12->frame.texture[0].size_data, sizeof(*d3d12->frame.texture),
&d3d12->pass[i].sampler, 0 },
&d3d12->frame.texture[0].size_data, sizeof(*d3d12->frame.texture)},
/* PassOutput */
{ &d3d12->pass[0].rt, sizeof(*d3d12->pass),
&d3d12->pass[0].rt.size_data, sizeof(*d3d12->pass),
&d3d12->pass[i].sampler, 0 },
&d3d12->pass[0].rt.size_data, sizeof(*d3d12->pass)},
/* PassFeedback */
{ &d3d12->pass[0].feedback, sizeof(*d3d12->pass),
&d3d12->pass[0].feedback.size_data, sizeof(*d3d12->pass),
&d3d12->pass[i].sampler, 0 },
&d3d12->pass[0].feedback.size_data, sizeof(*d3d12->pass)},
/* User */
{ &d3d12->luts[0], sizeof(*d3d12->luts),
&d3d12->luts[0].size_data, sizeof(*d3d12->luts),
&d3d12->luts[0].sampler, sizeof(*d3d12->luts) },
&d3d12->luts[0].size_data, sizeof(*d3d12->luts)},
},
{
&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))
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.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
desc.InputLayout.pInputElementDescs = 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]);
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);
@ -633,6 +641,8 @@ static void d3d12_gfx_free(void* data)
if (!d3d12)
return;
d3d12_gfx_sync(d3d12);
d3d12_free_shader_preset(d3d12);
font_driver_free_osd();
@ -941,6 +951,10 @@ static bool d3d12_gfx_frame(
d3d12_texture_t* texture = NULL;
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
PERF_START();
d3d12_gfx_sync(d3d12);
if (d3d12->resize_chain)
{
unsigned i;
@ -957,8 +971,6 @@ static bool d3d12_gfx_frame(
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.Height = video_info->height;
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);
}
PERF_START();
D3D12ResetCommandAllocator(d3d12->queue.allocator);
D3D12ResetGraphicsCommandList(
@ -995,6 +1006,10 @@ static bool d3d12_gfx_frame(
{
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 ||
d3d12->frame.texture[0].desc.Height != height)
d3d12->resize_render_targets = true;
@ -1003,7 +1018,12 @@ static bool d3d12_gfx_frame(
{
/* release all render targets first to avoid memory fragmentation */
for (i = 0; i < d3d12->shader_preset->passes; i++)
{
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)
@ -1124,15 +1144,36 @@ static bool d3d12_gfx_frame(
d3d12->desc.sampler_heap.cpu.ptr +
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.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
desc.MinLOD = -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);
}
@ -1185,6 +1226,7 @@ static bool d3d12_gfx_frame(
d3d12->queue.cmd, ROOT_ID_UBO, d3d12->frame.ubo_view.BufferLocation);
}
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
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_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
D3D12CloseGraphicsCommandList(d3d12->queue.cmd);
D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1, &d3d12->queue.cmd);
D3D12SignalCommandQueue(d3d12->queue.handle, d3d12->queue.fence, ++d3d12->queue.fenceValue);
#if 1
DXGIPresent(d3d12->chain.handle, !!d3d12->chain.vsync, 0);
@ -1255,18 +1299,6 @@ static bool d3d12_gfx_frame(
DXGIPresent1(d3d12->swapchain, 0, 0, &pp);
#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();
if (msg && *msg)
@ -1460,6 +1492,7 @@ static void d3d12_gfx_unload_texture(void* data, uintptr_t handle)
if (!texture)
return;
d3d12_gfx_sync((d3d12_video_t*)data);
d3d12_release_texture(texture);
free(texture);
}

View File

@ -228,9 +228,19 @@ static bool slang_process_reflection(
if (src.stage_mask)
{
texture_sem_t texture = {
(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),
(void*)((uintptr_t)map->textures[semantic].image + index * map->textures[semantic].image_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.binding = src.binding;
string id = get_semantic_name(sl_reflection, (slang_texture_semantic)semantic, index);

View File

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