mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-27 02:00:41 +00:00
(D3D10/11/12)
.add a d3d10 driver. .add more utility functions to d3d*_common files. .add an image transfer/convert function to dxgi_common. .various refactors / style nits.
This commit is contained in:
parent
96e96b9dfd
commit
a5bf9d8dc6
@ -1186,8 +1186,7 @@ ifeq ($(HAVE_VULKAN), 1)
|
||||
-I$(DEPS_DIR)/glslang \
|
||||
-I$(DEPS_DIR)/SPIRV-Cross
|
||||
|
||||
CXXFLAGS += -Wno-switch -Wno-sign-compare -fno-strict-aliasing -Wno-maybe-uninitialized -Wno-reorder -Wno-parentheses -Igfx/include
|
||||
CFLAGS += -Igfx/include
|
||||
CXXFLAGS += -Wno-switch -Wno-sign-compare -fno-strict-aliasing -Wno-maybe-uninitialized -Wno-reorder -Wno-parentheses
|
||||
|
||||
GLSLANG_OBJ := $(GLSLANG_SOURCES:.cpp=.o)
|
||||
SPIRV_CROSS_OBJ := $(SPIRV_CROSS_SOURCES:.cpp=.o)
|
||||
@ -1213,6 +1212,10 @@ ifeq ($(HAVE_VULKAN), 1)
|
||||
DEFINES += -DHAVE_SLANG
|
||||
endif
|
||||
|
||||
ifeq ($(findstring 1, $(HAVE_VULKAN) $(HAVE_D3D10) $(HAVE_D3D11) $(HAVE_D3D12)),1)
|
||||
INCLUDE_DIRS += -Igfx/include
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_WGL), 1)
|
||||
OBJ += gfx/drivers_context/wgl_ctx.o
|
||||
LIBS += -lcomctl32
|
||||
@ -1289,30 +1292,25 @@ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_D3D10), 1)
|
||||
OBJ += gfx/drivers/d3d10.o gfx/common/d3d10_common.o
|
||||
DEFINES += -DHAVE_D3D10
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_D3D11), 1)
|
||||
OBJ += gfx/drivers/d3d11.o gfx/common/d3d11_common.o
|
||||
DEFINES += -DHAVE_D3D11
|
||||
# LIBS += -ld3d11
|
||||
WANT_DXGI = 1
|
||||
WANT_D3DCOMPILER = 1
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_D3D12), 1)
|
||||
OBJ += gfx/drivers/d3d12.o gfx/common/d3d12_common.o
|
||||
DEFINES += -DHAVE_D3D12
|
||||
# LIBS += -ld3d12
|
||||
WANT_DXGI = 1
|
||||
WANT_D3DCOMPILER = 1
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_D3DCOMPILER), 1)
|
||||
ifneq ($(findstring 1, $(HAVE_D3D10) $(HAVE_D3D11) $(HAVE_D3D12)),)
|
||||
OBJ += gfx/common/d3dcompiler_common.o
|
||||
# LIBS += -ld3dcompiler
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_DXGI), 1)
|
||||
OBJ += gfx/common/dxgi_common.o
|
||||
# LIBS += -ldxgi
|
||||
CFLAGS += -Wno-unknown-pragmas
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_D3D8), 1)
|
||||
|
@ -14,6 +14,7 @@ VCINSTALLDIR := C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\$(NOTHING
|
||||
HAVE_D3DX := 1
|
||||
HAVE_D3D8 := 0
|
||||
HAVE_D3D9 := 1
|
||||
HAVE_D3D10 := 1
|
||||
HAVE_D3D11 := 1
|
||||
HAVE_D3D12 := 1
|
||||
HAVE_CG := 1
|
||||
@ -50,6 +51,7 @@ HAVE_CHEEVOS := 1
|
||||
HAVE_KEYMAPPER := 1
|
||||
|
||||
include Makefile.common
|
||||
CFLAGS := $(filter-out -Wno-unknown-pragmas,$(CFLAGS))
|
||||
CXXFLAGS := $(filter-out -fpermissive -Wno-switch -Wno-sign-compare -fno-strict-aliasing -Wno-maybe-uninitialized -Wno-reorder -Wno-parentheses,$(CXXFLAGS))
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
LIBS := $(filter-out -lstdc++,$(LIBS))
|
||||
|
@ -132,6 +132,7 @@ enum video_driver_enum
|
||||
VIDEO_SWITCH,
|
||||
VIDEO_D3D8,
|
||||
VIDEO_D3D9,
|
||||
VIDEO_D3D10,
|
||||
VIDEO_D3D11,
|
||||
VIDEO_D3D12,
|
||||
VIDEO_VG,
|
||||
@ -698,6 +699,8 @@ const char *config_get_default_video(void)
|
||||
return "d3d8";
|
||||
case VIDEO_D3D9:
|
||||
return "d3d9";
|
||||
case VIDEO_D3D10:
|
||||
return "d3d10";
|
||||
case VIDEO_D3D11:
|
||||
return "d3d11";
|
||||
case VIDEO_D3D12:
|
||||
|
128
gfx/common/d3d10_common.c
Normal file
128
gfx/common/d3d10_common.c
Normal file
@ -0,0 +1,128 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "d3d10_common.h"
|
||||
|
||||
#include <dynamic/dylib.h>
|
||||
|
||||
static dylib_t d3d10_dll;
|
||||
|
||||
typedef HRESULT (WINAPI *PFN_D3D10_CREATE_DEVICE_AND_SWAP_CHAIN)(
|
||||
IDXGIAdapter *pAdapter,
|
||||
D3D10_DRIVER_TYPE DriverType,
|
||||
HMODULE Software,
|
||||
UINT Flags,
|
||||
UINT SDKVersion,
|
||||
DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
|
||||
IDXGISwapChain **ppSwapChain,
|
||||
ID3D10Device **ppDevice);
|
||||
|
||||
HRESULT WINAPI D3D10CreateDeviceAndSwapChain(
|
||||
IDXGIAdapter *pAdapter,
|
||||
D3D10_DRIVER_TYPE DriverType,
|
||||
HMODULE Software,
|
||||
UINT Flags,
|
||||
UINT SDKVersion,
|
||||
DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
|
||||
IDXGISwapChain **ppSwapChain,
|
||||
ID3D10Device **ppDevice)
|
||||
|
||||
{
|
||||
static PFN_D3D10_CREATE_DEVICE_AND_SWAP_CHAIN fp;
|
||||
|
||||
if(!d3d10_dll)
|
||||
d3d10_dll = dylib_load("d3d10.dll");
|
||||
|
||||
if(!d3d10_dll)
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
|
||||
if(!fp)
|
||||
fp = (PFN_D3D10_CREATE_DEVICE_AND_SWAP_CHAIN)dylib_proc(d3d10_dll, "D3D10CreateDeviceAndSwapChain");
|
||||
|
||||
if(!fp)
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
|
||||
return fp(pAdapter,DriverType,Software, Flags, SDKVersion, pSwapChainDesc, ppSwapChain, ppDevice);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void d3d10_init_texture(D3D10Device device, d3d10_texture_t* texture)
|
||||
{
|
||||
Release(texture->handle);
|
||||
Release(texture->staging);
|
||||
Release(texture->view);
|
||||
|
||||
// .Usage = D3D10_USAGE_DYNAMIC,
|
||||
// .CPUAccessFlags = D3D10_CPU_ACCESS_WRITE,
|
||||
|
||||
texture->desc.MipLevels = 1;
|
||||
texture->desc.ArraySize = 1;
|
||||
texture->desc.SampleDesc.Count = 1;
|
||||
texture->desc.SampleDesc.Quality = 0;
|
||||
texture->desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
|
||||
texture->desc.CPUAccessFlags = 0;
|
||||
texture->desc.MiscFlags = 0;
|
||||
D3D10CreateTexture2D(device, &texture->desc, NULL, &texture->handle);
|
||||
|
||||
{
|
||||
D3D10_SHADER_RESOURCE_VIEW_DESC view_desc =
|
||||
{
|
||||
.Format = texture->desc.Format,
|
||||
.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D,
|
||||
.Texture2D.MostDetailedMip = 0,
|
||||
.Texture2D.MipLevels = -1,
|
||||
};
|
||||
D3D10CreateTexture2DShaderResourceView(device, texture->handle, &view_desc, &texture->view);
|
||||
}
|
||||
|
||||
{
|
||||
D3D10_TEXTURE2D_DESC desc = texture->desc;
|
||||
desc.BindFlags = 0;
|
||||
desc.Usage = D3D10_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
D3D10CreateTexture2D(device, &desc, NULL, &texture->staging);
|
||||
}
|
||||
}
|
||||
|
||||
void d3d10_update_texture(int width, int height, int pitch, DXGI_FORMAT format, const void* data, d3d10_texture_t* texture)
|
||||
{
|
||||
D3D10_MAPPED_TEXTURE2D mapped_texture;
|
||||
|
||||
D3D10MapTexture2D(texture->staging, 0, D3D10_MAP_WRITE, 0, &mapped_texture);
|
||||
|
||||
dxgi_copy(width, height, format, pitch, data, texture->desc.Format, mapped_texture.RowPitch, mapped_texture.pData);
|
||||
|
||||
D3D10UnmapTexture2D(texture->staging, 0);
|
||||
|
||||
if(texture->desc.Usage == D3D10_USAGE_DEFAULT)
|
||||
texture->dirty = true;
|
||||
}
|
||||
|
||||
DXGI_FORMAT d3d10_get_closest_match(D3D10Device device, DXGI_FORMAT desired_format, UINT desired_format_support)
|
||||
{
|
||||
DXGI_FORMAT* format = dxgi_get_format_fallback_list(desired_format);
|
||||
UINT format_support;
|
||||
|
||||
while(*format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
if(SUCCEEDED(D3D10CheckFormatSupport(device, *format, &format_support))
|
||||
&& ((format_support & desired_format_support) == desired_format_support))
|
||||
break;
|
||||
format++;
|
||||
}
|
||||
assert(*format);
|
||||
return *format;
|
||||
}
|
1147
gfx/common/d3d10_common.h
Normal file
1147
gfx/common/d3d10_common.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -41,3 +41,71 @@ HRESULT WINAPI D3D11CreateDeviceAndSwapChain( IDXGIAdapter* pAdapter,D3D_DRIVER_
|
||||
ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext);
|
||||
|
||||
}
|
||||
|
||||
void d3d11_init_texture(D3D11Device device, d3d11_texture_t* texture)
|
||||
{
|
||||
Release(texture->handle);
|
||||
Release(texture->staging);
|
||||
Release(texture->view);
|
||||
|
||||
// .Usage = D3D11_USAGE_DYNAMIC,
|
||||
// .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,
|
||||
|
||||
texture->desc.MipLevels = 1;
|
||||
texture->desc.ArraySize = 1;
|
||||
texture->desc.SampleDesc.Count = 1;
|
||||
texture->desc.SampleDesc.Quality = 0;
|
||||
texture->desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texture->desc.CPUAccessFlags = 0;
|
||||
texture->desc.MiscFlags = 0;
|
||||
D3D11CreateTexture2D(device, &texture->desc, NULL, &texture->handle);
|
||||
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC view_desc =
|
||||
{
|
||||
.Format = texture->desc.Format,
|
||||
.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D,
|
||||
.Texture2D.MostDetailedMip = 0,
|
||||
.Texture2D.MipLevels = -1,
|
||||
};
|
||||
D3D11CreateTexture2DShaderResourceView(device, texture->handle, &view_desc, &texture->view);
|
||||
}
|
||||
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc = texture->desc;
|
||||
desc.BindFlags = 0;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
D3D11CreateTexture2D(device, &desc, NULL, &texture->staging);
|
||||
}
|
||||
}
|
||||
|
||||
void d3d11_update_texture(D3D11DeviceContext ctx, int width, int height, int pitch, DXGI_FORMAT format, const void* data, d3d11_texture_t* texture)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_texture;
|
||||
|
||||
D3D11MapTexture2D(ctx, texture->staging, 0, D3D11_MAP_WRITE, 0, &mapped_texture);
|
||||
|
||||
dxgi_copy(width, height, format, pitch, data, texture->desc.Format, mapped_texture.RowPitch, mapped_texture.pData);
|
||||
|
||||
D3D11UnmapTexture2D(ctx, texture->staging, 0);
|
||||
|
||||
if(texture->desc.Usage == D3D11_USAGE_DEFAULT)
|
||||
texture->dirty = true;
|
||||
}
|
||||
|
||||
|
||||
DXGI_FORMAT d3d11_get_closest_match(D3D11Device device, DXGI_FORMAT desired_format, UINT desired_format_support)
|
||||
{
|
||||
DXGI_FORMAT* format = dxgi_get_format_fallback_list(desired_format);
|
||||
UINT format_support;
|
||||
while(*format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
if(SUCCEEDED(D3D11CheckFormatSupport(device, *format, &format_support))
|
||||
&& ((format_support & desired_format_support) == desired_format_support))
|
||||
break;
|
||||
format++;
|
||||
}
|
||||
assert(*format);
|
||||
return *format;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,13 +21,11 @@
|
||||
|
||||
#include "verbosity.h"
|
||||
|
||||
static dylib_t d3d12_dll;
|
||||
static dylib_t d3d12_dll;
|
||||
static const char *d3d12_dll_name = "d3d12.dll";
|
||||
|
||||
HRESULT WINAPI
|
||||
D3D12CreateDevice(IUnknown *pAdapter,
|
||||
D3D_FEATURE_LEVEL MinimumFeatureLevel,
|
||||
REFIID riid, void **ppDevice)
|
||||
HRESULT WINAPI D3D12CreateDevice(
|
||||
IUnknown *pAdapter, D3D_FEATURE_LEVEL MinimumFeatureLevel, REFIID riid, void **ppDevice)
|
||||
{
|
||||
if (!d3d12_dll)
|
||||
d3d12_dll = dylib_load(d3d12_dll_name);
|
||||
@ -46,8 +44,7 @@ D3D12CreateDevice(IUnknown *pAdapter,
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
}
|
||||
|
||||
HRESULT WINAPI
|
||||
D3D12GetDebugInterface(REFIID riid, void **ppvDebug)
|
||||
HRESULT WINAPI D3D12GetDebugInterface(REFIID riid, void **ppvDebug)
|
||||
{
|
||||
if (!d3d12_dll)
|
||||
d3d12_dll = dylib_load(d3d12_dll_name);
|
||||
@ -66,10 +63,10 @@ D3D12GetDebugInterface(REFIID riid, void **ppvDebug)
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
}
|
||||
|
||||
HRESULT WINAPI
|
||||
D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *pRootSignature,
|
||||
D3D_ROOT_SIGNATURE_VERSION Version,
|
||||
ID3DBlob **ppBlob, ID3DBlob **ppErrorBlob)
|
||||
HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *pRootSignature,
|
||||
D3D_ROOT_SIGNATURE_VERSION Version,
|
||||
ID3DBlob ** ppBlob,
|
||||
ID3DBlob ** ppErrorBlob)
|
||||
{
|
||||
if (!d3d12_dll)
|
||||
d3d12_dll = dylib_load(d3d12_dll_name);
|
||||
@ -79,7 +76,8 @@ D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *pRootSignature,
|
||||
static PFN_D3D12_SERIALIZE_ROOT_SIGNATURE fp;
|
||||
|
||||
if (!fp)
|
||||
fp = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)dylib_proc(d3d12_dll, "D3D12SerializeRootSignature");
|
||||
fp = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)dylib_proc(
|
||||
d3d12_dll, "D3D12SerializeRootSignature");
|
||||
|
||||
if (fp)
|
||||
return fp(pRootSignature, Version, ppBlob, ppErrorBlob);
|
||||
@ -88,9 +86,10 @@ D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *pRootSignature,
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
}
|
||||
|
||||
HRESULT WINAPI
|
||||
D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *pRootSignature,
|
||||
ID3DBlob **ppBlob, ID3DBlob **ppErrorBlob)
|
||||
HRESULT WINAPI D3D12SerializeVersionedRootSignature(
|
||||
const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *pRootSignature,
|
||||
ID3DBlob ** ppBlob,
|
||||
ID3DBlob ** ppErrorBlob)
|
||||
{
|
||||
if (!d3d12_dll)
|
||||
d3d12_dll = dylib_load(d3d12_dll_name);
|
||||
@ -100,8 +99,8 @@ D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *
|
||||
static PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE fp;
|
||||
|
||||
if (!fp)
|
||||
fp = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)dylib_proc(d3d12_dll,
|
||||
"D3D12SerializeRootSignature");
|
||||
fp = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)dylib_proc(
|
||||
d3d12_dll, "D3D12SerializeRootSignature");
|
||||
|
||||
if (fp)
|
||||
return fp(pRootSignature, ppBlob, ppErrorBlob);
|
||||
@ -110,7 +109,6 @@ D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
}
|
||||
|
||||
|
||||
#include <wiiu/wiiu_dbg.h>
|
||||
|
||||
bool d3d12_init_base(d3d12_video_t *d3d12)
|
||||
@ -144,19 +142,18 @@ bool d3d12_init_base(d3d12_video_t *d3d12)
|
||||
bool d3d12_init_queue(d3d12_video_t *d3d12)
|
||||
{
|
||||
{
|
||||
static const D3D12_COMMAND_QUEUE_DESC desc =
|
||||
{
|
||||
.Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
static const D3D12_COMMAND_QUEUE_DESC desc = {
|
||||
.Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
|
||||
};
|
||||
D3D12CreateCommandQueue(d3d12->device, &desc, &d3d12->queue.handle);
|
||||
}
|
||||
|
||||
D3D12CreateCommandAllocator(d3d12->device, D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
&d3d12->queue.allocator);
|
||||
D3D12CreateCommandAllocator(
|
||||
d3d12->device, D3D12_COMMAND_LIST_TYPE_DIRECT, &d3d12->queue.allocator);
|
||||
|
||||
D3D12CreateGraphicsCommandList(d3d12->device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
d3d12->queue.allocator, d3d12->pipe.handle, &d3d12->queue.cmd);
|
||||
d3d12->queue.allocator, d3d12->pipe.handle, &d3d12->queue.cmd);
|
||||
|
||||
D3D12CloseGraphicsCommandList(d3d12->queue.cmd);
|
||||
|
||||
@ -170,22 +167,21 @@ bool d3d12_init_queue(d3d12_video_t *d3d12)
|
||||
bool d3d12_init_swapchain(d3d12_video_t *d3d12, int width, int height, HWND hwnd)
|
||||
{
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC desc =
|
||||
{
|
||||
.BufferCount = countof(d3d12->chain.renderTargets),
|
||||
.BufferDesc.Width = width,
|
||||
DXGI_SWAP_CHAIN_DESC desc = {
|
||||
.BufferCount = countof(d3d12->chain.renderTargets),
|
||||
.BufferDesc.Width = width,
|
||||
.BufferDesc.Height = height,
|
||||
.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
.SampleDesc.Count = 1,
|
||||
.SampleDesc.Count = 1,
|
||||
#if 0
|
||||
.BufferDesc.RefreshRate.Numerator = 60,
|
||||
.BufferDesc.RefreshRate.Denominator = 1,
|
||||
.SampleDesc.Quality = 0,
|
||||
#endif
|
||||
.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
.OutputWindow = hwnd,
|
||||
.Windowed = TRUE,
|
||||
#if 1
|
||||
.Windowed = TRUE,
|
||||
#if 0
|
||||
.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
|
||||
#else
|
||||
.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
|
||||
@ -200,15 +196,16 @@ bool d3d12_init_swapchain(d3d12_video_t *d3d12, int width, int height, HWND hwnd
|
||||
|
||||
for (int i = 0; i < countof(d3d12->chain.renderTargets); i++)
|
||||
{
|
||||
d3d12->chain.desc_handles[i].ptr = d3d12->pipe.rtv_heap.cpu.ptr + i * d3d12->pipe.rtv_heap.stride;
|
||||
d3d12->chain.desc_handles[i].ptr =
|
||||
d3d12->pipe.rtv_heap.cpu.ptr + i * d3d12->pipe.rtv_heap.stride;
|
||||
DXGIGetSwapChainBuffer(d3d12->chain.handle, i, &d3d12->chain.renderTargets[i]);
|
||||
D3D12CreateRenderTargetView(d3d12->device, d3d12->chain.renderTargets[i],
|
||||
NULL, d3d12->chain.desc_handles[i]);
|
||||
D3D12CreateRenderTargetView(
|
||||
d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]);
|
||||
}
|
||||
|
||||
d3d12->chain.viewport.Width = width;
|
||||
d3d12->chain.viewport.Height = height;
|
||||
d3d12->chain.scissorRect.right = width;
|
||||
d3d12->chain.viewport.Width = width;
|
||||
d3d12->chain.viewport.Height = height;
|
||||
d3d12->chain.scissorRect.right = width;
|
||||
d3d12->chain.scissorRect.bottom = height;
|
||||
|
||||
return true;
|
||||
@ -217,74 +214,74 @@ bool d3d12_init_swapchain(d3d12_video_t *d3d12, int width, int height, HWND hwnd
|
||||
static void d3d12_init_descriptor_heap(D3D12Device device, d3d12_descriptor_heap_t *out)
|
||||
{
|
||||
D3D12CreateDescriptorHeap(device, &out->desc, &out->handle);
|
||||
out->cpu = D3D12GetCPUDescriptorHandleForHeapStart(out->handle);
|
||||
out->gpu = D3D12GetGPUDescriptorHandleForHeapStart(out->handle);
|
||||
out->cpu = D3D12GetCPUDescriptorHandleForHeapStart(out->handle);
|
||||
out->gpu = D3D12GetGPUDescriptorHandleForHeapStart(out->handle);
|
||||
out->stride = D3D12GetDescriptorHandleIncrementSize(device, out->desc.Type);
|
||||
}
|
||||
|
||||
static void d3d12_init_sampler(D3D12Device device, d3d12_descriptor_heap_t *heap, descriptor_heap_slot_t heap_index,
|
||||
D3D12_FILTER filter, D3D12_TEXTURE_ADDRESS_MODE address_mode, D3D12_GPU_DESCRIPTOR_HANDLE* dst)
|
||||
static void d3d12_init_sampler(D3D12Device device,
|
||||
d3d12_descriptor_heap_t * heap,
|
||||
descriptor_heap_slot_t heap_index,
|
||||
D3D12_FILTER filter,
|
||||
D3D12_TEXTURE_ADDRESS_MODE address_mode,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE * dst)
|
||||
{
|
||||
D3D12_SAMPLER_DESC sampler_desc =
|
||||
{
|
||||
.Filter = filter,
|
||||
.AddressU = address_mode,
|
||||
.AddressV = address_mode,
|
||||
.AddressW = address_mode,
|
||||
.MipLODBias = 0,
|
||||
.MaxAnisotropy = 0,
|
||||
D3D12_SAMPLER_DESC sampler_desc = {
|
||||
.Filter = filter,
|
||||
.AddressU = address_mode,
|
||||
.AddressV = address_mode,
|
||||
.AddressW = address_mode,
|
||||
.MipLODBias = 0,
|
||||
.MaxAnisotropy = 0,
|
||||
.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER,
|
||||
.BorderColor = {0.0f},
|
||||
.MinLOD = 0.0f,
|
||||
.MaxLOD = D3D12_FLOAT32_MAX,
|
||||
.BorderColor = { 0.0f },
|
||||
.MinLOD = 0.0f,
|
||||
.MaxLOD = D3D12_FLOAT32_MAX,
|
||||
};
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = {heap->cpu.ptr + heap_index * heap->stride};
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = { heap->cpu.ptr + heap_index * heap->stride };
|
||||
D3D12CreateSampler(device, &sampler_desc, handle);
|
||||
dst->ptr = heap->gpu.ptr + heap_index * heap->stride;
|
||||
}
|
||||
|
||||
bool d3d12_init_descriptors(d3d12_video_t *d3d12)
|
||||
{
|
||||
static const D3D12_DESCRIPTOR_RANGE srv_table[] =
|
||||
{
|
||||
static const D3D12_DESCRIPTOR_RANGE srv_table[] = {
|
||||
{
|
||||
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
|
||||
.NumDescriptors = 1,
|
||||
.BaseShaderRegister = 0,
|
||||
.RegisterSpace = 0,
|
||||
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
|
||||
.NumDescriptors = 1,
|
||||
.BaseShaderRegister = 0,
|
||||
.RegisterSpace = 0,
|
||||
#if 0
|
||||
.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC, /* version 1_1 only */
|
||||
#endif
|
||||
.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
},
|
||||
};
|
||||
static const D3D12_DESCRIPTOR_RANGE sampler_table[] =
|
||||
{
|
||||
static const D3D12_DESCRIPTOR_RANGE sampler_table[] = {
|
||||
{
|
||||
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
|
||||
.NumDescriptors = 1,
|
||||
.BaseShaderRegister = 0,
|
||||
.RegisterSpace = 0,
|
||||
.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
|
||||
.NumDescriptors = 1,
|
||||
.BaseShaderRegister = 0,
|
||||
.RegisterSpace = 0,
|
||||
.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
},
|
||||
};
|
||||
|
||||
static const D3D12_ROOT_PARAMETER rootParameters[] =
|
||||
{
|
||||
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(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,
|
||||
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||
.DescriptorTable = { countof(sampler_table), sampler_table },
|
||||
.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL,
|
||||
},
|
||||
};
|
||||
static const D3D12_ROOT_SIGNATURE_DESC desc =
|
||||
{
|
||||
.NumParameters = countof(rootParameters), rootParameters,
|
||||
static const D3D12_ROOT_SIGNATURE_DESC desc = {
|
||||
.NumParameters = countof(rootParameters),
|
||||
rootParameters,
|
||||
.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT,
|
||||
};
|
||||
|
||||
@ -295,37 +292,38 @@ bool d3d12_init_descriptors(d3d12_video_t *d3d12)
|
||||
|
||||
if (error)
|
||||
{
|
||||
RARCH_ERR("[D3D12]: CreateRootSignature failed :\n%s\n", (const char *)D3DGetBufferPointer(error));
|
||||
RARCH_ERR("[D3D12]: CreateRootSignature failed :\n%s\n",
|
||||
(const char *)D3DGetBufferPointer(error));
|
||||
Release(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12CreateRootSignature(d3d12->device, 0, D3DGetBufferPointer(signature),
|
||||
D3DGetBufferSize(signature), &d3d12->pipe.rootSignature);
|
||||
D3DGetBufferSize(signature), &d3d12->pipe.rootSignature);
|
||||
Release(signature);
|
||||
}
|
||||
|
||||
d3d12->pipe.rtv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
d3d12->pipe.rtv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
d3d12->pipe.rtv_heap.desc.NumDescriptors = countof(d3d12->chain.renderTargets);
|
||||
d3d12->pipe.rtv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
d3d12->pipe.rtv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->pipe.rtv_heap);
|
||||
|
||||
d3d12->pipe.srv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
d3d12->pipe.srv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
d3d12->pipe.srv_heap.desc.NumDescriptors = SRV_HEAP_SLOT_MAX;
|
||||
d3d12->pipe.srv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3d12->pipe.srv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->pipe.srv_heap);
|
||||
|
||||
d3d12->pipe.sampler_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
d3d12->pipe.sampler_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
d3d12->pipe.sampler_heap.desc.NumDescriptors = SAMPLER_HEAP_SLOT_MAX;
|
||||
d3d12->pipe.sampler_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3d12->pipe.sampler_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->pipe.sampler_heap);
|
||||
|
||||
d3d12_init_sampler(d3d12->device, &d3d12->pipe.sampler_heap,
|
||||
SAMPLER_HEAP_SLOT_LINEAR, D3D12_FILTER_MIN_MAG_MIP_LINEAR,
|
||||
D3D12_TEXTURE_ADDRESS_MODE_BORDER, &d3d12->sampler_linear);
|
||||
d3d12_init_sampler(d3d12->device, &d3d12->pipe.sampler_heap,
|
||||
SAMPLER_HEAP_SLOT_NEAREST, D3D12_FILTER_MIN_MAG_MIP_POINT,
|
||||
D3D12_TEXTURE_ADDRESS_MODE_BORDER, &d3d12->sampler_nearest);
|
||||
d3d12_init_sampler(d3d12->device, &d3d12->pipe.sampler_heap, SAMPLER_HEAP_SLOT_LINEAR,
|
||||
D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_BORDER,
|
||||
&d3d12->sampler_linear);
|
||||
d3d12_init_sampler(d3d12->device, &d3d12->pipe.sampler_heap, SAMPLER_HEAP_SLOT_NEAREST,
|
||||
D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_BORDER,
|
||||
&d3d12->sampler_nearest);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -334,44 +332,49 @@ bool d3d12_init_pipeline(d3d12_video_t *d3d12)
|
||||
D3DBlob vs_code;
|
||||
D3DBlob ps_code;
|
||||
|
||||
static const char stock [] =
|
||||
static const char stock[] =
|
||||
#include "gfx/drivers/d3d_shaders/opaque_sm5.hlsl.h"
|
||||
;
|
||||
;
|
||||
|
||||
static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] =
|
||||
{
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
|
||||
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
|
||||
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d12_vertex_t, color), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
|
||||
static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d12_vertex_t, color),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
|
||||
static const D3D12_RASTERIZER_DESC rasterizerDesc =
|
||||
{
|
||||
.FillMode = D3D12_FILL_MODE_SOLID,
|
||||
.CullMode = D3D12_CULL_MODE_BACK,
|
||||
static const D3D12_RASTERIZER_DESC rasterizerDesc = {
|
||||
.FillMode = D3D12_FILL_MODE_SOLID,
|
||||
.CullMode = D3D12_CULL_MODE_BACK,
|
||||
.FrontCounterClockwise = FALSE,
|
||||
.DepthBias = D3D12_DEFAULT_DEPTH_BIAS,
|
||||
.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
|
||||
.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
|
||||
.DepthClipEnable = TRUE,
|
||||
.MultisampleEnable = FALSE,
|
||||
.DepthBias = D3D12_DEFAULT_DEPTH_BIAS,
|
||||
.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
|
||||
.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
|
||||
.DepthClipEnable = TRUE,
|
||||
.MultisampleEnable = FALSE,
|
||||
.AntialiasedLineEnable = FALSE,
|
||||
.ForcedSampleCount = 0,
|
||||
.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
|
||||
.ForcedSampleCount = 0,
|
||||
.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
|
||||
};
|
||||
|
||||
static const D3D12_BLEND_DESC blendDesc =
|
||||
{
|
||||
.AlphaToCoverageEnable = FALSE,
|
||||
static const D3D12_BLEND_DESC blendDesc = {
|
||||
.AlphaToCoverageEnable = FALSE,
|
||||
.IndependentBlendEnable = FALSE,
|
||||
.RenderTarget[0] =
|
||||
{
|
||||
.BlendEnable = TRUE, .LogicOpEnable = FALSE,
|
||||
D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD,
|
||||
D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD,
|
||||
D3D12_LOGIC_OP_NOOP, D3D12_COLOR_WRITE_ENABLE_ALL,
|
||||
},
|
||||
{
|
||||
.BlendEnable = TRUE,
|
||||
.LogicOpEnable = FALSE,
|
||||
D3D12_BLEND_SRC_ALPHA,
|
||||
D3D12_BLEND_INV_SRC_ALPHA,
|
||||
D3D12_BLEND_OP_ADD,
|
||||
D3D12_BLEND_SRC_ALPHA,
|
||||
D3D12_BLEND_INV_SRC_ALPHA,
|
||||
D3D12_BLEND_OP_ADD,
|
||||
D3D12_LOGIC_OP_NOOP,
|
||||
D3D12_COLOR_WRITE_ENABLE_ALL,
|
||||
},
|
||||
};
|
||||
|
||||
if (!d3d_compile(stock, sizeof(stock), "VSMain", "vs_5_0", &vs_code))
|
||||
@ -381,21 +384,23 @@ bool d3d12_init_pipeline(d3d12_video_t *d3d12)
|
||||
return false;
|
||||
|
||||
{
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psodesc =
|
||||
{
|
||||
.pRootSignature = d3d12->pipe.rootSignature,
|
||||
.VS.pShaderBytecode = D3DGetBufferPointer(vs_code), D3DGetBufferSize(vs_code),
|
||||
.PS.pShaderBytecode = D3DGetBufferPointer(ps_code), D3DGetBufferSize(ps_code),
|
||||
.BlendState = blendDesc,
|
||||
.SampleMask = UINT_MAX,
|
||||
.RasterizerState = rasterizerDesc,
|
||||
.DepthStencilState.DepthEnable = FALSE,
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psodesc = {
|
||||
.pRootSignature = d3d12->pipe.rootSignature,
|
||||
.VS.pShaderBytecode = D3DGetBufferPointer(vs_code),
|
||||
D3DGetBufferSize(vs_code),
|
||||
.PS.pShaderBytecode = D3DGetBufferPointer(ps_code),
|
||||
D3DGetBufferSize(ps_code),
|
||||
.BlendState = blendDesc,
|
||||
.SampleMask = UINT_MAX,
|
||||
.RasterizerState = rasterizerDesc,
|
||||
.DepthStencilState.DepthEnable = FALSE,
|
||||
.DepthStencilState.StencilEnable = FALSE,
|
||||
.InputLayout.pInputElementDescs = inputElementDesc, countof(inputElementDesc),
|
||||
.InputLayout.pInputElementDescs = inputElementDesc,
|
||||
countof(inputElementDesc),
|
||||
.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||
.NumRenderTargets = 1,
|
||||
.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
.SampleDesc.Count = 1,
|
||||
.NumRenderTargets = 1,
|
||||
.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
.SampleDesc.Count = 1,
|
||||
};
|
||||
|
||||
D3D12CreateGraphicsPipelineState(d3d12->device, &psodesc, &d3d12->pipe.handle);
|
||||
@ -407,128 +412,144 @@ bool d3d12_init_pipeline(d3d12_video_t *d3d12)
|
||||
return true;
|
||||
}
|
||||
|
||||
void d3d12_create_vertex_buffer(D3D12Device device, D3D12_VERTEX_BUFFER_VIEW *view,
|
||||
D3D12Resource *vbo)
|
||||
void d3d12_create_vertex_buffer(
|
||||
D3D12Device device, D3D12_VERTEX_BUFFER_VIEW *view, D3D12Resource *vbo)
|
||||
{
|
||||
static const D3D12_HEAP_PROPERTIES heap_props =
|
||||
{
|
||||
.Type = D3D12_HEAP_TYPE_UPLOAD,
|
||||
static const D3D12_HEAP_PROPERTIES heap_props = {
|
||||
.Type = D3D12_HEAP_TYPE_UPLOAD,
|
||||
.CreationNodeMask = 1,
|
||||
.VisibleNodeMask = 1,
|
||||
.VisibleNodeMask = 1,
|
||||
};
|
||||
|
||||
D3D12_RESOURCE_DESC resource_desc =
|
||||
{
|
||||
.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
.Width = view->SizeInBytes,
|
||||
.Height = 1,
|
||||
D3D12_RESOURCE_DESC resource_desc = {
|
||||
.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
.Width = view->SizeInBytes,
|
||||
.Height = 1,
|
||||
.DepthOrArraySize = 1,
|
||||
.MipLevels = 1,
|
||||
.MipLevels = 1,
|
||||
.SampleDesc.Count = 1,
|
||||
.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
};
|
||||
|
||||
D3D12CreateCommittedResource(device, &heap_props, D3D12_HEAP_FLAG_NONE, &resource_desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, vbo);
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, vbo);
|
||||
view->BufferLocation = D3D12GetGPUVirtualAddress(*vbo);
|
||||
}
|
||||
|
||||
void d3d12_create_texture(D3D12Device device, d3d12_descriptor_heap_t *heap, descriptor_heap_slot_t heap_index,
|
||||
d3d12_texture_t *tex)
|
||||
void d3d12_init_texture(D3D12Device device,
|
||||
d3d12_descriptor_heap_t * heap,
|
||||
descriptor_heap_slot_t heap_index,
|
||||
d3d12_texture_t * texture)
|
||||
{
|
||||
{
|
||||
tex->desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
tex->desc.DepthOrArraySize = 1;
|
||||
tex->desc.MipLevels = 1;
|
||||
tex->desc.SampleDesc.Count = 1;
|
||||
Release(texture->handle);
|
||||
Release(texture->upload_buffer);
|
||||
|
||||
D3D12_HEAP_PROPERTIES heap_props = {D3D12_HEAP_TYPE_DEFAULT, 0, 0, 1, 1};
|
||||
D3D12CreateCommittedResource(device, &heap_props, D3D12_HEAP_FLAG_NONE, &tex->desc,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, NULL, &tex->handle);
|
||||
{
|
||||
texture->desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
texture->desc.DepthOrArraySize = 1;
|
||||
texture->desc.MipLevels = 1;
|
||||
texture->desc.SampleDesc.Count = 1;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heap_props = { D3D12_HEAP_TYPE_DEFAULT, 0, 0, 1, 1 };
|
||||
D3D12CreateCommittedResource(device, &heap_props, D3D12_HEAP_FLAG_NONE, &texture->desc,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, NULL, &texture->handle);
|
||||
}
|
||||
|
||||
D3D12GetCopyableFootprints(device, &tex->desc, 0, 1, 0, &tex->layout, &tex->num_rows,
|
||||
&tex->row_size_in_bytes, &tex->total_bytes);
|
||||
D3D12GetCopyableFootprints(device, &texture->desc, 0, 1, 0, &texture->layout, &texture->num_rows,
|
||||
&texture->row_size_in_bytes, &texture->total_bytes);
|
||||
|
||||
{
|
||||
D3D12_RESOURCE_DESC buffer_desc =
|
||||
{
|
||||
.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
.Width = tex->total_bytes,
|
||||
.Height = 1,
|
||||
D3D12_RESOURCE_DESC buffer_desc = {
|
||||
.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
.Width = texture->total_bytes,
|
||||
.Height = 1,
|
||||
.DepthOrArraySize = 1,
|
||||
.MipLevels = 1,
|
||||
.MipLevels = 1,
|
||||
.SampleDesc.Count = 1,
|
||||
.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
};
|
||||
D3D12_HEAP_PROPERTIES heap_props = {D3D12_HEAP_TYPE_UPLOAD, 0, 0, 1, 1};
|
||||
D3D12_HEAP_PROPERTIES heap_props = { D3D12_HEAP_TYPE_UPLOAD, 0, 0, 1, 1 };
|
||||
|
||||
D3D12CreateCommittedResource(device, &heap_props, D3D12_HEAP_FLAG_NONE, &buffer_desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &tex->upload_buffer);
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &texture->upload_buffer);
|
||||
}
|
||||
|
||||
{
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC view_desc =
|
||||
{
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC view_desc = {
|
||||
.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
||||
.Format = tex->desc.Format,
|
||||
.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D,
|
||||
.Texture2D.MipLevels = tex->desc.MipLevels,
|
||||
.Format = texture->desc.Format,
|
||||
.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D,
|
||||
.Texture2D.MipLevels = texture->desc.MipLevels,
|
||||
};
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = {heap->cpu.ptr + heap_index * heap->stride};
|
||||
D3D12CreateShaderResourceView(device, tex->handle, &view_desc, handle);
|
||||
tex->gpu_descriptor.ptr = heap->gpu.ptr + heap_index * heap->stride;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = { heap->cpu.ptr + heap_index * heap->stride };
|
||||
D3D12CreateShaderResourceView(device, texture->handle, &view_desc, handle);
|
||||
texture->gpu_descriptor.ptr = heap->gpu.ptr + heap_index * heap->stride;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void d3d12_upload_texture(D3D12GraphicsCommandList cmd, d3d12_texture_t *texture)
|
||||
{
|
||||
D3D12_TEXTURE_COPY_LOCATION src =
|
||||
{
|
||||
.pResource = texture->upload_buffer,
|
||||
.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||
D3D12_TEXTURE_COPY_LOCATION src = {
|
||||
.pResource = texture->upload_buffer,
|
||||
.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||
.PlacedFootprint = texture->layout,
|
||||
};
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dst =
|
||||
{
|
||||
.pResource = texture->handle,
|
||||
.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||
D3D12_TEXTURE_COPY_LOCATION dst = {
|
||||
.pResource = texture->handle,
|
||||
.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||
.SubresourceIndex = 0,
|
||||
};
|
||||
|
||||
d3d12_resource_transition(cmd, texture->handle,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST);
|
||||
d3d12_resource_transition(cmd, texture->handle, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST);
|
||||
|
||||
D3D12CopyTextureRegion(cmd, &dst, 0, 0, 0, &src, NULL);
|
||||
|
||||
d3d12_resource_transition(cmd, texture->handle,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
d3d12_resource_transition(cmd, texture->handle, D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
|
||||
texture->dirty = false;
|
||||
}
|
||||
|
||||
void d3d12_create_fullscreen_quad_vbo(D3D12Device device, D3D12_VERTEX_BUFFER_VIEW *view, D3D12Resource *vbo)
|
||||
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}},
|
||||
{{ 1.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}},
|
||||
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 } },
|
||||
{ { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
|
||||
};
|
||||
|
||||
view->SizeInBytes = sizeof(vertices);
|
||||
view->SizeInBytes = sizeof(vertices);
|
||||
view->StrideInBytes = sizeof(*vertices);
|
||||
d3d12_create_vertex_buffer(device, view, vbo);
|
||||
|
||||
{
|
||||
void *vertex_data_begin;
|
||||
D3D12_RANGE read_range = {0, 0};
|
||||
void * vertex_data_begin;
|
||||
D3D12_RANGE read_range = { 0, 0 };
|
||||
|
||||
D3D12Map(*vbo, 0, &read_range, &vertex_data_begin);
|
||||
memcpy(vertex_data_begin, vertices, sizeof(vertices));
|
||||
D3D12Unmap(*vbo, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
DXGI_FORMAT d3d12_get_closest_match(
|
||||
D3D12Device device, DXGI_FORMAT desired_format, D3D12_FORMAT_SUPPORT1 desired_format_support)
|
||||
{
|
||||
DXGI_FORMAT *format = dxgi_get_format_fallback_list(desired_format);
|
||||
UINT format_support;
|
||||
while (*format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support = { *format };
|
||||
if (SUCCEEDED(D3D12CheckFeatureSupport(
|
||||
device, D3D12_FEATURE_FORMAT_SUPPORT, &format_support, sizeof(format_support))) &&
|
||||
((format_support.Support1 & desired_format_support) == desired_format_support))
|
||||
break;
|
||||
format++;
|
||||
}
|
||||
assert(*format);
|
||||
return *format;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <dynamic/dylib.h>
|
||||
|
||||
#include "dxgi_common.h"
|
||||
@ -20,20 +21,222 @@
|
||||
HRESULT WINAPI CreateDXGIFactory1(REFIID riid, void **ppFactory)
|
||||
{
|
||||
static dylib_t dxgi_dll;
|
||||
static HRESULT (WINAPI *fp)(REFIID, void **);
|
||||
static HRESULT(WINAPI * fp)(REFIID, void **);
|
||||
|
||||
if(!dxgi_dll)
|
||||
if (!dxgi_dll)
|
||||
dxgi_dll = dylib_load("dxgi.dll");
|
||||
|
||||
if(!dxgi_dll)
|
||||
if (!dxgi_dll)
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
|
||||
if(!fp)
|
||||
fp = (HRESULT (WINAPI *)(REFIID, void **))dylib_proc(dxgi_dll, "CreateDXGIFactory1");
|
||||
if (!fp)
|
||||
fp = (HRESULT(WINAPI *)(REFIID, void **))dylib_proc(dxgi_dll, "CreateDXGIFactory1");
|
||||
|
||||
if(!fp)
|
||||
if (!fp)
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
|
||||
return fp(riid, ppFactory);
|
||||
}
|
||||
|
||||
DXGI_FORMAT *dxgi_get_format_fallback_list(DXGI_FORMAT format)
|
||||
{
|
||||
static DXGI_FORMAT format_unknown = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
switch ((unsigned)format)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
{
|
||||
static DXGI_FORMAT formats[] = { DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_UNKNOWN };
|
||||
return formats;
|
||||
}
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
{
|
||||
static DXGI_FORMAT formats[] = { DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_UNKNOWN };
|
||||
return formats;
|
||||
}
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
{
|
||||
static DXGI_FORMAT formats[] = { DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN };
|
||||
return formats;
|
||||
}
|
||||
case DXGI_FORMAT_B5G6R5_UNORM:
|
||||
{
|
||||
static DXGI_FORMAT formats[] = { DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_UNKNOWN };
|
||||
return formats;
|
||||
}
|
||||
case DXGI_FORMAT_EX_A4R4G4B4_UNORM:
|
||||
case DXGI_FORMAT_B4G4R4A4_UNORM:
|
||||
{
|
||||
static DXGI_FORMAT formats[] = { DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN };
|
||||
return formats;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return &format_unknown;
|
||||
}
|
||||
|
||||
#define FORMAT_PROCESS_( \
|
||||
src_type, src_rb, src_gb, src_bb, src_ab, src_rs, src_gs, src_bs, src_as, dst_type, dst_rb, \
|
||||
dst_gb, dst_bb, dst_ab, dst_rs, dst_gs, dst_bs, dst_as) \
|
||||
do \
|
||||
{ \
|
||||
if (((src_rs == dst_rs && src_rb == dst_rb) || !dst_rb) && \
|
||||
((src_gs == dst_gs && src_gb == dst_gb) || !dst_gb) && \
|
||||
((src_bs == dst_bs && src_bb == dst_bb) || !dst_bb) && \
|
||||
((src_as == dst_as && src_ab == dst_ab) || !dst_ab)) \
|
||||
{ \
|
||||
const UINT8 *in = src_data; \
|
||||
UINT8 * out = dst_data; \
|
||||
for (i = 0; i < height; i++) \
|
||||
{ \
|
||||
memcpy(out, in, width * sizeof(src_type)); \
|
||||
in += src_pitch ? src_pitch : width * sizeof(src_type); \
|
||||
out += dst_pitch ? dst_pitch : width * sizeof(dst_type); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
const src_type *src_ptr = (const src_type *)src_data; \
|
||||
dst_type * dst_ptr = (dst_type *)dst_data; \
|
||||
if (src_pitch) \
|
||||
src_pitch -= width * sizeof(*src_ptr); \
|
||||
if (dst_pitch) \
|
||||
dst_pitch -= width * sizeof(*dst_ptr); \
|
||||
for (i = 0; i < height; i++) \
|
||||
{ \
|
||||
for (j = 0; j < width; j++) \
|
||||
{ \
|
||||
unsigned r, g, b, a; \
|
||||
src_type src_val = *src_ptr++; \
|
||||
if (src_rb) \
|
||||
{ \
|
||||
r = (src_val >> src_rs) & ((1 << src_rb) - 1); \
|
||||
r = (src_rb < dst_rb) \
|
||||
? (r << (dst_rb - src_rb)) | \
|
||||
(r >> ((2 * src_rb > dst_rb) ? 2 * src_rb - dst_rb : 0)) \
|
||||
: r >> (src_rb - dst_rb); \
|
||||
} \
|
||||
if (src_gb) \
|
||||
{ \
|
||||
g = (src_val >> src_gs) & ((1 << src_gb) - 1); \
|
||||
g = (src_gb < dst_gb) \
|
||||
? (g << (dst_gb - src_gb)) | \
|
||||
(g >> ((2 * src_gb > dst_gb) ? 2 * src_gb - dst_gb : 0)) \
|
||||
: g >> (src_gb - dst_gb); \
|
||||
} \
|
||||
if (src_bb) \
|
||||
{ \
|
||||
b = (src_val >> src_bs) & ((1 << src_bb) - 1); \
|
||||
b = (src_bb < dst_bb) \
|
||||
? (b << (dst_bb - src_bb)) | \
|
||||
(b >> ((2 * src_bb > dst_bb) ? 2 * src_bb - dst_bb : 0)) \
|
||||
: b >> (src_bb - dst_bb); \
|
||||
} \
|
||||
if (src_ab) \
|
||||
{ \
|
||||
a = (src_val >> src_as) & ((1 << src_ab) - 1); \
|
||||
a = (src_ab < dst_ab) \
|
||||
? (a << (dst_ab - src_ab)) | \
|
||||
(a >> ((2 * src_ab > dst_ab) ? 2 * src_ab - dst_ab : 0)) \
|
||||
: a >> (src_ab - dst_ab); \
|
||||
} \
|
||||
*dst_ptr++ = ((src_rb ? r : 0) << dst_rs) | ((src_gb ? g : 0) << dst_gs) | \
|
||||
((src_bb ? b : 0) << dst_bs) | \
|
||||
((src_ab ? a : ((1 << dst_ab) - 1)) << dst_as); \
|
||||
} \
|
||||
src_ptr = (src_type *)((UINT8 *)src_ptr + src_pitch); \
|
||||
dst_ptr = (dst_type *)((UINT8 *)dst_ptr + dst_pitch); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FORMAT_PROCESS(args) FORMAT_PROCESS_ args
|
||||
|
||||
#define FORMAT_DST(st, dt) \
|
||||
case dt: \
|
||||
{ \
|
||||
FORMAT_PROCESS((st##_DESCS, dt##_DESCS)); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define FORMAT_SRC(st) \
|
||||
case st: \
|
||||
{ \
|
||||
switch ((unsigned)dst_format) \
|
||||
{ \
|
||||
FORMAT_DST_LIST(st); \
|
||||
default: \
|
||||
assert(0); \
|
||||
break; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
/* r, g, b, a r, g, b, a */
|
||||
#define DXGI_FORMAT_R8G8B8A8_UNORM_DESCS UINT32, 8, 8, 8, 8, 0, 8, 16, 24
|
||||
#define DXGI_FORMAT_B8G8R8X8_UNORM_DESCS UINT32, 8, 8, 8, 0, 16, 8, 0, 0
|
||||
#define DXGI_FORMAT_B8G8R8A8_UNORM_DESCS UINT32, 8, 8, 8, 8, 16, 8, 0, 24
|
||||
#define DXGI_FORMAT_B5G6R5_UNORM_DESCS UINT16, 5, 6, 5, 0, 11, 5, 0, 0
|
||||
#define DXGI_FORMAT_B5G5R5A1_UNORM_DESCS UINT16, 5, 5, 5, 1, 10, 5, 0, 11
|
||||
#define DXGI_FORMAT_B4G4R4A4_UNORM_DESCS UINT16, 4, 4, 4, 4, 8, 4, 0, 12
|
||||
#define DXGI_FORMAT_EX_A4R4G4B4_UNORM_DESCS UINT16, 4, 4, 4, 4, 4, 8, 12, 0
|
||||
|
||||
#define FORMAT_SRC_LIST() \
|
||||
FORMAT_SRC(DXGI_FORMAT_R8G8B8A8_UNORM); \
|
||||
FORMAT_SRC(DXGI_FORMAT_B8G8R8X8_UNORM); \
|
||||
FORMAT_SRC(DXGI_FORMAT_B5G6R5_UNORM); \
|
||||
FORMAT_SRC(DXGI_FORMAT_B5G5R5A1_UNORM); \
|
||||
FORMAT_SRC(DXGI_FORMAT_B4G4R4A4_UNORM); \
|
||||
FORMAT_SRC(DXGI_FORMAT_B8G8R8A8_UNORM); \
|
||||
FORMAT_SRC(DXGI_FORMAT_EX_A4R4G4B4_UNORM)
|
||||
|
||||
#define FORMAT_DST_LIST(srcfmt) \
|
||||
FORMAT_DST(srcfmt, DXGI_FORMAT_R8G8B8A8_UNORM); \
|
||||
FORMAT_DST(srcfmt, DXGI_FORMAT_B8G8R8X8_UNORM); \
|
||||
FORMAT_DST(srcfmt, DXGI_FORMAT_B5G6R5_UNORM); \
|
||||
FORMAT_DST(srcfmt, DXGI_FORMAT_B5G5R5A1_UNORM); \
|
||||
FORMAT_DST(srcfmt, DXGI_FORMAT_B4G4R4A4_UNORM); \
|
||||
FORMAT_DST(srcfmt, DXGI_FORMAT_B8G8R8A8_UNORM); \
|
||||
FORMAT_DST(srcfmt, DXGI_FORMAT_EX_A4R4G4B4_UNORM)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4293)
|
||||
#endif
|
||||
void dxgi_copy(
|
||||
int width,
|
||||
int height,
|
||||
DXGI_FORMAT src_format,
|
||||
int src_pitch,
|
||||
const void *src_data,
|
||||
DXGI_FORMAT dst_format,
|
||||
int dst_pitch,
|
||||
void * dst_data)
|
||||
{
|
||||
int i, j;
|
||||
#if defined(PERF_START) && defined(PERF_STOP)
|
||||
PERF_START();
|
||||
#endif
|
||||
|
||||
switch ((unsigned)src_format)
|
||||
{
|
||||
FORMAT_SRC_LIST();
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(PERF_START) && defined(PERF_STOP)
|
||||
PERF_STOP();
|
||||
#endif
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default : 4293)
|
||||
#endif
|
||||
|
@ -10,14 +10,15 @@
|
||||
#endif
|
||||
|
||||
#define CINTERFACE
|
||||
#include <assert.h>
|
||||
#include <dxgi1_5.h>
|
||||
|
||||
#ifndef countof
|
||||
#define countof(a) (sizeof(a)/ sizeof(*a))
|
||||
#define countof(a) (sizeof(a) / sizeof(*a))
|
||||
#endif
|
||||
|
||||
#ifndef __uuidof
|
||||
#define __uuidof(type) &IID_##type
|
||||
#define __uuidof(type) & IID_##type
|
||||
#endif
|
||||
|
||||
#ifndef COM_RELEASE_DECLARED
|
||||
@ -25,12 +26,18 @@
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
static inline ULONG Release(IUnknown* object)
|
||||
{
|
||||
return object->Release();
|
||||
if (object)
|
||||
return object->Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline ULONG Release(void* object)
|
||||
{
|
||||
return ((IUnknown*)object)->lpVtbl->Release(object);
|
||||
if (object)
|
||||
return ((IUnknown*)object)->lpVtbl->Release(object);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -93,10 +100,7 @@ static inline HRESULT DXGIMap(DXGISurface surface, DXGI_MAPPED_RECT* locked_rect
|
||||
{
|
||||
return surface->lpVtbl->Map(surface, locked_rect, map_flags);
|
||||
}
|
||||
static inline HRESULT DXGIUnmap(DXGISurface surface)
|
||||
{
|
||||
return surface->lpVtbl->Unmap(surface);
|
||||
}
|
||||
static inline HRESULT DXGIUnmap(DXGISurface surface) { return surface->lpVtbl->Unmap(surface); }
|
||||
static inline HRESULT DXGIGetDC(DXGISurface surface, BOOL discard, HDC* hdc)
|
||||
{
|
||||
return surface->lpVtbl->GetDC(surface, discard, hdc);
|
||||
@ -105,17 +109,20 @@ static inline HRESULT DXGIReleaseDC(DXGISurface surface, RECT* dirty_rect)
|
||||
{
|
||||
return surface->lpVtbl->ReleaseDC(surface, dirty_rect);
|
||||
}
|
||||
static inline ULONG DXGIReleaseOutput(DXGIOutput output)
|
||||
{
|
||||
return output->lpVtbl->Release(output);
|
||||
}
|
||||
static inline HRESULT DXGIGetDisplayModeList(DXGIOutput output, DXGI_FORMAT enum_format, UINT flags, UINT* num_modes, DXGI_MODE_DESC* desc)
|
||||
static inline ULONG DXGIReleaseOutput(DXGIOutput output) { return output->lpVtbl->Release(output); }
|
||||
static inline HRESULT DXGIGetDisplayModeList(
|
||||
DXGIOutput output, DXGI_FORMAT enum_format, UINT flags, UINT* num_modes, DXGI_MODE_DESC* desc)
|
||||
{
|
||||
return output->lpVtbl->GetDisplayModeList(output, enum_format, flags, num_modes, desc);
|
||||
}
|
||||
static inline HRESULT DXGIFindClosestMatchingMode(DXGIOutput output, DXGI_MODE_DESC* mode_to_match, DXGI_MODE_DESC* closest_match, void* concerned_device)
|
||||
static inline HRESULT DXGIFindClosestMatchingMode(
|
||||
DXGIOutput output,
|
||||
DXGI_MODE_DESC* mode_to_match,
|
||||
DXGI_MODE_DESC* closest_match,
|
||||
void* concerned_device)
|
||||
{
|
||||
return output->lpVtbl->FindClosestMatchingMode(output, mode_to_match, closest_match, (IUnknown*)concerned_device);
|
||||
return output->lpVtbl->FindClosestMatchingMode(
|
||||
output, mode_to_match, closest_match, (IUnknown*)concerned_device);
|
||||
}
|
||||
static inline HRESULT DXGIWaitForVBlank(DXGIOutput output)
|
||||
{
|
||||
@ -129,7 +136,8 @@ static inline void DXGIReleaseOwnership(DXGIOutput output)
|
||||
{
|
||||
output->lpVtbl->ReleaseOwnership(output);
|
||||
}
|
||||
static inline HRESULT DXGIGetGammaControlCapabilities(DXGIOutput output, DXGI_GAMMA_CONTROL_CAPABILITIES* gamma_caps)
|
||||
static inline HRESULT
|
||||
DXGIGetGammaControlCapabilities(DXGIOutput output, DXGI_GAMMA_CONTROL_CAPABILITIES* gamma_caps)
|
||||
{
|
||||
return output->lpVtbl->GetGammaControlCapabilities(output, gamma_caps);
|
||||
}
|
||||
@ -149,13 +157,17 @@ static inline HRESULT DXGIGetDisplaySurfaceData(DXGIOutput output, DXGISurface d
|
||||
{
|
||||
return output->lpVtbl->GetDisplaySurfaceData(output, (IDXGISurface*)destination);
|
||||
}
|
||||
static inline ULONG DXGIReleaseDevice(DXGIDevice device)
|
||||
static inline ULONG DXGIReleaseDevice(DXGIDevice device) { return device->lpVtbl->Release(device); }
|
||||
static inline HRESULT DXGICreateSurface(
|
||||
DXGIDevice device,
|
||||
DXGI_SURFACE_DESC* desc,
|
||||
UINT num_surfaces,
|
||||
DXGI_USAGE usage,
|
||||
DXGI_SHARED_RESOURCE* shared_resource,
|
||||
DXGISurface* surface)
|
||||
{
|
||||
return device->lpVtbl->Release(device);
|
||||
}
|
||||
static inline HRESULT DXGICreateSurface(DXGIDevice device, DXGI_SURFACE_DESC* desc, UINT num_surfaces, DXGI_USAGE usage, DXGI_SHARED_RESOURCE* shared_resource, DXGISurface* surface)
|
||||
{
|
||||
return device->lpVtbl->CreateSurface(device, desc, num_surfaces, usage, shared_resource, (IDXGISurface**)surface);
|
||||
return device->lpVtbl->CreateSurface(
|
||||
device, desc, num_surfaces, usage, shared_resource, (IDXGISurface**)surface);
|
||||
}
|
||||
static inline HRESULT DXGISetGPUThreadPriority(DXGIDevice device, INT priority)
|
||||
{
|
||||
@ -177,11 +189,14 @@ static inline HRESULT DXGIGetWindowAssociation(DXGIFactory factory, HWND* window
|
||||
{
|
||||
return factory->lpVtbl->GetWindowAssociation(factory, window_handle);
|
||||
}
|
||||
static inline HRESULT DXGICreateSwapChain(DXGIFactory factory, void* device, DXGI_SWAP_CHAIN_DESC* desc, DXGISwapChain* swap_chain)
|
||||
static inline HRESULT DXGICreateSwapChain(
|
||||
DXGIFactory factory, void* device, DXGI_SWAP_CHAIN_DESC* desc, DXGISwapChain* swap_chain)
|
||||
{
|
||||
return factory->lpVtbl->CreateSwapChain(factory, (IUnknown*)device, desc, (IDXGISwapChain**)swap_chain);
|
||||
return factory->lpVtbl->CreateSwapChain(
|
||||
factory, (IUnknown*)device, desc, (IDXGISwapChain**)swap_chain);
|
||||
}
|
||||
static inline HRESULT DXGICreateSoftwareAdapter(DXGIFactory factory, HMODULE module, DXGIAdapter* adapter)
|
||||
static inline HRESULT
|
||||
DXGICreateSoftwareAdapter(DXGIFactory factory, HMODULE module, DXGIAdapter* adapter)
|
||||
{
|
||||
return factory->lpVtbl->CreateSoftwareAdapter(factory, module, (IDXGIAdapter**)adapter);
|
||||
}
|
||||
@ -201,7 +216,8 @@ static inline HRESULT DXGIEnumOutputs(DXGIAdapter adapter, UINT id, DXGIOutput*
|
||||
{
|
||||
return adapter->lpVtbl->EnumOutputs(adapter, id, output);
|
||||
}
|
||||
static inline HRESULT DXGICheckInterfaceSupport(DXGIAdapter adapter, REFGUID interface_name, LARGE_INTEGER* u_m_d_version)
|
||||
static inline HRESULT
|
||||
DXGICheckInterfaceSupport(DXGIAdapter adapter, REFGUID interface_name, LARGE_INTEGER* u_m_d_version)
|
||||
{
|
||||
return adapter->lpVtbl->CheckInterfaceSupport(adapter, interface_name, u_m_d_version);
|
||||
}
|
||||
@ -225,23 +241,49 @@ static inline ULONG DXGIReleaseOutputDuplication(DXGIOutputDuplication output_du
|
||||
{
|
||||
return output_duplication->lpVtbl->Release(output_duplication);
|
||||
}
|
||||
static inline HRESULT DXGIAcquireNextFrame(DXGIOutputDuplication output_duplication, UINT timeout_in_milliseconds, DXGI_OUTDUPL_FRAME_INFO* frame_info, void* desktop_resource)
|
||||
static inline HRESULT DXGIAcquireNextFrame(
|
||||
DXGIOutputDuplication output_duplication,
|
||||
UINT timeout_in_milliseconds,
|
||||
DXGI_OUTDUPL_FRAME_INFO* frame_info,
|
||||
void* desktop_resource)
|
||||
{
|
||||
return output_duplication->lpVtbl->AcquireNextFrame(output_duplication, timeout_in_milliseconds, frame_info, (IDXGIResource**)desktop_resource);
|
||||
return output_duplication->lpVtbl->AcquireNextFrame(
|
||||
output_duplication, timeout_in_milliseconds, frame_info,
|
||||
(IDXGIResource**)desktop_resource);
|
||||
}
|
||||
static inline HRESULT DXGIGetFrameDirtyRects(DXGIOutputDuplication output_duplication, UINT dirty_rects_buffer_size, RECT* dirty_rects_buffer, UINT* dirty_rects_buffer_size_required)
|
||||
static inline HRESULT DXGIGetFrameDirtyRects(
|
||||
DXGIOutputDuplication output_duplication,
|
||||
UINT dirty_rects_buffer_size,
|
||||
RECT* dirty_rects_buffer,
|
||||
UINT* dirty_rects_buffer_size_required)
|
||||
{
|
||||
return output_duplication->lpVtbl->GetFrameDirtyRects(output_duplication, dirty_rects_buffer_size, dirty_rects_buffer, dirty_rects_buffer_size_required);
|
||||
return output_duplication->lpVtbl->GetFrameDirtyRects(
|
||||
output_duplication, dirty_rects_buffer_size, dirty_rects_buffer,
|
||||
dirty_rects_buffer_size_required);
|
||||
}
|
||||
static inline HRESULT DXGIGetFrameMoveRects(DXGIOutputDuplication output_duplication, UINT move_rects_buffer_size, DXGI_OUTDUPL_MOVE_RECT* move_rect_buffer, UINT* move_rects_buffer_size_required)
|
||||
static inline HRESULT DXGIGetFrameMoveRects(
|
||||
DXGIOutputDuplication output_duplication,
|
||||
UINT move_rects_buffer_size,
|
||||
DXGI_OUTDUPL_MOVE_RECT* move_rect_buffer,
|
||||
UINT* move_rects_buffer_size_required)
|
||||
{
|
||||
return output_duplication->lpVtbl->GetFrameMoveRects(output_duplication, move_rects_buffer_size, move_rect_buffer, move_rects_buffer_size_required);
|
||||
return output_duplication->lpVtbl->GetFrameMoveRects(
|
||||
output_duplication, move_rects_buffer_size, move_rect_buffer,
|
||||
move_rects_buffer_size_required);
|
||||
}
|
||||
static inline HRESULT DXGIGetFramePointerShape(DXGIOutputDuplication output_duplication, UINT pointer_shape_buffer_size, void* pointer_shape_buffer, UINT* pointer_shape_buffer_size_required, DXGI_OUTDUPL_POINTER_SHAPE_INFO* pointer_shape_info)
|
||||
static inline HRESULT DXGIGetFramePointerShape(
|
||||
DXGIOutputDuplication output_duplication,
|
||||
UINT pointer_shape_buffer_size,
|
||||
void* pointer_shape_buffer,
|
||||
UINT* pointer_shape_buffer_size_required,
|
||||
DXGI_OUTDUPL_POINTER_SHAPE_INFO* pointer_shape_info)
|
||||
{
|
||||
return output_duplication->lpVtbl->GetFramePointerShape(output_duplication, pointer_shape_buffer_size, pointer_shape_buffer, pointer_shape_buffer_size_required, pointer_shape_info);
|
||||
return output_duplication->lpVtbl->GetFramePointerShape(
|
||||
output_duplication, pointer_shape_buffer_size, pointer_shape_buffer,
|
||||
pointer_shape_buffer_size_required, pointer_shape_info);
|
||||
}
|
||||
static inline HRESULT DXGIMapDesktopSurface(DXGIOutputDuplication output_duplication, DXGI_MAPPED_RECT* locked_rect)
|
||||
static inline HRESULT
|
||||
DXGIMapDesktopSurface(DXGIOutputDuplication output_duplication, DXGI_MAPPED_RECT* locked_rect)
|
||||
{
|
||||
return output_duplication->lpVtbl->MapDesktopSurface(output_duplication, locked_rect);
|
||||
}
|
||||
@ -257,9 +299,11 @@ static inline ULONG DXGIReleaseDecodeSwapChain(DXGIDecodeSwapChain decode_swap_c
|
||||
{
|
||||
return decode_swap_chain->lpVtbl->Release(decode_swap_chain);
|
||||
}
|
||||
static inline HRESULT DXGIPresentBuffer(DXGIDecodeSwapChain decode_swap_chain, UINT buffer_to_present, UINT sync_interval, UINT flags)
|
||||
static inline HRESULT DXGIPresentBuffer(
|
||||
DXGIDecodeSwapChain decode_swap_chain, UINT buffer_to_present, UINT sync_interval, UINT flags)
|
||||
{
|
||||
return decode_swap_chain->lpVtbl->PresentBuffer(decode_swap_chain, buffer_to_present, sync_interval, flags);
|
||||
return decode_swap_chain->lpVtbl->PresentBuffer(
|
||||
decode_swap_chain, buffer_to_present, sync_interval, flags);
|
||||
}
|
||||
static inline HRESULT DXGISetSourceRect(DXGIDecodeSwapChain decode_swap_chain, RECT* rect)
|
||||
{
|
||||
@ -269,7 +313,8 @@ static inline HRESULT DXGISetTargetRect(DXGIDecodeSwapChain decode_swap_chain, R
|
||||
{
|
||||
return decode_swap_chain->lpVtbl->SetTargetRect(decode_swap_chain, rect);
|
||||
}
|
||||
static inline HRESULT DXGISetDestSize(DXGIDecodeSwapChain decode_swap_chain, UINT width, UINT height)
|
||||
static inline HRESULT
|
||||
DXGISetDestSize(DXGIDecodeSwapChain decode_swap_chain, UINT width, UINT height)
|
||||
{
|
||||
return decode_swap_chain->lpVtbl->SetDestSize(decode_swap_chain, width, height);
|
||||
}
|
||||
@ -281,15 +326,18 @@ static inline HRESULT DXGIGetTargetRect(DXGIDecodeSwapChain decode_swap_chain, R
|
||||
{
|
||||
return decode_swap_chain->lpVtbl->GetTargetRect(decode_swap_chain, rect);
|
||||
}
|
||||
static inline HRESULT DXGIGetDestSize(DXGIDecodeSwapChain decode_swap_chain, UINT* width, UINT* height)
|
||||
static inline HRESULT
|
||||
DXGIGetDestSize(DXGIDecodeSwapChain decode_swap_chain, UINT* width, UINT* height)
|
||||
{
|
||||
return decode_swap_chain->lpVtbl->GetDestSize(decode_swap_chain, width, height);
|
||||
}
|
||||
static inline HRESULT DXGISetColorSpace(DXGIDecodeSwapChain decode_swap_chain, DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS color_space)
|
||||
static inline HRESULT DXGISetColorSpace(
|
||||
DXGIDecodeSwapChain decode_swap_chain, DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS color_space)
|
||||
{
|
||||
return decode_swap_chain->lpVtbl->SetColorSpace(decode_swap_chain, color_space);
|
||||
}
|
||||
static inline DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS DXGIGetColorSpace(DXGIDecodeSwapChain decode_swap_chain)
|
||||
static inline DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS
|
||||
DXGIGetColorSpace(DXGIDecodeSwapChain decode_swap_chain)
|
||||
{
|
||||
return decode_swap_chain->lpVtbl->GetColorSpace(decode_swap_chain);
|
||||
}
|
||||
@ -297,19 +345,37 @@ static inline ULONG DXGIReleaseFactoryMedia(DXGIFactoryMedia factory_media)
|
||||
{
|
||||
return factory_media->lpVtbl->Release(factory_media);
|
||||
}
|
||||
static inline HRESULT DXGICreateSwapChainForCompositionSurfaceHandle(DXGIFactoryMedia factory_media, void* device, HANDLE h_surface, DXGI_SWAP_CHAIN_DESC1* desc, DXGIOutput restrict_to_output, DXGISwapChain* swap_chain)
|
||||
static inline HRESULT DXGICreateSwapChainForCompositionSurfaceHandle(
|
||||
DXGIFactoryMedia factory_media,
|
||||
void* device,
|
||||
HANDLE h_surface,
|
||||
DXGI_SWAP_CHAIN_DESC1* desc,
|
||||
DXGIOutput restrict_to_output,
|
||||
DXGISwapChain* swap_chain)
|
||||
{
|
||||
return factory_media->lpVtbl->CreateSwapChainForCompositionSurfaceHandle(factory_media, (IUnknown*)device, h_surface, desc, restrict_to_output, (IDXGISwapChain1**)swap_chain);
|
||||
return factory_media->lpVtbl->CreateSwapChainForCompositionSurfaceHandle(
|
||||
factory_media, (IUnknown*)device, h_surface, desc, restrict_to_output,
|
||||
(IDXGISwapChain1**)swap_chain);
|
||||
}
|
||||
static inline HRESULT DXGICreateDecodeSwapChainForCompositionSurfaceHandle(DXGIFactoryMedia factory_media, void* device, HANDLE h_surface, DXGI_DECODE_SWAP_CHAIN_DESC* desc, void* yuv_decode_buffers, DXGIOutput restrict_to_output, DXGIDecodeSwapChain* swap_chain)
|
||||
static inline HRESULT DXGICreateDecodeSwapChainForCompositionSurfaceHandle(
|
||||
DXGIFactoryMedia factory_media,
|
||||
void* device,
|
||||
HANDLE h_surface,
|
||||
DXGI_DECODE_SWAP_CHAIN_DESC* desc,
|
||||
void* yuv_decode_buffers,
|
||||
DXGIOutput restrict_to_output,
|
||||
DXGIDecodeSwapChain* swap_chain)
|
||||
{
|
||||
return factory_media->lpVtbl->CreateDecodeSwapChainForCompositionSurfaceHandle(factory_media, (IUnknown*)device, h_surface, desc, (IDXGIResource*)yuv_decode_buffers, restrict_to_output, swap_chain);
|
||||
return factory_media->lpVtbl->CreateDecodeSwapChainForCompositionSurfaceHandle(
|
||||
factory_media, (IUnknown*)device, h_surface, desc, (IDXGIResource*)yuv_decode_buffers,
|
||||
restrict_to_output, swap_chain);
|
||||
}
|
||||
static inline ULONG DXGIReleaseSwapChainMedia(DXGISwapChainMedia swap_chain_media)
|
||||
{
|
||||
return swap_chain_media->lpVtbl->Release(swap_chain_media);
|
||||
}
|
||||
static inline HRESULT DXGIGetFrameStatisticsMedia(DXGISwapChainMedia swap_chain_media, DXGI_FRAME_STATISTICS_MEDIA* stats)
|
||||
static inline HRESULT
|
||||
DXGIGetFrameStatisticsMedia(DXGISwapChainMedia swap_chain_media, DXGI_FRAME_STATISTICS_MEDIA* stats)
|
||||
{
|
||||
return swap_chain_media->lpVtbl->GetFrameStatisticsMedia(swap_chain_media, stats);
|
||||
}
|
||||
@ -317,9 +383,15 @@ static inline HRESULT DXGISetPresentDuration(DXGISwapChainMedia swap_chain_media
|
||||
{
|
||||
return swap_chain_media->lpVtbl->SetPresentDuration(swap_chain_media, duration);
|
||||
}
|
||||
static inline HRESULT DXGICheckPresentDurationSupport(DXGISwapChainMedia swap_chain_media, UINT desired_present_duration, UINT* closest_smaller_present_duration, UINT* closest_larger_present_duration)
|
||||
static inline HRESULT DXGICheckPresentDurationSupport(
|
||||
DXGISwapChainMedia swap_chain_media,
|
||||
UINT desired_present_duration,
|
||||
UINT* closest_smaller_present_duration,
|
||||
UINT* closest_larger_present_duration)
|
||||
{
|
||||
return swap_chain_media->lpVtbl->CheckPresentDurationSupport(swap_chain_media, desired_present_duration, closest_smaller_present_duration, closest_larger_present_duration);
|
||||
return swap_chain_media->lpVtbl->CheckPresentDurationSupport(
|
||||
swap_chain_media, desired_present_duration, closest_smaller_present_duration,
|
||||
closest_larger_present_duration);
|
||||
}
|
||||
static inline ULONG DXGIReleaseSwapChain(DXGISwapChain swap_chain)
|
||||
{
|
||||
@ -333,19 +405,29 @@ static inline HRESULT DXGIGetBuffer(DXGISwapChain swap_chain, UINT buffer, IDXGI
|
||||
{
|
||||
return swap_chain->lpVtbl->GetBuffer(swap_chain, buffer, __uuidof(IDXGISurface), (void**)out);
|
||||
}
|
||||
static inline HRESULT DXGISetFullscreenState(DXGISwapChain swap_chain, BOOL fullscreen, DXGIOutput target)
|
||||
static inline HRESULT
|
||||
DXGISetFullscreenState(DXGISwapChain swap_chain, BOOL fullscreen, DXGIOutput target)
|
||||
{
|
||||
return swap_chain->lpVtbl->SetFullscreenState(swap_chain, fullscreen, target);
|
||||
}
|
||||
static inline HRESULT DXGIGetFullscreenState(DXGISwapChain swap_chain, BOOL* fullscreen, DXGIOutput* target)
|
||||
static inline HRESULT
|
||||
DXGIGetFullscreenState(DXGISwapChain swap_chain, BOOL* fullscreen, DXGIOutput* target)
|
||||
{
|
||||
return swap_chain->lpVtbl->GetFullscreenState(swap_chain, fullscreen, target);
|
||||
}
|
||||
static inline HRESULT DXGIResizeBuffers(DXGISwapChain swap_chain, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swap_chain_flags)
|
||||
static inline HRESULT DXGIResizeBuffers(
|
||||
DXGISwapChain swap_chain,
|
||||
UINT buffer_count,
|
||||
UINT width,
|
||||
UINT height,
|
||||
DXGI_FORMAT new_format,
|
||||
UINT swap_chain_flags)
|
||||
{
|
||||
return swap_chain->lpVtbl->ResizeBuffers(swap_chain, buffer_count, width, height, new_format, swap_chain_flags);
|
||||
return swap_chain->lpVtbl->ResizeBuffers(
|
||||
swap_chain, buffer_count, width, height, new_format, swap_chain_flags);
|
||||
}
|
||||
static inline HRESULT DXGIResizeTarget(DXGISwapChain swap_chain, DXGI_MODE_DESC* new_target_parameters)
|
||||
static inline HRESULT
|
||||
DXGIResizeTarget(DXGISwapChain swap_chain, DXGI_MODE_DESC* new_target_parameters)
|
||||
{
|
||||
return swap_chain->lpVtbl->ResizeTarget(swap_chain, new_target_parameters);
|
||||
}
|
||||
@ -365,7 +447,8 @@ static inline HRESULT DXGIGetSwapChainDesc1(DXGISwapChain swap_chain, DXGI_SWAP_
|
||||
{
|
||||
return swap_chain->lpVtbl->GetDesc1(swap_chain, desc);
|
||||
}
|
||||
static inline HRESULT DXGIGetFullscreenDesc(DXGISwapChain swap_chain, DXGI_SWAP_CHAIN_FULLSCREEN_DESC* desc)
|
||||
static inline HRESULT
|
||||
DXGIGetFullscreenDesc(DXGISwapChain swap_chain, DXGI_SWAP_CHAIN_FULLSCREEN_DESC* desc)
|
||||
{
|
||||
return swap_chain->lpVtbl->GetFullscreenDesc(swap_chain, desc);
|
||||
}
|
||||
@ -373,15 +456,21 @@ static inline HRESULT DXGIGetHwnd(DXGISwapChain swap_chain, HWND* hwnd)
|
||||
{
|
||||
return swap_chain->lpVtbl->GetHwnd(swap_chain, hwnd);
|
||||
}
|
||||
static inline HRESULT DXGIPresent1(DXGISwapChain swap_chain, UINT sync_interval, UINT present_flags, DXGI_PRESENT_PARAMETERS* present_parameters)
|
||||
static inline HRESULT DXGIPresent1(
|
||||
DXGISwapChain swap_chain,
|
||||
UINT sync_interval,
|
||||
UINT present_flags,
|
||||
DXGI_PRESENT_PARAMETERS* present_parameters)
|
||||
{
|
||||
return swap_chain->lpVtbl->Present1(swap_chain, sync_interval, present_flags, present_parameters);
|
||||
return swap_chain->lpVtbl->Present1(
|
||||
swap_chain, sync_interval, present_flags, present_parameters);
|
||||
}
|
||||
static inline BOOL DXGIIsTemporaryMonoSupported(DXGISwapChain swap_chain)
|
||||
{
|
||||
return swap_chain->lpVtbl->IsTemporaryMonoSupported(swap_chain);
|
||||
}
|
||||
static inline HRESULT DXGIGetRestrictToOutput(DXGISwapChain swap_chain, DXGIOutput* restrict_to_output)
|
||||
static inline HRESULT
|
||||
DXGIGetRestrictToOutput(DXGISwapChain swap_chain, DXGIOutput* restrict_to_output)
|
||||
{
|
||||
return swap_chain->lpVtbl->GetRestrictToOutput(swap_chain, restrict_to_output);
|
||||
}
|
||||
@ -433,11 +522,13 @@ static inline UINT DXGIGetCurrentBackBufferIndex(DXGISwapChain swap_chain)
|
||||
{
|
||||
return swap_chain->lpVtbl->GetCurrentBackBufferIndex(swap_chain);
|
||||
}
|
||||
static inline HRESULT DXGICheckColorSpaceSupport(DXGISwapChain swap_chain, DXGI_COLOR_SPACE_TYPE color_space, UINT* color_space_support)
|
||||
static inline HRESULT DXGICheckColorSpaceSupport(
|
||||
DXGISwapChain swap_chain, DXGI_COLOR_SPACE_TYPE color_space, UINT* color_space_support)
|
||||
{
|
||||
return swap_chain->lpVtbl->CheckColorSpaceSupport(swap_chain, color_space, color_space_support);
|
||||
}
|
||||
static inline HRESULT DXGISetColorSpace1(DXGISwapChain swap_chain, DXGI_COLOR_SPACE_TYPE color_space)
|
||||
static inline HRESULT
|
||||
DXGISetColorSpace1(DXGISwapChain swap_chain, DXGI_COLOR_SPACE_TYPE color_space)
|
||||
{
|
||||
return swap_chain->lpVtbl->SetColorSpace1(swap_chain, color_space);
|
||||
}
|
||||
@ -448,3 +539,40 @@ static inline HRESULT DXGICreateFactory(DXGIFactory* factory)
|
||||
{
|
||||
return CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)factory);
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
typedef enum {
|
||||
DXGI_FORMAT_EX_A4R4G4B4_UNORM = 1000,
|
||||
} DXGI_FORMAT_EX;
|
||||
|
||||
DXGI_FORMAT* dxgi_get_format_fallback_list(DXGI_FORMAT format);
|
||||
|
||||
void dxgi_copy(
|
||||
int width,
|
||||
int height,
|
||||
DXGI_FORMAT src_format,
|
||||
int src_pitch,
|
||||
const void* src_data,
|
||||
DXGI_FORMAT dst_format,
|
||||
int dst_pitch,
|
||||
void* dst_data);
|
||||
|
||||
#if 1
|
||||
#include <performance_counters.h>
|
||||
#ifndef PERF_START
|
||||
#define PERF_START() \
|
||||
static struct retro_perf_counter perfcounter = { __FUNCTION__ }; \
|
||||
LARGE_INTEGER start, stop; \
|
||||
rarch_perf_register(&perfcounter); \
|
||||
perfcounter.call_cnt++; \
|
||||
QueryPerformanceCounter(&start)
|
||||
|
||||
#define PERF_STOP() \
|
||||
QueryPerformanceCounter(&stop); \
|
||||
perfcounter.total += stop.QuadPart - start.QuadPart
|
||||
#endif
|
||||
#else
|
||||
#define PERF_START()
|
||||
#define PERF_STOP()
|
||||
#endif
|
||||
|
@ -75,7 +75,7 @@ const GUID GUID_DEVINTERFACE_HID = { 0x4d1e55b2, 0xf16f, 0x11Cf, { 0x88, 0xcb, 0
|
||||
static HDEVNOTIFY notification_handler;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3D9) || defined(HAVE_D3D8)
|
||||
#if defined(HAVE_D3D8) || defined(HAVE_D3D9) || defined (HAVE_D3D10) || defined (HAVE_D3D11) || defined (HAVE_D3D12)
|
||||
extern bool dinput_handle_message(void *dinput, UINT message,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
extern void *dinput_gdi;
|
||||
@ -569,7 +569,7 @@ static void win32_set_droppable(ui_window_win32_t *window, bool droppable)
|
||||
DragAcceptFiles_func(window->hwnd, droppable);
|
||||
}
|
||||
|
||||
#if defined(HAVE_D3D9) || defined(HAVE_D3D8)
|
||||
#if defined(HAVE_D3D8) || defined(HAVE_D3D9) || defined (HAVE_D3D10) || defined (HAVE_D3D11) || defined (HAVE_D3D12)
|
||||
LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message,
|
||||
WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
|
@ -127,7 +127,7 @@ bool win32_taskbar_is_created(void);
|
||||
|
||||
void win32_set_taskbar_created(bool created);
|
||||
|
||||
#if defined(HAVE_D3D9) || defined(HAVE_D3D8)
|
||||
#if defined(HAVE_D3D8) || defined(HAVE_D3D9) || defined (HAVE_D3D10) || defined (HAVE_D3D11) || defined (HAVE_D3D12)
|
||||
LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message,
|
||||
WPARAM wparam, LPARAM lparam);
|
||||
#endif
|
||||
|
@ -37,7 +37,9 @@
|
||||
|
||||
#include "../font_driver.h"
|
||||
#include "../video_driver.h"
|
||||
#if defined(HAVE_D3D8) || defined(HAVE_D3D9)
|
||||
#include "../common/d3d_common.h"
|
||||
#endif
|
||||
#ifdef _XBOX
|
||||
#include "../../defines/xdk_defines.h"
|
||||
#endif
|
||||
|
446
gfx/drivers/d3d10.c
Normal file
446
gfx/drivers/d3d10.c
Normal file
@ -0,0 +1,446 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#include "driver.h"
|
||||
#include "verbosity.h"
|
||||
#include "configuration.h"
|
||||
#include "gfx/video_driver.h"
|
||||
#include "gfx/common/win32_common.h"
|
||||
#include "gfx/common/d3d10_common.h"
|
||||
#include "gfx/common/dxgi_common.h"
|
||||
#include "gfx/common/d3dcompiler_common.h"
|
||||
|
||||
static void*
|
||||
d3d10_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data)
|
||||
{
|
||||
WNDCLASSEX wndclass = { 0 };
|
||||
settings_t* settings = config_get_ptr();
|
||||
gfx_ctx_input_t inp = { input, input_data };
|
||||
d3d10_video_t* d3d10 = (d3d10_video_t*)calloc(1, sizeof(*d3d10));
|
||||
|
||||
if (!d3d10)
|
||||
return NULL;
|
||||
|
||||
win32_window_reset();
|
||||
win32_monitor_init();
|
||||
wndclass.lpfnWndProc = WndProcD3D;
|
||||
win32_window_init(&wndclass, true, NULL);
|
||||
|
||||
if (!win32_set_video_mode(d3d10, video->width, video->height, video->fullscreen))
|
||||
{
|
||||
RARCH_ERR("[D3D10]: win32_set_video_mode failed.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
gfx_ctx_d3d.input_driver(NULL, settings->arrays.input_joypad_driver, input, input_data);
|
||||
|
||||
{
|
||||
UINT flags = 0;
|
||||
DXGI_SWAP_CHAIN_DESC desc = {
|
||||
.BufferCount = 2,
|
||||
.BufferDesc.Width = video->width,
|
||||
.BufferDesc.Height = video->height,
|
||||
.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
// .BufferDesc.RefreshRate.Numerator = 60,
|
||||
// .BufferDesc.RefreshRate.Denominator = 1,
|
||||
.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
.OutputWindow = main_window.hwnd,
|
||||
.SampleDesc.Count = 1,
|
||||
.SampleDesc.Quality = 0,
|
||||
.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,
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
flags |= D3D10_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
D3D10CreateDeviceAndSwapChain(
|
||||
NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D10_SDK_VERSION, &desc,
|
||||
(IDXGISwapChain**)&d3d10->swapChain, &d3d10->device);
|
||||
}
|
||||
|
||||
{
|
||||
D3D10Texture2D backBuffer;
|
||||
DXGIGetSwapChainBufferD3D10(d3d10->swapChain, 0, &backBuffer);
|
||||
D3D10CreateTexture2DRenderTargetView(
|
||||
d3d10->device, backBuffer, NULL, &d3d10->renderTargetView);
|
||||
Release(backBuffer);
|
||||
}
|
||||
|
||||
D3D10SetRenderTargets(d3d10->device, 1, &d3d10->renderTargetView, NULL);
|
||||
|
||||
{
|
||||
D3D10_VIEWPORT vp = { 0, 0, video->width, video->height, 0.0f, 1.0f };
|
||||
D3D10SetViewports(d3d10->device, 1, &vp);
|
||||
}
|
||||
|
||||
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_SAMPLER_DESC desc = {
|
||||
.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT,
|
||||
.AddressU = D3D10_TEXTURE_ADDRESS_BORDER,
|
||||
.AddressV = D3D10_TEXTURE_ADDRESS_BORDER,
|
||||
.AddressW = D3D10_TEXTURE_ADDRESS_BORDER,
|
||||
.MaxAnisotropy = 1,
|
||||
.ComparisonFunc = D3D10_COMPARISON_NEVER,
|
||||
.MinLOD = -D3D10_FLOAT32_MAX,
|
||||
.MaxLOD = D3D10_FLOAT32_MAX,
|
||||
};
|
||||
D3D10CreateSamplerState(d3d10->device, &desc, &d3d10->sampler_nearest);
|
||||
|
||||
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
D3D10CreateSamplerState(d3d10->device, &desc, &d3d10->sampler_linear);
|
||||
}
|
||||
|
||||
{
|
||||
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 } },
|
||||
{ { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
|
||||
};
|
||||
|
||||
{
|
||||
D3D10_BUFFER_DESC desc = {
|
||||
.ByteWidth = sizeof(vertices),
|
||||
.Usage = D3D10_USAGE_DYNAMIC,
|
||||
.BindFlags = D3D10_BIND_VERTEX_BUFFER,
|
||||
.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE,
|
||||
};
|
||||
D3D10_SUBRESOURCE_DATA vertexData = { vertices };
|
||||
D3D10CreateBuffer(d3d10->device, &desc, &vertexData, &d3d10->frame.vbo);
|
||||
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
D3D10CreateBuffer(d3d10->device, &desc, &vertexData, &d3d10->menu.vbo);
|
||||
}
|
||||
D3D10SetPrimitiveTopology(d3d10->device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
}
|
||||
|
||||
{
|
||||
D3DBlob vs_code;
|
||||
D3DBlob ps_code;
|
||||
|
||||
static const char stock[] =
|
||||
#include "d3d_shaders/opaque_sm5.hlsl.h"
|
||||
;
|
||||
|
||||
D3D10_INPUT_ELEMENT_DESC desc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_vertex_t, position),
|
||||
D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d10_vertex_t, texcoord),
|
||||
D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d10_vertex_t, color),
|
||||
D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
d3d_compile(stock, sizeof(stock), "VSMain", "vs_4_0", &vs_code);
|
||||
d3d_compile(stock, sizeof(stock), "PSMain", "ps_4_0", &ps_code);
|
||||
|
||||
D3D10CreateVertexShader(
|
||||
d3d10->device, D3DGetBufferPointer(vs_code), D3DGetBufferSize(vs_code), &d3d10->vs);
|
||||
D3D10CreatePixelShader(
|
||||
d3d10->device, D3DGetBufferPointer(ps_code), D3DGetBufferSize(ps_code), &d3d10->ps);
|
||||
D3D10CreateInputLayout(
|
||||
d3d10->device, desc, countof(desc), D3DGetBufferPointer(vs_code),
|
||||
D3DGetBufferSize(vs_code), &d3d10->layout);
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
}
|
||||
|
||||
D3D10SetInputLayout(d3d10->device, d3d10->layout);
|
||||
D3D10SetVShader(d3d10->device, d3d10->vs);
|
||||
D3D10SetPShader(d3d10->device, d3d10->ps);
|
||||
|
||||
{
|
||||
D3D10_BLEND_DESC blend_desc = {
|
||||
.AlphaToCoverageEnable = FALSE,
|
||||
.BlendEnable = { TRUE },
|
||||
D3D10_BLEND_SRC_ALPHA,
|
||||
D3D10_BLEND_INV_SRC_ALPHA,
|
||||
D3D10_BLEND_OP_ADD,
|
||||
D3D10_BLEND_SRC_ALPHA,
|
||||
D3D10_BLEND_INV_SRC_ALPHA,
|
||||
D3D10_BLEND_OP_ADD,
|
||||
{ D3D10_COLOR_WRITE_ENABLE_ALL },
|
||||
};
|
||||
D3D10CreateBlendState(d3d10->device, &blend_desc, &d3d10->blend_enable);
|
||||
blend_desc.BlendEnable[0] = FALSE;
|
||||
D3D10CreateBlendState(d3d10->device, &blend_desc, &d3d10->blend_disable);
|
||||
}
|
||||
|
||||
return d3d10;
|
||||
|
||||
error:
|
||||
free(d3d10);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool d3d10_gfx_frame(
|
||||
void* data,
|
||||
const void* frame,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
uint64_t frame_count,
|
||||
unsigned pitch,
|
||||
const char* msg,
|
||||
video_frame_info_t* video_info)
|
||||
{
|
||||
(void)msg;
|
||||
|
||||
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
||||
PERF_START();
|
||||
D3D10ClearRenderTargetView(d3d10->device, d3d10->renderTargetView, d3d10->clearcolor);
|
||||
|
||||
if (frame && width && height)
|
||||
{
|
||||
D3D10_BOX frame_box = { 0, 0, 0, width, height, 1 };
|
||||
|
||||
if (d3d10->frame.texture.desc.Width != width || d3d10->frame.texture.desc.Height != height)
|
||||
{
|
||||
d3d10->frame.texture.desc.Width = width;
|
||||
d3d10->frame.texture.desc.Height = height;
|
||||
d3d10_init_texture(d3d10->device, &d3d10->frame.texture);
|
||||
}
|
||||
|
||||
d3d10_update_texture(width, height, pitch, d3d10->format, frame, &d3d10->frame.texture);
|
||||
D3D10CopyTexture2DSubresourceRegion(
|
||||
d3d10->device, d3d10->frame.texture.handle, 0, 0, 0, 0, d3d10->frame.texture.staging, 0,
|
||||
&frame_box);
|
||||
}
|
||||
|
||||
{
|
||||
UINT stride = sizeof(d3d10_vertex_t);
|
||||
UINT offset = 0;
|
||||
D3D10SetVertexBuffers(d3d10->device, 0, 1, &d3d10->frame.vbo, &stride, &offset);
|
||||
D3D10SetPShaderResources(d3d10->device, 0, 1, &d3d10->frame.texture.view);
|
||||
D3D10SetPShaderSamplers(d3d10->device, 0, 1, &d3d10->sampler_linear);
|
||||
|
||||
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.texture.dirty)
|
||||
D3D10CopyTexture2DSubresourceRegion(
|
||||
d3d10->device, d3d10->menu.texture.handle, 0, 0, 0, 0,
|
||||
d3d10->menu.texture.staging, 0, NULL);
|
||||
|
||||
D3D10SetVertexBuffers(d3d10->device, 0, 1, &d3d10->menu.vbo, &stride, &offset);
|
||||
D3D10SetPShaderResources(d3d10->device, 0, 1, &d3d10->menu.texture.view);
|
||||
D3D10SetPShaderSamplers(d3d10->device, 0, 1, &d3d10->sampler_linear);
|
||||
|
||||
D3D10Draw(d3d10->device, 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
DXGIPresent(d3d10->swapChain, !d3d10->vsync, 0);
|
||||
PERF_STOP();
|
||||
|
||||
if (msg && *msg)
|
||||
gfx_ctx_d3d.update_window_title(NULL, video_info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void d3d10_gfx_set_nonblock_state(void* data, bool toggle)
|
||||
{
|
||||
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
||||
d3d10->vsync = !toggle;
|
||||
}
|
||||
|
||||
static bool d3d10_gfx_alive(void* data)
|
||||
{
|
||||
(void)data;
|
||||
bool quit;
|
||||
bool resize;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
|
||||
win32_check_window(&quit, &resize, &width, &height);
|
||||
|
||||
if (width != 0 && height != 0)
|
||||
video_driver_set_size(&width, &height);
|
||||
|
||||
return !quit;
|
||||
}
|
||||
|
||||
static bool d3d10_gfx_focus(void* data) { return win32_has_focus(); }
|
||||
|
||||
static bool d3d10_gfx_suppress_screensaver(void* data, bool enable)
|
||||
{
|
||||
(void)data;
|
||||
(void)enable;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool d3d10_gfx_has_windowed(void* data)
|
||||
{
|
||||
(void)data;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void d3d10_gfx_free(void* data)
|
||||
{
|
||||
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
||||
|
||||
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->blend_enable);
|
||||
Release(d3d10->blend_disable);
|
||||
Release(d3d10->sampler_nearest);
|
||||
Release(d3d10->sampler_linear);
|
||||
Release(d3d10->ps);
|
||||
Release(d3d10->vs);
|
||||
Release(d3d10->layout);
|
||||
Release(d3d10->renderTargetView);
|
||||
Release(d3d10->swapChain);
|
||||
Release(d3d10->device);
|
||||
|
||||
win32_monitor_from_window();
|
||||
win32_destroy_window();
|
||||
free(d3d10);
|
||||
}
|
||||
|
||||
static bool d3d10_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path)
|
||||
{
|
||||
(void)data;
|
||||
(void)type;
|
||||
(void)path;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static bool d3d10_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle)
|
||||
{
|
||||
(void)data;
|
||||
(void)buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void d3d10_set_menu_texture_frame(
|
||||
void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha)
|
||||
{
|
||||
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
||||
int pitch = width * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t));
|
||||
DXGI_FORMAT format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_EX_A4R4G4B4_UNORM;
|
||||
|
||||
if (d3d10->menu.texture.desc.Width != width || d3d10->menu.texture.desc.Height != height)
|
||||
{
|
||||
d3d10->menu.texture.desc.Format = d3d10_get_closest_match_texture2D(d3d10->device, format);
|
||||
d3d10->menu.texture.desc.Width = width;
|
||||
d3d10->menu.texture.desc.Height = height;
|
||||
d3d10_init_texture(d3d10->device, &d3d10->menu.texture);
|
||||
}
|
||||
|
||||
d3d10_update_texture(width, height, pitch, format, frame, &d3d10->menu.texture);
|
||||
}
|
||||
static void d3d10_set_menu_texture_enable(void* data, bool state, bool full_screen)
|
||||
{
|
||||
d3d10_video_t* d3d10 = (d3d10_video_t*)data;
|
||||
|
||||
d3d10->menu.enabled = state;
|
||||
d3d10->menu.fullscreen = full_screen;
|
||||
}
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
static void d3d10_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface)
|
||||
{
|
||||
*iface = &d3d10_poke_interface;
|
||||
}
|
||||
|
||||
video_driver_t video_d3d10 = {
|
||||
d3d10_gfx_init,
|
||||
d3d10_gfx_frame,
|
||||
d3d10_gfx_set_nonblock_state,
|
||||
d3d10_gfx_alive,
|
||||
d3d10_gfx_focus,
|
||||
d3d10_gfx_suppress_screensaver,
|
||||
d3d10_gfx_has_windowed,
|
||||
d3d10_gfx_set_shader,
|
||||
d3d10_gfx_free,
|
||||
"d3d10",
|
||||
NULL, /* set_viewport */
|
||||
d3d10_gfx_set_rotation,
|
||||
d3d10_gfx_viewport_info,
|
||||
d3d10_gfx_read_viewport,
|
||||
NULL, /* read_frame_raw */
|
||||
|
||||
#ifdef HAVE_OVERLAY
|
||||
NULL, /* overlay_interface */
|
||||
#endif
|
||||
d3d10_gfx_get_poke_interface,
|
||||
};
|
@ -24,55 +24,16 @@
|
||||
#include "gfx/common/d3d11_common.h"
|
||||
#include "gfx/common/dxgi_common.h"
|
||||
#include "gfx/common/d3dcompiler_common.h"
|
||||
#include "performance_counters.h"
|
||||
#include <gfx/scaler/pixconv.h>
|
||||
|
||||
typedef struct d3d11_vertex_t
|
||||
static void*
|
||||
d3d11_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data)
|
||||
{
|
||||
float position[2];
|
||||
float texcoord[2];
|
||||
float color[4];
|
||||
} d3d11_vertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned cur_mon_id;
|
||||
DXGISwapChain swapChain;
|
||||
D3D11Device device;
|
||||
D3D_FEATURE_LEVEL supportedFeatureLevel;
|
||||
D3D11DeviceContext context;
|
||||
D3D11RenderTargetView renderTargetView;
|
||||
D3D11Buffer vertexBuffer;
|
||||
D3D11InputLayout layout;
|
||||
D3D11VertexShader vs;
|
||||
D3D11PixelShader ps;
|
||||
D3D11SamplerState sampler_nearest;
|
||||
D3D11SamplerState sampler_linear;
|
||||
D3D11Texture2D frame_default;
|
||||
D3D11Texture2D frame_staging;
|
||||
struct
|
||||
{
|
||||
D3D11Texture2D tex;
|
||||
D3D11ShaderResourceView view;
|
||||
D3D11Buffer vbo;
|
||||
int width;
|
||||
int height;
|
||||
bool enabled;
|
||||
bool fullscreen;
|
||||
} menu;
|
||||
int frame_width;
|
||||
int frame_height;
|
||||
D3D11ShaderResourceView frame_view;
|
||||
float clearcolor[4];
|
||||
bool vsync;
|
||||
bool rgb32;
|
||||
} d3d11_video_t;
|
||||
|
||||
static void* d3d11_gfx_init(const video_info_t* video,
|
||||
const input_driver_t** input, void** input_data)
|
||||
{
|
||||
WNDCLASSEX wndclass = {0};
|
||||
settings_t* settings = config_get_ptr();
|
||||
gfx_ctx_input_t inp = {input, input_data};
|
||||
d3d11_video_t* d3d11 = (d3d11_video_t*)calloc(1, sizeof(*d3d11));
|
||||
WNDCLASSEX wndclass = { 0 };
|
||||
settings_t* settings = config_get_ptr();
|
||||
gfx_ctx_input_t inp = { input, input_data };
|
||||
d3d11_video_t* d3d11 = (d3d11_video_t*)calloc(1, sizeof(*d3d11));
|
||||
|
||||
if (!d3d11)
|
||||
return NULL;
|
||||
@ -82,24 +43,18 @@ static void* d3d11_gfx_init(const video_info_t* video,
|
||||
wndclass.lpfnWndProc = WndProcD3D;
|
||||
win32_window_init(&wndclass, true, NULL);
|
||||
|
||||
if (!win32_set_video_mode(d3d11, video->width,
|
||||
video->height, video->fullscreen))
|
||||
if (!win32_set_video_mode(d3d11, video->width, video->height, video->fullscreen))
|
||||
{
|
||||
RARCH_ERR("[D3D11]: win32_set_video_mode failed.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
gfx_ctx_d3d.input_driver(NULL, settings->arrays.input_joypad_driver,
|
||||
input, input_data);
|
||||
|
||||
d3d11->rgb32 = video->rgb32;
|
||||
d3d11->vsync = video->vsync;
|
||||
gfx_ctx_d3d.input_driver(NULL, settings->arrays.input_joypad_driver, input, input_data);
|
||||
|
||||
{
|
||||
UINT flags = 0;
|
||||
D3D_FEATURE_LEVEL requested_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
DXGI_SWAP_CHAIN_DESC desc =
|
||||
{
|
||||
UINT flags = 0;
|
||||
D3D_FEATURE_LEVEL requested_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
DXGI_SWAP_CHAIN_DESC desc = {
|
||||
.BufferCount = 1,
|
||||
.BufferDesc.Width = video->width,
|
||||
.BufferDesc.Height = video->height,
|
||||
@ -120,78 +75,42 @@ static void* d3d11_gfx_init(const video_info_t* video,
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE,
|
||||
NULL, flags,
|
||||
&requested_feature_level, 1, D3D11_SDK_VERSION, &desc,
|
||||
(IDXGISwapChain**)&d3d11->swapChain, &d3d11->device,
|
||||
&d3d11->supportedFeatureLevel, &d3d11->context);
|
||||
D3D11CreateDeviceAndSwapChain(
|
||||
NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, &requested_feature_level, 1,
|
||||
D3D11_SDK_VERSION, &desc, (IDXGISwapChain**)&d3d11->swapChain, &d3d11->device,
|
||||
&d3d11->supportedFeatureLevel, &d3d11->ctx);
|
||||
}
|
||||
|
||||
{
|
||||
D3D11Texture2D backBuffer;
|
||||
DXGIGetSwapChainBufferD3D11(d3d11->swapChain, 0, &backBuffer);
|
||||
D3D11CreateTexture2DRenderTargetView(d3d11->device, backBuffer,
|
||||
NULL, &d3d11->renderTargetView);
|
||||
D3D11CreateTexture2DRenderTargetView(
|
||||
d3d11->device, backBuffer, NULL, &d3d11->renderTargetView);
|
||||
Release(backBuffer);
|
||||
}
|
||||
|
||||
D3D11SetRenderTargets(d3d11->context, 1,
|
||||
&d3d11->renderTargetView, NULL);
|
||||
D3D11SetRenderTargets(d3d11->ctx, 1, &d3d11->renderTargetView, NULL);
|
||||
|
||||
{
|
||||
D3D11_VIEWPORT vp = {0, 0, video->width, video->height, 0.0f, 1.0f};
|
||||
D3D11SetViewports(d3d11->context, 1, &vp);
|
||||
D3D11_VIEWPORT vp = { 0, 0, video->width, video->height, 0.0f, 1.0f };
|
||||
D3D11SetViewports(d3d11->ctx, 1, &vp);
|
||||
}
|
||||
|
||||
d3d11->vsync = video->vsync;
|
||||
d3d11->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM;
|
||||
|
||||
d3d11->frame_width = video->input_scale * RARCH_SCALE_BASE;
|
||||
d3d11->frame_height = video->input_scale * RARCH_SCALE_BASE;
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc =
|
||||
{
|
||||
.Width = d3d11->frame_width,
|
||||
.Height = d3d11->frame_height,
|
||||
.MipLevels = 1,
|
||||
.ArraySize = 1,
|
||||
.Format = DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
#if 0
|
||||
.Format = d3d11->rgb32 ?
|
||||
DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM,
|
||||
#endif
|
||||
.SampleDesc.Count = 1,
|
||||
.SampleDesc.Quality = 0,
|
||||
.Usage = D3D11_USAGE_DEFAULT,
|
||||
.BindFlags = D3D11_BIND_SHADER_RESOURCE,
|
||||
.CPUAccessFlags = 0,
|
||||
.MiscFlags = 0,
|
||||
};
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC view_desc =
|
||||
{
|
||||
.Format = desc.Format,
|
||||
.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D,
|
||||
.Texture2D.MostDetailedMip = 0,
|
||||
.Texture2D.MipLevels = -1,
|
||||
};
|
||||
d3d11->frame.texture.desc.Format =
|
||||
d3d11_get_closest_match_texture2D(d3d11->device, d3d11->format);
|
||||
d3d11->frame.texture.desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
D3D11CreateTexture2D(d3d11->device,
|
||||
&desc, NULL, &d3d11->frame_default);
|
||||
D3D11CreateTexture2DShaderResourceView(d3d11->device,
|
||||
d3d11->frame_default, &view_desc, &d3d11->frame_view);
|
||||
|
||||
desc.Format = desc.Format;
|
||||
desc.BindFlags = 0;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
|
||||
D3D11CreateTexture2D(d3d11->device, &desc,
|
||||
NULL, &d3d11->frame_staging);
|
||||
}
|
||||
d3d11->menu.texture.desc.Format = DXGI_FORMAT_B4G4R4A4_UNORM;
|
||||
d3d11->menu.texture.desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
{
|
||||
D3D11_SAMPLER_DESC desc =
|
||||
{
|
||||
D3D11_SAMPLER_DESC desc = {
|
||||
.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT,
|
||||
.AddressU = D3D11_TEXTURE_ADDRESS_BORDER,
|
||||
.AddressV = D3D11_TEXTURE_ADDRESS_BORDER,
|
||||
@ -208,70 +127,89 @@ static void* d3d11_gfx_init(const video_info_t* video,
|
||||
}
|
||||
|
||||
{
|
||||
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}},
|
||||
{{ 1.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}},
|
||||
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 } },
|
||||
{ { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
|
||||
};
|
||||
|
||||
{
|
||||
D3D11_BUFFER_DESC desc =
|
||||
{
|
||||
D3D11_BUFFER_DESC desc = {
|
||||
.Usage = D3D11_USAGE_DYNAMIC,
|
||||
.ByteWidth = sizeof(vertices),
|
||||
.BindFlags = D3D11_BIND_VERTEX_BUFFER,
|
||||
.StructureByteStride = 0, /* sizeof(Vertex) ? */
|
||||
.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,
|
||||
};
|
||||
D3D11_SUBRESOURCE_DATA vertexData = {vertices};
|
||||
D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->vertexBuffer);
|
||||
D3D11_SUBRESOURCE_DATA vertexData = { vertices };
|
||||
D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->frame.vbo);
|
||||
desc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
D3D11CreateBuffer(d3d11->device, &desc,
|
||||
&vertexData, &d3d11->menu.vbo);
|
||||
D3D11CreateBuffer(d3d11->device, &desc, &vertexData, &d3d11->menu.vbo);
|
||||
}
|
||||
D3D11SetPrimitiveTopology(d3d11->context,
|
||||
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
D3D11SetPrimitiveTopology(d3d11->ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
}
|
||||
|
||||
{
|
||||
D3DBlob vs_code;
|
||||
D3DBlob ps_code;
|
||||
|
||||
static const char stock [] =
|
||||
static const char stock[] =
|
||||
#include "d3d_shaders/opaque_sm5.hlsl.h"
|
||||
;
|
||||
;
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC desc[] =
|
||||
{
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, position), D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, texcoord), D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d11_vertex_t, color), D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
D3D11_INPUT_ELEMENT_DESC desc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, position),
|
||||
D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d11_vertex_t, texcoord),
|
||||
D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d11_vertex_t, color),
|
||||
D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
d3d_compile(stock, sizeof(stock), "VSMain", "vs_5_0", &vs_code);
|
||||
d3d_compile(stock, sizeof(stock), "PSMain", "ps_5_0", &ps_code);
|
||||
|
||||
D3D11CreateVertexShader(d3d11->device,
|
||||
D3DGetBufferPointer(vs_code), D3DGetBufferSize(vs_code),
|
||||
NULL, &d3d11->vs);
|
||||
D3D11CreatePixelShader(d3d11->device,
|
||||
D3DGetBufferPointer(ps_code), D3DGetBufferSize(ps_code),
|
||||
NULL, &d3d11->ps);
|
||||
D3D11CreateInputLayout(d3d11->device, desc, countof(desc),
|
||||
D3DGetBufferPointer(vs_code),
|
||||
D3D11CreateVertexShader(
|
||||
d3d11->device, D3DGetBufferPointer(vs_code), D3DGetBufferSize(vs_code), NULL,
|
||||
&d3d11->vs);
|
||||
D3D11CreatePixelShader(
|
||||
d3d11->device, D3DGetBufferPointer(ps_code), D3DGetBufferSize(ps_code), NULL,
|
||||
&d3d11->ps);
|
||||
D3D11CreateInputLayout(
|
||||
d3d11->device, desc, countof(desc), D3DGetBufferPointer(vs_code),
|
||||
D3DGetBufferSize(vs_code), &d3d11->layout);
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
}
|
||||
|
||||
D3D11SetInputLayout(d3d11->context, d3d11->layout);
|
||||
D3D11SetVShader(d3d11->context, d3d11->vs, NULL, 0);
|
||||
D3D11SetPShader(d3d11->context, d3d11->ps, NULL, 0);
|
||||
D3D11SetInputLayout(d3d11->ctx, d3d11->layout);
|
||||
D3D11SetVShader(d3d11->ctx, d3d11->vs, NULL, 0);
|
||||
D3D11SetPShader(d3d11->ctx, d3d11->ps, NULL, 0);
|
||||
|
||||
{
|
||||
D3D11_BLEND_DESC blend_desc = {
|
||||
.AlphaToCoverageEnable = FALSE,
|
||||
.IndependentBlendEnable = FALSE,
|
||||
.RenderTarget[0] =
|
||||
{
|
||||
.BlendEnable = TRUE,
|
||||
D3D11_BLEND_SRC_ALPHA,
|
||||
D3D11_BLEND_INV_SRC_ALPHA,
|
||||
D3D11_BLEND_OP_ADD,
|
||||
D3D11_BLEND_SRC_ALPHA,
|
||||
D3D11_BLEND_INV_SRC_ALPHA,
|
||||
D3D11_BLEND_OP_ADD,
|
||||
D3D11_COLOR_WRITE_ENABLE_ALL,
|
||||
},
|
||||
};
|
||||
D3D11CreateBlendState(d3d11->device, &blend_desc, &d3d11->blend_enable);
|
||||
blend_desc.RenderTarget[0].BlendEnable = FALSE;
|
||||
D3D11CreateBlendState(d3d11->device, &blend_desc, &d3d11->blend_disable);
|
||||
}
|
||||
|
||||
return d3d11;
|
||||
|
||||
@ -280,113 +218,69 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool d3d11_gfx_frame(void* data, const void* frame,
|
||||
unsigned width, unsigned height, uint64_t frame_count,
|
||||
unsigned pitch, const char* msg, video_frame_info_t* video_info)
|
||||
static bool d3d11_gfx_frame(
|
||||
void* data,
|
||||
const void* frame,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
uint64_t frame_count,
|
||||
unsigned pitch,
|
||||
const char* msg,
|
||||
video_frame_info_t* video_info)
|
||||
{
|
||||
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
|
||||
|
||||
(void)msg;
|
||||
PERF_START();
|
||||
D3D11ClearRenderTargetView(d3d11->ctx, d3d11->renderTargetView, d3d11->clearcolor);
|
||||
|
||||
if(frame && width && height)
|
||||
if (frame && width && height)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_frame;
|
||||
D3D11MapTexture2D(d3d11->context,
|
||||
d3d11->frame_staging, 0, D3D11_MAP_WRITE, 0, &mapped_frame);
|
||||
D3D11_BOX frame_box = { 0, 0, 0, width, height, 1 };
|
||||
|
||||
if (d3d11->frame.texture.desc.Width != width || d3d11->frame.texture.desc.Height != height)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
if (d3d11->rgb32)
|
||||
{
|
||||
const uint8_t *in = frame;
|
||||
uint8_t *out = mapped_frame.pData;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
memcpy(out, in, width * (d3d11->rgb32? 4 : 2));
|
||||
in += pitch;
|
||||
out += mapped_frame.RowPitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint16_t *in = frame;
|
||||
uint32_t *out = mapped_frame.pData;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
unsigned b = ((in[j] >> 11) & 0x1F);
|
||||
unsigned g = ((in[j] >> 5) & 0x3F);
|
||||
unsigned r = ((in[j] >> 0) & 0x1F);
|
||||
|
||||
out[j] = ((r >> 2) << 0) | (r << 3) |
|
||||
((g >> 4) << 8) | (g << 10) |
|
||||
((b >> 2) << 16) | (b << 19);
|
||||
|
||||
}
|
||||
in += width;
|
||||
out += mapped_frame.RowPitch / 4;
|
||||
}
|
||||
}
|
||||
|
||||
d3d11->frame.texture.desc.Width = width;
|
||||
d3d11->frame.texture.desc.Height = height;
|
||||
d3d11_init_texture(d3d11->device, &d3d11->frame.texture);
|
||||
}
|
||||
D3D11UnmapTexture2D(d3d11->context, d3d11->frame_staging, 0);
|
||||
D3D11_BOX frame_box = {0, 0, 0, width, height, 1};
|
||||
D3D11CopyTexture2DSubresourceRegion(d3d11->context,
|
||||
d3d11->frame_default, 0, 0 , 0 , 0,
|
||||
d3d11->frame_staging, 0, &frame_box);
|
||||
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_vbo;
|
||||
D3D11MapBuffer(d3d11->context, d3d11->vertexBuffer,
|
||||
0, D3D11_MAP_WRITE_NO_OVERWRITE, 0,
|
||||
&mapped_vbo);
|
||||
{
|
||||
d3d11_vertex_t* vbo = mapped_vbo.pData;
|
||||
vbo[0].texcoord[0] = 0.0f * (width / (float)d3d11->frame_width);
|
||||
vbo[0].texcoord[1] = 1.0f * (height / (float)d3d11->frame_height);
|
||||
vbo[1].texcoord[0] = 0.0f * (width / (float)d3d11->frame_width);
|
||||
vbo[1].texcoord[1] = 0.0f * (height / (float)d3d11->frame_height);
|
||||
vbo[2].texcoord[0] = 1.0f * (width / (float)d3d11->frame_width);
|
||||
vbo[2].texcoord[1] = 1.0f * (height / (float)d3d11->frame_height);
|
||||
vbo[3].texcoord[0] = 1.0f * (width / (float)d3d11->frame_width);
|
||||
vbo[3].texcoord[1] = 0.0f * (height / (float)d3d11->frame_height);
|
||||
}
|
||||
D3D11UnmapBuffer(d3d11->context, d3d11->vertexBuffer, 0);
|
||||
}
|
||||
d3d11_update_texture(
|
||||
d3d11->ctx, width, height, pitch, d3d11->format, frame, &d3d11->frame.texture);
|
||||
D3D11CopyTexture2DSubresourceRegion(
|
||||
d3d11->ctx, d3d11->frame.texture.handle, 0, 0, 0, 0, d3d11->frame.texture.staging, 0,
|
||||
&frame_box);
|
||||
}
|
||||
|
||||
D3D11ClearRenderTargetView(d3d11->context,
|
||||
d3d11->renderTargetView, d3d11->clearcolor);
|
||||
|
||||
{
|
||||
UINT stride = sizeof(d3d11_vertex_t);
|
||||
UINT offset = 0;
|
||||
D3D11SetVertexBuffers(d3d11->context, 0, 1,
|
||||
&d3d11->vertexBuffer, &stride, &offset);
|
||||
D3D11SetPShaderResources(d3d11->context, 0, 1, &d3d11->frame_view);
|
||||
D3D11SetPShaderSamplers(d3d11->context, 0, 1, &d3d11->sampler_linear);
|
||||
D3D11SetVertexBuffers(d3d11->ctx, 0, 1, &d3d11->frame.vbo, &stride, &offset);
|
||||
D3D11SetPShaderResources(d3d11->ctx, 0, 1, &d3d11->frame.texture.view);
|
||||
D3D11SetPShaderSamplers(d3d11->ctx, 0, 1, &d3d11->sampler_linear);
|
||||
|
||||
D3D11Draw(d3d11->context, 4, 0);
|
||||
D3D11SetBlendState(d3d11->ctx, d3d11->blend_disable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
|
||||
D3D11Draw(d3d11->ctx, 4, 0);
|
||||
D3D11SetBlendState(d3d11->ctx, d3d11->blend_enable, NULL, D3D11_DEFAULT_SAMPLE_MASK);
|
||||
|
||||
if (d3d11->menu.enabled)
|
||||
if (d3d11->menu.enabled && d3d11->menu.texture.handle)
|
||||
{
|
||||
D3D11SetVertexBuffers(d3d11->context, 0, 1,
|
||||
&d3d11->menu.vbo, &stride, &offset);
|
||||
D3D11SetPShaderResources(d3d11->context, 0, 1,
|
||||
&d3d11->menu.view);
|
||||
D3D11SetPShaderSamplers(d3d11->context, 0, 1,
|
||||
&d3d11->sampler_linear);
|
||||
if (d3d11->menu.texture.dirty)
|
||||
D3D11CopyTexture2DSubresourceRegion(
|
||||
d3d11->ctx, d3d11->menu.texture.handle, 0, 0, 0, 0, d3d11->menu.texture.staging,
|
||||
0, NULL);
|
||||
|
||||
D3D11Draw(d3d11->context, 4, 0);
|
||||
D3D11SetVertexBuffers(d3d11->ctx, 0, 1, &d3d11->menu.vbo, &stride, &offset);
|
||||
D3D11SetPShaderResources(d3d11->ctx, 0, 1, &d3d11->menu.texture.view);
|
||||
D3D11SetPShaderSamplers(d3d11->ctx, 0, 1, &d3d11->sampler_linear);
|
||||
|
||||
D3D11Draw(d3d11->ctx, 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
DXGIPresent(d3d11->swapChain, !!d3d11->vsync, 0);
|
||||
PERF_STOP();
|
||||
|
||||
if(msg && *msg)
|
||||
if (msg && *msg)
|
||||
gfx_ctx_d3d.update_window_title(NULL, video_info);
|
||||
|
||||
return true;
|
||||
@ -404,8 +298,8 @@ static void d3d11_gfx_set_nonblock_state(void* data, bool toggle)
|
||||
|
||||
static bool d3d11_gfx_alive(void* data)
|
||||
{
|
||||
bool quit;
|
||||
bool resize;
|
||||
bool quit;
|
||||
bool resize;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
|
||||
@ -419,10 +313,7 @@ static bool d3d11_gfx_alive(void* data)
|
||||
return !quit;
|
||||
}
|
||||
|
||||
static bool d3d11_gfx_focus(void* data)
|
||||
{
|
||||
return win32_has_focus();
|
||||
}
|
||||
static bool d3d11_gfx_focus(void* data) { return win32_has_focus(); }
|
||||
|
||||
static bool d3d11_gfx_suppress_screensaver(void* data, bool enable)
|
||||
{
|
||||
@ -444,25 +335,26 @@ static void d3d11_gfx_free(void* data)
|
||||
if (!d3d11)
|
||||
return;
|
||||
|
||||
if(d3d11->menu.tex)
|
||||
Release(d3d11->menu.tex);
|
||||
if(d3d11->menu.view)
|
||||
Release(d3d11->menu.view);
|
||||
Release(d3d11->frame.texture.view);
|
||||
Release(d3d11->frame.texture.handle);
|
||||
Release(d3d11->frame.texture.staging);
|
||||
Release(d3d11->frame.vbo);
|
||||
|
||||
Release(d3d11->menu.texture.handle);
|
||||
Release(d3d11->menu.texture.staging);
|
||||
Release(d3d11->menu.texture.view);
|
||||
Release(d3d11->menu.vbo);
|
||||
|
||||
Release(d3d11->blend_enable);
|
||||
Release(d3d11->blend_disable);
|
||||
Release(d3d11->sampler_nearest);
|
||||
Release(d3d11->sampler_linear);
|
||||
Release(d3d11->frame_view);
|
||||
Release(d3d11->frame_default);
|
||||
Release(d3d11->frame_staging);
|
||||
Release(d3d11->ps);
|
||||
Release(d3d11->vs);
|
||||
Release(d3d11->vertexBuffer);
|
||||
Release(d3d11->layout);
|
||||
Release(d3d11->renderTargetView);
|
||||
Release(d3d11->swapChain);
|
||||
Release(d3d11->context);
|
||||
Release(d3d11->ctx);
|
||||
Release(d3d11->device);
|
||||
|
||||
win32_monitor_from_window();
|
||||
@ -470,8 +362,7 @@ static void d3d11_gfx_free(void* data)
|
||||
free(d3d11);
|
||||
}
|
||||
|
||||
static bool d3d11_gfx_set_shader(void* data,
|
||||
enum rarch_shader_type type, const char* path)
|
||||
static bool d3d11_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path)
|
||||
{
|
||||
(void)data;
|
||||
(void)type;
|
||||
@ -480,22 +371,19 @@ static bool d3d11_gfx_set_shader(void* data,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void d3d11_gfx_set_rotation(void* data,
|
||||
unsigned rotation)
|
||||
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)
|
||||
static void d3d11_gfx_viewport_info(void* data, struct video_viewport* vp)
|
||||
{
|
||||
(void)data;
|
||||
(void)vp;
|
||||
}
|
||||
|
||||
static bool d3d11_gfx_read_viewport(void* data,
|
||||
uint8_t* buffer, bool is_idle)
|
||||
static bool d3d11_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle)
|
||||
{
|
||||
(void)data;
|
||||
(void)buffer;
|
||||
@ -503,144 +391,64 @@ static bool d3d11_gfx_read_viewport(void* data,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void d3d11_set_menu_texture_frame(void* data,
|
||||
const void* frame, bool rgb32, unsigned width, unsigned height,
|
||||
float alpha)
|
||||
static void d3d11_set_menu_texture_frame(
|
||||
void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha)
|
||||
{
|
||||
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
|
||||
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
|
||||
int pitch = width * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t));
|
||||
DXGI_FORMAT format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_EX_A4R4G4B4_UNORM;
|
||||
|
||||
if ( d3d11->menu.tex &&
|
||||
(d3d11->menu.width != width ||
|
||||
d3d11->menu.height != height))
|
||||
if (d3d11->menu.texture.desc.Width != width || d3d11->menu.texture.desc.Height != height)
|
||||
{
|
||||
Release(d3d11->menu.tex);
|
||||
d3d11->menu.tex = NULL;
|
||||
d3d11->menu.texture.desc.Format = d3d11_get_closest_match_texture2D(d3d11->device, format);
|
||||
d3d11->menu.texture.desc.Width = width;
|
||||
d3d11->menu.texture.desc.Height = height;
|
||||
d3d11_init_texture(d3d11->device, &d3d11->menu.texture);
|
||||
}
|
||||
|
||||
if (!d3d11->menu.tex)
|
||||
{
|
||||
d3d11->menu.width = width;
|
||||
d3d11->menu.height = height;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc =
|
||||
{
|
||||
.Width = d3d11->menu.width,
|
||||
.Height = d3d11->menu.height,
|
||||
.MipLevels = 1,
|
||||
.ArraySize = 1,
|
||||
.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
.SampleDesc.Count = 1,
|
||||
.SampleDesc.Quality = 0,
|
||||
.Usage = D3D11_USAGE_DYNAMIC,
|
||||
.BindFlags = D3D11_BIND_SHADER_RESOURCE,
|
||||
.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,
|
||||
.MiscFlags = 0,
|
||||
};
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC view_desc =
|
||||
{
|
||||
.Format = desc.Format,
|
||||
.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D,
|
||||
.Texture2D.MostDetailedMip = 0,
|
||||
.Texture2D.MipLevels = -1,
|
||||
};
|
||||
|
||||
D3D11CreateTexture2D(d3d11->device, &desc, NULL, &d3d11->menu.tex);
|
||||
D3D11CreateTexture2DShaderResourceView(d3d11->device,
|
||||
d3d11->menu.tex, &view_desc, &d3d11->menu.view);
|
||||
}
|
||||
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_frame;
|
||||
D3D11MapTexture2D(d3d11->context,
|
||||
d3d11->menu.tex, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_frame);
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
if (rgb32)
|
||||
{
|
||||
const uint32_t *in = frame;
|
||||
uint32_t *out = mapped_frame.pData;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
memcpy(out, in, width * 4);
|
||||
in += width;
|
||||
out += mapped_frame.RowPitch / 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint16_t *in = frame;
|
||||
uint32_t *out = mapped_frame.pData;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
unsigned r = ((in[j] >> 12) & 0xF);
|
||||
unsigned g = ((in[j] >> 8) & 0xF);
|
||||
unsigned b = ((in[j] >> 4) & 0xF);
|
||||
unsigned a = ((in[j] >> 0) & 0xF);
|
||||
|
||||
out[j] = (r << 0) | (r << 4) | (g << 8)
|
||||
| (g << 12) |(b << 16) | (b << 20)
|
||||
| (a << 24) | (a << 28);
|
||||
|
||||
}
|
||||
in += width;
|
||||
out += mapped_frame.RowPitch / 4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
D3D11UnmapTexture2D(d3d11->context, d3d11->menu.tex, 0);
|
||||
}
|
||||
d3d11_update_texture(d3d11->ctx, width, height, pitch, format, frame, &d3d11->menu.texture);
|
||||
}
|
||||
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)
|
||||
{
|
||||
d3d11_video_t* d3d11 = (d3d11_video_t*)data;
|
||||
|
||||
if (!d3d11)
|
||||
return;
|
||||
|
||||
d3d11->menu.enabled = state;
|
||||
d3d11->menu.fullscreen = full_screen;
|
||||
d3d11->menu.enabled = state;
|
||||
d3d11->menu.fullscreen = full_screen;
|
||||
}
|
||||
|
||||
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 */
|
||||
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_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)
|
||||
static void d3d11_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface)
|
||||
{
|
||||
*iface = &d3d11_poke_interface;
|
||||
}
|
||||
|
||||
video_driver_t video_d3d11 =
|
||||
{
|
||||
video_driver_t video_d3d11 = {
|
||||
d3d11_gfx_init,
|
||||
d3d11_gfx_frame,
|
||||
d3d11_gfx_set_nonblock_state,
|
||||
|
@ -25,9 +25,9 @@
|
||||
#include "gfx/common/d3d12_common.h"
|
||||
#include "gfx/common/d3dcompiler_common.h"
|
||||
|
||||
static void d3d12_set_filtering(void *data, unsigned index, bool smooth)
|
||||
static void d3d12_set_filtering(void* data, unsigned index, bool smooth)
|
||||
{
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t *)data;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
if (smooth)
|
||||
d3d12->frame.sampler = d3d12->sampler_linear;
|
||||
@ -35,13 +35,13 @@ static void d3d12_set_filtering(void *data, unsigned index, bool smooth)
|
||||
d3d12->frame.sampler = d3d12->sampler_nearest;
|
||||
}
|
||||
|
||||
static void *d3d12_gfx_init(const video_info_t *video,
|
||||
const input_driver_t **input, void **input_data)
|
||||
static void*
|
||||
d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data)
|
||||
{
|
||||
WNDCLASSEX wndclass = {0};
|
||||
settings_t *settings = config_get_ptr();
|
||||
gfx_ctx_input_t inp = {input, input_data};
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t *)calloc(1, sizeof(*d3d12));
|
||||
WNDCLASSEX wndclass = { 0 };
|
||||
settings_t* settings = config_get_ptr();
|
||||
gfx_ctx_input_t inp = { input, input_data };
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)calloc(1, sizeof(*d3d12));
|
||||
|
||||
if (!d3d12)
|
||||
return NULL;
|
||||
@ -59,9 +59,6 @@ static void *d3d12_gfx_init(const video_info_t *video,
|
||||
|
||||
gfx_ctx_d3d.input_driver(NULL, settings->arrays.input_joypad_driver, input, input_data);
|
||||
|
||||
d3d12->chain.vsync = video->vsync;
|
||||
d3d12->frame.rgb32 = video->rgb32;
|
||||
|
||||
if (!d3d12_init_base(d3d12))
|
||||
goto error;
|
||||
|
||||
@ -78,10 +75,14 @@ static void *d3d12_gfx_init(const video_info_t *video,
|
||||
goto error;
|
||||
|
||||
d3d12_create_fullscreen_quad_vbo(d3d12->device, &d3d12->frame.vbo_view, &d3d12->frame.vbo);
|
||||
d3d12_create_fullscreen_quad_vbo(d3d12->device, &d3d12->menu.vbo_view, &d3d12->menu.vbo);
|
||||
d3d12_create_fullscreen_quad_vbo(d3d12->device, &d3d12->menu.vbo_view, &d3d12->menu.vbo);
|
||||
|
||||
d3d12_set_filtering(d3d12, 0, video->smooth);
|
||||
|
||||
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);
|
||||
|
||||
return d3d12;
|
||||
|
||||
error:
|
||||
@ -90,105 +91,87 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool d3d12_gfx_frame(void *data, const void *frame,
|
||||
unsigned width, unsigned height, uint64_t frame_count,
|
||||
unsigned pitch, const char *msg, video_frame_info_t *video_info)
|
||||
static bool d3d12_gfx_frame(
|
||||
void* data,
|
||||
const void* frame,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
uint64_t frame_count,
|
||||
unsigned pitch,
|
||||
const char* msg,
|
||||
video_frame_info_t* video_info)
|
||||
{
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t *)data;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
(void)msg;
|
||||
|
||||
PERF_START();
|
||||
D3D12ResetCommandAllocator(d3d12->queue.allocator);
|
||||
|
||||
D3D12ResetGraphicsCommandList(d3d12->queue.cmd, d3d12->queue.allocator, d3d12->pipe.handle);
|
||||
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->pipe.rootSignature);
|
||||
{
|
||||
D3D12DescriptorHeap desc_heaps [] = {d3d12->pipe.srv_heap.handle, d3d12->pipe.sampler_heap.handle};
|
||||
D3D12DescriptorHeap desc_heaps[] = { d3d12->pipe.srv_heap.handle,
|
||||
d3d12->pipe.sampler_heap.handle };
|
||||
D3D12SetDescriptorHeaps(d3d12->queue.cmd, countof(desc_heaps), desc_heaps);
|
||||
}
|
||||
|
||||
d3d12_resource_transition(d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
|
||||
D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
d3d12_resource_transition(
|
||||
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(d3d12->queue.cmd, d3d12->chain.desc_handles[d3d12->chain.frame_index],
|
||||
d3d12->chain.clearcolor, 0, NULL);
|
||||
D3D12OMSetRenderTargets(
|
||||
d3d12->queue.cmd, 1, &d3d12->chain.desc_handles[d3d12->chain.frame_index], FALSE, NULL);
|
||||
D3D12ClearRenderTargetView(
|
||||
d3d12->queue.cmd, d3d12->chain.desc_handles[d3d12->chain.frame_index],
|
||||
d3d12->chain.clearcolor, 0, NULL);
|
||||
|
||||
D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
if (data && width && height)
|
||||
{
|
||||
if (!d3d12->frame.tex.handle || (d3d12->frame.tex.desc.Width != width)
|
||||
|| (d3d12->frame.tex.desc.Height != height))
|
||||
if (!d3d12->frame.texture.handle || (d3d12->frame.texture.desc.Width != width) ||
|
||||
(d3d12->frame.texture.desc.Height != height))
|
||||
{
|
||||
if (d3d12->frame.tex.handle)
|
||||
Release(d3d12->frame.tex.handle);
|
||||
|
||||
if (d3d12->frame.tex.upload_buffer)
|
||||
Release(d3d12->frame.tex.upload_buffer);
|
||||
|
||||
d3d12->frame.tex.desc.Width = width;
|
||||
d3d12->frame.tex.desc.Height = height;
|
||||
d3d12->frame.tex.desc.Format = d3d12->frame.rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM :
|
||||
DXGI_FORMAT_B5G6R5_UNORM;
|
||||
d3d12_create_texture(d3d12->device, &d3d12->pipe.srv_heap, SRV_HEAP_SLOT_FRAME_TEXTURE,
|
||||
&d3d12->frame.tex);
|
||||
d3d12->frame.texture.desc.Width = width;
|
||||
d3d12->frame.texture.desc.Height = height;
|
||||
d3d12_init_texture(
|
||||
d3d12->device, &d3d12->pipe.srv_heap, SRV_HEAP_SLOT_FRAME_TEXTURE,
|
||||
&d3d12->frame.texture);
|
||||
}
|
||||
d3d12_update_texture(width, height, pitch, d3d12->format, frame, &d3d12->frame.texture);
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
D3D12_RANGE read_range = {0, 0};
|
||||
const uint8_t *in = frame;
|
||||
uint8_t *out = NULL;
|
||||
|
||||
|
||||
D3D12Map(d3d12->frame.tex.upload_buffer, 0, &read_range, &out);
|
||||
out += d3d12->frame.tex.layout.Offset;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
memcpy(out, in, width * (d3d12->frame.rgb32 ? 4 : 2));
|
||||
in += pitch;
|
||||
out += d3d12->frame.tex.layout.Footprint.RowPitch;
|
||||
}
|
||||
|
||||
D3D12Unmap(d3d12->frame.tex.upload_buffer, 0, NULL);
|
||||
}
|
||||
|
||||
d3d12_upload_texture(d3d12->queue.cmd, &d3d12->frame.tex);
|
||||
|
||||
d3d12_set_texture(d3d12->queue.cmd, &d3d12->frame.tex);
|
||||
d3d12_upload_texture(d3d12->queue.cmd, &d3d12->frame.texture);
|
||||
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);
|
||||
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
|
||||
}
|
||||
|
||||
if (d3d12->menu.enabled && d3d12->menu.tex.handle)
|
||||
if (d3d12->menu.enabled && d3d12->menu.texture.handle)
|
||||
{
|
||||
if (d3d12->menu.tex.dirty)
|
||||
d3d12_upload_texture(d3d12->queue.cmd, &d3d12->menu.tex);
|
||||
if (d3d12->menu.texture.dirty)
|
||||
d3d12_upload_texture(d3d12->queue.cmd, &d3d12->menu.texture);
|
||||
|
||||
d3d12_set_texture(d3d12->queue.cmd, &d3d12->menu.tex);
|
||||
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);
|
||||
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
d3d12_resource_transition(d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
|
||||
d3d12_resource_transition(
|
||||
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);
|
||||
|
||||
#if 1
|
||||
DXGIPresent(d3d12->chain.handle, !!d3d12->chain.vsync, 0);
|
||||
// DXGIPresent(d3d12->chain.handle, !!d3d12->chain.vsync, 0);
|
||||
DXGIPresent(d3d12->chain.handle, 0, 0);
|
||||
#else
|
||||
DXGI_PRESENT_PARAMETERS pp = {0};
|
||||
DXGI_PRESENT_PARAMETERS pp = { 0 };
|
||||
DXGIPresent1(d3d12->swapchain, 0, 0, &pp);
|
||||
#endif
|
||||
|
||||
@ -197,12 +180,14 @@ static bool d3d12_gfx_frame(void *data, const void *frame,
|
||||
|
||||
if (D3D12GetCompletedValue(d3d12->queue.fence) < d3d12->queue.fenceValue)
|
||||
{
|
||||
D3D12SetEventOnCompletion(d3d12->queue.fence, d3d12->queue.fenceValue, d3d12->queue.fenceEvent);
|
||||
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)
|
||||
gfx_ctx_d3d.update_window_title(NULL, video_info);
|
||||
@ -210,17 +195,17 @@ static bool d3d12_gfx_frame(void *data, const void *frame,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void d3d12_gfx_set_nonblock_state(void *data, bool toggle)
|
||||
static void d3d12_gfx_set_nonblock_state(void* data, bool toggle)
|
||||
{
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t *)data;
|
||||
d3d12->chain.vsync = !toggle;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
d3d12->chain.vsync = !toggle;
|
||||
}
|
||||
|
||||
static bool d3d12_gfx_alive(void *data)
|
||||
static bool d3d12_gfx_alive(void* data)
|
||||
{
|
||||
(void)data;
|
||||
bool quit;
|
||||
bool resize;
|
||||
bool quit;
|
||||
bool resize;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
|
||||
@ -232,43 +217,31 @@ static bool d3d12_gfx_alive(void *data)
|
||||
return !quit;
|
||||
}
|
||||
|
||||
static bool d3d12_gfx_focus(void *data)
|
||||
{
|
||||
return win32_has_focus();
|
||||
}
|
||||
static bool d3d12_gfx_focus(void* data) { return win32_has_focus(); }
|
||||
|
||||
static bool d3d12_gfx_suppress_screensaver(void *data, bool enable)
|
||||
static bool d3d12_gfx_suppress_screensaver(void* data, bool enable)
|
||||
{
|
||||
(void)data;
|
||||
(void)enable;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool d3d12_gfx_has_windowed(void *data)
|
||||
static bool d3d12_gfx_has_windowed(void* data)
|
||||
{
|
||||
(void)data;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void d3d12_gfx_free(void *data)
|
||||
static void d3d12_gfx_free(void* data)
|
||||
{
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t *)data;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
Release(d3d12->frame.vbo);
|
||||
|
||||
if (d3d12->frame.tex.handle)
|
||||
Release(d3d12->frame.tex.handle);
|
||||
|
||||
if (d3d12->frame.tex.upload_buffer)
|
||||
Release(d3d12->frame.tex.upload_buffer);
|
||||
|
||||
Release(d3d12->frame.texture.handle);
|
||||
Release(d3d12->frame.texture.upload_buffer);
|
||||
Release(d3d12->menu.vbo);
|
||||
|
||||
if (d3d12->menu.tex.handle)
|
||||
Release(d3d12->menu.tex.handle);
|
||||
|
||||
if (d3d12->menu.tex.handle)
|
||||
Release(d3d12->menu.tex.upload_buffer);
|
||||
Release(d3d12->menu.texture.handle);
|
||||
Release(d3d12->menu.texture.upload_buffer);
|
||||
|
||||
Release(d3d12->pipe.sampler_heap.handle);
|
||||
Release(d3d12->pipe.srv_heap.handle);
|
||||
@ -295,8 +268,7 @@ static void d3d12_gfx_free(void *data)
|
||||
free(d3d12);
|
||||
}
|
||||
|
||||
static bool d3d12_gfx_set_shader(void *data,
|
||||
enum rarch_shader_type type, const char *path)
|
||||
static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path)
|
||||
{
|
||||
(void)data;
|
||||
(void)type;
|
||||
@ -305,21 +277,19 @@ static bool d3d12_gfx_set_shader(void *data,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void d3d12_gfx_set_rotation(void *data,
|
||||
unsigned rotation)
|
||||
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)
|
||||
static void d3d12_gfx_viewport_info(void* data, struct video_viewport* vp)
|
||||
{
|
||||
(void)data;
|
||||
(void)vp;
|
||||
}
|
||||
|
||||
static bool d3d12_gfx_read_viewport(void *data, uint8_t *buffer, bool is_idle)
|
||||
static bool d3d12_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle)
|
||||
{
|
||||
(void)data;
|
||||
(void)buffer;
|
||||
@ -327,78 +297,29 @@ static bool d3d12_gfx_read_viewport(void *data, uint8_t *buffer, bool is_idle)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void d3d12_set_menu_texture_frame(void *data,
|
||||
const void *frame, bool rgb32, unsigned width, unsigned height,
|
||||
float alpha)
|
||||
static void d3d12_set_menu_texture_frame(
|
||||
void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha)
|
||||
{
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t *)data;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
int pitch = width * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t));
|
||||
DXGI_FORMAT format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_EX_A4R4G4B4_UNORM;
|
||||
|
||||
if (!d3d12->menu.tex.handle || (d3d12->menu.tex.desc.Width != width)
|
||||
|| (d3d12->menu.tex.desc.Height = height))
|
||||
if (d3d12->menu.texture.desc.Width != width || d3d12->menu.texture.desc.Height != height)
|
||||
{
|
||||
if (d3d12->menu.tex.handle)
|
||||
Release(d3d12->menu.tex.handle);
|
||||
|
||||
if (d3d12->menu.tex.upload_buffer)
|
||||
Release(d3d12->menu.tex.upload_buffer);
|
||||
|
||||
d3d12->menu.tex.desc.Width = width;
|
||||
d3d12->menu.tex.desc.Height = height;
|
||||
d3d12->menu.tex.desc.Format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_B4G4R4A4_UNORM;
|
||||
d3d12_create_texture(d3d12->device, &d3d12->pipe.srv_heap, SRV_HEAP_SLOT_MENU_TEXTURE,
|
||||
&d3d12->menu.tex);
|
||||
d3d12->menu.texture.desc.Width = width;
|
||||
d3d12->menu.texture.desc.Height = height;
|
||||
d3d12->menu.texture.desc.Format = d3d12_get_closest_match_texture2D(d3d12->device, format);
|
||||
d3d12_init_texture(
|
||||
d3d12->device, &d3d12->pipe.srv_heap, SRV_HEAP_SLOT_MENU_TEXTURE, &d3d12->menu.texture);
|
||||
}
|
||||
|
||||
{
|
||||
unsigned i, j;
|
||||
D3D12_RANGE read_range = {0, 0};
|
||||
uint8_t *out = NULL;
|
||||
d3d12_update_texture(width, height, pitch, format, frame, &d3d12->menu.texture);
|
||||
|
||||
D3D12Map(d3d12->menu.tex.upload_buffer, 0, &read_range, &out);
|
||||
out += d3d12->menu.tex.layout.Offset;
|
||||
|
||||
if (rgb32)
|
||||
{
|
||||
const uint32_t *in = frame;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
memcpy(out, in, width * sizeof(*in));
|
||||
in += width;
|
||||
out += d3d12->menu.tex.layout.Footprint.RowPitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint16_t *in = frame;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
unsigned r = ((in[j] >> 12) & 0xF);
|
||||
unsigned g = ((in[j] >> 8) & 0xF);
|
||||
unsigned b = ((in[j] >> 4) & 0xF);
|
||||
unsigned a = ((in[j] >> 0) & 0xF);
|
||||
|
||||
((uint16_t *)out)[j] = (b << 0) | (g << 4) | (r << 8) | (a << 12);
|
||||
}
|
||||
|
||||
in += width;
|
||||
out += d3d12->menu.tex.layout.Footprint.RowPitch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
D3D12Unmap(d3d12->menu.tex.upload_buffer, 0, NULL);
|
||||
}
|
||||
|
||||
d3d12->menu.tex.dirty = true;
|
||||
d3d12->menu.alpha = alpha;
|
||||
|
||||
{
|
||||
D3D12_RANGE read_range = {0, 0};
|
||||
d3d12_vertex_t *v;
|
||||
D3D12_RANGE read_range = { 0, 0 };
|
||||
d3d12_vertex_t* v;
|
||||
|
||||
D3D12Map(d3d12->menu.vbo, 0, &read_range, &v);
|
||||
v[0].color[3] = alpha;
|
||||
@ -407,51 +328,47 @@ static void d3d12_set_menu_texture_frame(void *data,
|
||||
v[3].color[3] = alpha;
|
||||
D3D12Unmap(d3d12->menu.vbo, 0, NULL);
|
||||
}
|
||||
d3d12->menu.sampler = config_get_ptr()->bools.menu_linear_filter ?
|
||||
d3d12->sampler_linear : d3d12->sampler_nearest;
|
||||
d3d12->menu.sampler = config_get_ptr()->bools.menu_linear_filter ? d3d12->sampler_linear
|
||||
: d3d12->sampler_nearest;
|
||||
}
|
||||
static void d3d12_set_menu_texture_enable(void *data,
|
||||
bool state, bool full_screen)
|
||||
static void d3d12_set_menu_texture_enable(void* data, bool state, bool full_screen)
|
||||
{
|
||||
d3d12_video_t *d3d12 = (d3d12_video_t *)data;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
d3d12->menu.enabled = state;
|
||||
d3d12->menu.fullscreen = full_screen;
|
||||
d3d12->menu.enabled = state;
|
||||
d3d12->menu.fullscreen = full_screen;
|
||||
}
|
||||
|
||||
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 */
|
||||
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_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)
|
||||
static void d3d12_gfx_get_poke_interface(void* data, const video_poke_interface_t** iface)
|
||||
{
|
||||
*iface = &d3d12_poke_interface;
|
||||
}
|
||||
|
||||
video_driver_t video_d3d12 =
|
||||
{
|
||||
video_driver_t video_d3d12 = {
|
||||
d3d12_gfx_init,
|
||||
d3d12_gfx_frame,
|
||||
d3d12_gfx_set_nonblock_state,
|
||||
|
@ -262,6 +262,9 @@ static const video_driver_t *video_drivers[] = {
|
||||
#ifdef XENON
|
||||
&video_xenon360,
|
||||
#endif
|
||||
#if defined(HAVE_D3D10)
|
||||
&video_d3d10,
|
||||
#endif
|
||||
#if defined(HAVE_D3D11)
|
||||
&video_d3d11,
|
||||
#endif
|
||||
|
@ -1337,6 +1337,7 @@ extern video_driver_t video_ctr;
|
||||
extern video_driver_t video_switch;
|
||||
extern video_driver_t video_d3d8;
|
||||
extern video_driver_t video_d3d9;
|
||||
extern video_driver_t video_d3d10;
|
||||
extern video_driver_t video_d3d11;
|
||||
extern video_driver_t video_d3d12;
|
||||
extern video_driver_t video_gx;
|
||||
|
@ -345,6 +345,11 @@ VIDEO DRIVER
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3D10)
|
||||
#include "../gfx/drivers/d3d10.c"
|
||||
#include "../gfx/common/d3d10_common.c"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3D11)
|
||||
#include "../gfx/drivers/d3d11.c"
|
||||
#include "../gfx/common/d3d11_common.c"
|
||||
@ -355,7 +360,7 @@ VIDEO DRIVER
|
||||
#include "../gfx/common/d3d12_common.c"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3D11) || defined(HAVE_D3D12)
|
||||
#if defined(HAVE_D3D10) || defined(HAVE_D3D11) || defined(HAVE_D3D12)
|
||||
#include "../gfx/common/d3dcompiler_common.c"
|
||||
#include "../gfx/common/dxgi_common.c"
|
||||
#endif
|
||||
|
@ -119,6 +119,8 @@ vector<string> overloaded_list =
|
||||
"SetPrivateDataInterface",
|
||||
"SetPrivateData",
|
||||
"GetPrivateData",
|
||||
"Map",
|
||||
"Unmap",
|
||||
"Reset",
|
||||
"Signal",
|
||||
"BeginEvent",
|
||||
@ -136,6 +138,13 @@ vector<string> overloaded_list =
|
||||
"GetContextFlags",
|
||||
"GetCertificate",
|
||||
"GetCertificateSize",
|
||||
"Begin",
|
||||
"End",
|
||||
"GetData",
|
||||
|
||||
"CopySubresourceRegion",
|
||||
"CreateRenderTargetView",
|
||||
"CreateShaderResourceView",
|
||||
};
|
||||
|
||||
vector<string> action_list =
|
||||
@ -174,10 +183,11 @@ vector<string> base_objects_list =
|
||||
{
|
||||
"IUnknown",
|
||||
"ID3D12Object",
|
||||
"ID3D12Resource",
|
||||
// "ID3D12Resource",
|
||||
"IDXGIObject",
|
||||
"IDXGIResource",
|
||||
"D3D11Resource",
|
||||
// "ID3D11Resource",
|
||||
// "ID3D10Resource",
|
||||
};
|
||||
|
||||
//string insert_name(const char* fname, const char* name)
|
||||
|
Loading…
Reference in New Issue
Block a user