diff --git a/Makefile.msvc b/Makefile.msvc index db4c836216..1807342397 100644 --- a/Makefile.msvc +++ b/Makefile.msvc @@ -253,6 +253,7 @@ $(BUILD_DIR)/$(TARGET): $(OBJ) .$(TARGET).last %.depend: ; %.last: ; +%.h : ; clean: rm -f $(OBJ) $(TARGET) diff --git a/gfx/common/d3d10_common.h b/gfx/common/d3d10_common.h index f347c664b9..73997eb606 100644 --- a/gfx/common/d3d10_common.h +++ b/gfx/common/d3d10_common.h @@ -1073,6 +1073,9 @@ static inline HRESULT D3D10CreateTexture2DShaderResourceView( /* internal */ +#include +#include +#include "gfx/video_driver.h" #include typedef struct d3d10_vertex_t @@ -1099,13 +1102,22 @@ typedef struct D3D10Device device; D3D10RenderTargetView renderTargetView; D3D10InputLayout layout; + D3D10Buffer ubo; D3D10VertexShader vs; D3D10PixelShader ps; D3D10SamplerState sampler_nearest; D3D10SamplerState sampler_linear; D3D10BlendState blend_enable; D3D10BlendState blend_disable; + math_matrix_4x4 mvp, mvp_no_rot; + struct video_viewport vp; + D3D10_VIEWPORT viewport; + DXGI_FORMAT format; float clearcolor[4]; + bool vsync; + bool resize_chain; + bool keep_aspect; + bool resize_viewport; struct { d3d10_texture_t texture; @@ -1118,12 +1130,11 @@ typedef struct { d3d10_texture_t texture; D3D10Buffer vbo; + D3D10Buffer ubo; D3D10SamplerState sampler; + D3D10_VIEWPORT viewport; + int rotation; } frame; - DXGI_FORMAT format; - - bool vsync; - bool need_resize; } d3d10_video_t; void d3d10_init_texture(D3D10Device device, d3d10_texture_t* texture); diff --git a/gfx/common/d3d11_common.h b/gfx/common/d3d11_common.h index 8f2f561fda..e42e9ff056 100644 --- a/gfx/common/d3d11_common.h +++ b/gfx/common/d3d11_common.h @@ -2449,6 +2449,11 @@ D3D11UnmapBuffer(D3D11DeviceContext device_context, D3D11Buffer buffer, UINT sub device_context->lpVtbl->Unmap(device_context, (D3D11Resource)buffer, subresource); } + /* internal */ + +#include +#include +#include "gfx/video_driver.h" #include #include @@ -2477,13 +2482,22 @@ typedef struct D3D11DeviceContext ctx; D3D11RenderTargetView renderTargetView; D3D11InputLayout layout; + D3D11Buffer ubo; D3D11VertexShader vs; D3D11PixelShader ps; D3D11SamplerState sampler_nearest; D3D11SamplerState sampler_linear; D3D11BlendState blend_enable; D3D11BlendState blend_disable; + math_matrix_4x4 mvp, mvp_no_rot; + struct video_viewport vp; + D3D11_VIEWPORT viewport; + DXGI_FORMAT format; float clearcolor[4]; + bool vsync; + bool resize_chain; + bool keep_aspect; + bool resize_viewport; struct { d3d11_texture_t texture; @@ -2496,12 +2510,11 @@ typedef struct { d3d11_texture_t texture; D3D11Buffer vbo; + D3D11Buffer ubo; D3D11SamplerState sampler; + D3D11_VIEWPORT viewport; + int rotation; } frame; - DXGI_FORMAT format; - - bool vsync; - bool need_resize; } d3d11_video_t; void d3d11_init_texture(D3D11Device device, d3d11_texture_t* texture); diff --git a/gfx/common/d3d12_common.c b/gfx/common/d3d12_common.c index 2e292a7bec..abe3aec3c8 100644 --- a/gfx/common/d3d12_common.c +++ b/gfx/common/d3d12_common.c @@ -305,17 +305,26 @@ bool d3d12_init_descriptors(d3d12_video_t* d3d12) }, }; - static const D3D12_ROOT_PARAMETER rootParameters[] = { - { - .ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - .DescriptorTable = { countof(srv_table), srv_table }, - .ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL, - }, - { - .ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - .DescriptorTable = { countof(sampler_table), sampler_table }, - .ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL, - }, + static const D3D12_ROOT_PARAMETER rootParameters[ROOT_INDEX_MAX] = { + [ROOT_INDEX_TEXTURE_TABLE] = + { + .ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + .DescriptorTable = { countof(srv_table), srv_table }, + .ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL, + }, + [ROOT_INDEX_SAMPLER_TABLE] = + { + .ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + .DescriptorTable = { countof(sampler_table), sampler_table }, + .ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL, + }, + [ROOT_INDEX_UBO] = + { + .ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV, + .Descriptor.ShaderRegister = 0, + .Descriptor.RegisterSpace = 0, + .ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX, + }, }; static const D3D12_ROOT_SIGNATURE_DESC desc = { .NumParameters = countof(rootParameters), @@ -454,8 +463,8 @@ bool d3d12_init_pipeline(d3d12_video_t* d3d12) return true; } -void d3d12_create_vertex_buffer( - D3D12Device device, D3D12_VERTEX_BUFFER_VIEW* view, D3D12Resource* vbo) +D3D12_GPU_VIRTUAL_ADDRESS +d3d12_create_buffer(D3D12Device device, UINT size_in_bytes, D3D12Resource* buffer) { static const D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD, @@ -465,7 +474,7 @@ void d3d12_create_vertex_buffer( D3D12_RESOURCE_DESC resource_desc = { .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER, - .Width = view->SizeInBytes, + .Width = size_in_bytes, .Height = 1, .DepthOrArraySize = 1, .MipLevels = 1, @@ -475,8 +484,9 @@ void d3d12_create_vertex_buffer( D3D12CreateCommittedResource( device, (D3D12_HEAP_PROPERTIES*)&heap_props, D3D12_HEAP_FLAG_NONE, &resource_desc, - D3D12_RESOURCE_STATE_GENERIC_READ, NULL, vbo); - view->BufferLocation = D3D12GetGPUVirtualAddress(*vbo); + D3D12_RESOURCE_STATE_GENERIC_READ, NULL, buffer); + + return D3D12GetGPUVirtualAddress(*buffer); } void d3d12_init_texture( @@ -565,15 +575,15 @@ void d3d12_create_fullscreen_quad_vbo( D3D12Device device, D3D12_VERTEX_BUFFER_VIEW* view, D3D12Resource* vbo) { static const d3d12_vertex_t vertices[] = { - { { -1.0f, -1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { -1.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { 1.0f, -1.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, }; - view->SizeInBytes = sizeof(vertices); - view->StrideInBytes = sizeof(*vertices); - d3d12_create_vertex_buffer(device, view, vbo); + view->SizeInBytes = sizeof(vertices); + view->StrideInBytes = sizeof(*vertices); + view->BufferLocation = d3d12_create_buffer(device, view->SizeInBytes, vbo); { void* vertex_data_begin; diff --git a/gfx/common/d3d12_common.h b/gfx/common/d3d12_common.h index ec8902b25c..6a56b17434 100644 --- a/gfx/common/d3d12_common.h +++ b/gfx/common/d3d12_common.h @@ -1285,7 +1285,11 @@ D3D12GetGPUDescriptorHandleForHeapStart(D3D12DescriptorHeap descriptor_heap) } #endif -/* internal */ + /* internal */ + +#include +#include +#include "gfx/video_driver.h" typedef struct d3d12_vertex_t { @@ -1316,6 +1320,7 @@ typedef struct UINT64 total_bytes; bool dirty; } d3d12_texture_t; + typedef struct { unsigned cur_mon_id; @@ -1356,10 +1361,15 @@ typedef struct struct { - D3D12Resource vbo; - D3D12_VERTEX_BUFFER_VIEW vbo_view; - d3d12_texture_t texture; - D3D12_GPU_DESCRIPTOR_HANDLE sampler; + D3D12Resource ubo; + D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_view; + D3D12Resource vbo; + D3D12_VERTEX_BUFFER_VIEW vbo_view; + d3d12_texture_t texture; + D3D12_GPU_DESCRIPTOR_HANDLE sampler; + D3D12_VIEWPORT viewport; + D3D12_RECT scissorRect; + int rotation; } frame; struct @@ -1374,10 +1384,16 @@ typedef struct bool fullscreen; } menu; - DXGI_FORMAT format; - D3D12_GPU_DESCRIPTOR_HANDLE sampler_linear; - D3D12_GPU_DESCRIPTOR_HANDLE sampler_nearest; - bool need_resize; + D3D12Resource ubo; + D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_view; + DXGI_FORMAT format; + D3D12_GPU_DESCRIPTOR_HANDLE sampler_linear; + D3D12_GPU_DESCRIPTOR_HANDLE sampler_nearest; + math_matrix_4x4 mvp, mvp_no_rot; + struct video_viewport vp; + bool resize_chain; + bool keep_aspect; + bool resize_viewport; #ifdef DEBUG D3D12Debug debugController; @@ -1386,9 +1402,12 @@ typedef struct enum { - DESC_TABLE_INDEX_SRV_TEXTURE = 0, - DESC_TABLE_INDEX_SAMPLER, -}; + ROOT_INDEX_TEXTURE_TABLE = 0, + ROOT_INDEX_SAMPLER_TABLE, + ROOT_INDEX_UBO, + ROOT_INDEX_MAX, +} root_signature_parameter_index_t; + typedef enum { SAMPLER_HEAP_SLOT_LINEAR = 0, SAMPLER_HEAP_SLOT_NEAREST, @@ -1406,8 +1425,8 @@ bool d3d12_init_pipeline(d3d12_video_t* d3d12); bool d3d12_init_swapchain(d3d12_video_t* d3d12, int width, int height, HWND hwnd); bool d3d12_init_queue(d3d12_video_t* d3d12); -void d3d12_create_vertex_buffer( - D3D12Device device, D3D12_VERTEX_BUFFER_VIEW* view, D3D12Resource* vbo); +D3D12_GPU_VIRTUAL_ADDRESS +d3d12_create_buffer(D3D12Device device, UINT size_in_bytes, D3D12Resource* buffer); void d3d12_init_texture( D3D12Device device, @@ -1439,13 +1458,13 @@ static inline void d3d12_resource_transition( static inline void d3d12_set_texture(D3D12GraphicsCommandList cmd, const d3d12_texture_t* texture) { - D3D12SetGraphicsRootDescriptorTable(cmd, DESC_TABLE_INDEX_SRV_TEXTURE, texture->gpu_descriptor); + D3D12SetGraphicsRootDescriptorTable(cmd, ROOT_INDEX_TEXTURE_TABLE, texture->gpu_descriptor); } static inline void d3d12_set_sampler(D3D12GraphicsCommandList cmd, D3D12_GPU_DESCRIPTOR_HANDLE sampler) { - D3D12SetGraphicsRootDescriptorTable(cmd, DESC_TABLE_INDEX_SAMPLER, sampler); + D3D12SetGraphicsRootDescriptorTable(cmd, ROOT_INDEX_SAMPLER_TABLE, sampler); } static inline void d3d12_update_texture( diff --git a/gfx/drivers/d3d10.c b/gfx/drivers/d3d10.c index ab86d184cc..45d6386c98 100644 --- a/gfx/drivers/d3d10.c +++ b/gfx/drivers/d3d10.c @@ -25,6 +25,48 @@ #include "gfx/common/dxgi_common.h" #include "gfx/common/d3dcompiler_common.h" +static void d3d10_set_filtering(void* data, unsigned index, bool smooth) +{ + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (smooth) + d3d10->frame.sampler = d3d10->sampler_linear; + else + d3d10->frame.sampler = d3d10->sampler_nearest; +} + +static void d3d10_gfx_set_rotation(void* data, unsigned rotation) +{ + math_matrix_4x4 rot; + math_matrix_4x4* mvp; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + d3d10->frame.rotation = 3 * rotation; + + matrix_4x4_rotate_z(rot, d3d10->frame.rotation * (M_PI / 2.0f)); + matrix_4x4_multiply(d3d10->mvp, rot, d3d10->mvp_no_rot); + + D3D10MapBuffer(d3d10->frame.ubo, D3D10_MAP_WRITE_DISCARD, 0, (void**)&mvp); + *mvp = d3d10->mvp; + D3D10UnmapBuffer(d3d10->frame.ubo); +} + +static void d3d10_update_viewport(void* data, bool force_full) +{ + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + video_driver_update_viewport(&d3d10->vp, force_full, d3d10->keep_aspect); + + d3d10->frame.viewport.TopLeftX = (float)d3d10->vp.x; + d3d10->frame.viewport.TopLeftY = (float)d3d10->vp.y; + d3d10->frame.viewport.Width = (float)d3d10->vp.width; + d3d10->frame.viewport.Height = (float)d3d10->vp.height; + d3d10->frame.viewport.MaxDepth = 0.0f; + d3d10->frame.viewport.MaxDepth = 1.0f; + + d3d10->resize_viewport = false; +} + static void* d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data) { @@ -56,8 +98,10 @@ d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** i .BufferDesc.Width = video->width, .BufferDesc.Height = video->height, .BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM, - // .BufferDesc.RefreshRate.Numerator = 60, - // .BufferDesc.RefreshRate.Denominator = 1, +#if 0 + .BufferDesc.RefreshRate.Numerator = 60, + .BufferDesc.RefreshRate.Denominator = 1, +#endif .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT, .OutputWindow = main_window.hwnd, .SampleDesc.Count = 1, @@ -65,9 +109,9 @@ d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** i .Windowed = TRUE, .SwapEffect = DXGI_SWAP_EFFECT_DISCARD, #if 0 - .SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL, - .SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, - .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD, + .SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL, + .SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, + .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD, #endif }; @@ -89,19 +133,26 @@ d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** i } D3D10SetRenderTargets(d3d10->device, 1, &d3d10->renderTargetView, NULL); + d3d10->vp.full_width = video->width; + d3d10->vp.full_height = video->height; + d3d10->viewport.Width = video->width; + d3d10->viewport.Height = video->height; + d3d10->resize_viewport = true; + + matrix_4x4_ortho(d3d10->mvp_no_rot, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); { - D3D10_VIEWPORT vp = { 0, 0, video->width, video->height, 0.0f, 1.0f }; - D3D10SetViewports(d3d10->device, 1, &vp); + D3D10_BUFFER_DESC desc = { + .ByteWidth = sizeof(math_matrix_4x4), + .Usage = D3D10_USAGE_DYNAMIC, + .BindFlags = D3D10_BIND_CONSTANT_BUFFER, + .CPUAccessFlags = D3D10_CPU_ACCESS_WRITE, + }; + D3D10_SUBRESOURCE_DATA ubo_data = { &d3d10->mvp_no_rot }; + D3D10CreateBuffer(d3d10->device, &desc, &ubo_data, &d3d10->ubo); + D3D10CreateBuffer(d3d10->device, &desc, NULL, &d3d10->frame.ubo); } - - d3d10->vsync = video->vsync; - d3d10->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; - - d3d10->frame.texture.desc.Format = - d3d10_get_closest_match_texture2D(d3d10->device, d3d10->format); - d3d10->frame.texture.desc.Usage = D3D10_USAGE_DEFAULT; - d3d10->menu.texture.desc.Usage = D3D10_USAGE_DEFAULT; + d3d10_gfx_set_rotation(d3d10, 0); { D3D10_SAMPLER_DESC desc = { @@ -120,11 +171,22 @@ d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** i D3D10CreateSamplerState(d3d10->device, &desc, &d3d10->sampler_linear); } + d3d10_set_filtering(d3d10, 0, video->smooth); + + d3d10->keep_aspect = video->force_aspect; + d3d10->vsync = video->vsync; + d3d10->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; + + d3d10->frame.texture.desc.Format = + d3d10_get_closest_match_texture2D(d3d10->device, d3d10->format); + d3d10->frame.texture.desc.Usage = D3D10_USAGE_DEFAULT; + d3d10->menu.texture.desc.Usage = D3D10_USAGE_DEFAULT; + { d3d10_vertex_t vertices[] = { - { { -1.0f, -1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { -1.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { 1.0f, -1.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, }; @@ -218,10 +280,9 @@ static bool d3d10_gfx_frame( d3d10_video_t* d3d10 = (d3d10_video_t*)data; - if (d3d10->need_resize) + if (d3d10->resize_chain) { D3D10Texture2D backBuffer; - D3D10_VIEWPORT vp = { 0, 0, video_info->width, video_info->height, 0.0f, 1.0f }; Release(d3d10->renderTargetView); DXGIResizeBuffers(d3d10->swapChain, 0, 0, 0, 0, 0); @@ -232,9 +293,11 @@ static bool d3d10_gfx_frame( Release(backBuffer); D3D10SetRenderTargets(d3d10->device, 1, &d3d10->renderTargetView, NULL); - D3D10SetViewports(d3d10->device, 1, &vp); + d3d10->viewport.Width = video_info->width; + d3d10->viewport.Height = video_info->height; - d3d10->need_resize = false; + d3d10->resize_chain = false; + d3d10->resize_viewport = true; } PERF_START(); @@ -260,24 +323,34 @@ static bool d3d10_gfx_frame( { UINT stride = sizeof(d3d10_vertex_t); UINT offset = 0; +#if 0 /* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */ + if (d3d10->resize_viewport) +#endif + d3d10_update_viewport(d3d10, false); + + D3D10SetViewports(d3d10->device, 1, &d3d10->frame.viewport); D3D10SetVertexBuffers(d3d10->device, 0, 1, &d3d10->frame.vbo, &stride, &offset); + D3D10SetVShaderConstantBuffers(d3d10->device, 0, 1, &d3d10->frame.ubo); D3D10SetPShaderResources(d3d10->device, 0, 1, &d3d10->frame.texture.view); - D3D10SetPShaderSamplers(d3d10->device, 0, 1, &d3d10->sampler_linear); + D3D10SetPShaderSamplers(d3d10->device, 0, 1, &d3d10->frame.sampler); D3D10SetBlendState(d3d10->device, d3d10->blend_disable, NULL, D3D10_DEFAULT_SAMPLE_MASK); D3D10Draw(d3d10->device, 4, 0); D3D10SetBlendState(d3d10->device, d3d10->blend_enable, NULL, D3D10_DEFAULT_SAMPLE_MASK); - if (d3d10->menu.enabled) + if (d3d10->menu.enabled && d3d10->menu.texture.handle) { if (d3d10->menu.texture.dirty) D3D10CopyTexture2DSubresourceRegion( d3d10->device, d3d10->menu.texture.handle, 0, 0, 0, 0, d3d10->menu.texture.staging, 0, NULL); + if (d3d10->menu.fullscreen) + D3D10SetViewports(d3d10->device, 1, &d3d10->viewport); D3D10SetVertexBuffers(d3d10->device, 0, 1, &d3d10->menu.vbo, &stride, &offset); + D3D10SetVShaderConstantBuffers(d3d10->device, 0, 1, &d3d10->ubo); D3D10SetPShaderResources(d3d10->device, 0, 1, &d3d10->menu.texture.view); - D3D10SetPShaderSamplers(d3d10->device, 0, 1, &d3d10->sampler_linear); + D3D10SetPShaderSamplers(d3d10->device, 0, 1, &d3d10->menu.sampler); D3D10Draw(d3d10->device, 4, 0); } @@ -300,18 +373,13 @@ static void d3d10_gfx_set_nonblock_state(void* data, bool toggle) static bool d3d10_gfx_alive(void* data) { - (void)data; - bool quit; - bool resize; - unsigned width; - unsigned height; - + bool quit; d3d10_video_t* d3d10 = (d3d10_video_t*)data; - win32_check_window(&quit, &d3d10->need_resize, &width, &height); + win32_check_window(&quit, &d3d10->resize_chain, &d3d10->vp.full_width, &d3d10->vp.full_height); - if (width != 0 && height != 0) - video_driver_set_size(&width, &height); + if (d3d10->resize_chain && d3d10->vp.full_width != 0 && d3d10->vp.full_height != 0) + video_driver_set_size(&d3d10->vp.full_width, &d3d10->vp.full_height); return !quit; } @@ -335,16 +403,18 @@ static void d3d10_gfx_free(void* data) { d3d10_video_t* d3d10 = (d3d10_video_t*)data; + Release(d3d10->frame.ubo); + Release(d3d10->frame.vbo); Release(d3d10->frame.texture.view); Release(d3d10->frame.texture.handle); Release(d3d10->frame.texture.staging); - Release(d3d10->frame.vbo); Release(d3d10->menu.texture.handle); Release(d3d10->menu.texture.staging); Release(d3d10->menu.texture.view); Release(d3d10->menu.vbo); + Release(d3d10->ubo); Release(d3d10->blend_enable); Release(d3d10->blend_disable); Release(d3d10->sampler_nearest); @@ -370,16 +440,11 @@ static bool d3d10_gfx_set_shader(void* data, enum rarch_shader_type type, const return false; } -static void d3d10_gfx_set_rotation(void* data, unsigned rotation) -{ - (void)data; - (void)rotation; -} - static void d3d10_gfx_viewport_info(void* data, struct video_viewport* vp) { - (void)data; - (void)vp; + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + *vp = d3d10->vp; } static bool d3d10_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle) @@ -406,6 +471,8 @@ static void d3d10_set_menu_texture_frame( } d3d10_update_texture(width, height, pitch, format, frame, &d3d10->menu.texture); + d3d10->menu.sampler = config_get_ptr()->bools.menu_linear_filter ? d3d10->sampler_linear + : d3d10->sampler_nearest; } static void d3d10_set_menu_texture_enable(void* data, bool state, bool full_screen) { @@ -415,28 +482,47 @@ static void d3d10_set_menu_texture_enable(void* data, bool state, bool full_scre d3d10->menu.fullscreen = full_screen; } +static void d3d10_gfx_set_aspect_ratio(void* data, unsigned aspect_ratio_idx) +{ + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + if (!d3d10) + return; + + d3d10->keep_aspect = true; + d3d10->resize_viewport = true; +} + +static void d3d10_gfx_apply_state_changes(void* data) +{ + d3d10_video_t* d3d10 = (d3d10_video_t*)data; + + // if (d3d10) + // d3d10->resize_viewport = true; +} + static const video_poke_interface_t d3d10_poke_interface = { - NULL, /* set_coords */ - NULL, /* set_mvp */ - NULL, /* load_texture */ - NULL, /* unload_texture */ - NULL, /* set_video_mode */ - NULL, /* set_filtering */ - NULL, /* get_video_output_size */ - NULL, /* get_video_output_prev */ - NULL, /* get_video_output_next */ - NULL, /* get_current_framebuffer */ - NULL, /* get_proc_address */ - NULL, /* set_aspect_ratio */ - NULL, /* apply_state_changes */ - d3d10_set_menu_texture_frame, /* set_texture_frame */ - d3d10_set_menu_texture_enable, /* set_texture_enable */ - NULL, /* set_osd_msg */ - NULL, /* show_mouse */ - NULL, /* grab_mouse_toggle */ - NULL, /* get_current_shader */ - NULL, /* get_current_software_framebuffer */ - NULL, /* get_hw_render_interface */ + NULL, /* set_coords */ + NULL, /* set_mvp */ + NULL, /* load_texture */ + NULL, /* unload_texture */ + NULL, /* set_video_mode */ + d3d10_set_filtering, + NULL, /* get_video_output_size */ + NULL, /* get_video_output_prev */ + NULL, /* get_video_output_next */ + NULL, /* get_current_framebuffer */ + NULL, /* get_proc_address */ + d3d10_gfx_set_aspect_ratio, + d3d10_gfx_apply_state_changes, + d3d10_set_menu_texture_frame, + d3d10_set_menu_texture_enable, + NULL, /* set_osd_msg */ + NULL, /* show_mouse */ + NULL, /* grab_mouse_toggle */ + NULL, /* get_current_shader */ + NULL, /* get_current_software_framebuffer */ + NULL, /* get_hw_render_interface */ }; static void d3d10_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface) diff --git a/gfx/drivers/d3d11.c b/gfx/drivers/d3d11.c index 303c43803e..f79c2e69d9 100644 --- a/gfx/drivers/d3d11.c +++ b/gfx/drivers/d3d11.c @@ -28,6 +28,49 @@ #include "../common/d3dcompiler_common.h" #include "../../performance_counters.h" +static void d3d11_set_filtering(void* data, unsigned index, bool smooth) +{ + d3d11_video_t* d3d11 = (d3d11_video_t*)data; + + if (smooth) + d3d11->frame.sampler = d3d11->sampler_linear; + else + d3d11->frame.sampler = d3d11->sampler_nearest; +} + +static void d3d11_gfx_set_rotation(void* data, unsigned rotation) +{ + math_matrix_4x4 rot; + math_matrix_4x4* mvp; + d3d11_video_t* d3d11 = (d3d11_video_t*)data; + + d3d11->frame.rotation = 3 * rotation; + + matrix_4x4_rotate_z(rot, d3d11->frame.rotation * (M_PI / 2.0f)); + matrix_4x4_multiply(d3d11->mvp, rot, d3d11->mvp_no_rot); + + D3D11_MAPPED_SUBRESOURCE mapped_ubo; + D3D11MapBuffer(d3d11->ctx, d3d11->frame.ubo, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_ubo); + *(math_matrix_4x4*)mapped_ubo.pData = d3d11->mvp; + D3D11UnmapBuffer(d3d11->ctx, d3d11->frame.ubo, 0); +} + +static void d3d11_update_viewport(void* data, bool force_full) +{ + d3d11_video_t* d3d11 = (d3d11_video_t*)data; + + video_driver_update_viewport(&d3d11->vp, force_full, d3d11->keep_aspect); + + d3d11->frame.viewport.TopLeftX = (float)d3d11->vp.x; + d3d11->frame.viewport.TopLeftY = (float)d3d11->vp.y; + d3d11->frame.viewport.Width = (float)d3d11->vp.width; + d3d11->frame.viewport.Height = (float)d3d11->vp.height; + d3d11->frame.viewport.MaxDepth = 0.0f; + d3d11->frame.viewport.MaxDepth = 1.0f; + + d3d11->resize_viewport = false; +} + static void* d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data) { @@ -95,11 +138,11 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i D3D11SetRenderTargets(d3d11->ctx, 1, &d3d11->renderTargetView, NULL); - { - D3D11_VIEWPORT vp = { 0, 0, video->width, video->height, 0.0f, 1.0f }; - D3D11SetViewports(d3d11->ctx, 1, &vp); - } - + d3d11->vp.full_width = video->width; + d3d11->vp.full_height = video->height; + d3d11->viewport.Width = video->width; + d3d11->viewport.Height = video->height; + d3d11->resize_viewport = true; d3d11->vsync = video->vsync; d3d11->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; @@ -110,6 +153,21 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i d3d11->menu.texture.desc.Format = DXGI_FORMAT_B4G4R4A4_UNORM; d3d11->menu.texture.desc.Usage = D3D11_USAGE_DEFAULT; + matrix_4x4_ortho(d3d11->mvp_no_rot, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); + + { + D3D11_BUFFER_DESC desc = { + .ByteWidth = sizeof(math_matrix_4x4), + .Usage = D3D11_USAGE_DYNAMIC, + .BindFlags = D3D11_BIND_CONSTANT_BUFFER, + .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE, + }; + D3D11_SUBRESOURCE_DATA ubo_data = { &d3d11->mvp_no_rot }; + D3D11CreateBuffer(d3d11->device, &desc, &ubo_data, &d3d11->ubo); + D3D11CreateBuffer(d3d11->device, &desc, NULL, &d3d11->frame.ubo); + } + d3d11_gfx_set_rotation(d3d11, 0); + { D3D11_SAMPLER_DESC desc = { .Filter = D3D11_FILTER_MIN_MAG_MIP_POINT, @@ -127,11 +185,13 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i D3D11CreateSamplerState(d3d11->device, &desc, &d3d11->sampler_linear); } + d3d11_set_filtering(d3d11, 0, video->smooth); + { d3d11_vertex_t vertices[] = { - { { -1.0f, -1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { -1.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { 1.0f, -1.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, { { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, }; @@ -144,11 +204,10 @@ d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** i .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE, }; D3D11_SUBRESOURCE_DATA vertexData = { vertices }; - D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->frame.vbo); + D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->menu.vbo); desc.Usage = D3D11_USAGE_IMMUTABLE; desc.CPUAccessFlags = 0; - - D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->menu.vbo); + D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->frame.vbo); } D3D11SetPrimitiveTopology(d3d11->ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); } @@ -231,10 +290,9 @@ static bool d3d11_gfx_frame( { d3d11_video_t* d3d11 = (d3d11_video_t*)data; - if (d3d11->need_resize) + if (d3d11->resize_chain) { D3D11Texture2D backBuffer; - D3D11_VIEWPORT vp = { 0, 0, video_info->width, video_info->height, 0.0f, 1.0f }; Release(d3d11->renderTargetView); DXGIResizeBuffers(d3d11->swapChain, 0, 0, 0, 0, 0); @@ -245,9 +303,11 @@ static bool d3d11_gfx_frame( Release(backBuffer); D3D11SetRenderTargets(d3d11->ctx, 1, &d3d11->renderTargetView, NULL); - D3D11SetViewports(d3d11->ctx, 1, &vp); + d3d11->viewport.Width = video_info->width; + d3d11->viewport.Height = video_info->height; - d3d11->need_resize = false; + d3d11->resize_chain = false; + d3d11->resize_viewport = true; } PERF_START(); @@ -274,9 +334,17 @@ static bool d3d11_gfx_frame( { UINT stride = sizeof(d3d11_vertex_t); UINT offset = 0; + +#if 0 /* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */ + if (d3d11->resize_viewport) +#endif + d3d11_update_viewport(d3d11, false); + + D3D11SetViewports(d3d11->ctx, 1, &d3d11->frame.viewport); D3D11SetVertexBuffers(d3d11->ctx, 0, 1, &d3d11->frame.vbo, &stride, &offset); + D3D11SetVShaderConstantBuffers(d3d11->ctx, 0, 1, &d3d11->frame.ubo); D3D11SetPShaderResources(d3d11->ctx, 0, 1, &d3d11->frame.texture.view); - D3D11SetPShaderSamplers(d3d11->ctx, 0, 1, &d3d11->sampler_linear); + D3D11SetPShaderSamplers(d3d11->ctx, 0, 1, &d3d11->frame.sampler); D3D11SetBlendState(d3d11->ctx, d3d11->blend_disable, NULL, D3D11_DEFAULT_SAMPLE_MASK); D3D11Draw(d3d11->ctx, 4, 0); @@ -289,9 +357,12 @@ static bool d3d11_gfx_frame( d3d11->ctx, d3d11->menu.texture.handle, 0, 0, 0, 0, d3d11->menu.texture.staging, 0, NULL); + if (d3d11->menu.fullscreen) + D3D11SetViewports(d3d11->ctx, 1, &d3d11->viewport); D3D11SetVertexBuffers(d3d11->ctx, 0, 1, &d3d11->menu.vbo, &stride, &offset); + D3D11SetVShaderConstantBuffers(d3d11->ctx, 0, 1, &d3d11->ubo); D3D11SetPShaderResources(d3d11->ctx, 0, 1, &d3d11->menu.texture.view); - D3D11SetPShaderSamplers(d3d11->ctx, 0, 1, &d3d11->sampler_linear); + D3D11SetPShaderSamplers(d3d11->ctx, 0, 1, &d3d11->menu.sampler); D3D11Draw(d3d11->ctx, 4, 0); } @@ -318,17 +389,13 @@ static void d3d11_gfx_set_nonblock_state(void* data, bool toggle) static bool d3d11_gfx_alive(void* data) { - bool quit; - bool resize; - unsigned width; - unsigned height; - + bool quit; d3d11_video_t* d3d11 = (d3d11_video_t*)data; - win32_check_window(&quit, &d3d11->need_resize, &width, &height); + win32_check_window(&quit, &d3d11->resize_chain, &d3d11->vp.full_width, &d3d11->vp.full_height); - if (width != 0 && height != 0) - video_driver_set_size(&width, &height); + if (d3d11->resize_chain && d3d11->vp.full_width != 0 && d3d11->vp.full_height != 0) + video_driver_set_size(&d3d11->vp.full_width, &d3d11->vp.full_height); return !quit; } @@ -355,6 +422,7 @@ static void d3d11_gfx_free(void* data) if (!d3d11) return; + Release(d3d11->frame.ubo); Release(d3d11->frame.texture.view); Release(d3d11->frame.texture.handle); Release(d3d11->frame.texture.staging); @@ -365,6 +433,7 @@ static void d3d11_gfx_free(void* data) Release(d3d11->menu.texture.view); Release(d3d11->menu.vbo); + Release(d3d11->ubo); Release(d3d11->blend_enable); Release(d3d11->blend_disable); Release(d3d11->sampler_nearest); @@ -391,16 +460,11 @@ static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const return false; } -static void d3d11_gfx_set_rotation(void* data, unsigned rotation) -{ - (void)data; - (void)rotation; -} - static void d3d11_gfx_viewport_info(void* data, struct video_viewport* vp) { - (void)data; - (void)vp; + d3d11_video_t* d3d11 = (d3d11_video_t*)data; + + *vp = d3d11->vp; } static bool d3d11_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle) @@ -427,6 +491,8 @@ static void d3d11_set_menu_texture_frame( } d3d11_update_texture(d3d11->ctx, width, height, pitch, format, frame, &d3d11->menu.texture); + d3d11->menu.sampler = config_get_ptr()->bools.menu_linear_filter ? d3d11->sampler_linear + : d3d11->sampler_nearest; } static void d3d11_set_menu_texture_enable(void* data, bool state, bool full_screen) { @@ -439,28 +505,47 @@ static void d3d11_set_menu_texture_enable(void* data, bool state, bool full_scre d3d11->menu.fullscreen = full_screen; } +static void d3d11_gfx_set_aspect_ratio(void* data, unsigned aspect_ratio_idx) +{ + d3d11_video_t* d3d11 = (d3d11_video_t*)data; + + if (!d3d11) + return; + + d3d11->keep_aspect = true; + d3d11->resize_viewport = true; +} + +static void d3d11_gfx_apply_state_changes(void* data) +{ + d3d11_video_t* d3d11 = (d3d11_video_t*)data; + + if (d3d11) + d3d11->resize_viewport = true; +} + static const video_poke_interface_t d3d11_poke_interface = { - NULL, /* set_coords */ - NULL, /* set_mvp */ - NULL, /* load_texture */ - NULL, /* unload_texture */ - NULL, /* set_video_mode */ - NULL, /* set_filtering */ - NULL, /* get_video_output_size */ - NULL, /* get_video_output_prev */ - NULL, /* get_video_output_next */ - NULL, /* get_current_framebuffer */ - NULL, /* get_proc_address */ - NULL, /* set_aspect_ratio */ - NULL, /* apply_state_changes */ - d3d11_set_menu_texture_frame, /* set_texture_frame */ - d3d11_set_menu_texture_enable, /* set_texture_enable */ - NULL, /* set_osd_msg */ - NULL, /* show_mouse */ - NULL, /* grab_mouse_toggle */ - NULL, /* get_current_shader */ - NULL, /* get_current_software_framebuffer */ - NULL, /* get_hw_render_interface */ + NULL, /* set_coords */ + NULL, /* set_mvp */ + NULL, /* load_texture */ + NULL, /* unload_texture */ + NULL, /* set_video_mode */ + d3d11_set_filtering, + NULL, /* get_video_output_size */ + NULL, /* get_video_output_prev */ + NULL, /* get_video_output_next */ + NULL, /* get_current_framebuffer */ + NULL, /* get_proc_address */ + d3d11_gfx_set_aspect_ratio, + d3d11_gfx_apply_state_changes, + d3d11_set_menu_texture_frame, + d3d11_set_menu_texture_enable, + NULL, /* set_osd_msg */ + NULL, /* show_mouse */ + NULL, /* grab_mouse_toggle */ + NULL, /* get_current_shader */ + NULL, /* get_current_software_framebuffer */ + NULL, /* get_hw_render_interface */ }; static void d3d11_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface) diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 29a8c64db2..7c69238155 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -35,6 +35,45 @@ static void d3d12_set_filtering(void* data, unsigned index, bool smooth) d3d12->frame.sampler = d3d12->sampler_nearest; } +static void d3d12_gfx_set_rotation(void* data, unsigned rotation) +{ + math_matrix_4x4 rot; + math_matrix_4x4* mvp; + D3D12_RANGE read_range = { 0, 0 }; + d3d12_video_t* d3d12 = (d3d12_video_t*)data; + + d3d12->frame.rotation = 3 * rotation; + + matrix_4x4_rotate_z(rot, d3d12->frame.rotation * (M_PI / 2.0f)); + matrix_4x4_multiply(d3d12->mvp, rot, d3d12->mvp_no_rot); + + D3D12Map(d3d12->frame.ubo, 0, &read_range, (void**)&mvp); + *mvp = d3d12->mvp; + D3D12Unmap(d3d12->frame.ubo, 0, NULL); +} + +static void d3d12_update_viewport(void* data, bool force_full) +{ + d3d12_video_t* d3d12 = (d3d12_video_t*)data; + + video_driver_update_viewport(&d3d12->vp, force_full, d3d12->keep_aspect); + + d3d12->frame.viewport.TopLeftX = (float)d3d12->vp.x; + d3d12->frame.viewport.TopLeftY = (float)d3d12->vp.y; + d3d12->frame.viewport.Width = (float)d3d12->vp.width; + d3d12->frame.viewport.Height = (float)d3d12->vp.height; + d3d12->frame.viewport.MaxDepth = 0.0f; + d3d12->frame.viewport.MaxDepth = 1.0f; + + /* having to add vp.x and vp.y here doesn't make any sense */ + d3d12->frame.scissorRect.top = 0; + d3d12->frame.scissorRect.left = 0; + d3d12->frame.scissorRect.right = d3d12->vp.x + d3d12->vp.width; + d3d12->frame.scissorRect.bottom = d3d12->vp.y + d3d12->vp.height; + + d3d12->resize_viewport = false; +} + static void* d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data) { @@ -79,9 +118,34 @@ d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** i d3d12_set_filtering(d3d12, 0, video->smooth); + d3d12->keep_aspect = video->force_aspect; d3d12->chain.vsync = video->vsync; d3d12->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; - d3d12->frame.texture.desc.Format = d3d12_get_closest_match_texture2D(d3d12->device, d3d12->format); + d3d12->frame.texture.desc.Format = + d3d12_get_closest_match_texture2D(d3d12->device, d3d12->format); + + d3d12->ubo_view.SizeInBytes = sizeof(math_matrix_4x4); + d3d12->ubo_view.BufferLocation = + d3d12_create_buffer(d3d12->device, d3d12->ubo_view.SizeInBytes, &d3d12->ubo); + + d3d12->frame.ubo_view.SizeInBytes = sizeof(math_matrix_4x4); + d3d12->frame.ubo_view.BufferLocation = + d3d12_create_buffer(d3d12->device, d3d12->frame.ubo_view.SizeInBytes, &d3d12->frame.ubo); + + matrix_4x4_ortho(d3d12->mvp_no_rot, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); + + { + math_matrix_4x4* mvp; + D3D12_RANGE read_range = { 0, 0 }; + D3D12Map(d3d12->ubo, 0, &read_range, (void**)&mvp); + *mvp = d3d12->mvp_no_rot; + D3D12Unmap(d3d12->ubo, 0, NULL); + } + + d3d12_gfx_set_rotation(d3d12, 0); + d3d12->vp.full_width = video->width; + d3d12->vp.full_height = video->height; + d3d12->resize_viewport = true; return d3d12; @@ -103,7 +167,7 @@ static bool d3d12_gfx_frame( { d3d12_video_t* d3d12 = (d3d12_video_t*)data; - if (d3d12->need_resize) + if (d3d12->resize_chain) { int i; @@ -119,16 +183,11 @@ static bool d3d12_gfx_frame( d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]); } - d3d12->chain.viewport.Width = video_info->width; - d3d12->chain.viewport.Height = video_info->height; - d3d12->chain.scissorRect.right = video_info->width; - d3d12->chain.scissorRect.bottom = video_info->height; d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle); - - d3d12->need_resize = false; + d3d12->resize_chain = false; + d3d12->resize_viewport = true; } - PERF_START(); D3D12ResetCommandAllocator(d3d12->queue.allocator); @@ -144,8 +203,6 @@ static bool d3d12_gfx_frame( d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); - D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport); - D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect); D3D12OMSetRenderTargets( d3d12->queue.cmd, 1, &d3d12->chain.desc_handles[d3d12->chain.frame_index], FALSE, NULL); D3D12ClearRenderTargetView( @@ -153,11 +210,9 @@ static bool d3d12_gfx_frame( d3d12->chain.clearcolor, 0, NULL); D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - if (data && width && height) { - if (!d3d12->frame.texture.handle || (d3d12->frame.texture.desc.Width != width) || - (d3d12->frame.texture.desc.Height != height)) + if (d3d12->frame.texture.desc.Width != width || d3d12->frame.texture.desc.Height != height) { d3d12->frame.texture.desc.Width = width; d3d12->frame.texture.desc.Height = height; @@ -169,7 +224,16 @@ static bool d3d12_gfx_frame( d3d12_upload_texture(d3d12->queue.cmd, &d3d12->frame.texture); } +#if 0 /* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */ + if (d3d12->resize_viewport) +#endif + d3d12_update_viewport(d3d12, false); + D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->frame.viewport); + D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->frame.scissorRect); + + D3D12SetGraphicsRootConstantBufferView( + d3d12->queue.cmd, ROOT_INDEX_UBO, d3d12->frame.ubo_view.BufferLocation); d3d12_set_texture(d3d12->queue.cmd, &d3d12->frame.texture); d3d12_set_sampler(d3d12->queue.cmd, d3d12->frame.sampler); D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->frame.vbo_view); @@ -180,6 +244,15 @@ static bool d3d12_gfx_frame( if (d3d12->menu.texture.dirty) d3d12_upload_texture(d3d12->queue.cmd, &d3d12->menu.texture); + D3D12SetGraphicsRootConstantBufferView( + d3d12->queue.cmd, ROOT_INDEX_UBO, d3d12->ubo_view.BufferLocation); + + if (d3d12->menu.fullscreen) + { + D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport); + D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect); + } + d3d12_set_texture(d3d12->queue.cmd, &d3d12->menu.texture); d3d12_set_sampler(d3d12->queue.cmd, d3d12->menu.sampler); D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->menu.vbo_view); @@ -228,18 +301,13 @@ static void d3d12_gfx_set_nonblock_state(void* data, bool toggle) static bool d3d12_gfx_alive(void* data) { - (void)data; - bool quit; - bool resize; - unsigned width; - unsigned height; - + bool quit; d3d12_video_t* d3d12 = (d3d12_video_t*)data; - win32_check_window(&quit, &d3d12->need_resize, &width, &height); + win32_check_window(&quit, &d3d12->resize_chain, &d3d12->vp.full_width, &d3d12->vp.full_height); - if (width != 0 && height != 0) - video_driver_set_size(&width, &height); + if (d3d12->resize_chain && d3d12->vp.full_width != 0 && d3d12->vp.full_height != 0) + video_driver_set_size(&d3d12->vp.full_width, &d3d12->vp.full_height); return !quit; } @@ -263,6 +331,7 @@ static void d3d12_gfx_free(void* data) { d3d12_video_t* d3d12 = (d3d12_video_t*)data; + Release(d3d12->frame.ubo); Release(d3d12->frame.vbo); Release(d3d12->frame.texture.handle); Release(d3d12->frame.texture.upload_buffer); @@ -270,6 +339,7 @@ static void d3d12_gfx_free(void* data) Release(d3d12->menu.texture.handle); Release(d3d12->menu.texture.upload_buffer); + Release(d3d12->ubo); Release(d3d12->pipe.sampler_heap.handle); Release(d3d12->pipe.srv_heap.handle); Release(d3d12->pipe.rtv_heap.handle); @@ -304,16 +374,11 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const return false; } -static void d3d12_gfx_set_rotation(void* data, unsigned rotation) -{ - (void)data; - (void)rotation; -} - static void d3d12_gfx_viewport_info(void* data, struct video_viewport* vp) { - (void)data; - (void)vp; + d3d12_video_t* d3d12 = (d3d12_video_t*)data; + + *vp = d3d12->vp; } static bool d3d12_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle) @@ -366,28 +431,47 @@ static void d3d12_set_menu_texture_enable(void* data, bool state, bool full_scre d3d12->menu.fullscreen = full_screen; } +static void d3d12_gfx_set_aspect_ratio(void* data, unsigned aspect_ratio_idx) +{ + d3d12_video_t* d3d12 = (d3d12_video_t*)data; + + if (!d3d12) + return; + + d3d12->keep_aspect = true; + d3d12->resize_viewport = true; +} + +static void d3d12_gfx_apply_state_changes(void* data) +{ + d3d12_video_t* d3d12 = (d3d12_video_t*)data; + + if (d3d12) + d3d12->resize_viewport = true; +} + static const video_poke_interface_t d3d12_poke_interface = { - NULL, /* set_coords */ - NULL, /* set_mvp */ - NULL, /* load_texture */ - NULL, /* unload_texture */ - NULL, /* set_video_mode */ - NULL, /* set_filtering */ - NULL, /* get_video_output_size */ - NULL, /* get_video_output_prev */ - NULL, /* get_video_output_next */ - NULL, /* get_current_framebuffer */ - NULL, /* get_proc_address */ - NULL, /* set_aspect_ratio */ - NULL, /* apply_state_changes */ - d3d12_set_menu_texture_frame, /* set_texture_frame */ - d3d12_set_menu_texture_enable, /* set_texture_enable */ - NULL, /* set_osd_msg */ - NULL, /* show_mouse */ - NULL, /* grab_mouse_toggle */ - NULL, /* get_current_shader */ - NULL, /* get_current_software_framebuffer */ - NULL, /* get_hw_render_interface */ + NULL, /* set_coords */ + NULL, /* set_mvp */ + NULL, /* load_texture */ + NULL, /* unload_texture */ + NULL, /* set_video_mode */ + d3d12_set_filtering, + NULL, /* get_video_output_size */ + NULL, /* get_video_output_prev */ + NULL, /* get_video_output_next */ + NULL, /* get_current_framebuffer */ + NULL, /* get_proc_address */ + d3d12_gfx_set_aspect_ratio, + d3d12_gfx_apply_state_changes, + d3d12_set_menu_texture_frame, + d3d12_set_menu_texture_enable, + NULL, /* set_osd_msg */ + NULL, /* show_mouse */ + NULL, /* grab_mouse_toggle */ + NULL, /* get_current_shader */ + NULL, /* get_current_software_framebuffer */ + NULL, /* get_hw_render_interface */ }; static void d3d12_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface) diff --git a/gfx/drivers/d3d_shaders/opaque_sm5.hlsl.h b/gfx/drivers/d3d_shaders/opaque_sm5.hlsl.h index f0e7b13bc9..56c7c96adb 100644 --- a/gfx/drivers/d3d_shaders/opaque_sm5.hlsl.h +++ b/gfx/drivers/d3d_shaders/opaque_sm5.hlsl.h @@ -7,10 +7,11 @@ SRC( float2 texcoord : TEXCOORD0; float4 color : COLOR; }; + uniform float4x4 modelViewProj; PSInput VSMain(float4 position : POSITION, float2 texcoord : TEXCOORD0, float4 color : COLOR) { PSInput result; - result.position = position; + result.position = mul(modelViewProj, position); result.texcoord = texcoord; result.color = color; return result; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index f651ef43de..1b47308f42 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -1764,12 +1764,108 @@ void video_driver_monitor_reset(void) void video_driver_set_aspect_ratio(void) { settings_t *settings = config_get_ptr(); + + switch (settings->uints.video_aspect_ratio_idx) + { + case ASPECT_RATIO_SQUARE: + video_driver_set_viewport_square_pixel(); + break; + + case ASPECT_RATIO_CORE: + video_driver_set_viewport_core(); + break; + + case ASPECT_RATIO_CONFIG: + video_driver_set_viewport_config(); + break; + + default: + break; + } + + video_driver_set_aspect_ratio_value( + aspectratio_lut[settings->uints.video_aspect_ratio_idx].value); + if (!video_driver_poke || !video_driver_poke->set_aspect_ratio) return; video_driver_poke->set_aspect_ratio( video_driver_data, settings->uints.video_aspect_ratio_idx); } +void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bool keep_aspect) +{ + gfx_ctx_aspect_t aspect_data; + float device_aspect = (float)vp->full_width / vp->full_height; + settings_t* settings = config_get_ptr(); + + aspect_data.aspect = &device_aspect; + aspect_data.width = vp->full_width; + aspect_data.height = vp->full_height; + + video_context_driver_translate_aspect(&aspect_data); + + vp->x = 0; + vp->y = 0; + vp->width = vp->full_width; + vp->height = vp->full_height; + + if (settings->bools.video_scale_integer && !force_full) + { + video_viewport_get_scaled_integer( + vp, vp->full_width, vp->full_height, video_driver_get_aspect_ratio(), keep_aspect); + } + else if (keep_aspect && !force_full) + { + float desired_aspect = video_driver_get_aspect_ratio(); + +#if defined(HAVE_MENU) + if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM) + { + const struct video_viewport* custom = video_viewport_get_custom(); + + vp->x = custom->x; + vp->y = custom->y; + vp->width = custom->width; + vp->height = custom->height; + } + else +#endif + { + float delta; + + if (fabsf(device_aspect - desired_aspect) < 0.0001f) + { + /* If the aspect ratios of screen and desired aspect + * ratio are sufficiently equal (floating point stuff), + * assume they are actually equal. + */ + } + else if (device_aspect > desired_aspect) + { + delta = (desired_aspect / device_aspect - 1.0f) / 2.0f + 0.5f; + vp->x = (int)roundf(vp->full_width * (0.5f - delta)); + vp->width = (unsigned)roundf(2.0f * vp->full_width * delta); + vp->y = 0; + vp->height = vp->full_height; + } + else + { + vp->x = 0; + vp->width = vp->full_width; + delta = (device_aspect / desired_aspect - 1.0f) / 2.0f + 0.5f; + vp->y = (int)roundf(vp->full_height * (0.5f - delta)); + vp->height = (unsigned)roundf(2.0f * vp->full_height * delta); + } + } + } + +#if defined(RARCH_MOBILE) + /* In portrait mode, we want viewport to gravitate to top of screen. */ + if (device_aspect < 1.0f) + d3d12->vp.y = 0; +#endif +} + void video_driver_show_mouse(void) { if (video_driver_poke && video_driver_poke->show_mouse) diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 1cf7ac49f1..41d7c9772a 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -934,6 +934,7 @@ void video_driver_free(void); void video_driver_free_hw_context(void); void video_driver_monitor_reset(void); void video_driver_set_aspect_ratio(void); +void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bool keep_aspect); void video_driver_show_mouse(void); void video_driver_hide_mouse(void); void video_driver_set_nonblock_state(bool toggle);