[vlc-devel] [PATCH] direct3d11: simplify the I420 handling
Steve Lhomme
robux4 at videolabs.io
Mon Oct 16 13:25:33 CEST 2017
Rather than use buffers in the GPU and then copy in the staging texture, use
CPU buffers and copy in the staging texture from there.
Fixes #18766
---
In Direct3D9 we can create I420 textures, but given the fast speed to read/write
from these buffers it's unlikely to be in the GPU. There must be a copy later
when actually displaying those.
---
modules/video_chroma/d3d11_fmt.h | 1 -
modules/video_output/win32/direct3d11.c | 324 +++++++++++++-------------------
2 files changed, 131 insertions(+), 194 deletions(-)
diff --git a/modules/video_chroma/d3d11_fmt.h b/modules/video_chroma/d3d11_fmt.h
index db462111ba..d88c3d2419 100644
--- a/modules/video_chroma/d3d11_fmt.h
+++ b/modules/video_chroma/d3d11_fmt.h
@@ -46,7 +46,6 @@ struct picture_sys_t
ID3D11VideoProcessorOutputView *processorOutput; /* when used as processor output */
ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW];
DXGI_FORMAT formatTexture;
- bool mapped;
};
#include "../codec/avcodec/va_surface.h"
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index b8241f3df4..5914d65487 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -412,47 +412,6 @@ static void Direct3D11UnmapPoolTexture(picture_t *picture)
ID3D11DeviceContext_Unmap(p_sys->context, p_sys->resource[KNOWN_DXGI_INDEX], 0);
}
-static int Direct3D11LockDirectTexture(picture_t *picture)
-{
- picture_sys_t *p_sys = picture->p_sys;
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT hr;
- D3D11_TEXTURE2D_DESC texDesc;
- int i;
-
- for (i = 0; i < picture->i_planes; i++) {
- hr = ID3D11DeviceContext_Map(p_sys->context, p_sys->resource[i], 0, D3D11_MAP_WRITE, 0, &mappedResource);
- if( FAILED(hr) )
- break;
- ID3D11Texture2D_GetDesc(p_sys->texture[i], &texDesc);
- picture->p[i].p_pixels = mappedResource.pData;
- picture->p[i].i_pitch = mappedResource.RowPitch;
- picture->p[i].i_lines = texDesc.Height;
- assert(picture->p[i].i_visible_pitch <= picture->p[i].i_pitch);
- assert(picture->p[i].i_visible_lines <= picture->p[i].i_lines);
- }
-
- if( FAILED(hr) )
- {
- while (i-- > 0)
- ID3D11DeviceContext_Unmap(p_sys->context, p_sys->resource[i+1], 0);
- return VLC_EGENERIC;
- }
-
- p_sys->mapped = true;
- return VLC_SUCCESS;
-}
-
-static void Direct3D11UnlockDirectTexture(picture_t *picture)
-{
- picture_sys_t *p_sys = ActivePictureSys(picture);
- if (p_sys->mapped) {
- for (int i = 0; i < picture->i_planes; i++)
- ID3D11DeviceContext_Unmap(p_sys->context, p_sys->resource[i], 0);
- p_sys->mapped = false;
- }
-}
-
#if !VLC_WINSTORE_APP
static int OpenHwnd(vout_display_t *vd)
{
@@ -623,9 +582,8 @@ static void Close(vlc_object_t *object)
}
static int AllocateTextures(vout_display_t *vd, const d3d_format_t *cfg,
- video_format_t *fmt, unsigned pool_size,
- ID3D11Texture2D *textures[],
- bool pool_type_display)
+ const video_format_t *fmt, unsigned pool_size,
+ ID3D11Texture2D *textures[])
{
vout_display_sys_t *sys = vd->sys;
plane_t planes[PICTURE_PLANE_MAX];
@@ -637,13 +595,22 @@ static int AllocateTextures(vout_display_t *vd, const d3d_format_t *cfg,
texDesc.MipLevels = 1;
texDesc.SampleDesc.Count = 1;
texDesc.MiscFlags = 0; //D3D11_RESOURCE_MISC_SHARED;
+ texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ if (is_d3d11_opaque(fmt->i_chroma)) {
+ texDesc.BindFlags |= D3D11_BIND_DECODER;
+ texDesc.Usage = D3D11_USAGE_DEFAULT;
+ texDesc.CPUAccessFlags = 0;
+ } else {
+ texDesc.Usage = D3D11_USAGE_DYNAMIC;
+ texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ }
+ texDesc.ArraySize = pool_size;
+
const vlc_chroma_description_t *p_chroma_desc = vlc_fourcc_GetChromaDescription( fmt->i_chroma );
if( !p_chroma_desc )
return VLC_EGENERIC;
if (cfg->formatTexture == DXGI_FORMAT_UNKNOWN) {
- int i_width_aligned = fmt->i_width;
- int i_height_aligned = fmt->i_height;
if (p_chroma_desc->plane_count == 0)
{
msg_Dbg(vd, "failed to get the pixel format planes for %4.4s", (char *)&fmt->i_chroma);
@@ -656,47 +623,19 @@ static int AllocateTextures(vout_display_t *vd, const d3d_format_t *cfg,
assert(cfg->resourceFormat[1] == cfg->resourceFormat[0]);
assert(cfg->resourceFormat[2] == cfg->resourceFormat[0]);
- if (pool_type_display) {
- texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- texDesc.Usage = D3D11_USAGE_DEFAULT;
- } else {
- texDesc.Usage = D3D11_USAGE_STAGING;
- texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-
- /* align on 16 pixel boundaries */
- i_width_aligned = ( i_width_aligned + 15 ) & ~15;
- i_height_aligned = ( i_height_aligned + 15 ) & ~15;
- }
-
for( int i = 0; i < plane_count; i++ )
{
plane_t *p = &planes[i];
- p->i_lines = i_height_aligned * p_chroma_desc->p[i].h.num / p_chroma_desc->p[i].h.den;
+ p->i_lines = fmt->i_height * p_chroma_desc->p[i].h.num / p_chroma_desc->p[i].h.den;
p->i_visible_lines = fmt->i_visible_height * p_chroma_desc->p[i].h.num / p_chroma_desc->p[i].h.den;
- p->i_pitch = i_width_aligned * p_chroma_desc->p[i].w.num / p_chroma_desc->p[i].w.den * p_chroma_desc->pixel_size;
+ p->i_pitch = fmt->i_width * p_chroma_desc->p[i].w.num / p_chroma_desc->p[i].w.den * p_chroma_desc->pixel_size;
p->i_visible_pitch = fmt->i_visible_width * p_chroma_desc->p[i].w.num / p_chroma_desc->p[i].w.den * p_chroma_desc->pixel_size;
p->i_pixel_pitch = p_chroma_desc->pixel_size;
}
-
- if (!pool_type_display) {
- assert( (planes[0].i_pitch % 16) == 0 );
- }
-
- texDesc.ArraySize = 1;
} else {
plane_count = 1;
texDesc.Format = cfg->formatTexture;
- texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- if (is_d3d11_opaque(fmt->i_chroma)) {
- texDesc.BindFlags |= D3D11_BIND_DECODER;
- texDesc.Usage = D3D11_USAGE_DEFAULT;
- texDesc.CPUAccessFlags = 0;
- } else {
- texDesc.Usage = D3D11_USAGE_DYNAMIC;
- texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- }
- texDesc.ArraySize = pool_size;
texDesc.Height = fmt->i_height;
texDesc.Width = fmt->i_width;
@@ -767,9 +706,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
ID3D11Texture2D *textures[pool_size * D3D11_MAX_SHADER_VIEW];
picture_t **pictures = NULL;
picture_t *picture;
- unsigned plane;
unsigned picture_count = 0;
- picture_pool_configuration_t pool_cfg = {};
if (sys->sys.pool)
return sys->sys.pool;
@@ -781,10 +718,6 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
surface_fmt.i_width = sys->picQuad.i_width;
surface_fmt.i_height = sys->picQuad.i_height;
- if (AllocateTextures(vd, sys->picQuadConfig, &surface_fmt, pool_size, textures,
- sys->picQuadConfig->formatTexture != DXGI_FORMAT_UNKNOWN))
- goto error;
-
if (!vd->info.is_slow) {
HRESULT hr;
ID3D10Multithread *pMultithread;
@@ -795,44 +728,50 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
}
}
- pictures = calloc(pool_size, sizeof(*pictures));
- if (!pictures)
- goto error;
+ if (sys->picQuadConfig->formatTexture != DXGI_FORMAT_UNKNOWN)
+ {
+ if (AllocateTextures(vd, sys->picQuadConfig, &surface_fmt, pool_size, textures))
+ goto error;
- for (picture_count = 0; picture_count < pool_size; picture_count++) {
- picture_sys_t *picsys = calloc(1, sizeof(*picsys));
- if (unlikely(picsys == NULL))
+ pictures = calloc(pool_size, sizeof(*pictures));
+ if (!pictures)
goto error;
- for (plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
- picsys->texture[plane] = textures[picture_count * D3D11_MAX_SHADER_VIEW + plane];
+ for (picture_count = 0; picture_count < pool_size; picture_count++) {
+ picture_sys_t *picsys = calloc(1, sizeof(*picsys));
+ if (unlikely(picsys == NULL))
+ goto error;
- picsys->slice_index = picture_count;
- picsys->formatTexture = sys->picQuadConfig->formatTexture;
- picsys->context = sys->d3dcontext;
+ for (unsigned plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
+ picsys->texture[plane] = textures[picture_count * D3D11_MAX_SHADER_VIEW + plane];
- picture_resource_t resource = {
- .p_sys = picsys,
- .pf_destroy = DestroyDisplayPoolPicture,
- };
+ picsys->slice_index = picture_count;
+ picsys->formatTexture = sys->picQuadConfig->formatTexture;
+ picsys->context = sys->d3dcontext;
- picture = picture_NewFromResource(&surface_fmt, &resource);
- if (unlikely(picture == NULL)) {
- free(picsys);
- msg_Err( vd, "Failed to create picture %d in the pool.", picture_count );
- goto error;
- }
+ picture_resource_t resource = {
+ .p_sys = picsys,
+ .pf_destroy = DestroyDisplayPoolPicture,
+ };
- pictures[picture_count] = picture;
- /* each picture_t holds a ref to the context and release it on Destroy */
- ID3D11DeviceContext_AddRef(picsys->context);
+ picture = picture_NewFromResource(&surface_fmt, &resource);
+ if (unlikely(picture == NULL)) {
+ free(picsys);
+ msg_Err( vd, "Failed to create picture %d in the pool.", picture_count );
+ goto error;
+ }
+
+ pictures[picture_count] = picture;
+ /* each picture_t holds a ref to the context and release it on Destroy */
+ ID3D11DeviceContext_AddRef(picsys->context);
+ }
}
#ifdef HAVE_ID3D11VIDEODECODER
if (!is_d3d11_opaque(surface_fmt.i_chroma) || sys->legacy_shader)
{
/* we need a staging texture */
- if (AllocateTextures(vd, sys->picQuadConfig, &surface_fmt, 1, textures, true))
+ if (AllocateTextures(vd, sys->picQuadConfig, &surface_fmt, 1, textures))
goto error;
sys->picQuad.p_chroma_sampling = vlc_fourcc_GetChromaDescription( surface_fmt.i_chroma );
@@ -862,20 +801,25 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned pool_size)
}
if (sys->picQuadConfig->formatTexture == DXGI_FORMAT_UNKNOWN)
+ sys->sys.pool = picture_pool_NewFromFormat( &surface_fmt, pool_size );
+ else
{
- pool_cfg.lock = Direct3D11LockDirectTexture;
- pool_cfg.unlock = Direct3D11UnlockDirectTexture;
- }
- else if (vd->info.is_slow) {
- pool_cfg.lock = Direct3D11MapPoolTexture;
- //pool_cfg.unlock = Direct3D11UnmapPoolTexture;
+ picture_pool_configuration_t pool_cfg = {
+ .picture = pictures,
+ .picture_count = pool_size,
+ };
+ if (vd->info.is_slow) {
+ pool_cfg.lock = Direct3D11MapPoolTexture;
+ //pool_cfg.unlock = Direct3D11UnmapPoolTexture;
+ }
+ sys->sys.pool = picture_pool_NewExtended( &pool_cfg );
}
- pool_cfg.picture = pictures;
- pool_cfg.picture_count = pool_size;
- sys->sys.pool = picture_pool_NewExtended( &pool_cfg );
error:
if (sys->sys.pool == NULL) {
+ picture_pool_configuration_t pool_cfg = {
+ .picture_count = 0,
+ };
if (pictures) {
msg_Dbg(vd, "Failed to create the picture d3d11 pool");
for (unsigned i=0;i<picture_count; ++i)
@@ -884,7 +828,6 @@ error:
}
/* create an empty pool to avoid crashing */
- pool_cfg.picture_count = 0;
sys->sys.pool = picture_pool_NewExtended( &pool_cfg );
} else {
msg_Dbg(vd, "D3D11 pool succeed with %d surfaces (%dx%d) context 0x%p",
@@ -1254,92 +1197,87 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
{
vout_display_sys_t *sys = vd->sys;
- picture_sys_t *p_sys = ActivePictureSys(picture);
-
-#if defined(HAVE_ID3D11VIDEODECODER)
- if (sys->context_lock != INVALID_HANDLE_VALUE && is_d3d11_opaque(picture->format.i_chroma))
- WaitForSingleObjectEx( sys->context_lock, INFINITE, FALSE );
-#endif
- if (p_sys->formatTexture == DXGI_FORMAT_UNKNOWN)
+ if (sys->picQuadConfig->formatTexture == DXGI_FORMAT_UNKNOWN)
{
- Direct3D11UnlockDirectTexture(picture);
- for (int plane = 0; plane < D3D11_MAX_SHADER_VIEW; plane++)
- {
- if (!p_sys->resource[plane])
- continue;
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ D3D11_TEXTURE2D_DESC texDesc;
+ int i;
+ HRESULT hr;
- unsigned int width = sys->picQuad.i_width;
- unsigned int height = sys->picQuad.i_height;
- unsigned int x_offset = picture->format.i_x_offset;
- unsigned int y_offset = picture->format.i_y_offset;
- x_offset = x_offset * sys->picQuad.p_chroma_sampling->p[plane].h.num / sys->picQuad.p_chroma_sampling->p[plane].h.den;
- y_offset = y_offset * sys->picQuad.p_chroma_sampling->p[plane].w.num / sys->picQuad.p_chroma_sampling->p[plane].w.den;
- width = width * sys->picQuad.p_chroma_sampling->p[plane].h.num / sys->picQuad.p_chroma_sampling->p[plane].h.den;
- height = height * sys->picQuad.p_chroma_sampling->p[plane].w.num / sys->picQuad.p_chroma_sampling->p[plane].w.den;
+ for (i = 0; i < picture->i_planes; i++) {
+ hr = ID3D11DeviceContext_Map(sys->d3dcontext, sys->stagingSys.resource[i],
+ 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if( FAILED(hr) )
+ break;
+ ID3D11Texture2D_GetDesc(sys->stagingSys.texture[i], &texDesc);
+ plane_t texture_plane;
+ texture_plane.i_lines = texDesc.Height;
+ texture_plane.i_pitch = mappedResource.RowPitch;
+ texture_plane.p_pixels = mappedResource.pData;
+ texture_plane.i_visible_lines = picture->p[i].i_visible_lines;
+ texture_plane.i_visible_pitch = picture->p[i].i_visible_pitch;
+ plane_CopyPixels(&texture_plane, &picture->p[i]);
+ ID3D11DeviceContext_Unmap(sys->d3dcontext, sys->stagingSys.resource[i], 0);
+ }
+ }
+ else
+ {
+ picture_sys_t *p_sys = ActivePictureSys(picture);
+#if defined(HAVE_ID3D11VIDEODECODER)
+ if (sys->context_lock != INVALID_HANDLE_VALUE && is_d3d11_opaque(picture->format.i_chroma))
+ WaitForSingleObjectEx( sys->context_lock, INFINITE, FALSE );
+#endif
+ if (!is_d3d11_opaque(picture->format.i_chroma) || sys->legacy_shader) {
+ D3D11_TEXTURE2D_DESC texDesc;
+ if (!is_d3d11_opaque(picture->format.i_chroma))
+ Direct3D11UnmapPoolTexture(picture);
+ ID3D11Texture2D_GetDesc(sys->stagingSys.texture[0], &texDesc);
D3D11_BOX box = {
- .top = y_offset,
- .bottom = y_offset + height,
- .left = x_offset,
- .right = x_offset + width,
+ .top = 0,
+ .bottom = picture->format.i_y_offset + picture->format.i_visible_height,
+ .left = 0,
+ .right = picture->format.i_x_offset + picture->format.i_visible_width,
.back = 1,
};
+ if ( sys->picQuadConfig->formatTexture != DXGI_FORMAT_R8G8B8A8_UNORM &&
+ sys->picQuadConfig->formatTexture != DXGI_FORMAT_B5G6R5_UNORM )
+ {
+ box.bottom = (box.bottom + 0x01) & ~0x01;
+ box.right = (box.right + 0x01) & ~0x01;
+ }
+ assert(box.right <= texDesc.Width);
+ assert(box.bottom <= texDesc.Height);
ID3D11DeviceContext_CopySubresourceRegion(sys->d3dcontext,
- sys->stagingSys.resource[plane],
+ sys->stagingSys.resource[KNOWN_DXGI_INDEX],
0, 0, 0, 0,
- p_sys->resource[plane],
- 0, &box);
- }
- }
- else if (!is_d3d11_opaque(picture->format.i_chroma) || sys->legacy_shader) {
- D3D11_TEXTURE2D_DESC texDesc;
- if (!is_d3d11_opaque(picture->format.i_chroma))
- Direct3D11UnmapPoolTexture(picture);
- ID3D11Texture2D_GetDesc(sys->stagingSys.texture[0], &texDesc);
- D3D11_BOX box = {
- .top = 0,
- .bottom = picture->format.i_y_offset + picture->format.i_visible_height,
- .left = 0,
- .right = picture->format.i_x_offset + picture->format.i_visible_width,
- .back = 1,
- };
- if ( sys->picQuadConfig->formatTexture != DXGI_FORMAT_R8G8B8A8_UNORM &&
- sys->picQuadConfig->formatTexture != DXGI_FORMAT_B5G6R5_UNORM )
- {
- box.bottom = (box.bottom + 0x01) & ~0x01;
- box.right = (box.right + 0x01) & ~0x01;
+ p_sys->resource[KNOWN_DXGI_INDEX],
+ p_sys->slice_index, &box);
}
- assert(box.right <= texDesc.Width);
- assert(box.bottom <= texDesc.Height);
- ID3D11DeviceContext_CopySubresourceRegion(sys->d3dcontext,
- sys->stagingSys.resource[KNOWN_DXGI_INDEX],
- 0, 0, 0, 0,
- p_sys->resource[KNOWN_DXGI_INDEX],
- p_sys->slice_index, &box);
- }
- else
- {
- D3D11_TEXTURE2D_DESC texDesc;
- ID3D11Texture2D_GetDesc(p_sys->texture[0], &texDesc);
- if (texDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
+ else
{
- /* for performance reason we don't want to allocate this during
- * display, do it preferrably when creating the texture */
- assert(p_sys->resourceView[0]!=NULL);
- }
+ D3D11_TEXTURE2D_DESC texDesc;
+ ID3D11Texture2D_GetDesc(p_sys->texture[0], &texDesc);
+ if (texDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
+ {
+ /* for performance reason we don't want to allocate this during
+ * display, do it preferrably when creating the texture */
+ assert(p_sys->resourceView[0]!=NULL);
+ }
- if ( sys->picQuad.i_height != texDesc.Height ||
- sys->picQuad.i_width != texDesc.Width )
- {
- /* the decoder produced different sizes than the vout, we need to
- * adjust the vertex */
- sys->picQuad.i_height = texDesc.Height;
- sys->picQuad.i_width = texDesc.Width;
-
- BEFORE_UPDATE_RECTS;
- UpdateRects(vd, NULL, true);
- AFTER_UPDATE_RECTS;
- UpdateSize(vd);
+ if ( sys->picQuad.i_height != texDesc.Height ||
+ sys->picQuad.i_width != texDesc.Width )
+ {
+ /* the decoder produced different sizes than the vout, we need to
+ * adjust the vertex */
+ sys->picQuad.i_height = texDesc.Height;
+ sys->picQuad.i_width = texDesc.Width;
+
+ BEFORE_UPDATE_RECTS;
+ UpdateRects(vd, NULL, true);
+ AFTER_UPDATE_RECTS;
+ UpdateSize(vd);
+ }
}
}
@@ -3051,7 +2989,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
if (unlikely(d3dquad==NULL)) {
continue;
}
- if (AllocateTextures(vd, sys->d3dregion_format, &r->fmt, 1, textures, true)) {
+ if (AllocateTextures(vd, sys->d3dregion_format, &r->fmt, 1, textures)) {
msg_Err(vd, "Failed to allocate %dx%d texture for OSD",
r->fmt.i_visible_width, r->fmt.i_visible_height);
for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++)
--
2.14.2
More information about the vlc-devel
mailing list