RetroArch/gfx/drivers_display/gfx_display_d3d12.c

315 lines
11 KiB
C
Raw Normal View History

2018-02-08 00:17:09 +01:00
/* RetroArch - A frontend for libretro.
* Copyright (C) 2014-2018 - Ali Bouhlel
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#define CINTERFACE
#include <retro_miscellaneous.h>
#ifdef HAVE_CONFIG_H
2021-08-18 14:19:48 -04:00
#include "../../config.h"
2018-02-08 00:17:09 +01:00
#endif
2020-02-16 15:10:07 +01:00
#include "../gfx_display.h"
2018-02-08 00:17:09 +01:00
#include "../common/d3d12_common.h"
2018-02-08 00:17:09 +01:00
static void gfx_display_d3d12_blend_begin(void *data)
2018-02-08 00:17:09 +01:00
{
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
D3D12GraphicsCommandList cmd = d3d12->queue.cmd;
d3d12->sprites.pipe = d3d12->sprites.pipe_blend;
cmd->lpVtbl->SetPipelineState(cmd, (D3D12PipelineState)d3d12->sprites.pipe);
2018-02-08 00:17:09 +01:00
}
static void gfx_display_d3d12_blend_end(void *data)
2018-02-08 00:17:09 +01:00
{
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
D3D12GraphicsCommandList cmd = d3d12->queue.cmd;
d3d12->sprites.pipe = d3d12->sprites.pipe_noblend;
cmd->lpVtbl->SetPipelineState(cmd, (D3D12PipelineState)d3d12->sprites.pipe);
2018-02-08 00:17:09 +01:00
}
2020-02-16 15:10:07 +01:00
static void gfx_display_d3d12_draw(gfx_display_ctx_draw_t *draw,
void *data, unsigned video_width, unsigned video_height)
2018-02-08 00:17:09 +01:00
{
D3D12GraphicsCommandList cmd;
int vertex_count = 1;
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
2018-02-08 00:17:09 +01:00
if (!d3d12 || !draw || !draw->texture)
return;
cmd = d3d12->queue.cmd;
2020-08-14 15:58:43 +02:00
switch (draw->pipeline_id)
2018-02-08 00:17:09 +01:00
{
case VIDEO_SHADER_MENU:
case VIDEO_SHADER_MENU_2:
case VIDEO_SHADER_MENU_3:
case VIDEO_SHADER_MENU_4:
case VIDEO_SHADER_MENU_5:
case VIDEO_SHADER_MENU_6:
cmd->lpVtbl->SetPipelineState(cmd, (D3D12PipelineState)d3d12->pipes[draw->pipeline_id]);
cmd->lpVtbl->DrawInstanced(cmd, draw->coords->vertices, 1, 0, 0);
cmd->lpVtbl->SetPipelineState(cmd, (D3D12PipelineState)d3d12->sprites.pipe);
cmd->lpVtbl->IASetPrimitiveTopology(cmd, D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
cmd->lpVtbl->IASetVertexBuffers(cmd, 0, 1, &d3d12->sprites.vbo_view);
2018-02-08 00:17:09 +01:00
return;
}
2018-02-08 17:11:24 +01:00
if (draw->coords->vertex && draw->coords->tex_coord && draw->coords->color)
vertex_count = draw->coords->vertices;
if ( (!(d3d12->flags & D3D12_ST_FLAG_SPRITES_ENABLE))
|| (vertex_count > d3d12->sprites.capacity))
2018-02-08 00:17:09 +01:00
return;
2018-02-08 17:11:24 +01:00
if (d3d12->sprites.offset + vertex_count > d3d12->sprites.capacity)
2018-02-08 00:17:09 +01:00
d3d12->sprites.offset = 0;
{
2018-02-08 17:11:24 +01:00
d3d12_sprite_t* sprite;
2022-05-16 22:26:46 +02:00
D3D12_RANGE range;
range.Begin = 0;
range.End = 0;
2018-02-08 17:11:24 +01:00
D3D12Map(d3d12->sprites.vbo, 0, &range, (void**)&sprite);
sprite += d3d12->sprites.offset;
if (vertex_count == 1)
{
2023-01-08 18:31:04 +01:00
sprite->pos.x = draw->x / (float)d3d12->chain.viewport.Width;
sprite->pos.y =
(d3d12->chain.viewport.Height - draw->y - draw->height) /
(float)d3d12->chain.viewport.Height;
sprite->pos.w = draw->width / (float)d3d12->chain.viewport.Width;
sprite->pos.h = draw->height / (float)d3d12->chain.viewport.Height;
2018-02-08 17:11:24 +01:00
sprite->coords.u = 0.0f;
sprite->coords.v = 0.0f;
sprite->coords.w = 1.0f;
sprite->coords.h = 1.0f;
if (draw->scale_factor)
sprite->params.scaling = draw->scale_factor;
else
sprite->params.scaling = 1.0f;
2023-01-08 18:31:04 +01:00
sprite->params.rotation = draw->rotation;
2018-02-08 17:11:24 +01:00
2023-01-08 18:31:04 +01:00
sprite->colors[3] = DXGI_COLOR_RGBA(
0xFF * draw->coords->color[0], 0xFF * draw->coords->color[1],
0xFF * draw->coords->color[2], 0xFF * draw->coords->color[3]);
2023-01-08 18:31:04 +01:00
sprite->colors[2] = DXGI_COLOR_RGBA(
0xFF * draw->coords->color[4], 0xFF * draw->coords->color[5],
0xFF * draw->coords->color[6], 0xFF * draw->coords->color[7]);
2023-01-08 18:31:04 +01:00
sprite->colors[1] = DXGI_COLOR_RGBA(
0xFF * draw->coords->color[8], 0xFF * draw->coords->color[9],
2018-02-08 17:11:24 +01:00
0xFF * draw->coords->color[10], 0xFF * draw->coords->color[11]);
2023-01-08 18:31:04 +01:00
sprite->colors[0] = DXGI_COLOR_RGBA(
2018-02-08 17:11:24 +01:00
0xFF * draw->coords->color[12], 0xFF * draw->coords->color[13],
0xFF * draw->coords->color[14], 0xFF * draw->coords->color[15]);
}
2018-02-08 00:17:09 +01:00
else
2018-02-08 17:11:24 +01:00
{
int i;
const float* vertex = draw->coords->vertex;
const float* tex_coord = draw->coords->tex_coord;
const float* color = draw->coords->color;
for (i = 0; i < vertex_count; i++)
{
d3d12_vertex_t* v = (d3d12_vertex_t*)sprite;
v->position[0] = *vertex++;
v->position[1] = *vertex++;
v->texcoord[0] = *tex_coord++;
v->texcoord[1] = *tex_coord++;
v->color[0] = *color++;
v->color[1] = *color++;
v->color[2] = *color++;
v->color[3] = *color++;
sprite++;
}
cmd->lpVtbl->SetPipelineState(cmd,
(D3D12PipelineState)d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
cmd->lpVtbl->IASetPrimitiveTopology(cmd,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
2018-02-08 17:11:24 +01:00
}
range.Begin = d3d12->sprites.offset * sizeof(*sprite);
range.End = (d3d12->sprites.offset + vertex_count) * sizeof(*sprite);
2018-02-08 00:17:09 +01:00
D3D12Unmap(d3d12->sprites.vbo, 0, &range);
}
{
d3d12_texture_t* texture = (d3d12_texture_t*)draw->texture;
if (texture->dirty)
{
d3d12_upload_texture(cmd, texture, d3d12);
2018-02-08 17:11:24 +01:00
if (vertex_count > 1)
cmd->lpVtbl->SetPipelineState(cmd,
(D3D12PipelineState)d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
else
cmd->lpVtbl->SetPipelineState(cmd,
(D3D12PipelineState)d3d12->sprites.pipe);
}
cmd->lpVtbl->SetGraphicsRootDescriptorTable(cmd, ROOT_ID_TEXTURE_T, texture->gpu_descriptor[0]);
cmd->lpVtbl->SetGraphicsRootDescriptorTable(cmd, ROOT_ID_SAMPLER_T, texture->sampler);
2018-02-08 17:11:24 +01:00
}
cmd->lpVtbl->DrawInstanced(cmd, vertex_count, 1, d3d12->sprites.offset, 0);
2018-02-08 17:11:24 +01:00
d3d12->sprites.offset += vertex_count;
if (vertex_count > 1)
{
cmd->lpVtbl->SetPipelineState(cmd, (D3D12PipelineState)d3d12->sprites.pipe);
cmd->lpVtbl->IASetPrimitiveTopology(cmd, D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
2018-02-08 00:17:09 +01:00
}
}
2020-02-16 15:10:07 +01:00
static void gfx_display_d3d12_draw_pipeline(gfx_display_ctx_draw_t *draw,
2021-04-08 00:38:24 +02:00
gfx_display_t *p_disp,
void *data, unsigned video_width, unsigned video_height)
2018-02-08 00:17:09 +01:00
{
D3D12GraphicsCommandList cmd;
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
2018-02-08 00:17:09 +01:00
if (!d3d12 || !draw)
return;
cmd = d3d12->queue.cmd;
2020-08-14 15:58:43 +02:00
switch (draw->pipeline_id)
2018-02-08 00:17:09 +01:00
{
case VIDEO_SHADER_MENU:
case VIDEO_SHADER_MENU_2:
{
2020-09-25 10:31:07 +02:00
video_coord_array_t* ca = &p_disp->dispca;
2018-02-08 00:17:09 +01:00
if (!d3d12->menu_pipeline_vbo)
{
2022-05-16 22:26:46 +02:00
D3D12_RANGE read_range;
2018-02-08 00:17:09 +01:00
void* vertex_data_begin;
2023-01-08 18:31:04 +01:00
d3d12->menu_pipeline_vbo_view.StrideInBytes = 2 * sizeof(float);
d3d12->menu_pipeline_vbo_view.SizeInBytes =
2018-02-08 00:17:09 +01:00
ca->coords.vertices * d3d12->menu_pipeline_vbo_view.StrideInBytes;
d3d12->menu_pipeline_vbo_view.BufferLocation = d3d12_create_buffer(
d3d12->device, d3d12->menu_pipeline_vbo_view.SizeInBytes,
&d3d12->menu_pipeline_vbo);
2022-05-16 22:26:46 +02:00
read_range.Begin = 0;
read_range.End = 0;
2023-01-08 18:31:04 +01:00
D3D12Map(d3d12->menu_pipeline_vbo, 0,
&read_range, &vertex_data_begin);
memcpy(vertex_data_begin, ca->coords.vertex,
d3d12->menu_pipeline_vbo_view.SizeInBytes);
2018-02-08 00:17:09 +01:00
D3D12Unmap(d3d12->menu_pipeline_vbo, 0, NULL);
}
cmd->lpVtbl->IASetVertexBuffers(cmd, 0, 1,
2023-01-08 18:31:04 +01:00
&d3d12->menu_pipeline_vbo_view);
2018-02-08 00:17:09 +01:00
draw->coords->vertices = ca->coords.vertices;
break;
}
case VIDEO_SHADER_MENU_3:
case VIDEO_SHADER_MENU_4:
case VIDEO_SHADER_MENU_5:
case VIDEO_SHADER_MENU_6:
cmd->lpVtbl->IASetVertexBuffers(cmd, 0, 1, &d3d12->frame.vbo_view);
2018-02-08 00:17:09 +01:00
draw->coords->vertices = 4;
break;
default:
return;
}
cmd->lpVtbl->IASetPrimitiveTopology(cmd,
2023-01-08 18:31:04 +01:00
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
2018-02-08 00:17:09 +01:00
d3d12->ubo_values.time += 0.01f;
{
2022-05-16 22:26:46 +02:00
D3D12_RANGE read_range;
2018-02-08 00:17:09 +01:00
d3d12_uniform_t* mapped_ubo;
2022-05-16 22:26:46 +02:00
read_range.Begin = 0;
read_range.End = 0;
2018-02-08 00:17:09 +01:00
D3D12Map(d3d12->ubo, 0, &read_range, (void**)&mapped_ubo);
*mapped_ubo = d3d12->ubo_values;
D3D12Unmap(d3d12->ubo, 0, NULL);
}
cmd->lpVtbl->SetGraphicsRootConstantBufferView(cmd, ROOT_ID_UBO,
2023-01-08 18:31:04 +01:00
d3d12->ubo_view.BufferLocation);
2018-02-08 00:17:09 +01:00
}
void gfx_display_d3d12_scissor_begin(void *data,
unsigned video_width, unsigned video_height,
int x, int y, unsigned width, unsigned height)
2019-01-28 19:31:27 +01:00
{
2019-04-08 15:22:21 +02:00
D3D12_RECT rect;
D3D12GraphicsCommandList cmd;
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
2019-01-28 19:31:27 +01:00
if (!d3d12)
2019-01-28 19:31:27 +01:00
return;
cmd = d3d12->queue.cmd;
2019-04-08 15:22:21 +02:00
rect.left = x;
rect.top = y;
rect.right = width + x;
rect.bottom = height + y;
cmd->lpVtbl->RSSetScissorRects(cmd, 1, &rect);
2019-01-28 19:31:27 +01:00
}
void gfx_display_d3d12_scissor_end(void *data,
unsigned video_width,
unsigned video_height)
2019-01-28 19:31:27 +01:00
{
2019-04-08 15:22:21 +02:00
D3D12_RECT rect;
D3D12GraphicsCommandList cmd;
d3d12_video_t *d3d12 = (d3d12_video_t*)data;
2019-01-28 19:31:27 +01:00
if (!d3d12)
return;
cmd = d3d12->queue.cmd;
2019-04-10 00:22:36 -04:00
rect.left = 0;
rect.top = 0;
2020-03-08 01:28:15 +01:00
rect.right = video_width;
rect.bottom = video_height;
2019-01-28 19:31:27 +01:00
cmd->lpVtbl->RSSetScissorRects(cmd, 1, &rect);
2019-01-28 19:31:27 +01:00
}
2020-02-16 15:10:07 +01:00
gfx_display_ctx_driver_t gfx_display_ctx_d3d12 = {
gfx_display_d3d12_draw,
gfx_display_d3d12_draw_pipeline,
gfx_display_d3d12_blend_begin,
gfx_display_d3d12_blend_end,
2020-09-26 21:40:16 +02:00
NULL, /* get_default_mvp */
NULL, /* get_default_vertices */
NULL, /* get_default_tex_coords */
FONT_DRIVER_RENDER_D3D12_API,
2020-02-16 15:10:07 +01:00
GFX_VIDEO_DRIVER_DIRECT3D12,
"d3d12",
true,
2020-02-16 15:10:07 +01:00
gfx_display_d3d12_scissor_begin,
gfx_display_d3d12_scissor_end
2018-02-08 00:17:09 +01:00
};