virgl: Add tests for virgl_staging_mgr
Signed-off-by: Alexandros Frantzis <alexandros.frantzis@collabora.com> Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
This commit is contained in:
parent
55a58dfcfb
commit
790d1a0b17
|
@ -56,3 +56,7 @@ driver_virgl = declare_dependency(
|
|||
compile_args : '-DGALLIUM_VIRGL',
|
||||
link_with : [libvirgl, libvirgldrm, libvirglvtest],
|
||||
)
|
||||
|
||||
if with_tests
|
||||
subdir('tests')
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# Copyright © 2019 Collabora Ltd.
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
test(
|
||||
'virgl_staging_mgr',
|
||||
executable(
|
||||
'virgl_staging_mgr_test',
|
||||
files('virgl_staging_mgr_test.cpp'),
|
||||
dependencies : [dep_thread, idep_gtest],
|
||||
include_directories : [inc_common, include_directories('..')],
|
||||
link_with : [libvirgl, libgallium],
|
||||
),
|
||||
suite : ['virgl'],
|
||||
)
|
|
@ -0,0 +1,389 @@
|
|||
/*
|
||||
* Copyright 2019 Collabora Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "virgl_context.h"
|
||||
#include "virgl_resource.h"
|
||||
#include "virgl_screen.h"
|
||||
#include "virgl_staging_mgr.h"
|
||||
#include "virgl_winsys.h"
|
||||
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
struct virgl_hw_res {
|
||||
struct pipe_reference reference;
|
||||
uint32_t target;
|
||||
uint32_t bind;
|
||||
uint32_t size;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static struct virgl_hw_res *
|
||||
fake_resource_create(struct virgl_winsys *vws,
|
||||
enum pipe_texture_target target,
|
||||
uint32_t format, uint32_t bind,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t depth, uint32_t array_size,
|
||||
uint32_t last_level, uint32_t nr_samples,
|
||||
uint32_t size)
|
||||
{
|
||||
struct virgl_hw_res *hw_res = CALLOC_STRUCT(virgl_hw_res);
|
||||
|
||||
pipe_reference_init(&hw_res->reference, 1);
|
||||
|
||||
hw_res->target = target;
|
||||
hw_res->bind = bind;
|
||||
hw_res->size = size;
|
||||
hw_res->data = CALLOC(size, 1);
|
||||
|
||||
return hw_res;
|
||||
}
|
||||
|
||||
static void
|
||||
fake_resource_reference(struct virgl_winsys *vws,
|
||||
struct virgl_hw_res **dres,
|
||||
struct virgl_hw_res *sres)
|
||||
{
|
||||
struct virgl_hw_res *old = *dres;
|
||||
|
||||
if (pipe_reference(&(*dres)->reference, &sres->reference)) {
|
||||
FREE(old->data);
|
||||
FREE(old);
|
||||
}
|
||||
|
||||
*dres = sres;
|
||||
}
|
||||
|
||||
static void *
|
||||
fake_resource_map(struct virgl_winsys *vws, struct virgl_hw_res *hw_res)
|
||||
{
|
||||
return hw_res->data;
|
||||
}
|
||||
|
||||
static struct pipe_context *
|
||||
fake_virgl_context_create()
|
||||
{
|
||||
struct virgl_context *vctx = CALLOC_STRUCT(virgl_context);
|
||||
struct virgl_screen *vs = CALLOC_STRUCT(virgl_screen);
|
||||
struct virgl_winsys *vws = CALLOC_STRUCT(virgl_winsys);
|
||||
|
||||
vctx->base.screen = &vs->base;
|
||||
vs->vws = vws;
|
||||
|
||||
vs->vws->resource_create = fake_resource_create;
|
||||
vs->vws->resource_reference = fake_resource_reference;
|
||||
vs->vws->resource_map = fake_resource_map;
|
||||
|
||||
return &vctx->base;
|
||||
}
|
||||
|
||||
static void
|
||||
fake_virgl_context_destroy(struct pipe_context *ctx)
|
||||
{
|
||||
struct virgl_context *vctx = virgl_context(ctx);
|
||||
struct virgl_screen *vs = virgl_screen(ctx->screen);
|
||||
|
||||
FREE(vs->vws);
|
||||
FREE(vs);
|
||||
FREE(vctx);
|
||||
}
|
||||
|
||||
static void *
|
||||
resource_map(struct virgl_hw_res *hw_res)
|
||||
{
|
||||
return hw_res->data;
|
||||
}
|
||||
|
||||
static void
|
||||
release_resources(struct virgl_hw_res *resources[], unsigned len)
|
||||
{
|
||||
for (unsigned i = 0; i < len; ++i)
|
||||
fake_resource_reference(NULL, &resources[i], NULL);
|
||||
}
|
||||
|
||||
class VirglStagingMgr : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
VirglStagingMgr() : ctx(fake_virgl_context_create())
|
||||
{
|
||||
virgl_staging_init(&staging, ctx, staging_size);
|
||||
}
|
||||
|
||||
~VirglStagingMgr()
|
||||
{
|
||||
virgl_staging_destroy(&staging);
|
||||
fake_virgl_context_destroy(ctx);
|
||||
}
|
||||
|
||||
static const unsigned staging_size;
|
||||
struct pipe_context * const ctx;
|
||||
struct virgl_staging_mgr staging;
|
||||
};
|
||||
|
||||
const unsigned VirglStagingMgr::staging_size = 4096;
|
||||
|
||||
class VirglStagingMgrWithAlignment : public VirglStagingMgr,
|
||||
public ::testing::WithParamInterface<unsigned>
|
||||
{
|
||||
protected:
|
||||
VirglStagingMgrWithAlignment() : alignment(GetParam()) {}
|
||||
const unsigned alignment;
|
||||
};
|
||||
|
||||
TEST_P(VirglStagingMgrWithAlignment,
|
||||
suballocations_are_non_overlapping_in_same_resource)
|
||||
{
|
||||
const unsigned alloc_sizes[] = {16, 450, 79, 240, 128, 1001};
|
||||
const unsigned num_resources = sizeof(alloc_sizes) / sizeof(alloc_sizes[0]);
|
||||
struct virgl_hw_res *out_resource[num_resources] = {0};
|
||||
unsigned expected_offset = 0;
|
||||
unsigned out_offset;
|
||||
void *map_ptr;
|
||||
bool alloc_succeeded;
|
||||
|
||||
for (unsigned i = 0; i < num_resources; ++i) {
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, alloc_sizes[i], alignment, &out_offset,
|
||||
&out_resource[i], &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
EXPECT_EQ(out_offset, expected_offset);
|
||||
ASSERT_NE(out_resource[i], nullptr);
|
||||
if (i > 0) {
|
||||
EXPECT_EQ(out_resource[i], out_resource[i - 1]);
|
||||
}
|
||||
EXPECT_EQ(map_ptr,
|
||||
(uint8_t*)resource_map(out_resource[i]) + expected_offset);
|
||||
|
||||
expected_offset += alloc_sizes[i];
|
||||
expected_offset = align(expected_offset, alignment);
|
||||
}
|
||||
|
||||
release_resources(out_resource, num_resources);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(WithAlignment,
|
||||
VirglStagingMgrWithAlignment,
|
||||
::testing::Values(1, 16),
|
||||
testing::PrintToStringParamName());
|
||||
|
||||
TEST_F(VirglStagingMgr,
|
||||
non_fitting_allocation_reallocates_resource)
|
||||
{
|
||||
struct virgl_hw_res *out_resource[2] = {0};
|
||||
unsigned out_offset;
|
||||
void *map_ptr;
|
||||
bool alloc_succeeded;
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, staging_size - 1, 1, &out_offset,
|
||||
&out_resource[0], &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
EXPECT_EQ(out_offset, 0);
|
||||
ASSERT_NE(out_resource[0], nullptr);
|
||||
EXPECT_EQ(map_ptr, resource_map(out_resource[0]));
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, 2, 1, &out_offset,
|
||||
&out_resource[1], &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
EXPECT_EQ(out_offset, 0);
|
||||
ASSERT_NE(out_resource[1], nullptr);
|
||||
EXPECT_EQ(map_ptr, resource_map(out_resource[1]));
|
||||
/* New resource with same size as old resource. */
|
||||
EXPECT_NE(out_resource[1], out_resource[0]);
|
||||
EXPECT_EQ(out_resource[1]->size, out_resource[0]->size);
|
||||
|
||||
release_resources(out_resource, 2);
|
||||
}
|
||||
|
||||
TEST_F(VirglStagingMgr,
|
||||
non_fitting_aligned_allocation_reallocates_resource)
|
||||
{
|
||||
struct virgl_hw_res *out_resource[2] = {0};
|
||||
unsigned out_offset;
|
||||
void *map_ptr;
|
||||
bool alloc_succeeded;
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, staging_size - 1, 1, &out_offset,
|
||||
&out_resource[0], &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
EXPECT_EQ(out_offset, 0);
|
||||
ASSERT_NE(out_resource[0], nullptr);
|
||||
EXPECT_EQ(map_ptr, resource_map(out_resource[0]));
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, 1, 16, &out_offset,
|
||||
&out_resource[1], &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
EXPECT_EQ(out_offset, 0);
|
||||
ASSERT_NE(out_resource[1], nullptr);
|
||||
EXPECT_EQ(map_ptr, resource_map(out_resource[1]));
|
||||
/* New resource with same size as old resource. */
|
||||
EXPECT_NE(out_resource[1], out_resource[0]);
|
||||
EXPECT_EQ(out_resource[1]->size, out_resource[0]->size);
|
||||
|
||||
release_resources(out_resource, 2);
|
||||
}
|
||||
|
||||
TEST_F(VirglStagingMgr,
|
||||
large_non_fitting_allocation_reallocates_large_resource)
|
||||
{
|
||||
struct virgl_hw_res *out_resource[2] = {0};
|
||||
unsigned out_offset;
|
||||
void *map_ptr;
|
||||
bool alloc_succeeded;
|
||||
|
||||
ASSERT_LT(staging_size, 5123);
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, 5123, 1, &out_offset,
|
||||
&out_resource[0], &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
EXPECT_EQ(out_offset, 0);
|
||||
ASSERT_NE(out_resource[0], nullptr);
|
||||
EXPECT_EQ(map_ptr, resource_map(out_resource[0]));
|
||||
EXPECT_GE(out_resource[0]->size, 5123);
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, 19345, 1, &out_offset,
|
||||
&out_resource[1], &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
EXPECT_EQ(out_offset, 0);
|
||||
ASSERT_NE(out_resource[1], nullptr);
|
||||
EXPECT_EQ(map_ptr, resource_map(out_resource[1]));
|
||||
/* New resource */
|
||||
EXPECT_NE(out_resource[1], out_resource[0]);
|
||||
EXPECT_GE(out_resource[1]->size, 19345);
|
||||
|
||||
release_resources(out_resource, 2);
|
||||
}
|
||||
|
||||
TEST_F(VirglStagingMgr, releases_resource_on_destruction)
|
||||
{
|
||||
struct virgl_hw_res *out_resource = NULL;
|
||||
unsigned out_offset;
|
||||
void *map_ptr;
|
||||
bool alloc_succeeded;
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, 128, 1, &out_offset,
|
||||
&out_resource, &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
ASSERT_NE(out_resource, nullptr);
|
||||
/* The resource is referenced both by staging internally,
|
||||
* and out_resource.
|
||||
*/
|
||||
EXPECT_EQ(out_resource->reference.count, 2);
|
||||
|
||||
/* Destroying staging releases the internal reference. */
|
||||
virgl_staging_destroy(&staging);
|
||||
EXPECT_EQ(out_resource->reference.count, 1);
|
||||
|
||||
release_resources(&out_resource, 1);
|
||||
}
|
||||
|
||||
static struct virgl_hw_res *
|
||||
failing_resource_create(struct virgl_winsys *vws,
|
||||
enum pipe_texture_target target,
|
||||
uint32_t format, uint32_t bind,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t depth, uint32_t array_size,
|
||||
uint32_t last_level, uint32_t nr_samples,
|
||||
uint32_t size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST_F(VirglStagingMgr, fails_gracefully_if_resource_create_fails)
|
||||
{
|
||||
struct virgl_screen *vs = virgl_screen(ctx->screen);
|
||||
struct virgl_hw_res *out_resource = NULL;
|
||||
unsigned out_offset;
|
||||
void *map_ptr;
|
||||
bool alloc_succeeded;
|
||||
|
||||
vs->vws->resource_create = failing_resource_create;
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, 128, 1, &out_offset,
|
||||
&out_resource, &map_ptr);
|
||||
|
||||
EXPECT_FALSE(alloc_succeeded);
|
||||
EXPECT_EQ(out_resource, nullptr);
|
||||
EXPECT_EQ(map_ptr, nullptr);
|
||||
}
|
||||
|
||||
static void *
|
||||
failing_resource_map(struct virgl_winsys *vws, struct virgl_hw_res *hw_res)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST_F(VirglStagingMgr, fails_gracefully_if_map_fails)
|
||||
{
|
||||
struct virgl_screen *vs = virgl_screen(ctx->screen);
|
||||
struct virgl_hw_res *out_resource = NULL;
|
||||
unsigned out_offset;
|
||||
void *map_ptr;
|
||||
bool alloc_succeeded;
|
||||
|
||||
vs->vws->resource_map = failing_resource_map;
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, 128, 1, &out_offset,
|
||||
&out_resource, &map_ptr);
|
||||
|
||||
EXPECT_FALSE(alloc_succeeded);
|
||||
EXPECT_EQ(out_resource, nullptr);
|
||||
EXPECT_EQ(map_ptr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(VirglStagingMgr, uses_staging_buffer_resource)
|
||||
{
|
||||
struct virgl_hw_res *out_resource = NULL;
|
||||
unsigned out_offset;
|
||||
void *map_ptr;
|
||||
bool alloc_succeeded;
|
||||
|
||||
alloc_succeeded =
|
||||
virgl_staging_alloc(&staging, 128, 1, &out_offset,
|
||||
&out_resource, &map_ptr);
|
||||
|
||||
EXPECT_TRUE(alloc_succeeded);
|
||||
ASSERT_NE(out_resource, nullptr);
|
||||
EXPECT_EQ(out_resource->target, PIPE_BUFFER);
|
||||
EXPECT_EQ(out_resource->bind, VIRGL_BIND_STAGING);
|
||||
|
||||
release_resources(&out_resource, 1);
|
||||
}
|
Loading…
Reference in New Issue