|
|
|
@@ -303,6 +303,7 @@ convert_planar_resource(struct d3d12_resource *res)
|
|
|
|
|
plane_res->base.b.next = next;
|
|
|
|
|
next = &plane_res->base.b;
|
|
|
|
|
|
|
|
|
|
plane_res->plane_slice = plane;
|
|
|
|
|
plane_res->base.b.format = util_format_get_plane_format(res->base.b.format, plane);
|
|
|
|
|
plane_res->base.b.width0 = util_format_get_plane_width(res->base.b.format, plane, res->base.b.width0);
|
|
|
|
|
plane_res->base.b.height0 = util_format_get_plane_height(res->base.b.format, plane, res->base.b.height0);
|
|
|
|
@@ -317,6 +318,7 @@ convert_planar_resource(struct d3d12_resource *res)
|
|
|
|
|
assert(plane_res->base.b.width0 == footprint->Width);
|
|
|
|
|
assert(plane_res->base.b.height0 == footprint->Height);
|
|
|
|
|
assert(plane_res->base.b.depth0 == footprint->Depth);
|
|
|
|
|
assert(plane_res->first_plane == &res->base.b);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -331,6 +333,8 @@ d3d12_resource_create(struct pipe_screen *pscreen,
|
|
|
|
|
|
|
|
|
|
res->base.b = *templ;
|
|
|
|
|
res->overall_format = templ->format;
|
|
|
|
|
res->plane_slice = 0;
|
|
|
|
|
res->first_plane = &res->base.b;
|
|
|
|
|
|
|
|
|
|
if (D3D12_DEBUG_RESOURCE & d3d12_debug) {
|
|
|
|
|
debug_printf("D3D12: Create %sresource %s@%d %dx%dx%d as:%d mip:%d\n",
|
|
|
|
@@ -550,6 +554,8 @@ d3d12_resource_from_handle(struct pipe_screen *pscreen,
|
|
|
|
|
handle->format = res->overall_format;
|
|
|
|
|
|
|
|
|
|
res->dxgi_format = d3d12_get_format(res->overall_format);
|
|
|
|
|
res->plane_slice = handle->plane;
|
|
|
|
|
res->first_plane = &res->base.b;
|
|
|
|
|
|
|
|
|
|
if (!res->bo) {
|
|
|
|
|
res->bo = d3d12_bo_wrap_res(screen, d3d12_res, res->overall_format, d3d12_permanently_resident);
|
|
|
|
@@ -609,6 +615,151 @@ d3d12_resource_get_handle(struct pipe_screen *pscreen,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct pipe_resource *
|
|
|
|
|
d3d12_resource_from_resource(struct pipe_screen *pscreen,
|
|
|
|
|
ID3D12Resource* input_res)
|
|
|
|
|
{
|
|
|
|
|
D3D12_RESOURCE_DESC input_desc = input_res->GetDesc();
|
|
|
|
|
struct winsys_handle handle;
|
|
|
|
|
memset(&handle, 0, sizeof(handle));
|
|
|
|
|
handle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
|
|
|
|
|
handle.format = d3d12_get_pipe_format(input_desc.Format);
|
|
|
|
|
handle.com_obj = input_res;
|
|
|
|
|
|
|
|
|
|
struct pipe_resource templ;
|
|
|
|
|
memset(&templ, 0, sizeof(templ));
|
|
|
|
|
if(input_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) {
|
|
|
|
|
templ.target = PIPE_BUFFER;
|
|
|
|
|
} else {
|
|
|
|
|
templ.target = (input_desc.DepthOrArraySize > 1) ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
templ.format = d3d12_get_pipe_format(input_desc.Format);
|
|
|
|
|
templ.width0 = input_desc.Width;
|
|
|
|
|
templ.height0 = input_desc.Height;
|
|
|
|
|
templ.depth0 = input_desc.DepthOrArraySize;
|
|
|
|
|
templ.array_size = input_desc.DepthOrArraySize;
|
|
|
|
|
templ.flags = 0;
|
|
|
|
|
|
|
|
|
|
return d3d12_resource_from_handle(
|
|
|
|
|
pscreen,
|
|
|
|
|
&templ,
|
|
|
|
|
&handle,
|
|
|
|
|
PIPE_USAGE_DEFAULT
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* On Map/Unmap operations, we readback or flush all the underlying planes
|
|
|
|
|
* of planar resources. The map/unmap operation from the caller is
|
|
|
|
|
* expected to be done for res->plane_slice plane only, but some
|
|
|
|
|
* callers expect adjacent allocations for next contiguous plane access
|
|
|
|
|
*
|
|
|
|
|
* In this function, we take the res and box the caller passed, and the plane_* properties
|
|
|
|
|
* that are currently being readback/flushed, and adjust the d3d12_transfer ptrans
|
|
|
|
|
* accordingly for the GPU copy operation between planes.
|
|
|
|
|
*/
|
|
|
|
|
static void d3d12_adjust_transfer_dimensions_for_plane(const struct d3d12_resource *res,
|
|
|
|
|
unsigned plane_slice,
|
|
|
|
|
unsigned plane_stride,
|
|
|
|
|
unsigned plane_layer_stride,
|
|
|
|
|
unsigned plane_offset,
|
|
|
|
|
const struct pipe_box* original_box,
|
|
|
|
|
struct pipe_transfer *ptrans/*inout*/)
|
|
|
|
|
{
|
|
|
|
|
/* Adjust strides, offsets to the corresponding plane*/
|
|
|
|
|
ptrans->stride = plane_stride;
|
|
|
|
|
ptrans->layer_stride = plane_layer_stride;
|
|
|
|
|
ptrans->offset = plane_offset;
|
|
|
|
|
|
|
|
|
|
/* Find multipliers such that:*/
|
|
|
|
|
/* first_plane.width = width_multiplier * planes[res->plane_slice].width*/
|
|
|
|
|
/* first_plane.height = height_multiplier * planes[res->plane_slice].height*/
|
|
|
|
|
float width_multiplier = res->first_plane->width0 / (float) util_format_get_plane_width(res->overall_format, res->plane_slice, res->first_plane->width0);
|
|
|
|
|
float height_multiplier = res->first_plane->height0 / (float) util_format_get_plane_height(res->overall_format, res->plane_slice, res->first_plane->height0);
|
|
|
|
|
|
|
|
|
|
/* Normalize box back to overall dimensions (first plane)*/
|
|
|
|
|
ptrans->box.width = width_multiplier * original_box->width;
|
|
|
|
|
ptrans->box.height = height_multiplier * original_box->height;
|
|
|
|
|
ptrans->box.x = width_multiplier * original_box->x;
|
|
|
|
|
ptrans->box.y = height_multiplier * original_box->y;
|
|
|
|
|
|
|
|
|
|
/* Now adjust dimensions to plane_slice*/
|
|
|
|
|
ptrans->box.width = util_format_get_plane_width(res->overall_format, plane_slice, ptrans->box.width);
|
|
|
|
|
ptrans->box.height = util_format_get_plane_height(res->overall_format, plane_slice, ptrans->box.height);
|
|
|
|
|
ptrans->box.x = util_format_get_plane_width(res->overall_format, plane_slice, ptrans->box.x);
|
|
|
|
|
ptrans->box.y = util_format_get_plane_height(res->overall_format, plane_slice, ptrans->box.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
void d3d12_resource_get_planes_info(pipe_resource *pres,
|
|
|
|
|
unsigned num_planes,
|
|
|
|
|
pipe_resource **planes,
|
|
|
|
|
unsigned *strides,
|
|
|
|
|
unsigned *layer_strides,
|
|
|
|
|
unsigned *offsets,
|
|
|
|
|
unsigned *staging_res_size)
|
|
|
|
|
{
|
|
|
|
|
struct d3d12_resource* res = d3d12_resource(pres);
|
|
|
|
|
*staging_res_size = 0;
|
|
|
|
|
struct pipe_resource *cur_plane_resource = res->first_plane;
|
|
|
|
|
for (uint plane_slice = 0; plane_slice < num_planes; ++plane_slice) {
|
|
|
|
|
planes[plane_slice] = cur_plane_resource;
|
|
|
|
|
int width = util_format_get_plane_width(res->base.b.format, plane_slice, res->first_plane->width0);
|
|
|
|
|
int height = util_format_get_plane_height(res->base.b.format, plane_slice, res->first_plane->height0);
|
|
|
|
|
|
|
|
|
|
strides[plane_slice] = align(util_format_get_stride(cur_plane_resource->format, width),
|
|
|
|
|
D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
|
|
|
|
|
|
|
|
|
|
layer_strides[plane_slice] = align(util_format_get_2d_size(cur_plane_resource->format,
|
|
|
|
|
strides[plane_slice],
|
|
|
|
|
height),
|
|
|
|
|
D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
|
|
|
|
|
|
|
|
|
|
offsets[plane_slice] = *staging_res_size;
|
|
|
|
|
*staging_res_size += layer_strides[plane_slice];
|
|
|
|
|
cur_plane_resource = cur_plane_resource->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get stride and offset for the given pipe resource without the need to get
|
|
|
|
|
* a winsys_handle.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
d3d12_resource_get_info(struct pipe_screen *pscreen,
|
|
|
|
|
struct pipe_resource *pres,
|
|
|
|
|
unsigned *stride,
|
|
|
|
|
unsigned *offset)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
struct d3d12_resource* res = d3d12_resource(pres);
|
|
|
|
|
unsigned num_planes = util_format_get_num_planes(res->overall_format);
|
|
|
|
|
|
|
|
|
|
pipe_resource* planes[num_planes];
|
|
|
|
|
unsigned int strides[num_planes];
|
|
|
|
|
unsigned int layer_strides[num_planes];
|
|
|
|
|
unsigned int offsets[num_planes];
|
|
|
|
|
unsigned staging_res_size = 0;
|
|
|
|
|
d3d12_resource_get_planes_info(
|
|
|
|
|
pres,
|
|
|
|
|
num_planes,
|
|
|
|
|
planes,
|
|
|
|
|
strides,
|
|
|
|
|
layer_strides,
|
|
|
|
|
offsets,
|
|
|
|
|
&staging_res_size
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if(stride) {
|
|
|
|
|
*stride = strides[res->plane_slice];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(offset) {
|
|
|
|
|
*offset = offsets[res->plane_slice];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
d3d12_screen_resource_init(struct pipe_screen *pscreen)
|
|
|
|
|
{
|
|
|
|
@@ -616,6 +767,7 @@ d3d12_screen_resource_init(struct pipe_screen *pscreen)
|
|
|
|
|
pscreen->resource_from_handle = d3d12_resource_from_handle;
|
|
|
|
|
pscreen->resource_get_handle = d3d12_resource_get_handle;
|
|
|
|
|
pscreen->resource_destroy = d3d12_resource_destroy;
|
|
|
|
|
pscreen->resource_get_info = d3d12_resource_get_info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
@@ -636,7 +788,7 @@ get_subresource_id(struct d3d12_resource *res, unsigned resid,
|
|
|
|
|
unsigned layer_stride = res->base.b.last_level + 1;
|
|
|
|
|
|
|
|
|
|
return resid * resource_stride + z * layer_stride +
|
|
|
|
|
base_level;
|
|
|
|
|
base_level + res->plane_slice * resource_stride;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static D3D12_TEXTURE_COPY_LOCATION
|
|
|
|
@@ -674,6 +826,7 @@ fill_buffer_location(struct d3d12_context *ctx,
|
|
|
|
|
buf_loc.pResource = d3d12_resource_underlying(staging_res, &offset);
|
|
|
|
|
buf_loc.PlacedFootprint = footprint;
|
|
|
|
|
buf_loc.PlacedFootprint.Offset += offset;
|
|
|
|
|
buf_loc.PlacedFootprint.Offset += trans->base.b.offset;
|
|
|
|
|
|
|
|
|
|
if (util_format_has_depth(util_format_description(res->base.b.format)) &&
|
|
|
|
|
screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
|
|
|
|
@@ -1286,6 +1439,72 @@ d3d12_transfer_map(struct pipe_context *pctx,
|
|
|
|
|
} else {
|
|
|
|
|
ptr = nullptr;
|
|
|
|
|
}
|
|
|
|
|
} else if(util_format_is_yuv(res->overall_format)) {
|
|
|
|
|
|
|
|
|
|
/* Get planes information*/
|
|
|
|
|
|
|
|
|
|
unsigned num_planes = util_format_get_num_planes(res->overall_format);
|
|
|
|
|
pipe_resource* planes[num_planes];
|
|
|
|
|
unsigned int strides[num_planes];
|
|
|
|
|
unsigned int layer_strides[num_planes];
|
|
|
|
|
unsigned int offsets[num_planes];
|
|
|
|
|
unsigned staging_res_size = 0;
|
|
|
|
|
|
|
|
|
|
d3d12_resource_get_planes_info(
|
|
|
|
|
pres,
|
|
|
|
|
num_planes,
|
|
|
|
|
planes,
|
|
|
|
|
strides,
|
|
|
|
|
layer_strides,
|
|
|
|
|
offsets,
|
|
|
|
|
&staging_res_size
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/* Allocate a buffer for all the planes to fit in adjacent memory*/
|
|
|
|
|
|
|
|
|
|
pipe_resource_usage staging_usage = (usage & (PIPE_MAP_READ | PIPE_MAP_READ_WRITE)) ?
|
|
|
|
|
PIPE_USAGE_STAGING : PIPE_USAGE_STREAM;
|
|
|
|
|
trans->staging_res = pipe_buffer_create(pctx->screen, 0,
|
|
|
|
|
staging_usage,
|
|
|
|
|
staging_res_size);
|
|
|
|
|
if (!trans->staging_res)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res);
|
|
|
|
|
|
|
|
|
|
/* Readback contents into the buffer allocation now if map was intended for read*/
|
|
|
|
|
|
|
|
|
|
/* Read all planes if readback needed*/
|
|
|
|
|
if (usage & PIPE_MAP_READ) {
|
|
|
|
|
pipe_box original_box = ptrans->box;
|
|
|
|
|
for (uint plane_slice = 0; plane_slice < num_planes; ++plane_slice) {
|
|
|
|
|
/* Adjust strides, offsets, box to the corresponding plane for the copytexture operation*/
|
|
|
|
|
d3d12_adjust_transfer_dimensions_for_plane(res,
|
|
|
|
|
plane_slice,
|
|
|
|
|
strides[plane_slice],
|
|
|
|
|
layer_strides[plane_slice],
|
|
|
|
|
offsets[plane_slice],
|
|
|
|
|
&original_box,
|
|
|
|
|
ptrans/*inout*/);
|
|
|
|
|
/* Perform the readback*/
|
|
|
|
|
if(!transfer_image_to_buf(ctx, d3d12_resource(planes[plane_slice]), staging_res, trans, 0)){
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d3d12_flush_cmdlist_and_wait(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Map the whole staging buffer containing all the planes contiguously*/
|
|
|
|
|
/* Just offset the resulting ptr to the according plane offset*/
|
|
|
|
|
|
|
|
|
|
range.End = staging_res_size - range.Begin;
|
|
|
|
|
uint8_t* all_planes_map = (uint8_t*) d3d12_bo_map(staging_res->bo, &range);
|
|
|
|
|
|
|
|
|
|
ptrans->stride = strides[res->plane_slice];
|
|
|
|
|
ptrans->layer_stride = layer_strides[res->plane_slice];
|
|
|
|
|
ptr = all_planes_map + offsets[res->plane_slice];
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
ptrans->stride = align(util_format_get_stride(pres->format, box->width),
|
|
|
|
|
D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
|
|
|
|
@@ -1364,6 +1583,7 @@ static void
|
|
|
|
|
d3d12_transfer_unmap(struct pipe_context *pctx,
|
|
|
|
|
struct pipe_transfer *ptrans)
|
|
|
|
|
{
|
|
|
|
|
struct d3d12_context *ctx = d3d12_context(pctx);
|
|
|
|
|
struct d3d12_resource *res = d3d12_resource(ptrans->resource);
|
|
|
|
|
struct d3d12_transfer *trans = (struct d3d12_transfer *)ptrans;
|
|
|
|
|
D3D12_RANGE range = { 0, 0 };
|
|
|
|
@@ -1373,27 +1593,81 @@ d3d12_transfer_unmap(struct pipe_context *pctx,
|
|
|
|
|
write_zs_surface(pctx, res, trans);
|
|
|
|
|
free(trans->data);
|
|
|
|
|
} else if (trans->staging_res) {
|
|
|
|
|
struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res);
|
|
|
|
|
if(util_format_is_yuv(res->overall_format)) {
|
|
|
|
|
|
|
|
|
|
if (trans->base.b.usage & PIPE_MAP_WRITE) {
|
|
|
|
|
assert(ptrans->box.x >= 0);
|
|
|
|
|
range.Begin = res->base.b.target == PIPE_BUFFER ?
|
|
|
|
|
(unsigned)ptrans->box.x % BUFFER_MAP_ALIGNMENT : 0;
|
|
|
|
|
range.End = staging_res->base.b.width0 - range.Begin;
|
|
|
|
|
/* Get planes information*/
|
|
|
|
|
unsigned num_planes = util_format_get_num_planes(res->overall_format);
|
|
|
|
|
pipe_resource* planes[num_planes];
|
|
|
|
|
unsigned int strides[num_planes];
|
|
|
|
|
unsigned int layer_strides[num_planes];
|
|
|
|
|
unsigned int offsets[num_planes];
|
|
|
|
|
unsigned staging_res_size = 0;
|
|
|
|
|
|
|
|
|
|
d3d12_resource_get_planes_info(
|
|
|
|
|
ptrans->resource,
|
|
|
|
|
num_planes,
|
|
|
|
|
planes,
|
|
|
|
|
strides,
|
|
|
|
|
layer_strides,
|
|
|
|
|
offsets,
|
|
|
|
|
&staging_res_size
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/* Flush the changed contents into the GPU texture*/
|
|
|
|
|
|
|
|
|
|
/* In theory we should just flush only the contents for the plane*/
|
|
|
|
|
/* requested in res->plane_slice, but the VAAPI frontend has this*/
|
|
|
|
|
/* behaviour in which they assume that mapping the first plane of*/
|
|
|
|
|
/* NV12, P010, etc resources will will give them a buffer containing*/
|
|
|
|
|
/* both Y and UV planes contigously in vaDeriveImage and then vaMapBuffer*/
|
|
|
|
|
/* so, flush them all*/
|
|
|
|
|
|
|
|
|
|
struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res);
|
|
|
|
|
if (trans->base.b.usage & PIPE_MAP_WRITE) {
|
|
|
|
|
assert(ptrans->box.x >= 0);
|
|
|
|
|
range.Begin = res->base.b.target == PIPE_BUFFER ?
|
|
|
|
|
(unsigned)ptrans->box.x % BUFFER_MAP_ALIGNMENT : 0;
|
|
|
|
|
range.End = staging_res->base.b.width0 - range.Begin;
|
|
|
|
|
|
|
|
|
|
d3d12_bo_unmap(staging_res->bo, &range);
|
|
|
|
|
pipe_box original_box = ptrans->box;
|
|
|
|
|
for (uint plane_slice = 0; plane_slice < num_planes; ++plane_slice) {
|
|
|
|
|
/* Adjust strides, offsets to the corresponding plane for the copytexture operation*/
|
|
|
|
|
d3d12_adjust_transfer_dimensions_for_plane(res,
|
|
|
|
|
plane_slice,
|
|
|
|
|
strides[plane_slice],
|
|
|
|
|
layer_strides[plane_slice],
|
|
|
|
|
offsets[plane_slice],
|
|
|
|
|
&original_box,
|
|
|
|
|
ptrans/*inout*/);
|
|
|
|
|
|
|
|
|
|
transfer_buf_to_image(ctx, d3d12_resource(planes[plane_slice]), staging_res, trans, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pipe_resource_reference(&trans->staging_res, NULL);
|
|
|
|
|
} else {
|
|
|
|
|
struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res);
|
|
|
|
|
if (trans->base.b.usage & PIPE_MAP_WRITE) {
|
|
|
|
|
assert(ptrans->box.x >= 0);
|
|
|
|
|
range.Begin = res->base.b.target == PIPE_BUFFER ?
|
|
|
|
|
(unsigned)ptrans->box.x % BUFFER_MAP_ALIGNMENT : 0;
|
|
|
|
|
range.End = staging_res->base.b.width0 - range.Begin;
|
|
|
|
|
}
|
|
|
|
|
d3d12_bo_unmap(staging_res->bo, &range);
|
|
|
|
|
|
|
|
|
|
if (trans->base.b.usage & PIPE_MAP_WRITE) {
|
|
|
|
|
struct d3d12_context *ctx = d3d12_context(pctx);
|
|
|
|
|
if (res->base.b.target == PIPE_BUFFER) {
|
|
|
|
|
uint64_t dst_offset = trans->base.b.box.x;
|
|
|
|
|
uint64_t src_offset = dst_offset % BUFFER_MAP_ALIGNMENT;
|
|
|
|
|
transfer_buf_to_buf(ctx, staging_res, res, src_offset, dst_offset, ptrans->box.width);
|
|
|
|
|
} else
|
|
|
|
|
transfer_buf_to_image(ctx, res, staging_res, trans, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pipe_resource_reference(&trans->staging_res, NULL);
|
|
|
|
|
}
|
|
|
|
|
d3d12_bo_unmap(staging_res->bo, &range);
|
|
|
|
|
|
|
|
|
|
if (trans->base.b.usage & PIPE_MAP_WRITE) {
|
|
|
|
|
struct d3d12_context *ctx = d3d12_context(pctx);
|
|
|
|
|
if (res->base.b.target == PIPE_BUFFER) {
|
|
|
|
|
uint64_t dst_offset = trans->base.b.box.x;
|
|
|
|
|
uint64_t src_offset = dst_offset % BUFFER_MAP_ALIGNMENT;
|
|
|
|
|
transfer_buf_to_buf(ctx, staging_res, res, src_offset, dst_offset, ptrans->box.width);
|
|
|
|
|
} else
|
|
|
|
|
transfer_buf_to_image(ctx, res, staging_res, trans, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pipe_resource_reference(&trans->staging_res, NULL);
|
|
|
|
|
} else {
|
|
|
|
|
if (trans->base.b.usage & PIPE_MAP_WRITE) {
|
|
|
|
|
range.Begin = ptrans->box.x;
|
|
|
|
|