New upstream version 23.2.1+dfsg1

This commit is contained in:
Simon Chopin 2019-07-27 14:47:10 +02:00
parent cdc9a9fc87
commit b14f9eae6d
1017 changed files with 37232 additions and 11111 deletions

View file

@ -30,6 +30,7 @@ set_target_properties(libobs-d3d11
PREFIX "")
target_link_libraries(libobs-d3d11
libobs
d3d9
d3d11
dxgi)

View file

@ -17,14 +17,14 @@
#include "d3d11-subsystem.hpp"
inline void gs_vertex_buffer::Rebuild()
void gs_vertex_buffer::Rebuild()
{
uvBuffers.clear();
uvSizes.clear();
BuildBuffers();
}
inline void gs_index_buffer::Rebuild(ID3D11Device *dev)
void gs_index_buffer::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateBuffer(&bd, &srd, &indexBuffer);
if (FAILED(hr))
@ -55,7 +55,7 @@ void gs_texture_2d::RebuildSharedTextureFallback()
isShared = false;
}
inline void gs_texture_2d::Rebuild(ID3D11Device *dev)
void gs_texture_2d::Rebuild(ID3D11Device *dev)
{
HRESULT hr;
if (isShared) {
@ -89,9 +89,61 @@ inline void gs_texture_2d::Rebuild(ID3D11Device *dev)
if (FAILED(hr))
throw HRError("Failed to create GDI surface", hr);
}
acquired = false;
if ((td.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0) {
ComQIPtr<IDXGIResource> dxgi_res(texture);
if (dxgi_res)
GetSharedHandle(dxgi_res);
device_texture_acquire_sync(this, 0, INFINITE);
}
}
inline void gs_zstencil_buffer::Rebuild(ID3D11Device *dev)
void gs_texture_2d::RebuildNV12_Y(ID3D11Device *dev)
{
gs_texture_2d *tex_uv = pairedNV12texture;
HRESULT hr;
hr = dev->CreateTexture2D(&td, nullptr, &texture);
if (FAILED(hr))
throw HRError("Failed to create 2D texture", hr);
hr = dev->CreateShaderResourceView(texture, &resourceDesc, &shaderRes);
if (FAILED(hr))
throw HRError("Failed to create resource view", hr);
if (isRenderTarget)
InitRenderTargets();
tex_uv->RebuildNV12_UV(dev);
acquired = false;
if ((td.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0) {
ComQIPtr<IDXGIResource> dxgi_res(texture);
if (dxgi_res)
GetSharedHandle(dxgi_res);
device_texture_acquire_sync(this, 0, INFINITE);
}
}
void gs_texture_2d::RebuildNV12_UV(ID3D11Device *dev)
{
gs_texture_2d *tex_y = pairedNV12texture;
HRESULT hr;
texture = tex_y->texture;
hr = dev->CreateShaderResourceView(texture, &resourceDesc, &shaderRes);
if (FAILED(hr))
throw HRError("Failed to create resource view", hr);
if (isRenderTarget)
InitRenderTargets();
}
void gs_zstencil_buffer::Rebuild(ID3D11Device *dev)
{
HRESULT hr;
hr = dev->CreateTexture2D(&td, nullptr, &texture);
@ -103,21 +155,21 @@ inline void gs_zstencil_buffer::Rebuild(ID3D11Device *dev)
throw HRError("Failed to create depth stencil view", hr);
}
inline void gs_stage_surface::Rebuild(ID3D11Device *dev)
void gs_stage_surface::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateTexture2D(&td, nullptr, &texture);
if (FAILED(hr))
throw HRError("Failed to create staging surface", hr);
}
inline void gs_sampler_state::Rebuild(ID3D11Device *dev)
void gs_sampler_state::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateSamplerState(&sd, state.Assign());
if (FAILED(hr))
throw HRError("Failed to create sampler state", hr);
}
inline void gs_vertex_shader::Rebuild(ID3D11Device *dev)
void gs_vertex_shader::Rebuild(ID3D11Device *dev)
{
HRESULT hr;
hr = dev->CreateVertexShader(data.data(), data.size(), nullptr, &shader);
@ -142,7 +194,7 @@ inline void gs_vertex_shader::Rebuild(ID3D11Device *dev)
}
}
inline void gs_pixel_shader::Rebuild(ID3D11Device *dev)
void gs_pixel_shader::Rebuild(ID3D11Device *dev)
{
HRESULT hr;
@ -164,7 +216,7 @@ inline void gs_pixel_shader::Rebuild(ID3D11Device *dev)
}
}
inline void gs_swap_chain::Rebuild(ID3D11Device *dev)
void gs_swap_chain::Rebuild(ID3D11Device *dev)
{
HRESULT hr = device->factory->CreateSwapChain(dev, &swapDesc, &swap);
if (FAILED(hr))
@ -172,21 +224,21 @@ inline void gs_swap_chain::Rebuild(ID3D11Device *dev)
Init();
}
inline void SavedBlendState::Rebuild(ID3D11Device *dev)
void SavedBlendState::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateBlendState(&bd, &state);
if (FAILED(hr))
throw HRError("Failed to create blend state", hr);
}
inline void SavedZStencilState::Rebuild(ID3D11Device *dev)
void SavedZStencilState::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateDepthStencilState(&dsd, &state);
if (FAILED(hr))
throw HRError("Failed to create depth stencil state", hr);
}
inline void SavedRasterState::Rebuild(ID3D11Device *dev)
void SavedRasterState::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateRasterizerState(&rd, &state);
if (FAILED(hr))
@ -287,7 +339,14 @@ try {
((gs_index_buffer*)obj)->Rebuild(dev);
break;
case gs_type::gs_texture_2d:
((gs_texture_2d*)obj)->Rebuild(dev);
{
gs_texture_2d *tex = (gs_texture_2d*)obj;
if (!tex->nv12) {
tex->Rebuild(dev);
} else if (!tex->chroma) {
tex->RebuildNV12_Y(dev);
}
}
break;
case gs_type::gs_zstencil_buffer:
((gs_zstencil_buffer*)obj)->Rebuild(dev);

View file

@ -137,8 +137,11 @@ void gs_shader::BuildConstantBuffer()
case GS_SHADER_PARAM_BOOL:
case GS_SHADER_PARAM_INT:
case GS_SHADER_PARAM_FLOAT: size = sizeof(float); break;
case GS_SHADER_PARAM_INT2:
case GS_SHADER_PARAM_VEC2: size = sizeof(vec2); break;
case GS_SHADER_PARAM_INT3:
case GS_SHADER_PARAM_VEC3: size = sizeof(float)*3; break;
case GS_SHADER_PARAM_INT4:
case GS_SHADER_PARAM_VEC4: size = sizeof(vec4); break;
case GS_SHADER_PARAM_MATRIX4X4:
size = sizeof(float)*4*4;

View file

@ -41,3 +41,28 @@ gs_stage_surface::gs_stage_surface(gs_device_t *device, uint32_t width,
if (FAILED(hr))
throw HRError("Failed to create staging surface", hr);
}
gs_stage_surface::gs_stage_surface(gs_device_t *device, uint32_t width,
uint32_t height)
: gs_obj (device, gs_type::gs_stage_surface),
width (width),
height (height),
format (GS_UNKNOWN),
dxgiFormat (DXGI_FORMAT_NV12)
{
HRESULT hr;
memset(&td, 0, sizeof(td));
td.Width = width;
td.Height = height;
td.MipLevels = 1;
td.ArraySize = 1;
td.Format = dxgiFormat;
td.SampleDesc.Count = 1;
td.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
td.Usage = D3D11_USAGE_STAGING;
hr = device->device->CreateTexture2D(&td, NULL, texture.Assign());
if (FAILED(hr))
throw HRError("Failed to create staging surface", hr);
}

View file

@ -18,7 +18,10 @@
#include <cinttypes>
#include <util/base.h>
#include <util/platform.h>
#include <util/dstr.h>
#include <util/util.hpp>
#include <graphics/matrix3.h>
#include <d3d9.h>
#include "d3d11-subsystem.hpp"
struct UnsupportedHWError : HRError {
@ -227,6 +230,120 @@ const static D3D_FEATURE_LEVEL featureLevels[] =
D3D_FEATURE_LEVEL_9_3,
};
/* ------------------------------------------------------------------------- */
#define VERT_IN_OUT "\
struct VertInOut { \
float4 pos : POSITION; \
}; "
#define NV12_Y_PS VERT_IN_OUT "\
float main(VertInOut vert_in) : TARGET \
{ \
return 1.0; \
}"
#define NV12_UV_PS VERT_IN_OUT "\
float2 main(VertInOut vert_in) : TARGET \
{ \
return float2(1.0, 1.0); \
}"
#define NV12_VS VERT_IN_OUT "\
VertInOut main(VertInOut vert_in) \
{ \
VertInOut vert_out; \
vert_out.pos = float4(vert_in.pos.xyz, 1.0); \
return vert_out; \
} "
/* ------------------------------------------------------------------------- */
#define NV12_CX 128
#define NV12_CY 128
bool gs_device::HasBadNV12Output()
try {
vec3 points[4];
vec3_set(&points[0], -1.0f, -1.0f, 0.0f);
vec3_set(&points[1], -1.0f, 1.0f, 0.0f);
vec3_set(&points[2], 1.0f, -1.0f, 0.0f);
vec3_set(&points[3], 1.0f, 1.0f, 0.0f);
gs_texture_2d nv12_y(this, NV12_CX, NV12_CY, GS_R8, 1, nullptr,
GS_RENDER_TARGET | GS_SHARED_KM_TEX, GS_TEXTURE_2D,
false, true);
gs_texture_2d nv12_uv(this, nv12_y.texture,
GS_RENDER_TARGET | GS_SHARED_KM_TEX);
gs_vertex_shader nv12_vs(this, "", NV12_VS);
gs_pixel_shader nv12_y_ps(this, "", NV12_Y_PS);
gs_pixel_shader nv12_uv_ps(this, "", NV12_UV_PS);
gs_stage_surface nv12_stage(this, NV12_CX, NV12_CY);
gs_vb_data *vbd = gs_vbdata_create();
vbd->num = 4;
vbd->points = (vec3*)bmemdup(&points, sizeof(points));
gs_vertex_buffer buf(this, vbd, 0);
device_load_vertexbuffer(this, &buf);
device_load_vertexshader(this, &nv12_vs);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
device_set_viewport(this, 0, 0, NV12_CX, NV12_CY);
device_set_cull_mode(this, GS_NEITHER);
device_enable_depth_test(this, false);
device_enable_blending(this, false);
LoadVertexBufferData();
device_set_render_target(this, &nv12_y, nullptr);
device_load_pixelshader(this, &nv12_y_ps);
UpdateBlendState();
UpdateRasterState();
UpdateZStencilState();
context->Draw(4, 0);
device_set_viewport(this, 0, 0, NV12_CX/2, NV12_CY/2);
device_set_render_target(this, &nv12_uv, nullptr);
device_load_pixelshader(this, &nv12_uv_ps);
UpdateBlendState();
UpdateRasterState();
UpdateZStencilState();
context->Draw(4, 0);
device_load_pixelshader(this, nullptr);
device_load_vertexshader(this, nullptr);
device_set_render_target(this, nullptr, nullptr);
device_stage_texture(this, &nv12_stage, &nv12_y);
uint8_t *data;
uint32_t linesize;
bool bad_driver = false;
if (gs_stagesurface_map(&nv12_stage, &data, &linesize)) {
bad_driver = data[linesize * NV12_CY] == 0;
gs_stagesurface_unmap(&nv12_stage);
} else {
throw "Could not map surface";
}
if (bad_driver) {
blog(LOG_WARNING, "Bad NV12 texture handling detected! "
"Disabling NV12 texture support.");
}
return bad_driver;
} catch (HRError error) {
blog(LOG_WARNING, "HasBadNV12Output failed: %s (%08lX)",
error.str, error.hr);
return false;
} catch (const char *error) {
blog(LOG_WARNING, "HasBadNV12Output failed: %s", error);
return false;
}
void gs_device::InitDevice(uint32_t adapterIdx)
{
wstring adapterName;
@ -244,11 +361,10 @@ void gs_device::InitDevice(uint32_t adapterIdx)
adapterName = (adapter->GetDesc(&desc) == S_OK) ? desc.Description :
L"<unknown>";
char *adapterNameUTF8;
BPtr<char> adapterNameUTF8;
os_wcs_to_utf8_ptr(adapterName.c_str(), 0, &adapterNameUTF8);
blog(LOG_INFO, "Loading up D3D11 on adapter %s (%" PRIu32 ")",
adapterNameUTF8, adapterIdx);
bfree(adapterNameUTF8);
adapterNameUTF8.Get(), adapterIdx);
hr = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN,
NULL, createFlags, featureLevels,
@ -260,6 +376,49 @@ void gs_device::InitDevice(uint32_t adapterIdx)
blog(LOG_INFO, "D3D11 loaded successfully, feature level used: %u",
(unsigned int)levelUsed);
/* ---------------------------------------- */
/* check for nv12 texture output support */
nv12Supported = false;
ComQIPtr<ID3D11Device1> d3d11_1(device);
if (!d3d11_1) {
return;
}
/* needs to support extended resource sharing */
D3D11_FEATURE_DATA_D3D11_OPTIONS opts = {};
hr = d3d11_1->CheckFeatureSupport(
D3D11_FEATURE_D3D11_OPTIONS,
&opts, sizeof(opts));
if (FAILED(hr) || !opts.ExtendedResourceSharing) {
return;
}
/* needs to support the actual format */
UINT support = 0;
hr = device->CheckFormatSupport(
DXGI_FORMAT_NV12,
&support);
if (FAILED(hr)) {
return;
}
if ((support & D3D11_FORMAT_SUPPORT_TEXTURE2D) == 0) {
return;
}
/* must be usable as a render target */
if ((support & D3D11_FORMAT_SUPPORT_RENDER_TARGET) == 0) {
return;
}
if (HasBadNV12Output()) {
return;
}
nv12Supported = true;
}
static inline void ConvertStencilSide(D3D11_DEPTH_STENCILOP_DESC &desc,
@ -505,7 +664,7 @@ static inline void EnumD3DAdapters(
ComPtr<IDXGIFactory1> factory;
ComPtr<IDXGIAdapter1> adapter;
HRESULT hr;
UINT i = 0;
UINT i;
IID factoryIID = (GetWinVer() >= 0x602) ? dxgiFactory2 :
__uuidof(IDXGIFactory1);
@ -514,7 +673,7 @@ static inline void EnumD3DAdapters(
if (FAILED(hr))
throw HRError("Failed to create DXGIFactory", hr);
while (factory->EnumAdapters1(i++, adapter.Assign()) == S_OK) {
for (i = 0; factory->EnumAdapters1(i, adapter.Assign()) == S_OK; ++i) {
DXGI_ADAPTER_DESC desc;
char name[512] = "";
@ -528,7 +687,7 @@ static inline void EnumD3DAdapters(
os_wcs_to_utf8(desc.Description, 0, name, sizeof(name));
if (!callback(param, name, i - 1))
if (!callback(param, name, i))
break;
}
}
@ -550,10 +709,10 @@ bool device_enum_adapters(
static inline void LogAdapterMonitors(IDXGIAdapter1 *adapter)
{
UINT i = 0;
UINT i;
ComPtr<IDXGIOutput> output;
while (adapter->EnumOutputs(i++, &output) == S_OK) {
for (i = 0; adapter->EnumOutputs(i, &output) == S_OK; ++i) {
DXGI_OUTPUT_DESC desc;
if (FAILED(output->GetDesc(&desc)))
continue;
@ -575,7 +734,7 @@ static inline void LogD3DAdapters()
ComPtr<IDXGIFactory1> factory;
ComPtr<IDXGIAdapter1> adapter;
HRESULT hr;
UINT i = 0;
UINT i;
blog(LOG_INFO, "Available Video Adapters: ");
@ -586,7 +745,7 @@ static inline void LogD3DAdapters()
if (FAILED(hr))
throw HRError("Failed to create DXGIFactory", hr);
while (factory->EnumAdapters1(i++, adapter.Assign()) == S_OK) {
for (i = 0; factory->EnumAdapters1(i, adapter.Assign()) == S_OK; ++i) {
DXGI_ADAPTER_DESC desc;
char name[512] = "";
@ -736,8 +895,7 @@ gs_texture_t *device_texture_create(gs_device_t *device, uint32_t width,
gs_texture *texture = NULL;
try {
texture = new gs_texture_2d(device, width, height, color_format,
levels, data, flags, GS_TEXTURE_2D, false,
false);
levels, data, flags, GS_TEXTURE_2D, false);
} catch (HRError error) {
blog(LOG_ERROR, "device_texture_create (D3D11): %s (%08lX)",
error.str, error.hr);
@ -756,8 +914,7 @@ gs_texture_t *device_cubetexture_create(gs_device_t *device, uint32_t size,
gs_texture *texture = NULL;
try {
texture = new gs_texture_2d(device, size, size, color_format,
levels, data, flags, GS_TEXTURE_CUBE, false,
false);
levels, data, flags, GS_TEXTURE_CUBE, false);
} catch (HRError error) {
blog(LOG_ERROR, "device_cubetexture_create (D3D11): %s "
"(%08lX)",
@ -1317,7 +1474,7 @@ void device_stage_texture(gs_device_t *device, gs_stagesurf_t *dst,
throw "Source texture must be a 2D texture";
if (!dst)
throw "Destination surface is NULL";
if (dst->format != src->format)
if (dst->format != GS_UNKNOWN && dst->format != src->format)
throw "Source and destination formats do not match";
if (dst->width != src2d->width ||
dst->height != src2d->height)
@ -2056,6 +2213,29 @@ extern "C" EXPORT bool device_shared_texture_available(void)
return true;
}
extern "C" EXPORT bool device_nv12_available(gs_device_t *device)
{
return device->nv12Supported;
}
extern "C" EXPORT void device_debug_marker_begin(gs_device_t *,
const char *markername, const float color[4])
{
D3DCOLOR bgra = D3DCOLOR_ARGB((DWORD)(255.0f * color[3]),
(DWORD)(255.0f * color[0]), (DWORD)(255.0f * color[1]),
(DWORD)(255.0f * color[2]));
wchar_t wide[64];
os_utf8_to_wcs(markername, 0, wide, _countof(wide));
D3DPERF_BeginEvent(bgra, wide);
}
extern "C" EXPORT void device_debug_marker_end(gs_device_t *)
{
D3DPERF_EndEvent();
}
extern "C" EXPORT gs_texture_t *device_texture_create_gdi(gs_device_t *device,
uint32_t width, uint32_t height)
{
@ -2063,7 +2243,7 @@ extern "C" EXPORT gs_texture_t *device_texture_create_gdi(gs_device_t *device,
try {
texture = new gs_texture_2d(device, width, height, GS_BGRA,
1, nullptr, GS_RENDER_TARGET, GS_TEXTURE_2D,
true, false);
true);
} catch (HRError error) {
blog(LOG_ERROR, "device_texture_create_gdi (D3D11): %s (%08lX)",
error.str, error.hr);
@ -2132,3 +2312,112 @@ extern "C" EXPORT gs_texture_t *device_texture_open_shared(gs_device_t *device,
return texture;
}
extern "C" EXPORT uint32_t device_texture_get_shared_handle(gs_texture_t *tex)
{
gs_texture_2d *tex2d = reinterpret_cast<gs_texture_2d *>(tex);
if (tex->type != GS_TEXTURE_2D)
return GS_INVALID_HANDLE;
return tex2d->isShared ? tex2d->sharedHandle : GS_INVALID_HANDLE;
}
int device_texture_acquire_sync(gs_texture_t *tex, uint64_t key, uint32_t ms)
{
gs_texture_2d *tex2d = reinterpret_cast<gs_texture_2d *>(tex);
if (tex->type != GS_TEXTURE_2D)
return -1;
if (tex2d->acquired)
return 0;
ComQIPtr<IDXGIKeyedMutex> keyedMutex(tex2d->texture);
if (!keyedMutex)
return -1;
HRESULT hr = keyedMutex->AcquireSync(key, ms);
if (hr == S_OK) {
tex2d->acquired = true;
return 0;
} else if (hr == WAIT_TIMEOUT) {
return ETIMEDOUT;
}
return -1;
}
extern "C" EXPORT int device_texture_release_sync(gs_texture_t *tex,
uint64_t key)
{
gs_texture_2d *tex2d = reinterpret_cast<gs_texture_2d *>(tex);
if (tex->type != GS_TEXTURE_2D)
return -1;
if (!tex2d->acquired)
return 0;
ComQIPtr<IDXGIKeyedMutex> keyedMutex(tex2d->texture);
if (!keyedMutex)
return -1;
HRESULT hr = keyedMutex->ReleaseSync(key);
if (hr == S_OK) {
tex2d->acquired = false;
return 0;
}
return -1;
}
extern "C" EXPORT bool device_texture_create_nv12(gs_device_t *device,
gs_texture_t **p_tex_y, gs_texture_t **p_tex_uv,
uint32_t width, uint32_t height, uint32_t flags)
{
if (!device->nv12Supported)
return false;
*p_tex_y = nullptr;
*p_tex_uv = nullptr;
gs_texture_2d *tex_y;
gs_texture_2d *tex_uv;
try {
tex_y = new gs_texture_2d(device, width, height, GS_R8, 1,
nullptr, flags, GS_TEXTURE_2D, false, true);
tex_uv = new gs_texture_2d(device, tex_y->texture, flags);
} catch (HRError error) {
blog(LOG_ERROR, "gs_texture_create_nv12 (D3D11): %s (%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
return false;
} catch (const char *error) {
blog(LOG_ERROR, "gs_texture_create_nv12 (D3D11): %s", error);
return false;
}
tex_y->pairedNV12texture = tex_uv;
tex_uv->pairedNV12texture = tex_y;
*p_tex_y = tex_y;
*p_tex_uv = tex_uv;
return true;
}
extern "C" EXPORT gs_stagesurf_t *device_stagesurface_create_nv12(
gs_device_t *device, uint32_t width, uint32_t height)
{
gs_stage_surface *surf = NULL;
try {
surf = new gs_stage_surface(device, width, height);
} catch (HRError error) {
blog(LOG_ERROR, "device_stagesurface_create (D3D11): %s "
"(%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
}
return surf;
}

View file

@ -27,7 +27,7 @@
#include <windows.h>
#include <dxgi.h>
#include <dxgi1_2.h>
#include <d3d11.h>
#include <d3d11_1.h>
#include <d3dcompiler.h>
#include <util/base.h>
@ -80,6 +80,7 @@ static inline DXGI_FORMAT ConvertGSTextureFormat(gs_color_format format)
case GS_DXT1: return DXGI_FORMAT_BC1_UNORM;
case GS_DXT3: return DXGI_FORMAT_BC2_UNORM;
case GS_DXT5: return DXGI_FORMAT_BC3_UNORM;
case GS_R8G8: return DXGI_FORMAT_R8G8_UNORM;
}
return DXGI_FORMAT_UNKNOWN;
@ -90,6 +91,7 @@ static inline gs_color_format ConvertDXGITextureFormat(DXGI_FORMAT format)
switch ((unsigned long)format) {
case DXGI_FORMAT_A8_UNORM: return GS_A8;
case DXGI_FORMAT_R8_UNORM: return GS_R8;
case DXGI_FORMAT_R8G8_UNORM: return GS_R8G8;
case DXGI_FORMAT_R8G8B8A8_UNORM: return GS_RGBA;
case DXGI_FORMAT_B8G8R8X8_UNORM: return GS_BGRX;
case DXGI_FORMAT_B8G8R8A8_UNORM: return GS_BGRA;
@ -267,7 +269,7 @@ struct gs_vertex_buffer : gs_obj {
uvBuffers.clear();
}
inline void Rebuild();
void Rebuild();
gs_vertex_buffer(gs_device_t *device, struct gs_vb_data *data,
uint32_t flags);
@ -294,7 +296,7 @@ struct gs_index_buffer : gs_obj {
void InitBuffer();
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release() {indexBuffer.Release();}
@ -310,7 +312,7 @@ struct gs_texture : gs_obj {
ComPtr<ID3D11ShaderResourceView> shaderRes;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesc = {};
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline gs_texture(gs_texture_type type, uint32_t levels,
gs_color_format format)
@ -344,13 +346,19 @@ struct gs_texture_2d : gs_texture {
ComPtr<IDXGISurface1> gdiSurface;
uint32_t width = 0, height = 0;
uint32_t flags = 0;
DXGI_FORMAT dxgiFormat = DXGI_FORMAT_UNKNOWN;
bool isRenderTarget = false;
bool isGDICompatible = false;
bool isDynamic = false;
bool isShared = false;
bool genMipmaps = false;
uint32_t sharedHandle = 0;
uint32_t sharedHandle = GS_INVALID_HANDLE;
gs_texture_2d *pairedNV12texture = nullptr;
bool nv12 = false;
bool chroma = false;
bool acquired = false;
vector<vector<uint8_t>> data;
vector<D3D11_SUBRESOURCE_DATA> srd;
@ -361,9 +369,12 @@ struct gs_texture_2d : gs_texture {
void InitResourceView();
void InitRenderTargets();
void BackupTexture(const uint8_t **data);
void GetSharedHandle(IDXGIResource *dxgi_res);
void RebuildSharedTextureFallback();
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
void RebuildNV12_Y(ID3D11Device *dev);
void RebuildNV12_UV(ID3D11Device *dev);
inline void Release()
{
@ -382,8 +393,11 @@ struct gs_texture_2d : gs_texture {
gs_texture_2d(gs_device_t *device, uint32_t width, uint32_t height,
gs_color_format colorFormat, uint32_t levels,
const uint8_t **data, uint32_t flags,
gs_texture_type type, bool gdiCompatible, bool shared);
gs_texture_type type, bool gdiCompatible,
bool nv12 = false);
gs_texture_2d(gs_device_t *device, ID3D11Texture2D *nv12,
uint32_t flags);
gs_texture_2d(gs_device_t *device, uint32_t handle);
};
@ -400,7 +414,7 @@ struct gs_zstencil_buffer : gs_obj {
void InitBuffer();
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release()
{
@ -427,7 +441,7 @@ struct gs_stage_surface : gs_obj {
gs_color_format format;
DXGI_FORMAT dxgiFormat;
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release()
{
@ -436,6 +450,7 @@ struct gs_stage_surface : gs_obj {
gs_stage_surface(gs_device_t *device, uint32_t width, uint32_t height,
gs_color_format colorFormat);
gs_stage_surface(gs_device_t *device, uint32_t width, uint32_t height);
};
struct gs_sampler_state : gs_obj {
@ -443,7 +458,7 @@ struct gs_sampler_state : gs_obj {
D3D11_SAMPLER_DESC sd = {};
gs_sampler_info info;
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release() {state.Release();}
@ -532,7 +547,7 @@ struct gs_vertex_shader : gs_shader {
bool hasTangents;
uint32_t nTexUnits;
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release()
{
@ -579,7 +594,7 @@ struct gs_pixel_shader : gs_shader {
ComPtr<ID3D11PixelShader> shader;
vector<unique_ptr<ShaderSampler>> samplers;
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release()
{
@ -615,7 +630,7 @@ struct gs_swap_chain : gs_obj {
void Resize(uint32_t cx, uint32_t cy);
void Init();
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release()
{
@ -644,7 +659,7 @@ struct BlendState {
srcFactorC (GS_BLEND_SRCALPHA),
destFactorC (GS_BLEND_INVSRCALPHA),
srcFactorA (GS_BLEND_ONE),
destFactorA (GS_BLEND_ONE),
destFactorA (GS_BLEND_INVSRCALPHA),
redEnabled (true),
greenEnabled (true),
blueEnabled (true),
@ -662,7 +677,7 @@ struct SavedBlendState : BlendState {
ComPtr<ID3D11BlendState> state;
D3D11_BLEND_DESC bd;
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release()
{
@ -719,7 +734,7 @@ struct SavedZStencilState : ZStencilState {
ComPtr<ID3D11DepthStencilState> state;
D3D11_DEPTH_STENCIL_DESC dsd;
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release()
{
@ -754,7 +769,7 @@ struct SavedRasterState : RasterState {
ComPtr<ID3D11RasterizerState> state;
D3D11_RASTERIZER_DESC rd;
inline void Rebuild(ID3D11Device *dev);
void Rebuild(ID3D11Device *dev);
inline void Release()
{
@ -779,6 +794,7 @@ struct gs_device {
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
uint32_t adpIdx = 0;
bool nv12Supported = false;
gs_texture_2d *curRenderTarget = nullptr;
gs_zstencil_buffer *curZStencilBuffer = nullptr;
@ -845,6 +861,11 @@ struct gs_device {
void RebuildDevice();
bool HasBadNV12Output();
gs_device(uint32_t adapterIdx);
~gs_device();
};
extern "C" EXPORT int device_texture_acquire_sync(gs_texture_t *tex,
uint64_t key, uint32_t ms);

View file

@ -71,6 +71,20 @@ void gs_texture_2d::BackupTexture(const uint8_t **data)
}
}
void gs_texture_2d::GetSharedHandle(IDXGIResource *dxgi_res)
{
HANDLE handle;
HRESULT hr;
hr = dxgi_res->GetSharedHandle(&handle);
if (FAILED(hr)) {
blog(LOG_WARNING, "GetSharedHandle: Failed to "
"get shared handle: %08lX", hr);
} else {
sharedHandle = (uint32_t)(uintptr_t)handle;
}
}
void gs_texture_2d::InitTexture(const uint8_t **data)
{
HRESULT hr;
@ -80,7 +94,7 @@ void gs_texture_2d::InitTexture(const uint8_t **data)
td.Height = height;
td.MipLevels = genMipmaps ? 0 : levels;
td.ArraySize = type == GS_TEXTURE_CUBE ? 6 : 1;
td.Format = dxgiFormat;
td.Format = nv12 ? DXGI_FORMAT_NV12 : dxgiFormat;
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
td.SampleDesc.Count = 1;
td.CPUAccessFlags = isDynamic ? D3D11_CPU_ACCESS_WRITE : 0;
@ -96,6 +110,11 @@ void gs_texture_2d::InitTexture(const uint8_t **data)
if (isGDICompatible)
td.MiscFlags |= D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
if ((flags & GS_SHARED_KM_TEX) != 0)
td.MiscFlags |= D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
else if ((flags & GS_SHARED_TEX) != 0)
td.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
if (data) {
BackupTexture(data);
InitSRD(srd);
@ -112,6 +131,36 @@ void gs_texture_2d::InitTexture(const uint8_t **data)
if (FAILED(hr))
throw HRError("Failed to create GDI surface", hr);
}
if (isShared) {
ComPtr<IDXGIResource> dxgi_res;
texture->SetEvictionPriority(DXGI_RESOURCE_PRIORITY_MAXIMUM);
hr = texture->QueryInterface(__uuidof(IDXGIResource),
(void**)&dxgi_res);
if (FAILED(hr)) {
blog(LOG_WARNING, "InitTexture: Failed to query "
"interface: %08lX", hr);
} else {
GetSharedHandle(dxgi_res);
if (flags & GS_SHARED_KM_TEX) {
ComPtr<IDXGIKeyedMutex> km;
hr = texture->QueryInterface(
__uuidof(IDXGIKeyedMutex),
(void**)&km);
if (FAILED(hr)) {
throw HRError("Failed to query "
"IDXGIKeyedMutex",
hr);
}
km->AcquireSync(0, INFINITE);
acquired = true;
}
}
}
}
void gs_texture_2d::InitResourceView()
@ -123,10 +172,12 @@ void gs_texture_2d::InitResourceView()
if (type == GS_TEXTURE_CUBE) {
resourceDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
resourceDesc.TextureCube.MipLevels = genMipmaps ? -1 : 1;
resourceDesc.TextureCube.MipLevels =
genMipmaps || !levels ? -1 : levels;
} else {
resourceDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceDesc.Texture2D.MipLevels = genMipmaps ? -1 : 1;
resourceDesc.Texture2D.MipLevels =
genMipmaps || !levels ? -1 : levels;
}
hr = device->device->CreateShaderResourceView(texture, &resourceDesc,
@ -139,7 +190,12 @@ void gs_texture_2d::InitRenderTargets()
{
HRESULT hr;
if (type == GS_TEXTURE_2D) {
hr = device->device->CreateRenderTargetView(texture, NULL,
D3D11_RENDER_TARGET_VIEW_DESC rtv;
rtv.Format = dxgiFormat;
rtv.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtv.Texture2D.MipSlice = 0;
hr = device->device->CreateRenderTargetView(texture, &rtv,
renderTarget[0].Assign());
if (FAILED(hr))
throw HRError("Failed to create render target view",
@ -162,20 +218,25 @@ void gs_texture_2d::InitRenderTargets()
}
}
#define SHARED_FLAGS (GS_SHARED_TEX | GS_SHARED_KM_TEX)
gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t width,
uint32_t height, gs_color_format colorFormat, uint32_t levels,
const uint8_t **data, uint32_t flags, gs_texture_type type,
bool gdiCompatible, bool shared)
const uint8_t **data, uint32_t flags_, gs_texture_type type,
bool gdiCompatible, bool nv12_)
: gs_texture (device, gs_type::gs_texture_2d, type, levels,
colorFormat),
width (width),
height (height),
flags (flags_),
dxgiFormat (ConvertGSTextureFormat(format)),
isRenderTarget ((flags & GS_RENDER_TARGET) != 0),
isRenderTarget ((flags_ & GS_RENDER_TARGET) != 0),
isGDICompatible (gdiCompatible),
isDynamic ((flags & GS_DYNAMIC) != 0),
isShared (shared),
genMipmaps ((flags & GS_BUILD_MIPMAPS) != 0)
isDynamic ((flags_ & GS_DYNAMIC) != 0),
isShared ((flags_ & SHARED_FLAGS) != 0),
genMipmaps ((flags_ & GS_BUILD_MIPMAPS) != 0),
sharedHandle (GS_INVALID_HANDLE),
nv12 (nv12_)
{
InitTexture(data);
InitResourceView();
@ -184,6 +245,33 @@ gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t width,
InitRenderTargets();
}
gs_texture_2d::gs_texture_2d(gs_device_t *device, ID3D11Texture2D *nv12tex,
uint32_t flags_)
: gs_texture (device, gs_type::gs_texture_2d, GS_TEXTURE_2D),
isRenderTarget ((flags_ & GS_RENDER_TARGET) != 0),
isDynamic ((flags_ & GS_DYNAMIC) != 0),
isShared ((flags_ & SHARED_FLAGS) != 0),
genMipmaps ((flags_ & GS_BUILD_MIPMAPS) != 0),
nv12 (true)
{
texture = nv12tex;
texture->GetDesc(&td);
this->type = GS_TEXTURE_2D;
this->format = GS_R8G8;
this->flags = flags_;
this->levels = 1;
this->device = device;
this->chroma = true;
this->width = td.Width / 2;
this->height = td.Height / 2;
this->dxgiFormat = DXGI_FORMAT_R8G8_UNORM;
InitResourceView();
if (isRenderTarget)
InitRenderTargets();
}
gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t handle)
: gs_texture (device, gs_type::gs_texture_2d,
GS_TEXTURE_2D),