Add VideoViewsTests.CreateVideoTextureWithoutInitializedData

Chromium creates gbm_bo buffers without the
GBM_BO_USE_SW_WRITE_RARELY flag to hold the video frames from VAAPI
decoder. The added case could better cover this and catch the recent
mesa regression:
  https://gitlab.freedesktop.org/mesa/mesa/-/issues/5940

Bug: chromium:1258986
Change-Id: Ib8313b35fe90928aae03791560d80fdb47bcea32
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/91081
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
This commit is contained in:
jchen10 2022-05-24 03:01:15 +00:00 committed by Dawn LUCI CQ
parent 136a0a4269
commit c45f11ddb5
5 changed files with 64 additions and 31 deletions

View File

@ -194,13 +194,25 @@ wgpu::ShaderModule VideoViewsTests::GetTestVertexShaderModule() const {
})");
}
// Create video texture uninitialized.
TEST_P(VideoViewsTests, CreateVideoTextureWithoutInitializedData) {
std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture =
mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm,
wgpu::TextureUsage::TextureBinding,
/*isCheckerboard*/ false,
/*initialized*/ false);
ASSERT_NE(platformTexture.get(), nullptr);
mBackend->DestroyVideoTextureForTest(std::move(platformTexture));
}
// Samples the luminance (Y) plane from an imported NV12 texture into a single channel of an RGBA
// output attachment and checks for the expected pixel value in the rendered quad.
TEST_P(VideoViewsTests, NV12SampleYtoR) {
std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture =
mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm,
wgpu::TextureUsage::TextureBinding,
/*isCheckerboard*/ false);
/*isCheckerboard*/ false,
/*initialized*/ true);
ASSERT_NE(platformTexture.get(), nullptr);
if (!platformTexture->CanWrapAsWGPUTexture()) {
mBackend->DestroyVideoTextureForTest(std::move(platformTexture));
@ -257,7 +269,8 @@ TEST_P(VideoViewsTests, NV12SampleUVtoRG) {
std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture =
mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm,
wgpu::TextureUsage::TextureBinding,
/*isCheckerboard*/ false);
/*isCheckerboard*/ false,
/*initialized*/ true);
ASSERT_NE(platformTexture.get(), nullptr);
if (!platformTexture->CanWrapAsWGPUTexture()) {
mBackend->DestroyVideoTextureForTest(std::move(platformTexture));
@ -320,7 +333,8 @@ TEST_P(VideoViewsTests, NV12SampleYUVtoRGB) {
std::unique_ptr<VideoViewsTestBackend::PlatformTexture> platformTexture =
mBackend->CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm,
wgpu::TextureUsage::TextureBinding,
/*isCheckerboard*/ true);
/*isCheckerboard*/ true,
/*initialized*/ true);
ASSERT_NE(platformTexture.get(), nullptr);
if (!platformTexture->CanWrapAsWGPUTexture()) {
mBackend->DestroyVideoTextureForTest(std::move(platformTexture));

View File

@ -46,7 +46,8 @@ class VideoViewsTestBackend {
};
virtual std::unique_ptr<PlatformTexture> CreateVideoTextureForTest(wgpu::TextureFormat format,
wgpu::TextureUsage usage,
bool isCheckerboard) = 0;
bool isCheckerboard,
bool initialized) = 0;
virtual void DestroyVideoTextureForTest(std::unique_ptr<PlatformTexture>&& platformTexture) = 0;
};

View File

