libobs/graphics, libobs-d3d11: Add P010 support
This commit is contained in:
parent
a147315f33
commit
fee3703f40
9 changed files with 200 additions and 48 deletions
|
|
@ -122,9 +122,9 @@ void gs_texture_2d::Rebuild(ID3D11Device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
void gs_texture_2d::RebuildNV12_Y(ID3D11Device *dev)
|
||||
void gs_texture_2d::RebuildPaired_Y(ID3D11Device *dev)
|
||||
{
|
||||
gs_texture_2d *tex_uv = pairedNV12texture;
|
||||
gs_texture_2d *tex_uv = pairedTexture;
|
||||
HRESULT hr;
|
||||
|
||||
hr = dev->CreateTexture2D(&td, nullptr, &texture);
|
||||
|
|
@ -147,7 +147,7 @@ void gs_texture_2d::RebuildNV12_Y(ID3D11Device *dev)
|
|||
if (isRenderTarget)
|
||||
InitRenderTargets();
|
||||
|
||||
tex_uv->RebuildNV12_UV(dev);
|
||||
tex_uv->RebuildPaired_UV(dev);
|
||||
|
||||
acquired = false;
|
||||
|
||||
|
|
@ -159,9 +159,9 @@ void gs_texture_2d::RebuildNV12_Y(ID3D11Device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
void gs_texture_2d::RebuildNV12_UV(ID3D11Device *dev)
|
||||
void gs_texture_2d::RebuildPaired_UV(ID3D11Device *dev)
|
||||
{
|
||||
gs_texture_2d *tex_y = pairedNV12texture;
|
||||
gs_texture_2d *tex_y = pairedTexture;
|
||||
HRESULT hr;
|
||||
|
||||
texture = tex_y->texture;
|
||||
|
|
@ -501,10 +501,10 @@ try {
|
|||
break;
|
||||
case gs_type::gs_texture_2d: {
|
||||
gs_texture_2d *tex = (gs_texture_2d *)obj;
|
||||
if (!tex->nv12) {
|
||||
if (!tex->pairedTexture) {
|
||||
tex->Rebuild(dev);
|
||||
} else if (!tex->chroma) {
|
||||
tex->RebuildNV12_Y(dev);
|
||||
tex->RebuildPaired_Y(dev);
|
||||
}
|
||||
} break;
|
||||
case gs_type::gs_zstencil_buffer:
|
||||
|
|
|
|||
|
|
@ -43,12 +43,12 @@ gs_stage_surface::gs_stage_surface(gs_device_t *device, uint32_t width,
|
|||
}
|
||||
|
||||
gs_stage_surface::gs_stage_surface(gs_device_t *device, uint32_t width,
|
||||
uint32_t height)
|
||||
uint32_t height, bool p010)
|
||||
: gs_obj(device, gs_type::gs_stage_surface),
|
||||
width(width),
|
||||
height(height),
|
||||
format(GS_UNKNOWN),
|
||||
dxgiFormat(DXGI_FORMAT_NV12)
|
||||
dxgiFormat(p010 ? DXGI_FORMAT_P010 : DXGI_FORMAT_NV12)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ try {
|
|||
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_stage_surface nv12_stage(this, NV12_CX, NV12_CY, false);
|
||||
|
||||
gs_vb_data *vbd = gs_vbdata_create();
|
||||
vbd->num = 4;
|
||||
|
|
@ -516,6 +516,16 @@ static bool set_priority(ID3D11Device *device)
|
|||
|
||||
#endif
|
||||
|
||||
static bool CheckFormat(ID3D11Device *device, DXGI_FORMAT format)
|
||||
{
|
||||
constexpr UINT required = D3D11_FORMAT_SUPPORT_TEXTURE2D |
|
||||
D3D11_FORMAT_SUPPORT_RENDER_TARGET;
|
||||
|
||||
UINT support = 0;
|
||||
return SUCCEEDED(device->CheckFormatSupport(format, &support)) &&
|
||||
((support & required) == required);
|
||||
}
|
||||
|
||||
void gs_device::InitDevice(uint32_t adapterIdx)
|
||||
{
|
||||
wstring adapterName;
|
||||
|
|
@ -567,6 +577,7 @@ void gs_device::InitDevice(uint32_t adapterIdx)
|
|||
/* check for nv12 texture output support */
|
||||
|
||||
nv12Supported = false;
|
||||
p010Supported = false;
|
||||
|
||||
/* WARP NV12 support is suspected to be buggy on older Windows */
|
||||
if (desc.VendorId == 0x1414 && desc.DeviceId == 0x8c) {
|
||||
|
|
@ -586,27 +597,9 @@ void gs_device::InitDevice(uint32_t adapterIdx)
|
|||
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;
|
||||
nv12Supported = CheckFormat(device, DXGI_FORMAT_NV12) &&
|
||||
!HasBadNV12Output();
|
||||
p010Supported = nv12Supported && CheckFormat(device, DXGI_FORMAT_P010);
|
||||
}
|
||||
|
||||
static inline void ConvertStencilSide(D3D11_DEPTH_STENCILOP_DESC &desc,
|
||||
|
|
@ -2924,6 +2917,11 @@ extern "C" EXPORT bool device_nv12_available(gs_device_t *device)
|
|||
return device->nv12Supported;
|
||||
}
|
||||
|
||||
extern "C" EXPORT bool device_p010_available(gs_device_t *device)
|
||||
{
|
||||
return device->p010Supported;
|
||||
}
|
||||
|
||||
extern "C" EXPORT void device_debug_marker_begin(gs_device_t *,
|
||||
const char *markername,
|
||||
const float color[4])
|
||||
|
|
@ -3143,8 +3141,47 @@ device_texture_create_nv12(gs_device_t *device, gs_texture_t **p_tex_y,
|
|||
return false;
|
||||
}
|
||||
|
||||
tex_y->pairedNV12texture = tex_uv;
|
||||
tex_uv->pairedNV12texture = tex_y;
|
||||
tex_y->pairedTexture = tex_uv;
|
||||
tex_uv->pairedTexture = tex_y;
|
||||
|
||||
*p_tex_y = tex_y;
|
||||
*p_tex_uv = tex_uv;
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" EXPORT bool
|
||||
device_texture_create_p010(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->p010Supported)
|
||||
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_R16, 1,
|
||||
nullptr, flags, GS_TEXTURE_2D, false,
|
||||
true);
|
||||
tex_uv = new gs_texture_2d(device, tex_y->texture, flags);
|
||||
|
||||
} catch (const HRError &error) {
|
||||
blog(LOG_ERROR, "gs_texture_create_p010 (D3D11): %s (%08lX)",
|
||||
error.str, error.hr);
|
||||
LogD3D11ErrorDetails(error, device);
|
||||
return false;
|
||||
|
||||
} catch (const char *error) {
|
||||
blog(LOG_ERROR, "gs_texture_create_p010 (D3D11): %s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
tex_y->pairedTexture = tex_uv;
|
||||
tex_uv->pairedTexture = tex_y;
|
||||
|
||||
*p_tex_y = tex_y;
|
||||
*p_tex_uv = tex_uv;
|
||||
|
|
@ -3157,7 +3194,25 @@ device_stagesurface_create_nv12(gs_device_t *device, uint32_t width,
|
|||
{
|
||||
gs_stage_surface *surf = NULL;
|
||||
try {
|
||||
surf = new gs_stage_surface(device, width, height);
|
||||
surf = new gs_stage_surface(device, width, height, false);
|
||||
} catch (const HRError &error) {
|
||||
blog(LOG_ERROR,
|
||||
"device_stagesurface_create (D3D11): %s "
|
||||
"(%08lX)",
|
||||
error.str, error.hr);
|
||||
LogD3D11ErrorDetails(error, device);
|
||||
}
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
extern "C" EXPORT gs_stagesurf_t *
|
||||
device_stagesurface_create_p010(gs_device_t *device, uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
gs_stage_surface *surf = NULL;
|
||||
try {
|
||||
surf = new gs_stage_surface(device, width, height, true);
|
||||
} catch (const HRError &error) {
|
||||
blog(LOG_ERROR,
|
||||
"device_stagesurface_create (D3D11): %s "
|
||||
|
|
|
|||
|
|
@ -515,8 +515,8 @@ struct gs_texture_2d : gs_texture {
|
|||
bool genMipmaps = false;
|
||||
uint32_t sharedHandle = GS_INVALID_HANDLE;
|
||||
|
||||
gs_texture_2d *pairedNV12texture = nullptr;
|
||||
bool nv12 = false;
|
||||
gs_texture_2d *pairedTexture = nullptr;
|
||||
bool twoPlane = false;
|
||||
bool chroma = false;
|
||||
bool acquired = false;
|
||||
|
||||
|
|
@ -533,8 +533,8 @@ struct gs_texture_2d : gs_texture {
|
|||
|
||||
void RebuildSharedTextureFallback();
|
||||
void Rebuild(ID3D11Device *dev);
|
||||
void RebuildNV12_Y(ID3D11Device *dev);
|
||||
void RebuildNV12_UV(ID3D11Device *dev);
|
||||
void RebuildPaired_Y(ID3D11Device *dev);
|
||||
void RebuildPaired_UV(ID3D11Device *dev);
|
||||
|
||||
inline void Release()
|
||||
{
|
||||
|
|
@ -554,7 +554,7 @@ struct gs_texture_2d : gs_texture {
|
|||
gs_color_format colorFormat, uint32_t levels,
|
||||
const uint8_t *const *data, uint32_t flags,
|
||||
gs_texture_type type, bool gdiCompatible,
|
||||
bool nv12 = false);
|
||||
bool twoPlane = false);
|
||||
|
||||
gs_texture_2d(gs_device_t *device, ID3D11Texture2D *nv12,
|
||||
uint32_t flags);
|
||||
|
|
@ -654,7 +654,8 @@ 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);
|
||||
gs_stage_surface(gs_device_t *device, uint32_t width, uint32_t height,
|
||||
bool p010);
|
||||
};
|
||||
|
||||
struct gs_sampler_state : gs_obj {
|
||||
|
|
@ -985,6 +986,7 @@ struct gs_device {
|
|||
ComPtr<ID3D11DeviceContext> context;
|
||||
uint32_t adpIdx = 0;
|
||||
bool nv12Supported = false;
|
||||
bool p010Supported = false;
|
||||
|
||||
gs_texture_2d *curRenderTarget = nullptr;
|
||||
gs_zstencil_buffer *curZStencilBuffer = nullptr;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,9 @@ void gs_texture_2d::InitTexture(const uint8_t *const *data)
|
|||
td.Height = height;
|
||||
td.MipLevels = genMipmaps ? 0 : levels;
|
||||
td.ArraySize = type == GS_TEXTURE_CUBE ? 6 : 1;
|
||||
td.Format = nv12 ? DXGI_FORMAT_NV12 : dxgiFormatResource;
|
||||
td.Format = twoPlane ? ((format == GS_R16) ? DXGI_FORMAT_P010
|
||||
: DXGI_FORMAT_NV12)
|
||||
: dxgiFormatResource;
|
||||
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
td.SampleDesc.Count = 1;
|
||||
td.CPUAccessFlags = isDynamic ? D3D11_CPU_ACCESS_WRITE : 0;
|
||||
|
|
@ -266,7 +268,7 @@ 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 *const *data,
|
||||
uint32_t flags_, gs_texture_type type,
|
||||
bool gdiCompatible, bool nv12_)
|
||||
bool gdiCompatible, bool twoPlane_)
|
||||
: gs_texture(device, gs_type::gs_texture_2d, type, levels, colorFormat),
|
||||
width(width),
|
||||
height(height),
|
||||
|
|
@ -280,7 +282,7 @@ gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t width,
|
|||
isShared((flags_ & SHARED_FLAGS) != 0),
|
||||
genMipmaps((flags_ & GS_BUILD_MIPMAPS) != 0),
|
||||
sharedHandle(GS_INVALID_HANDLE),
|
||||
nv12(nv12_)
|
||||
twoPlane(twoPlane_)
|
||||
{
|
||||
InitTexture(data);
|
||||
InitResourceView();
|
||||
|
|
@ -296,22 +298,26 @@ gs_texture_2d::gs_texture_2d(gs_device_t *device, ID3D11Texture2D *nv12tex,
|
|||
isDynamic((flags_ & GS_DYNAMIC) != 0),
|
||||
isShared((flags_ & SHARED_FLAGS) != 0),
|
||||
genMipmaps((flags_ & GS_BUILD_MIPMAPS) != 0),
|
||||
nv12(true),
|
||||
twoPlane(true),
|
||||
texture(nv12tex)
|
||||
{
|
||||
texture->GetDesc(&td);
|
||||
|
||||
const bool p010 = td.Format == DXGI_FORMAT_P010;
|
||||
const DXGI_FORMAT dxgi_format = p010 ? DXGI_FORMAT_R16G16_UNORM
|
||||
: DXGI_FORMAT_R8G8_UNORM;
|
||||
|
||||
this->type = GS_TEXTURE_2D;
|
||||
this->format = GS_R8G8;
|
||||
this->format = p010 ? GS_RG16 : 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->dxgiFormatResource = DXGI_FORMAT_R8G8_UNORM;
|
||||
this->dxgiFormatView = DXGI_FORMAT_R8G8_UNORM;
|
||||
this->dxgiFormatViewLinear = DXGI_FORMAT_R8G8_UNORM;
|
||||
this->dxgiFormatResource = dxgi_format;
|
||||
this->dxgiFormatView = dxgi_format;
|
||||
this->dxgiFormatViewLinear = dxgi_format;
|
||||
|
||||
InitResourceView();
|
||||
if (isRenderTarget)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue