(D3D11) multi-pass shaders: add support for wrap modes and lut

mipmapping.
This commit is contained in:
aliaspider 2018-02-02 17:18:41 +01:00
parent 2a25e284af
commit 6fe3a31617
4 changed files with 83 additions and 49 deletions

View File

@ -2504,8 +2504,7 @@ typedef struct
D3D11RenderTargetView renderTargetView; D3D11RenderTargetView renderTargetView;
D3D11Buffer ubo; D3D11Buffer ubo;
d3d11_uniform_t ubo_values; d3d11_uniform_t ubo_values;
D3D11SamplerState sampler_nearest; D3D11SamplerState samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX];
D3D11SamplerState sampler_linear;
D3D11BlendState blend_enable; D3D11BlendState blend_enable;
D3D11BlendState blend_disable; D3D11BlendState blend_disable;
D3D11BlendState blend_pipeline; D3D11BlendState blend_pipeline;

View File

@ -39,10 +39,13 @@ static void d3d11_set_filtering(void* data, unsigned index, bool smooth)
{ {
d3d11_video_t* d3d11 = (d3d11_video_t*)data; d3d11_video_t* d3d11 = (d3d11_video_t*)data;
if (smooth) for (int i = 0; i < RARCH_WRAP_MAX; i++)
d3d11->frame.texture.sampler = d3d11->sampler_linear; {
else if (smooth)
d3d11->frame.texture.sampler = d3d11->sampler_nearest; d3d11->samplers[RARCH_FILTER_UNSPEC][i] = d3d11->samplers[RARCH_FILTER_LINEAR][i];
else
d3d11->samplers[RARCH_FILTER_UNSPEC][i] = d3d11->samplers[RARCH_FILTER_NEAREST][i];
}
} }
static void d3d11_gfx_set_rotation(void* data, unsigned rotation) static void d3d11_gfx_set_rotation(void* data, unsigned rotation)
@ -218,43 +221,44 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const
#else #else
bool save_hlsl = false; bool save_hlsl = false;
#endif #endif
const char* vs_src = d3d11->shader_preset->pass[i].source.string.vertex; static const char vs_ext[] = ".vs.hlsl";
const char* ps_src = d3d11->shader_preset->pass[i].source.string.fragment; static const char ps_ext[] = ".ps.hlsl";
const char* vs_ext = ".vs.hlsl"; char vs_path[PATH_MAX_LENGTH];
const char* ps_ext = ".ps.hlsl"; char ps_path[PATH_MAX_LENGTH];
int base_len = strlen(d3d11->shader_preset->pass[i].source.path) - strlen(".slang"); const char* slang_path = d3d11->shader_preset->pass[i].source.path;
char* vs_filename = (char*)malloc(base_len + strlen(vs_ext) + 1); const char* vs_src = d3d11->shader_preset->pass[i].source.string.vertex;
char* ps_filename = (char*)malloc(base_len + strlen(ps_ext) + 1); const char* ps_src = d3d11->shader_preset->pass[i].source.string.fragment;
int base_len = strlen(slang_path) - strlen(".slang");
strncpy(vs_filename, d3d11->shader_preset->pass[i].source.path, base_len); if(base_len <= 0)
strncpy(ps_filename, d3d11->shader_preset->pass[i].source.path, base_len); base_len = strlen(slang_path);
strncpy(vs_filename + base_len, vs_ext, strlen(vs_ext) + 1);
strncpy(ps_filename + base_len, ps_ext, strlen(ps_ext) + 1); strncpy(vs_path, slang_path, base_len);
strncpy(ps_path, slang_path, base_len);
strncpy(vs_path + base_len, vs_ext, sizeof(vs_ext));
strncpy(ps_path + base_len, ps_ext, sizeof(ps_ext));
if (!d3d11_init_shader( if (!d3d11_init_shader(
d3d11->device, vs_src, 0, vs_filename, "main", NULL, NULL, desc, countof(desc), d3d11->device, vs_src, 0, vs_path, "main", NULL, NULL, desc, countof(desc),
&d3d11->pass[i].shader)) &d3d11->pass[i].shader))
save_hlsl = true; save_hlsl = true;
if (!d3d11_init_shader( if (!d3d11_init_shader(
d3d11->device, ps_src, 0, ps_filename, NULL, "main", NULL, NULL, 0, d3d11->device, ps_src, 0, ps_path, NULL, "main", NULL, NULL, 0,
&d3d11->pass[i].shader)) &d3d11->pass[i].shader))
save_hlsl = true; save_hlsl = true;
if (save_hlsl) if (save_hlsl)
{ {
FILE* fp = fopen(vs_filename, "w"); FILE* fp = fopen(vs_path, "w");
fwrite(vs_src, 1, strlen(vs_src), fp); fwrite(vs_src, 1, strlen(vs_src), fp);
fclose(fp); fclose(fp);
fp = fopen(ps_filename, "w"); fp = fopen(ps_path, "w");
fwrite(ps_src, 1, strlen(ps_src), fp); fwrite(ps_src, 1, strlen(ps_src), fp);
fclose(fp); fclose(fp);
} }
free(vs_filename);
free(ps_filename);
free(d3d11->shader_preset->pass[i].source.string.vertex); free(d3d11->shader_preset->pass[i].source.string.vertex);
free(d3d11->shader_preset->pass[i].source.string.fragment); free(d3d11->shader_preset->pass[i].source.string.fragment);
@ -293,15 +297,20 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const
d3d11->luts[i].desc.Width = image.width; d3d11->luts[i].desc.Width = image.width;
d3d11->luts[i].desc.Height = image.height; d3d11->luts[i].desc.Height = image.height;
d3d11->luts[i].desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; d3d11->luts[i].desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
if(d3d11->shader_preset->lut[i].mipmap)
d3d11->luts[i].desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
d3d11_init_texture(d3d11->device, &d3d11->luts[i]); d3d11_init_texture(d3d11->device, &d3d11->luts[i]);
d3d11_update_texture( d3d11_update_texture(
d3d11->ctx, image.width, image.height, 0, DXGI_FORMAT_R8G8B8A8_UNORM, image.pixels, d3d11->ctx, image.width, image.height, 0, DXGI_FORMAT_R8G8B8A8_UNORM, image.pixels,
&d3d11->luts[i]); &d3d11->luts[i]);
image_texture_free(&image); image_texture_free(&image);
d3d11->luts[i].sampler = d3d11->shader_preset->lut[i].filter == RARCH_FILTER_NEAREST d3d11->luts[i].sampler =
? d3d11->sampler_nearest d3d11->samplers[d3d11->shader_preset->lut[i].filter][d3d11->shader_preset->lut[i].wrap];
: d3d11->sampler_linear;
} }
video_shader_resolve_current_parameters(conf, d3d11->shader_preset); video_shader_resolve_current_parameters(conf, d3d11->shader_preset);
@ -350,8 +359,11 @@ static void d3d11_gfx_free(void* data)
Release(d3d11->blend_enable); Release(d3d11->blend_enable);
Release(d3d11->blend_disable); Release(d3d11->blend_disable);
Release(d3d11->sampler_nearest); for (int i = 0; i < RARCH_WRAP_MAX; i++)
Release(d3d11->sampler_linear); {
Release(d3d11->samplers[RARCH_FILTER_LINEAR][i]);
Release(d3d11->samplers[RARCH_FILTER_NEAREST][i]);
}
Release(d3d11->state); Release(d3d11->state);
Release(d3d11->renderTargetView); Release(d3d11->renderTargetView);
@ -478,19 +490,41 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i
{ {
D3D11_SAMPLER_DESC desc = { D3D11_SAMPLER_DESC desc = {
.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT,
.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP,
.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP,
.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP,
.MaxAnisotropy = 1, .MaxAnisotropy = 1,
.ComparisonFunc = D3D11_COMPARISON_NEVER, .ComparisonFunc = D3D11_COMPARISON_NEVER,
.MinLOD = -D3D11_FLOAT32_MAX, .MinLOD = -D3D11_FLOAT32_MAX,
.MaxLOD = D3D11_FLOAT32_MAX, .MaxLOD = D3D11_FLOAT32_MAX,
}; };
D3D11CreateSamplerState(d3d11->device, &desc, &d3d11->sampler_nearest); /* Initialize samplers */
for (int i = 0; i < RARCH_WRAP_MAX; i++)
{
switch (i)
{
case RARCH_WRAP_BORDER:
desc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
break;
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; case RARCH_WRAP_EDGE:
D3D11CreateSamplerState(d3d11->device, &desc, &d3d11->sampler_linear); desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
break;
case RARCH_WRAP_REPEAT:
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
break;
case RARCH_WRAP_MIRRORED_REPEAT:
desc.AddressU = D3D11_TEXTURE_ADDRESS_MIRROR;
break;
}
desc.AddressV = desc.AddressU;
desc.AddressW = desc.AddressU;
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
D3D11CreateSamplerState(d3d11->device, &desc, &d3d11->samplers[RARCH_FILTER_LINEAR][i]);
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
D3D11CreateSamplerState(d3d11->device, &desc, &d3d11->samplers[RARCH_FILTER_NEAREST][i]);
}
} }
d3d11_set_filtering(d3d11, 0, video->smooth); d3d11_set_filtering(d3d11, 0, video->smooth);
@ -708,7 +742,7 @@ static bool d3d11_init_frame_textures(d3d11_video_t* d3d11, unsigned width, unsi
{ {
struct video_shader_pass* pass = &d3d11->shader_preset->pass[i]; struct video_shader_pass* pass = &d3d11->shader_preset->pass[i];
if(pass->fbo.valid) if (pass->fbo.valid)
{ {
switch (pass->fbo.type_x) switch (pass->fbo.type_x)
@ -755,11 +789,10 @@ static bool d3d11_init_frame_textures(d3d11_video_t* d3d11, unsigned width, unsi
} }
else if (i == (d3d11->shader_preset->passes - 1)) else if (i == (d3d11->shader_preset->passes - 1))
{ {
width = d3d11->vp.width; width = d3d11->vp.width;
height = d3d11->vp.height; height = d3d11->vp.height;
} }
RARCH_LOG("[D3D11]: Updating framebuffer size %u x %u.\n", width, height); RARCH_LOG("[D3D11]: Updating framebuffer size %u x %u.\n", width, height);
if ((i != (d3d11->shader_preset->passes - 1)) || (width != d3d11->vp.width) || if ((i != (d3d11->shader_preset->passes - 1)) || (width != d3d11->vp.width) ||
@ -782,8 +815,7 @@ static bool d3d11_init_frame_textures(d3d11_video_t* d3d11, unsigned width, unsi
d3d11->pass[i].rt.size_data.w = 1.0f / height; d3d11->pass[i].rt.size_data.w = 1.0f / height;
} }
d3d11->pass[i].sampler = pass->filter == RARCH_FILTER_NEAREST ? d3d11->sampler_nearest d3d11->pass[i].sampler = d3d11->samplers[pass->filter][pass->wrap];
: d3d11->sampler_linear;
for (int j = 0; j < d3d11->pass[i].semantics.texture_count; j++) for (int j = 0; j < d3d11->pass[i].semantics.texture_count; j++)
{ {
@ -936,7 +968,8 @@ static bool d3d11_gfx_frame(
{ {
d3d11_set_shader(d3d11->ctx, &d3d11->shaders[VIDEO_SHADER_STOCK_BLEND]); d3d11_set_shader(d3d11->ctx, &d3d11->shaders[VIDEO_SHADER_STOCK_BLEND]);
D3D11SetPShaderResources(d3d11->ctx, 0, 1, &texture->view); D3D11SetPShaderResources(d3d11->ctx, 0, 1, &texture->view);
D3D11SetPShaderSamplers(d3d11->ctx, 0, 1, &d3d11->frame.texture.sampler); D3D11SetPShaderSamplers(
d3d11->ctx, 0, 1, &d3d11->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
D3D11SetVShaderConstantBuffers(d3d11->ctx, 0, 1, &d3d11->frame.ubo); D3D11SetVShaderConstantBuffers(d3d11->ctx, 0, 1, &d3d11->frame.ubo);
} }
@ -1063,9 +1096,10 @@ static void d3d11_set_menu_texture_frame(
} }
d3d11_update_texture(d3d11->ctx, width, height, 0, format, frame, &d3d11->menu.texture); d3d11_update_texture(d3d11->ctx, width, height, 0, format, frame, &d3d11->menu.texture);
d3d11->menu.texture.sampler = config_get_ptr()->bools.menu_linear_filter d3d11->menu.texture.sampler = d3d11->samplers
? d3d11->sampler_linear [config_get_ptr()->bools.menu_linear_filter
: d3d11->sampler_nearest; ? RARCH_FILTER_LINEAR
: RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT];
} }
static void d3d11_set_menu_texture_enable(void* data, bool state, bool full_screen) static void d3d11_set_menu_texture_enable(void* data, bool state, bool full_screen)
@ -1129,13 +1163,13 @@ static uintptr_t d3d11_gfx_load_texture(
texture->desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; texture->desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
/* fallthrough */ /* fallthrough */
case TEXTURE_FILTER_LINEAR: case TEXTURE_FILTER_LINEAR:
texture->sampler = d3d11->sampler_linear; texture->sampler = d3d11->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_DEFAULT];
break; break;
case TEXTURE_FILTER_MIPMAP_NEAREST: case TEXTURE_FILTER_MIPMAP_NEAREST:
texture->desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; texture->desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
/* fallthrough */ /* fallthrough */
case TEXTURE_FILTER_NEAREST: case TEXTURE_FILTER_NEAREST:
texture->sampler = d3d11->sampler_nearest; texture->sampler = d3d11->samplers[RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT];
break; break;
} }

View File

@ -51,7 +51,7 @@ d3d11_font_init_font(void* data, const char* font_path, float font_size, bool is
} }
font->atlas = font->font_driver->get_atlas(font->font_data); font->atlas = font->font_driver->get_atlas(font->font_data);
font->texture.sampler = d3d11->sampler_linear; font->texture.sampler = d3d11->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_BORDER];
font->texture.desc.Width = font->atlas->width; font->texture.desc.Width = font->atlas->width;
font->texture.desc.Height = font->atlas->height; font->texture.desc.Height = font->atlas->height;
font->texture.desc.Format = DXGI_FORMAT_A8_UNORM; font->texture.desc.Format = DXGI_FORMAT_A8_UNORM;

View File

@ -62,7 +62,8 @@ enum
{ {
RARCH_FILTER_UNSPEC = 0, RARCH_FILTER_UNSPEC = 0,
RARCH_FILTER_LINEAR, RARCH_FILTER_LINEAR,
RARCH_FILTER_NEAREST RARCH_FILTER_NEAREST,
RARCH_FILTER_MAX
}; };
enum gfx_wrap_type enum gfx_wrap_type