@ -125,9 +125,17 @@ class VideoViewsTestBackendGbm : public VideoViewsTestBackend {
std::unique_ptr<VideoViewsTestBackend::PlatformTexture> CreateVideoTextureForTest(
wgpu::TextureFormat format,
wgpu::TextureUsage usage,
bool isCheckerboard) override {
uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING | GBM_BO_USE_HW_VIDEO_DECODER |
GBM_BO_USE_SW_WRITE_RARELY;
bool isCheckerboard,
bool initialized) override {
// The flags Chromium is using for the VAAPI decoder.
uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING | GBM_BO_USE_HW_VIDEO_DECODER;
if (initialized) {
// The flag specifically used for tests, which need to initialize the GBM buffer with
// the expected raw video data via CPU, and then sample and draw the buffer via GPU.
// With the flag added, the buffer's drm modifier will be DRM_FORMAT_MOD_LINEAR instead
// of I915_FORMAT_MOD_Y_TILED.
flags |= GBM_BO_USE_SW_WRITE_RARELY;
}
gbm_bo* gbmBo = gbm_bo_create(mGbmDevice, VideoViewsTests::kYUVImageDataWidthInTexels,
VideoViewsTests::kYUVImageDataHeightInTexels,
GetGbmBoFormat(format), flags);
@ -135,17 +143,19 @@ class VideoViewsTestBackendGbm : public VideoViewsTestBackend {
return nullptr;
}
void* mapHandle = nullptr;
uint32_t strideBytes = 0;
void* addr = gbm_bo_map(gbmBo, 0, 0, VideoViewsTests::kYUVImageDataWidthInTexels,
VideoViewsTests::kYUVImageDataHeightInTexels, GBM_BO_TRANSFER_WRITE,
&strideBytes, &mapHandle);
EXPECT_NE(addr, nullptr);
std::vector<uint8_t> initialData =
VideoViewsTests::GetTestTextureData(format, isCheckerboard);
std::memcpy(addr, initialData.data(), initialData.size());
if (initialized) {
void* mapHandle = nullptr;
uint32_t strideBytes = 0;
void* addr = gbm_bo_map(gbmBo, 0, 0, VideoViewsTests::kYUVImageDataWidthInTexels,
VideoViewsTests::kYUVImageDataHeightInTexels,
GBM_BO_TRANSFER_WRITE, &strideBytes, &mapHandle);
EXPECT_NE(addr, nullptr);
std::vector<uint8_t> initialData =
VideoViewsTests::GetTestTextureData(format, isCheckerboard);
std::memcpy(addr, initialData.data(), initialData.size());
gbm_bo_unmap(gbmBo, mapHandle);
gbm_bo_unmap(gbmBo, mapHandle);
}
wgpu::TextureDescriptor textureDesc;
textureDesc.format = format;
@ -168,9 +178,12 @@ class VideoViewsTestBackendGbm : public VideoViewsTestBackend {
descriptor.drmModifier = gbm_bo_get_modifier(gbmBo);
descriptor.waitFDs = {};
return std::make_unique<PlatformTextureGbm>(
wgpu::Texture::Acquire(dawn::native::vulkan::WrapVulkanImage(mWGPUDevice, &descriptor)),
gbmBo);
WGPUTexture texture = dawn::native::vulkan::WrapVulkanImage(mWGPUDevice, &descriptor);
if (texture != nullptr) {
return std::make_unique<PlatformTextureGbm>(wgpu::Texture::Acquire(texture), gbmBo);
} else {
return nullptr;
}
}
void DestroyVideoTextureForTest(

View File

@ -86,7 +86,8 @@ class VideoViewsTestBackendIOSurface : public VideoViewsTestBackend {
std::unique_ptr<VideoViewsTestBackend::PlatformTexture> CreateVideoTextureForTest(
wgpu::TextureFormat format,
wgpu::TextureUsage usage,
bool isCheckerboard) override {
bool isCheckerboard,
bool initialized) override {
CFMutableDictionaryRef dict(CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
@ -134,15 +135,17 @@ class VideoViewsTestBackendIOSurface : public VideoViewsTestBackend {
IOSurfaceRef surface = IOSurfaceCreate(dict);
CFRelease(dict);
IOSurfaceLock(surface, 0, nullptr);
for (size_t plane = 0; plane < num_planes; ++plane) {
std::vector<uint8_t> data = VideoViewsTests::GetTestTextureDataWithPlaneIndex(
plane, IOSurfaceGetBytesPerRowOfPlane(surface, plane),
IOSurfaceGetHeightOfPlane(surface, plane), isCheckerboard);
void* pointer = IOSurfaceGetBaseAddressOfPlane(surface, plane);
memcpy(pointer, data.data(), data.size());
if (initialized) {
IOSurfaceLock(surface, 0, nullptr);
for (size_t plane = 0; plane < num_planes; ++plane) {
std::vector<uint8_t> data = VideoViewsTests::GetTestTextureDataWithPlaneIndex(
plane, IOSurfaceGetBytesPerRowOfPlane(surface, plane),
IOSurfaceGetHeightOfPlane(surface, plane), isCheckerboard);
void* pointer = IOSurfaceGetBaseAddressOfPlane(surface, plane);
memcpy(pointer, data.data(), data.size());
}
IOSurfaceUnlock(surface, 0, nullptr);
}
IOSurfaceUnlock(surface, 0, nullptr);
wgpu::TextureDescriptor textureDesc;
textureDesc.format = format;

View File

@ -90,7 +90,8 @@ class VideoViewsTestBackendWin : public VideoViewsTestBackend {
std::unique_ptr<VideoViewsTestBackend::PlatformTexture> CreateVideoTextureForTest(
wgpu::TextureFormat format,
wgpu::TextureUsage usage,
bool isCheckerboard) override {
bool isCheckerboard,
bool initialized) override {
wgpu::TextureDescriptor textureDesc;
textureDesc.format = format;
textureDesc.dimension = wgpu::TextureDimension::e2D;
@ -121,7 +122,8 @@ class VideoViewsTestBackendWin : public VideoViewsTestBackend {
subres.SysMemPitch = VideoViewsTests::kYUVImageDataWidthInTexels;
ComPtr<ID3D11Texture2D> d3d11Texture;
HRESULT hr = mD3d11Device->CreateTexture2D(&d3dDescriptor, &subres, &d3d11Texture);
HRESULT hr = mD3d11Device->CreateTexture2D(
&d3dDescriptor, (initialized ? &subres : nullptr), &d3d11Texture);
ASSERT(hr == S_OK);
ComPtr<IDXGIResource1> dxgiResource;