1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "d3d12_resource.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "d3d12_blit.h" 27bf215546Sopenharmony_ci#include "d3d12_context.h" 28bf215546Sopenharmony_ci#include "d3d12_format.h" 29bf215546Sopenharmony_ci#include "d3d12_screen.h" 30bf215546Sopenharmony_ci#include "d3d12_debug.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "pipebuffer/pb_bufmgr.h" 33bf215546Sopenharmony_ci#include "util/slab.h" 34bf215546Sopenharmony_ci#include "util/format/u_format.h" 35bf215546Sopenharmony_ci#include "util/u_inlines.h" 36bf215546Sopenharmony_ci#include "util/u_memory.h" 37bf215546Sopenharmony_ci#include "util/format/u_format_zs.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "frontend/sw_winsys.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include <dxguids/dxguids.h> 42bf215546Sopenharmony_ci#include <memory> 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci#ifndef GENERIC_ALL 45bf215546Sopenharmony_ci // This is only added to winadapter.h in newer DirectX-Headers 46bf215546Sopenharmony_ci#define GENERIC_ALL 0x10000000L 47bf215546Sopenharmony_ci#endif 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_cistatic bool 50bf215546Sopenharmony_cican_map_directly(struct pipe_resource *pres) 51bf215546Sopenharmony_ci{ 52bf215546Sopenharmony_ci return pres->target == PIPE_BUFFER && 53bf215546Sopenharmony_ci pres->usage != PIPE_USAGE_DEFAULT && 54bf215546Sopenharmony_ci pres->usage != PIPE_USAGE_IMMUTABLE; 55bf215546Sopenharmony_ci} 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_cistatic void 58bf215546Sopenharmony_ciinit_valid_range(struct d3d12_resource *res) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci if (can_map_directly(&res->base.b)) 61bf215546Sopenharmony_ci util_range_init(&res->valid_buffer_range); 62bf215546Sopenharmony_ci} 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_cistatic void 65bf215546Sopenharmony_cid3d12_resource_destroy(struct pipe_screen *pscreen, 66bf215546Sopenharmony_ci struct pipe_resource *presource) 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci struct d3d12_resource *resource = d3d12_resource(presource); 69bf215546Sopenharmony_ci threaded_resource_deinit(presource); 70bf215546Sopenharmony_ci if (can_map_directly(presource)) 71bf215546Sopenharmony_ci util_range_destroy(&resource->valid_buffer_range); 72bf215546Sopenharmony_ci if (resource->bo) 73bf215546Sopenharmony_ci d3d12_bo_unreference(resource->bo); 74bf215546Sopenharmony_ci FREE(resource); 75bf215546Sopenharmony_ci} 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_cistatic bool 78bf215546Sopenharmony_ciresource_is_busy(struct d3d12_context *ctx, 79bf215546Sopenharmony_ci struct d3d12_resource *res, 80bf215546Sopenharmony_ci bool want_to_write) 81bf215546Sopenharmony_ci{ 82bf215546Sopenharmony_ci if (d3d12_batch_has_references(d3d12_current_batch(ctx), res->bo, want_to_write)) 83bf215546Sopenharmony_ci return true; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci bool busy = false; 86bf215546Sopenharmony_ci d3d12_foreach_submitted_batch(ctx, batch) { 87bf215546Sopenharmony_ci if (!d3d12_reset_batch(ctx, batch, 0)) 88bf215546Sopenharmony_ci busy |= d3d12_batch_has_references(batch, res->bo, want_to_write); 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci return busy; 91bf215546Sopenharmony_ci} 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_civoid 94bf215546Sopenharmony_cid3d12_resource_wait_idle(struct d3d12_context *ctx, 95bf215546Sopenharmony_ci struct d3d12_resource *res, 96bf215546Sopenharmony_ci bool want_to_write) 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci if (d3d12_batch_has_references(d3d12_current_batch(ctx), res->bo, want_to_write)) { 99bf215546Sopenharmony_ci d3d12_flush_cmdlist_and_wait(ctx); 100bf215546Sopenharmony_ci } else { 101bf215546Sopenharmony_ci d3d12_foreach_submitted_batch(ctx, batch) { 102bf215546Sopenharmony_ci if (d3d12_batch_has_references(batch, res->bo, want_to_write)) 103bf215546Sopenharmony_ci d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE); 104bf215546Sopenharmony_ci } 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_civoid 109bf215546Sopenharmony_cid3d12_resource_release(struct d3d12_resource *resource) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci if (!resource->bo) 112bf215546Sopenharmony_ci return; 113bf215546Sopenharmony_ci d3d12_bo_unreference(resource->bo); 114bf215546Sopenharmony_ci resource->bo = NULL; 115bf215546Sopenharmony_ci} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_cistatic bool 118bf215546Sopenharmony_ciinit_buffer(struct d3d12_screen *screen, 119bf215546Sopenharmony_ci struct d3d12_resource *res, 120bf215546Sopenharmony_ci const struct pipe_resource *templ) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci struct pb_desc buf_desc; 123bf215546Sopenharmony_ci struct pb_manager *bufmgr; 124bf215546Sopenharmony_ci struct pb_buffer *buf; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci /* Assert that we don't want to create a buffer with one of the emulated 127bf215546Sopenharmony_ci * formats, these are (currently) only supported when passing the vertex 128bf215546Sopenharmony_ci * element state */ 129bf215546Sopenharmony_ci assert(templ->format == d3d12_emulated_vtx_format(templ->format)); 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci switch (templ->usage) { 132bf215546Sopenharmony_ci case PIPE_USAGE_DEFAULT: 133bf215546Sopenharmony_ci case PIPE_USAGE_IMMUTABLE: 134bf215546Sopenharmony_ci bufmgr = screen->cache_bufmgr; 135bf215546Sopenharmony_ci buf_desc.usage = (pb_usage_flags)PB_USAGE_GPU_READ_WRITE; 136bf215546Sopenharmony_ci break; 137bf215546Sopenharmony_ci case PIPE_USAGE_DYNAMIC: 138bf215546Sopenharmony_ci case PIPE_USAGE_STREAM: 139bf215546Sopenharmony_ci bufmgr = screen->slab_bufmgr; 140bf215546Sopenharmony_ci buf_desc.usage = (pb_usage_flags)(PB_USAGE_CPU_WRITE | PB_USAGE_GPU_READ); 141bf215546Sopenharmony_ci break; 142bf215546Sopenharmony_ci case PIPE_USAGE_STAGING: 143bf215546Sopenharmony_ci bufmgr = screen->readback_slab_bufmgr; 144bf215546Sopenharmony_ci buf_desc.usage = (pb_usage_flags)(PB_USAGE_GPU_WRITE | PB_USAGE_CPU_READ_WRITE); 145bf215546Sopenharmony_ci break; 146bf215546Sopenharmony_ci default: 147bf215546Sopenharmony_ci unreachable("Invalid pipe usage"); 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci /* We can't suballocate buffers that might be bound as a sampler view, *only* 151bf215546Sopenharmony_ci * because in the case of R32G32B32 formats (12 bytes per pixel), it's not possible 152bf215546Sopenharmony_ci * to guarantee the offset will be divisible. 153bf215546Sopenharmony_ci */ 154bf215546Sopenharmony_ci if (templ->bind & PIPE_BIND_SAMPLER_VIEW) 155bf215546Sopenharmony_ci bufmgr = screen->cache_bufmgr; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci buf_desc.alignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT; 158bf215546Sopenharmony_ci res->dxgi_format = DXGI_FORMAT_UNKNOWN; 159bf215546Sopenharmony_ci buf = bufmgr->create_buffer(bufmgr, templ->width0, &buf_desc); 160bf215546Sopenharmony_ci if (!buf) 161bf215546Sopenharmony_ci return false; 162bf215546Sopenharmony_ci res->bo = d3d12_bo_wrap_buffer(screen, buf); 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci return true; 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_cistatic bool 168bf215546Sopenharmony_ciinit_texture(struct d3d12_screen *screen, 169bf215546Sopenharmony_ci struct d3d12_resource *res, 170bf215546Sopenharmony_ci const struct pipe_resource *templ, 171bf215546Sopenharmony_ci ID3D12Heap *heap, 172bf215546Sopenharmony_ci uint64_t placed_offset) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci ID3D12Resource *d3d12_res; 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci res->mip_levels = templ->last_level + 1; 177bf215546Sopenharmony_ci res->dxgi_format = d3d12_get_format(templ->format); 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci D3D12_RESOURCE_DESC desc; 180bf215546Sopenharmony_ci desc.Format = res->dxgi_format; 181bf215546Sopenharmony_ci desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; 182bf215546Sopenharmony_ci desc.Width = templ->width0; 183bf215546Sopenharmony_ci desc.Height = templ->height0; 184bf215546Sopenharmony_ci desc.DepthOrArraySize = templ->array_size; 185bf215546Sopenharmony_ci desc.MipLevels = templ->last_level + 1; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci desc.SampleDesc.Count = MAX2(templ->nr_samples, 1); 188bf215546Sopenharmony_ci desc.SampleDesc.Quality = 0; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci desc.Flags = D3D12_RESOURCE_FLAG_NONE; 191bf215546Sopenharmony_ci desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci switch (templ->target) { 194bf215546Sopenharmony_ci case PIPE_BUFFER: 195bf215546Sopenharmony_ci desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; 196bf215546Sopenharmony_ci desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; 197bf215546Sopenharmony_ci desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; 198bf215546Sopenharmony_ci break; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 201bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 202bf215546Sopenharmony_ci desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D; 203bf215546Sopenharmony_ci break; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 206bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 207bf215546Sopenharmony_ci desc.DepthOrArraySize *= 6; 208bf215546Sopenharmony_ci FALLTHROUGH; 209bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 210bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 211bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 212bf215546Sopenharmony_ci desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; 213bf215546Sopenharmony_ci break; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 216bf215546Sopenharmony_ci desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D; 217bf215546Sopenharmony_ci desc.DepthOrArraySize = templ->depth0; 218bf215546Sopenharmony_ci break; 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci default: 221bf215546Sopenharmony_ci unreachable("Invalid texture type"); 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci if (templ->bind & PIPE_BIND_SHADER_BUFFER) 225bf215546Sopenharmony_ci desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci if (templ->bind & PIPE_BIND_RENDER_TARGET) 228bf215546Sopenharmony_ci desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci if (templ->bind & PIPE_BIND_DEPTH_STENCIL) { 231bf215546Sopenharmony_ci desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci /* Sadly, we can't set D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE in the 234bf215546Sopenharmony_ci * case where PIPE_BIND_SAMPLER_VIEW isn't set, because that would 235bf215546Sopenharmony_ci * prevent us from using the resource with u_blitter, which requires 236bf215546Sopenharmony_ci * sneaking in sampler-usage throught the back-door. 237bf215546Sopenharmony_ci */ 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci if (screen->support_shader_images && templ->nr_samples <= 1) { 241bf215546Sopenharmony_ci /* Ideally, we'd key off of PIPE_BIND_SHADER_IMAGE for this, but it doesn't 242bf215546Sopenharmony_ci * seem to be set properly. So, all UAV-capable resources need the UAV flag. 243bf215546Sopenharmony_ci */ 244bf215546Sopenharmony_ci D3D12_FEATURE_DATA_FORMAT_SUPPORT support = { desc.Format }; 245bf215546Sopenharmony_ci if (SUCCEEDED(screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &support, sizeof(support))) && 246bf215546Sopenharmony_ci (support.Support2 & (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE)) == 247bf215546Sopenharmony_ci (D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE)) { 248bf215546Sopenharmony_ci desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; 249bf215546Sopenharmony_ci desc.Format = d3d12_get_typeless_format(templ->format); 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if (templ->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_LINEAR)) 254bf215546Sopenharmony_ci desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci HRESULT hres = E_FAIL; 257bf215546Sopenharmony_ci enum d3d12_residency_status init_residency; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci if (heap) { 260bf215546Sopenharmony_ci init_residency = d3d12_permanently_resident; 261bf215546Sopenharmony_ci hres = screen->dev->CreatePlacedResource(heap, 262bf215546Sopenharmony_ci placed_offset, 263bf215546Sopenharmony_ci &desc, 264bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_COMMON, 265bf215546Sopenharmony_ci nullptr, 266bf215546Sopenharmony_ci IID_PPV_ARGS(&d3d12_res)); 267bf215546Sopenharmony_ci } else { 268bf215546Sopenharmony_ci D3D12_HEAP_PROPERTIES heap_pris = GetCustomHeapProperties(screen->dev, D3D12_HEAP_TYPE_DEFAULT); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci D3D12_HEAP_FLAGS heap_flags = screen->support_create_not_resident ? 271bf215546Sopenharmony_ci D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT : D3D12_HEAP_FLAG_NONE; 272bf215546Sopenharmony_ci init_residency = screen->support_create_not_resident ? d3d12_evicted : d3d12_resident; 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci hres = screen->dev->CreateCommittedResource(&heap_pris, 275bf215546Sopenharmony_ci heap_flags, 276bf215546Sopenharmony_ci &desc, 277bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_COMMON, 278bf215546Sopenharmony_ci NULL, 279bf215546Sopenharmony_ci IID_PPV_ARGS(&d3d12_res)); 280bf215546Sopenharmony_ci } 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci if (FAILED(hres)) 283bf215546Sopenharmony_ci return false; 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (screen->winsys && (templ->bind & PIPE_BIND_DISPLAY_TARGET)) { 286bf215546Sopenharmony_ci struct sw_winsys *winsys = screen->winsys; 287bf215546Sopenharmony_ci res->dt = winsys->displaytarget_create(screen->winsys, 288bf215546Sopenharmony_ci res->base.b.bind, 289bf215546Sopenharmony_ci res->base.b.format, 290bf215546Sopenharmony_ci templ->width0, 291bf215546Sopenharmony_ci templ->height0, 292bf215546Sopenharmony_ci 64, NULL, 293bf215546Sopenharmony_ci &res->dt_stride); 294bf215546Sopenharmony_ci } 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci res->bo = d3d12_bo_wrap_res(screen, d3d12_res, init_residency); 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci return true; 299bf215546Sopenharmony_ci} 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_cistatic void 302bf215546Sopenharmony_ciconvert_planar_resource(struct d3d12_resource *res) 303bf215546Sopenharmony_ci{ 304bf215546Sopenharmony_ci unsigned num_planes = util_format_get_num_planes(res->base.b.format); 305bf215546Sopenharmony_ci if (num_planes <= 1 || res->base.b.next || !res->bo) 306bf215546Sopenharmony_ci return; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci struct pipe_resource *next = nullptr; 309bf215546Sopenharmony_ci struct pipe_resource *planes[3] = { 310bf215546Sopenharmony_ci &res->base.b, nullptr, nullptr 311bf215546Sopenharmony_ci }; 312bf215546Sopenharmony_ci for (int plane = num_planes - 1; plane >= 0; --plane) { 313bf215546Sopenharmony_ci struct d3d12_resource *plane_res = d3d12_resource(planes[plane]); 314bf215546Sopenharmony_ci if (!plane_res) { 315bf215546Sopenharmony_ci plane_res = CALLOC_STRUCT(d3d12_resource); 316bf215546Sopenharmony_ci *plane_res = *res; 317bf215546Sopenharmony_ci d3d12_bo_reference(plane_res->bo); 318bf215546Sopenharmony_ci pipe_reference_init(&plane_res->base.b.reference, 1); 319bf215546Sopenharmony_ci threaded_resource_init(&plane_res->base.b, false); 320bf215546Sopenharmony_ci } 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci plane_res->base.b.next = next; 323bf215546Sopenharmony_ci next = &plane_res->base.b; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci plane_res->plane_slice = plane; 326bf215546Sopenharmony_ci plane_res->base.b.format = util_format_get_plane_format(res->base.b.format, plane); 327bf215546Sopenharmony_ci plane_res->base.b.width0 = util_format_get_plane_width(res->base.b.format, plane, res->base.b.width0); 328bf215546Sopenharmony_ci plane_res->base.b.height0 = util_format_get_plane_height(res->base.b.format, plane, res->base.b.height0); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci#if DEBUG 331bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(res->base.b.screen); 332bf215546Sopenharmony_ci D3D12_RESOURCE_DESC desc = GetDesc(res->bo->res); 333bf215546Sopenharmony_ci D3D12_PLACED_SUBRESOURCE_FOOTPRINT placed_footprint = {}; 334bf215546Sopenharmony_ci D3D12_SUBRESOURCE_FOOTPRINT *footprint = &placed_footprint.Footprint; 335bf215546Sopenharmony_ci unsigned subresource = plane * desc.MipLevels * desc.DepthOrArraySize; 336bf215546Sopenharmony_ci screen->dev->GetCopyableFootprints(&desc, subresource, 1, 0, &placed_footprint, nullptr, nullptr, nullptr); 337bf215546Sopenharmony_ci assert(plane_res->base.b.width0 == footprint->Width); 338bf215546Sopenharmony_ci assert(plane_res->base.b.height0 == footprint->Height); 339bf215546Sopenharmony_ci assert(plane_res->base.b.depth0 == footprint->Depth); 340bf215546Sopenharmony_ci assert(plane_res->first_plane == &res->base.b); 341bf215546Sopenharmony_ci#endif 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci} 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_cistatic struct pipe_resource * 346bf215546Sopenharmony_cid3d12_resource_create_or_place(struct d3d12_screen *screen, 347bf215546Sopenharmony_ci struct d3d12_resource *res, 348bf215546Sopenharmony_ci const struct pipe_resource *templ, 349bf215546Sopenharmony_ci ID3D12Heap *heap, 350bf215546Sopenharmony_ci uint64_t placed_offset) 351bf215546Sopenharmony_ci{ 352bf215546Sopenharmony_ci bool ret; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci res->base.b = *templ; 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci res->overall_format = templ->format; 357bf215546Sopenharmony_ci res->plane_slice = 0; 358bf215546Sopenharmony_ci res->first_plane = &res->base.b; 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci if (D3D12_DEBUG_RESOURCE & d3d12_debug) { 361bf215546Sopenharmony_ci debug_printf("D3D12: Create %sresource %s@%d %dx%dx%d as:%d mip:%d\n", 362bf215546Sopenharmony_ci templ->usage == PIPE_USAGE_STAGING ? "STAGING " :"", 363bf215546Sopenharmony_ci util_format_name(templ->format), templ->nr_samples, 364bf215546Sopenharmony_ci templ->width0, templ->height0, templ->depth0, 365bf215546Sopenharmony_ci templ->array_size, templ->last_level); 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci pipe_reference_init(&res->base.b.reference, 1); 369bf215546Sopenharmony_ci res->base.b.screen = &screen->base; 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (templ->target == PIPE_BUFFER && !heap) { 372bf215546Sopenharmony_ci ret = init_buffer(screen, res, templ); 373bf215546Sopenharmony_ci } else { 374bf215546Sopenharmony_ci ret = init_texture(screen, res, templ, heap, placed_offset); 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci if (!ret) { 378bf215546Sopenharmony_ci FREE(res); 379bf215546Sopenharmony_ci return NULL; 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci init_valid_range(res); 383bf215546Sopenharmony_ci threaded_resource_init(&res->base.b, 384bf215546Sopenharmony_ci templ->usage == PIPE_USAGE_DEFAULT && 385bf215546Sopenharmony_ci templ->target == PIPE_BUFFER); 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci memset(&res->bind_counts, 0, sizeof(d3d12_resource::bind_counts)); 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci convert_planar_resource(res); 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci return &res->base.b; 392bf215546Sopenharmony_ci} 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_cistatic struct pipe_resource * 395bf215546Sopenharmony_cid3d12_resource_create(struct pipe_screen *pscreen, 396bf215546Sopenharmony_ci const struct pipe_resource *templ) 397bf215546Sopenharmony_ci{ 398bf215546Sopenharmony_ci struct d3d12_resource *res = CALLOC_STRUCT(d3d12_resource); 399bf215546Sopenharmony_ci if (!res) 400bf215546Sopenharmony_ci return NULL; 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci return d3d12_resource_create_or_place(d3d12_screen(pscreen), res, templ, nullptr, 0); 403bf215546Sopenharmony_ci} 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_cistatic struct pipe_resource * 406bf215546Sopenharmony_cid3d12_resource_from_handle(struct pipe_screen *pscreen, 407bf215546Sopenharmony_ci const struct pipe_resource *templ, 408bf215546Sopenharmony_ci struct winsys_handle *handle, unsigned usage) 409bf215546Sopenharmony_ci{ 410bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pscreen); 411bf215546Sopenharmony_ci if (handle->type != WINSYS_HANDLE_TYPE_D3D12_RES && 412bf215546Sopenharmony_ci handle->type != WINSYS_HANDLE_TYPE_FD && 413bf215546Sopenharmony_ci handle->type != WINSYS_HANDLE_TYPE_WIN32_NAME) 414bf215546Sopenharmony_ci return NULL; 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci struct d3d12_resource *res = CALLOC_STRUCT(d3d12_resource); 417bf215546Sopenharmony_ci if (!res) 418bf215546Sopenharmony_ci return NULL; 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci if (templ && templ->next) { 421bf215546Sopenharmony_ci struct d3d12_resource* next = d3d12_resource(templ->next); 422bf215546Sopenharmony_ci if (next->bo) { 423bf215546Sopenharmony_ci res->base.b = *templ; 424bf215546Sopenharmony_ci res->bo = next->bo; 425bf215546Sopenharmony_ci d3d12_bo_reference(res->bo); 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci } 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci#ifdef _WIN32 430bf215546Sopenharmony_ci HANDLE d3d_handle = handle->handle; 431bf215546Sopenharmony_ci#else 432bf215546Sopenharmony_ci HANDLE d3d_handle = (HANDLE) (intptr_t) handle->handle; 433bf215546Sopenharmony_ci#endif 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci#ifdef _WIN32 436bf215546Sopenharmony_ci HANDLE d3d_handle_to_close = nullptr; 437bf215546Sopenharmony_ci if (handle->type == WINSYS_HANDLE_TYPE_WIN32_NAME) { 438bf215546Sopenharmony_ci screen->dev->OpenSharedHandleByName((LPCWSTR)handle->name, GENERIC_ALL, &d3d_handle_to_close); 439bf215546Sopenharmony_ci d3d_handle = d3d_handle_to_close; 440bf215546Sopenharmony_ci } 441bf215546Sopenharmony_ci#endif 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci ID3D12Resource *d3d12_res = nullptr; 444bf215546Sopenharmony_ci ID3D12Heap *d3d12_heap = nullptr; 445bf215546Sopenharmony_ci if (res->bo) { 446bf215546Sopenharmony_ci d3d12_res = res->bo->res; 447bf215546Sopenharmony_ci } else if (handle->type == WINSYS_HANDLE_TYPE_D3D12_RES) { 448bf215546Sopenharmony_ci IUnknown *obj = (IUnknown *)handle->com_obj; 449bf215546Sopenharmony_ci (void)obj->QueryInterface(&d3d12_res); 450bf215546Sopenharmony_ci (void)obj->QueryInterface(&d3d12_heap); 451bf215546Sopenharmony_ci obj->Release(); 452bf215546Sopenharmony_ci } else { 453bf215546Sopenharmony_ci screen->dev->OpenSharedHandle(d3d_handle, IID_PPV_ARGS(&d3d12_res)); 454bf215546Sopenharmony_ci } 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci#ifdef _WIN32 457bf215546Sopenharmony_ci if (d3d_handle_to_close) { 458bf215546Sopenharmony_ci CloseHandle(d3d_handle_to_close); 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci#endif 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci D3D12_PLACED_SUBRESOURCE_FOOTPRINT placed_footprint = {}; 463bf215546Sopenharmony_ci D3D12_SUBRESOURCE_FOOTPRINT *footprint = &placed_footprint.Footprint; 464bf215546Sopenharmony_ci D3D12_RESOURCE_DESC incoming_res_desc; 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci if (!d3d12_res && !d3d12_heap) 467bf215546Sopenharmony_ci goto invalid; 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci if (d3d12_heap) { 470bf215546Sopenharmony_ci assert(templ); 471bf215546Sopenharmony_ci assert(!res->bo); 472bf215546Sopenharmony_ci assert(!d3d12_res); 473bf215546Sopenharmony_ci return d3d12_resource_create_or_place(screen, res, templ, d3d12_heap, handle->offset); 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci pipe_reference_init(&res->base.b.reference, 1); 477bf215546Sopenharmony_ci res->base.b.screen = pscreen; 478bf215546Sopenharmony_ci incoming_res_desc = GetDesc(d3d12_res); 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci /* Get a description for this plane */ 481bf215546Sopenharmony_ci if (templ && handle->format != templ->format) { 482bf215546Sopenharmony_ci unsigned subresource = handle->plane * incoming_res_desc.MipLevels * incoming_res_desc.DepthOrArraySize; 483bf215546Sopenharmony_ci screen->dev->GetCopyableFootprints(&incoming_res_desc, subresource, 1, 0, &placed_footprint, nullptr, nullptr, nullptr); 484bf215546Sopenharmony_ci } else { 485bf215546Sopenharmony_ci footprint->Format = incoming_res_desc.Format; 486bf215546Sopenharmony_ci footprint->Width = incoming_res_desc.Width; 487bf215546Sopenharmony_ci footprint->Height = incoming_res_desc.Height; 488bf215546Sopenharmony_ci footprint->Depth = incoming_res_desc.DepthOrArraySize; 489bf215546Sopenharmony_ci } 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci if (footprint->Width > UINT32_MAX || 492bf215546Sopenharmony_ci footprint->Height > UINT16_MAX) { 493bf215546Sopenharmony_ci debug_printf("d3d12: Importing resource too large\n"); 494bf215546Sopenharmony_ci goto invalid; 495bf215546Sopenharmony_ci } 496bf215546Sopenharmony_ci res->base.b.width0 = incoming_res_desc.Width; 497bf215546Sopenharmony_ci res->base.b.height0 = incoming_res_desc.Height; 498bf215546Sopenharmony_ci res->base.b.depth0 = 1; 499bf215546Sopenharmony_ci res->base.b.array_size = 1; 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci switch (incoming_res_desc.Dimension) { 502bf215546Sopenharmony_ci case D3D12_RESOURCE_DIMENSION_BUFFER: 503bf215546Sopenharmony_ci res->base.b.target = PIPE_BUFFER; 504bf215546Sopenharmony_ci res->base.b.bind = PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_CONSTANT_BUFFER | 505bf215546Sopenharmony_ci PIPE_BIND_INDEX_BUFFER | PIPE_BIND_STREAM_OUTPUT | PIPE_BIND_SHADER_BUFFER | 506bf215546Sopenharmony_ci PIPE_BIND_COMMAND_ARGS_BUFFER | PIPE_BIND_QUERY_BUFFER; 507bf215546Sopenharmony_ci break; 508bf215546Sopenharmony_ci case D3D12_RESOURCE_DIMENSION_TEXTURE1D: 509bf215546Sopenharmony_ci res->base.b.target = incoming_res_desc.DepthOrArraySize > 1 ? 510bf215546Sopenharmony_ci PIPE_TEXTURE_1D_ARRAY : PIPE_TEXTURE_1D; 511bf215546Sopenharmony_ci res->base.b.array_size = incoming_res_desc.DepthOrArraySize; 512bf215546Sopenharmony_ci break; 513bf215546Sopenharmony_ci case D3D12_RESOURCE_DIMENSION_TEXTURE2D: 514bf215546Sopenharmony_ci res->base.b.target = incoming_res_desc.DepthOrArraySize > 1 ? 515bf215546Sopenharmony_ci PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D; 516bf215546Sopenharmony_ci res->base.b.array_size = incoming_res_desc.DepthOrArraySize; 517bf215546Sopenharmony_ci break; 518bf215546Sopenharmony_ci case D3D12_RESOURCE_DIMENSION_TEXTURE3D: 519bf215546Sopenharmony_ci res->base.b.target = PIPE_TEXTURE_3D; 520bf215546Sopenharmony_ci res->base.b.depth0 = footprint->Depth; 521bf215546Sopenharmony_ci break; 522bf215546Sopenharmony_ci default: 523bf215546Sopenharmony_ci unreachable("Invalid dimension"); 524bf215546Sopenharmony_ci break; 525bf215546Sopenharmony_ci } 526bf215546Sopenharmony_ci res->base.b.nr_samples = incoming_res_desc.SampleDesc.Count; 527bf215546Sopenharmony_ci res->base.b.last_level = incoming_res_desc.MipLevels - 1; 528bf215546Sopenharmony_ci res->base.b.usage = PIPE_USAGE_DEFAULT; 529bf215546Sopenharmony_ci res->base.b.bind |= PIPE_BIND_SHARED; 530bf215546Sopenharmony_ci if (incoming_res_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) 531bf215546Sopenharmony_ci res->base.b.bind |= PIPE_BIND_RENDER_TARGET | PIPE_BIND_BLENDABLE | PIPE_BIND_DISPLAY_TARGET; 532bf215546Sopenharmony_ci if (incoming_res_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) 533bf215546Sopenharmony_ci res->base.b.bind |= PIPE_BIND_DEPTH_STENCIL; 534bf215546Sopenharmony_ci if (incoming_res_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) 535bf215546Sopenharmony_ci res->base.b.bind |= PIPE_BIND_SHADER_IMAGE; 536bf215546Sopenharmony_ci if ((incoming_res_desc.Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE) == D3D12_RESOURCE_FLAG_NONE) 537bf215546Sopenharmony_ci res->base.b.bind |= PIPE_BIND_SAMPLER_VIEW; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci if (templ) { 540bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_2D_ARRAY && 541bf215546Sopenharmony_ci (templ->target == PIPE_TEXTURE_CUBE || 542bf215546Sopenharmony_ci templ->target == PIPE_TEXTURE_CUBE_ARRAY)) { 543bf215546Sopenharmony_ci if (res->base.b.array_size < 6) { 544bf215546Sopenharmony_ci debug_printf("d3d12: Importing cube resource with too few array layers\n"); 545bf215546Sopenharmony_ci goto invalid; 546bf215546Sopenharmony_ci } 547bf215546Sopenharmony_ci res->base.b.target = templ->target; 548bf215546Sopenharmony_ci res->base.b.array_size /= 6; 549bf215546Sopenharmony_ci } 550bf215546Sopenharmony_ci unsigned templ_samples = MAX2(templ->nr_samples, 1); 551bf215546Sopenharmony_ci if (res->base.b.target != templ->target || 552bf215546Sopenharmony_ci footprint->Width != templ->width0 || 553bf215546Sopenharmony_ci footprint->Height != templ->height0 || 554bf215546Sopenharmony_ci footprint->Depth != templ->depth0 || 555bf215546Sopenharmony_ci res->base.b.array_size != templ->array_size || 556bf215546Sopenharmony_ci incoming_res_desc.SampleDesc.Count != templ_samples || 557bf215546Sopenharmony_ci res->base.b.last_level != templ->last_level) { 558bf215546Sopenharmony_ci debug_printf("d3d12: Importing resource with mismatched dimensions: " 559bf215546Sopenharmony_ci "plane: %d, target: %d vs %d, width: %d vs %d, height: %d vs %d, " 560bf215546Sopenharmony_ci "depth: %d vs %d, array_size: %d vs %d, samples: %d vs %d, mips: %d vs %d\n", 561bf215546Sopenharmony_ci handle->plane, 562bf215546Sopenharmony_ci res->base.b.target, templ->target, 563bf215546Sopenharmony_ci footprint->Width, templ->width0, 564bf215546Sopenharmony_ci footprint->Height, templ->height0, 565bf215546Sopenharmony_ci footprint->Depth, templ->depth0, 566bf215546Sopenharmony_ci res->base.b.array_size, templ->array_size, 567bf215546Sopenharmony_ci incoming_res_desc.SampleDesc.Count, templ_samples, 568bf215546Sopenharmony_ci res->base.b.last_level + 1, templ->last_level + 1); 569bf215546Sopenharmony_ci goto invalid; 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci if (templ->target != PIPE_BUFFER) { 572bf215546Sopenharmony_ci if ((footprint->Format != d3d12_get_format(templ->format) && 573bf215546Sopenharmony_ci footprint->Format != d3d12_get_typeless_format(templ->format)) || 574bf215546Sopenharmony_ci (incoming_res_desc.Format != d3d12_get_format((enum pipe_format)handle->format) && 575bf215546Sopenharmony_ci incoming_res_desc.Format != d3d12_get_typeless_format((enum pipe_format)handle->format))) { 576bf215546Sopenharmony_ci debug_printf("d3d12: Importing resource with mismatched format: " 577bf215546Sopenharmony_ci "plane could be DXGI format %d or %d, but is %d, " 578bf215546Sopenharmony_ci "overall could be DXGI format %d or %d, but is %d\n", 579bf215546Sopenharmony_ci d3d12_get_format(templ->format), 580bf215546Sopenharmony_ci d3d12_get_typeless_format(templ->format), 581bf215546Sopenharmony_ci footprint->Format, 582bf215546Sopenharmony_ci d3d12_get_format((enum pipe_format)handle->format), 583bf215546Sopenharmony_ci d3d12_get_typeless_format((enum pipe_format)handle->format), 584bf215546Sopenharmony_ci incoming_res_desc.Format); 585bf215546Sopenharmony_ci goto invalid; 586bf215546Sopenharmony_ci } 587bf215546Sopenharmony_ci } 588bf215546Sopenharmony_ci /* In an ideal world we'd be able to validate this, but gallium's use of bind 589bf215546Sopenharmony_ci * flags during resource creation is pretty bad: some bind flags are always set 590bf215546Sopenharmony_ci * (like PIPE_BIND_RENDER_TARGET) while others are never set (PIPE_BIND_SHADER_BUFFER) 591bf215546Sopenharmony_ci * 592bf215546Sopenharmony_ci if (templ->bind & ~res->base.b.bind) { 593bf215546Sopenharmony_ci debug_printf("d3d12: Imported resource doesn't have necessary bind flags\n"); 594bf215546Sopenharmony_ci goto invalid; 595bf215546Sopenharmony_ci } */ 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci res->base.b.format = templ->format; 598bf215546Sopenharmony_ci res->overall_format = (enum pipe_format)handle->format; 599bf215546Sopenharmony_ci } else { 600bf215546Sopenharmony_ci /* Search the pipe format lookup table for an entry */ 601bf215546Sopenharmony_ci res->base.b.format = d3d12_get_pipe_format(incoming_res_desc.Format); 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci if (res->base.b.format == PIPE_FORMAT_NONE) { 604bf215546Sopenharmony_ci /* Convert from typeless to a reasonable default */ 605bf215546Sopenharmony_ci res->base.b.format = d3d12_get_default_pipe_format(incoming_res_desc.Format); 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci if (res->base.b.format == PIPE_FORMAT_NONE) { 608bf215546Sopenharmony_ci debug_printf("d3d12: Unable to deduce non-typeless resource format %d\n", incoming_res_desc.Format); 609bf215546Sopenharmony_ci goto invalid; 610bf215546Sopenharmony_ci } 611bf215546Sopenharmony_ci } 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci res->overall_format = res->base.b.format; 614bf215546Sopenharmony_ci } 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci if (!templ) 617bf215546Sopenharmony_ci handle->format = res->overall_format; 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci res->dxgi_format = d3d12_get_format(res->overall_format); 620bf215546Sopenharmony_ci res->plane_slice = handle->plane; 621bf215546Sopenharmony_ci res->first_plane = &res->base.b; 622bf215546Sopenharmony_ci 623bf215546Sopenharmony_ci if (!res->bo) { 624bf215546Sopenharmony_ci res->bo = d3d12_bo_wrap_res(screen, d3d12_res, d3d12_permanently_resident); 625bf215546Sopenharmony_ci } 626bf215546Sopenharmony_ci init_valid_range(res); 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci threaded_resource_init(&res->base.b, false); 629bf215546Sopenharmony_ci convert_planar_resource(res); 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci return &res->base.b; 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ciinvalid: 634bf215546Sopenharmony_ci if (res->bo) 635bf215546Sopenharmony_ci d3d12_bo_unreference(res->bo); 636bf215546Sopenharmony_ci else if (d3d12_res) 637bf215546Sopenharmony_ci d3d12_res->Release(); 638bf215546Sopenharmony_ci FREE(res); 639bf215546Sopenharmony_ci return NULL; 640bf215546Sopenharmony_ci} 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_cistatic bool 643bf215546Sopenharmony_cid3d12_resource_get_handle(struct pipe_screen *pscreen, 644bf215546Sopenharmony_ci struct pipe_context *pcontext, 645bf215546Sopenharmony_ci struct pipe_resource *pres, 646bf215546Sopenharmony_ci struct winsys_handle *handle, 647bf215546Sopenharmony_ci unsigned usage) 648bf215546Sopenharmony_ci{ 649bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(pres); 650bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pscreen); 651bf215546Sopenharmony_ci 652bf215546Sopenharmony_ci switch (handle->type) { 653bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_D3D12_RES: 654bf215546Sopenharmony_ci handle->com_obj = d3d12_resource_resource(res); 655bf215546Sopenharmony_ci return true; 656bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_FD: { 657bf215546Sopenharmony_ci HANDLE d3d_handle = nullptr; 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ci screen->dev->CreateSharedHandle(d3d12_resource_resource(res), 660bf215546Sopenharmony_ci nullptr, 661bf215546Sopenharmony_ci GENERIC_ALL, 662bf215546Sopenharmony_ci nullptr, 663bf215546Sopenharmony_ci &d3d_handle); 664bf215546Sopenharmony_ci if (!d3d_handle) 665bf215546Sopenharmony_ci return false; 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci#ifdef _WIN32 668bf215546Sopenharmony_ci handle->handle = d3d_handle; 669bf215546Sopenharmony_ci#else 670bf215546Sopenharmony_ci handle->handle = (int)(intptr_t)d3d_handle; 671bf215546Sopenharmony_ci#endif 672bf215546Sopenharmony_ci handle->format = pres->format; 673bf215546Sopenharmony_ci handle->modifier = ~0ull; 674bf215546Sopenharmony_ci return true; 675bf215546Sopenharmony_ci } 676bf215546Sopenharmony_ci default: 677bf215546Sopenharmony_ci return false; 678bf215546Sopenharmony_ci } 679bf215546Sopenharmony_ci} 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_cistruct pipe_resource * 682bf215546Sopenharmony_cid3d12_resource_from_resource(struct pipe_screen *pscreen, 683bf215546Sopenharmony_ci ID3D12Resource* input_res) 684bf215546Sopenharmony_ci{ 685bf215546Sopenharmony_ci D3D12_RESOURCE_DESC input_desc = GetDesc(input_res); 686bf215546Sopenharmony_ci struct winsys_handle handle; 687bf215546Sopenharmony_ci memset(&handle, 0, sizeof(handle)); 688bf215546Sopenharmony_ci handle.type = WINSYS_HANDLE_TYPE_D3D12_RES; 689bf215546Sopenharmony_ci handle.format = d3d12_get_pipe_format(input_desc.Format); 690bf215546Sopenharmony_ci handle.com_obj = input_res; 691bf215546Sopenharmony_ci 692bf215546Sopenharmony_ci struct pipe_resource templ; 693bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 694bf215546Sopenharmony_ci if(input_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { 695bf215546Sopenharmony_ci templ.target = PIPE_BUFFER; 696bf215546Sopenharmony_ci } else { 697bf215546Sopenharmony_ci templ.target = (input_desc.DepthOrArraySize > 1) ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D; 698bf215546Sopenharmony_ci } 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci templ.format = d3d12_get_pipe_format(input_desc.Format); 701bf215546Sopenharmony_ci templ.width0 = input_desc.Width; 702bf215546Sopenharmony_ci templ.height0 = input_desc.Height; 703bf215546Sopenharmony_ci templ.depth0 = input_desc.DepthOrArraySize; 704bf215546Sopenharmony_ci templ.array_size = input_desc.DepthOrArraySize; 705bf215546Sopenharmony_ci templ.flags = 0; 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci return d3d12_resource_from_handle( 708bf215546Sopenharmony_ci pscreen, 709bf215546Sopenharmony_ci &templ, 710bf215546Sopenharmony_ci &handle, 711bf215546Sopenharmony_ci PIPE_USAGE_DEFAULT 712bf215546Sopenharmony_ci ); 713bf215546Sopenharmony_ci} 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci/** 716bf215546Sopenharmony_ci * On Map/Unmap operations, we readback or flush all the underlying planes 717bf215546Sopenharmony_ci * of planar resources. The map/unmap operation from the caller is 718bf215546Sopenharmony_ci * expected to be done for res->plane_slice plane only, but some 719bf215546Sopenharmony_ci * callers expect adjacent allocations for next contiguous plane access 720bf215546Sopenharmony_ci * 721bf215546Sopenharmony_ci * In this function, we take the res and box the caller passed, and the plane_* properties 722bf215546Sopenharmony_ci * that are currently being readback/flushed, and adjust the d3d12_transfer ptrans 723bf215546Sopenharmony_ci * accordingly for the GPU copy operation between planes. 724bf215546Sopenharmony_ci */ 725bf215546Sopenharmony_cistatic void d3d12_adjust_transfer_dimensions_for_plane(const struct d3d12_resource *res, 726bf215546Sopenharmony_ci unsigned plane_slice, 727bf215546Sopenharmony_ci unsigned plane_stride, 728bf215546Sopenharmony_ci unsigned plane_layer_stride, 729bf215546Sopenharmony_ci unsigned plane_offset, 730bf215546Sopenharmony_ci const struct pipe_box* original_box, 731bf215546Sopenharmony_ci struct pipe_transfer *ptrans/*inout*/) 732bf215546Sopenharmony_ci{ 733bf215546Sopenharmony_ci /* Adjust strides, offsets to the corresponding plane*/ 734bf215546Sopenharmony_ci ptrans->stride = plane_stride; 735bf215546Sopenharmony_ci ptrans->layer_stride = plane_layer_stride; 736bf215546Sopenharmony_ci ptrans->offset = plane_offset; 737bf215546Sopenharmony_ci 738bf215546Sopenharmony_ci /* Find multipliers such that:*/ 739bf215546Sopenharmony_ci /* first_plane.width = width_multiplier * planes[res->plane_slice].width*/ 740bf215546Sopenharmony_ci /* first_plane.height = height_multiplier * planes[res->plane_slice].height*/ 741bf215546Sopenharmony_ci float width_multiplier = res->first_plane->width0 / (float) util_format_get_plane_width(res->overall_format, res->plane_slice, res->first_plane->width0); 742bf215546Sopenharmony_ci float height_multiplier = res->first_plane->height0 / (float) util_format_get_plane_height(res->overall_format, res->plane_slice, res->first_plane->height0); 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_ci /* Normalize box back to overall dimensions (first plane)*/ 745bf215546Sopenharmony_ci ptrans->box.width = width_multiplier * original_box->width; 746bf215546Sopenharmony_ci ptrans->box.height = height_multiplier * original_box->height; 747bf215546Sopenharmony_ci ptrans->box.x = width_multiplier * original_box->x; 748bf215546Sopenharmony_ci ptrans->box.y = height_multiplier * original_box->y; 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_ci /* Now adjust dimensions to plane_slice*/ 751bf215546Sopenharmony_ci ptrans->box.width = util_format_get_plane_width(res->overall_format, plane_slice, ptrans->box.width); 752bf215546Sopenharmony_ci ptrans->box.height = util_format_get_plane_height(res->overall_format, plane_slice, ptrans->box.height); 753bf215546Sopenharmony_ci ptrans->box.x = util_format_get_plane_width(res->overall_format, plane_slice, ptrans->box.x); 754bf215546Sopenharmony_ci ptrans->box.y = util_format_get_plane_height(res->overall_format, plane_slice, ptrans->box.y); 755bf215546Sopenharmony_ci} 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_cistatic 758bf215546Sopenharmony_civoid d3d12_resource_get_planes_info(pipe_resource *pres, 759bf215546Sopenharmony_ci unsigned num_planes, 760bf215546Sopenharmony_ci pipe_resource **planes, 761bf215546Sopenharmony_ci unsigned *strides, 762bf215546Sopenharmony_ci unsigned *layer_strides, 763bf215546Sopenharmony_ci unsigned *offsets, 764bf215546Sopenharmony_ci unsigned *staging_res_size) 765bf215546Sopenharmony_ci{ 766bf215546Sopenharmony_ci struct d3d12_resource* res = d3d12_resource(pres); 767bf215546Sopenharmony_ci *staging_res_size = 0; 768bf215546Sopenharmony_ci struct pipe_resource *cur_plane_resource = res->first_plane; 769bf215546Sopenharmony_ci for (uint plane_slice = 0; plane_slice < num_planes; ++plane_slice) { 770bf215546Sopenharmony_ci planes[plane_slice] = cur_plane_resource; 771bf215546Sopenharmony_ci int width = util_format_get_plane_width(res->base.b.format, plane_slice, res->first_plane->width0); 772bf215546Sopenharmony_ci int height = util_format_get_plane_height(res->base.b.format, plane_slice, res->first_plane->height0); 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci strides[plane_slice] = align(util_format_get_stride(cur_plane_resource->format, width), 775bf215546Sopenharmony_ci D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); 776bf215546Sopenharmony_ci 777bf215546Sopenharmony_ci layer_strides[plane_slice] = align(util_format_get_2d_size(cur_plane_resource->format, 778bf215546Sopenharmony_ci strides[plane_slice], 779bf215546Sopenharmony_ci height), 780bf215546Sopenharmony_ci D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); 781bf215546Sopenharmony_ci 782bf215546Sopenharmony_ci offsets[plane_slice] = *staging_res_size; 783bf215546Sopenharmony_ci *staging_res_size += layer_strides[plane_slice]; 784bf215546Sopenharmony_ci cur_plane_resource = cur_plane_resource->next; 785bf215546Sopenharmony_ci } 786bf215546Sopenharmony_ci} 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_cistatic constexpr unsigned d3d12_max_planes = 3; 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_ci/** 791bf215546Sopenharmony_ci * Get stride and offset for the given pipe resource without the need to get 792bf215546Sopenharmony_ci * a winsys_handle. 793bf215546Sopenharmony_ci */ 794bf215546Sopenharmony_civoid 795bf215546Sopenharmony_cid3d12_resource_get_info(struct pipe_screen *pscreen, 796bf215546Sopenharmony_ci struct pipe_resource *pres, 797bf215546Sopenharmony_ci unsigned *stride, 798bf215546Sopenharmony_ci unsigned *offset) 799bf215546Sopenharmony_ci{ 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci struct d3d12_resource* res = d3d12_resource(pres); 802bf215546Sopenharmony_ci unsigned num_planes = util_format_get_num_planes(res->overall_format); 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci pipe_resource *planes[d3d12_max_planes]; 805bf215546Sopenharmony_ci unsigned int strides[d3d12_max_planes]; 806bf215546Sopenharmony_ci unsigned int layer_strides[d3d12_max_planes]; 807bf215546Sopenharmony_ci unsigned int offsets[d3d12_max_planes]; 808bf215546Sopenharmony_ci unsigned staging_res_size = 0; 809bf215546Sopenharmony_ci d3d12_resource_get_planes_info( 810bf215546Sopenharmony_ci pres, 811bf215546Sopenharmony_ci num_planes, 812bf215546Sopenharmony_ci planes, 813bf215546Sopenharmony_ci strides, 814bf215546Sopenharmony_ci layer_strides, 815bf215546Sopenharmony_ci offsets, 816bf215546Sopenharmony_ci &staging_res_size 817bf215546Sopenharmony_ci ); 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_ci if(stride) { 820bf215546Sopenharmony_ci *stride = strides[res->plane_slice]; 821bf215546Sopenharmony_ci } 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci if(offset) { 824bf215546Sopenharmony_ci *offset = offsets[res->plane_slice]; 825bf215546Sopenharmony_ci } 826bf215546Sopenharmony_ci} 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_cistatic struct pipe_memory_object * 829bf215546Sopenharmony_cid3d12_memobj_create_from_handle(struct pipe_screen *pscreen, struct winsys_handle *handle, bool dedicated) 830bf215546Sopenharmony_ci{ 831bf215546Sopenharmony_ci if (handle->type != WINSYS_HANDLE_TYPE_WIN32_HANDLE && 832bf215546Sopenharmony_ci handle->type != WINSYS_HANDLE_TYPE_WIN32_NAME) { 833bf215546Sopenharmony_ci debug_printf("d3d12: Unsupported memobj handle type\n"); 834bf215546Sopenharmony_ci return NULL; 835bf215546Sopenharmony_ci } 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pscreen); 838bf215546Sopenharmony_ci IUnknown *obj; 839bf215546Sopenharmony_ci#ifdef _WIN32 840bf215546Sopenharmony_ci HANDLE d3d_handle = handle->handle; 841bf215546Sopenharmony_ci#else 842bf215546Sopenharmony_ci HANDLE d3d_handle = (HANDLE)(intptr_t)handle->handle; 843bf215546Sopenharmony_ci#endif 844bf215546Sopenharmony_ci 845bf215546Sopenharmony_ci#ifdef _WIN32 846bf215546Sopenharmony_ci HANDLE d3d_handle_to_close = nullptr; 847bf215546Sopenharmony_ci if (handle->type == WINSYS_HANDLE_TYPE_WIN32_NAME) { 848bf215546Sopenharmony_ci screen->dev->OpenSharedHandleByName((LPCWSTR) handle->name, GENERIC_ALL, &d3d_handle_to_close); 849bf215546Sopenharmony_ci d3d_handle = d3d_handle_to_close; 850bf215546Sopenharmony_ci } 851bf215546Sopenharmony_ci#endif 852bf215546Sopenharmony_ci 853bf215546Sopenharmony_ci screen->dev->OpenSharedHandle(d3d_handle, IID_PPV_ARGS(&obj)); 854bf215546Sopenharmony_ci 855bf215546Sopenharmony_ci#ifdef _WIN32 856bf215546Sopenharmony_ci if (d3d_handle_to_close) { 857bf215546Sopenharmony_ci CloseHandle(d3d_handle_to_close); 858bf215546Sopenharmony_ci } 859bf215546Sopenharmony_ci#endif 860bf215546Sopenharmony_ci 861bf215546Sopenharmony_ci if (!obj) { 862bf215546Sopenharmony_ci debug_printf("d3d12: Failed to open memobj handle as anything\n"); 863bf215546Sopenharmony_ci return NULL; 864bf215546Sopenharmony_ci } 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci struct d3d12_memory_object *memobj = CALLOC_STRUCT(d3d12_memory_object); 867bf215546Sopenharmony_ci if (!memobj) { 868bf215546Sopenharmony_ci obj->Release(); 869bf215546Sopenharmony_ci return NULL; 870bf215546Sopenharmony_ci } 871bf215546Sopenharmony_ci memobj->base.dedicated = dedicated; 872bf215546Sopenharmony_ci 873bf215546Sopenharmony_ci (void)obj->QueryInterface(&memobj->res); 874bf215546Sopenharmony_ci (void)obj->QueryInterface(&memobj->heap); 875bf215546Sopenharmony_ci obj->Release(); 876bf215546Sopenharmony_ci if (!memobj->res && !memobj->heap) { 877bf215546Sopenharmony_ci debug_printf("d3d12: Memory object isn't a resource or heap\n"); 878bf215546Sopenharmony_ci free(memobj); 879bf215546Sopenharmony_ci return NULL; 880bf215546Sopenharmony_ci } 881bf215546Sopenharmony_ci 882bf215546Sopenharmony_ci bool expect_dedicated = memobj->res != nullptr; 883bf215546Sopenharmony_ci if (dedicated != expect_dedicated) 884bf215546Sopenharmony_ci debug_printf("d3d12: Expected dedicated to be %s for imported %s\n", 885bf215546Sopenharmony_ci expect_dedicated ? "true" : "false", 886bf215546Sopenharmony_ci expect_dedicated ? "resource" : "heap"); 887bf215546Sopenharmony_ci 888bf215546Sopenharmony_ci return &memobj->base; 889bf215546Sopenharmony_ci} 890bf215546Sopenharmony_ci 891bf215546Sopenharmony_cistatic void 892bf215546Sopenharmony_cid3d12_memobj_destroy(struct pipe_screen *pscreen, struct pipe_memory_object *pmemobj) 893bf215546Sopenharmony_ci{ 894bf215546Sopenharmony_ci struct d3d12_memory_object *memobj = d3d12_memory_object(pmemobj); 895bf215546Sopenharmony_ci if (memobj->res) 896bf215546Sopenharmony_ci memobj->res->Release(); 897bf215546Sopenharmony_ci if (memobj->heap) 898bf215546Sopenharmony_ci memobj->heap->Release(); 899bf215546Sopenharmony_ci free(memobj); 900bf215546Sopenharmony_ci} 901bf215546Sopenharmony_ci 902bf215546Sopenharmony_cistatic pipe_resource * 903bf215546Sopenharmony_cid3d12_resource_from_memobj(struct pipe_screen *pscreen, 904bf215546Sopenharmony_ci const struct pipe_resource *templ, 905bf215546Sopenharmony_ci struct pipe_memory_object *pmemobj, 906bf215546Sopenharmony_ci uint64_t offset) 907bf215546Sopenharmony_ci{ 908bf215546Sopenharmony_ci struct d3d12_memory_object *memobj = d3d12_memory_object(pmemobj); 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci struct winsys_handle whandle = {}; 911bf215546Sopenharmony_ci whandle.type = WINSYS_HANDLE_TYPE_D3D12_RES; 912bf215546Sopenharmony_ci whandle.com_obj = memobj->res ? (void *) memobj->res : (void *) memobj->heap; 913bf215546Sopenharmony_ci whandle.offset = offset; 914bf215546Sopenharmony_ci whandle.format = templ->format; 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci // WINSYS_HANDLE_TYPE_D3D12_RES implies taking ownership of the reference 917bf215546Sopenharmony_ci ((IUnknown *)whandle.com_obj)->AddRef(); 918bf215546Sopenharmony_ci return d3d12_resource_from_handle(pscreen, templ, &whandle, 0); 919bf215546Sopenharmony_ci} 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_civoid 922bf215546Sopenharmony_cid3d12_screen_resource_init(struct pipe_screen *pscreen) 923bf215546Sopenharmony_ci{ 924bf215546Sopenharmony_ci pscreen->resource_create = d3d12_resource_create; 925bf215546Sopenharmony_ci pscreen->resource_from_handle = d3d12_resource_from_handle; 926bf215546Sopenharmony_ci pscreen->resource_get_handle = d3d12_resource_get_handle; 927bf215546Sopenharmony_ci pscreen->resource_destroy = d3d12_resource_destroy; 928bf215546Sopenharmony_ci pscreen->resource_get_info = d3d12_resource_get_info; 929bf215546Sopenharmony_ci 930bf215546Sopenharmony_ci pscreen->memobj_create_from_handle = d3d12_memobj_create_from_handle; 931bf215546Sopenharmony_ci pscreen->memobj_destroy = d3d12_memobj_destroy; 932bf215546Sopenharmony_ci pscreen->resource_from_memobj = d3d12_resource_from_memobj; 933bf215546Sopenharmony_ci} 934bf215546Sopenharmony_ci 935bf215546Sopenharmony_ciunsigned int 936bf215546Sopenharmony_ciget_subresource_id(struct d3d12_resource *res, unsigned resid, 937bf215546Sopenharmony_ci unsigned z, unsigned base_level) 938bf215546Sopenharmony_ci{ 939bf215546Sopenharmony_ci unsigned resource_stride = res->base.b.last_level + 1; 940bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_1D_ARRAY || 941bf215546Sopenharmony_ci res->base.b.target == PIPE_TEXTURE_2D_ARRAY) 942bf215546Sopenharmony_ci resource_stride *= res->base.b.array_size; 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_CUBE) 945bf215546Sopenharmony_ci resource_stride *= 6; 946bf215546Sopenharmony_ci 947bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_CUBE_ARRAY) 948bf215546Sopenharmony_ci resource_stride *= 6 * res->base.b.array_size; 949bf215546Sopenharmony_ci 950bf215546Sopenharmony_ci unsigned layer_stride = res->base.b.last_level + 1; 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci return resid * resource_stride + z * layer_stride + 953bf215546Sopenharmony_ci base_level + res->plane_slice * resource_stride; 954bf215546Sopenharmony_ci} 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_cistatic D3D12_TEXTURE_COPY_LOCATION 957bf215546Sopenharmony_cifill_texture_location(struct d3d12_resource *res, 958bf215546Sopenharmony_ci struct d3d12_transfer *trans, unsigned resid, unsigned z) 959bf215546Sopenharmony_ci{ 960bf215546Sopenharmony_ci D3D12_TEXTURE_COPY_LOCATION tex_loc = {0}; 961bf215546Sopenharmony_ci int subres = get_subresource_id(res, resid, z, trans->base.b.level); 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ci tex_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; 964bf215546Sopenharmony_ci tex_loc.SubresourceIndex = subres; 965bf215546Sopenharmony_ci tex_loc.pResource = d3d12_resource_resource(res); 966bf215546Sopenharmony_ci return tex_loc; 967bf215546Sopenharmony_ci} 968bf215546Sopenharmony_ci 969bf215546Sopenharmony_cistatic D3D12_TEXTURE_COPY_LOCATION 970bf215546Sopenharmony_cifill_buffer_location(struct d3d12_context *ctx, 971bf215546Sopenharmony_ci struct d3d12_resource *res, 972bf215546Sopenharmony_ci struct d3d12_resource *staging_res, 973bf215546Sopenharmony_ci struct d3d12_transfer *trans, 974bf215546Sopenharmony_ci unsigned depth, 975bf215546Sopenharmony_ci unsigned resid, unsigned z) 976bf215546Sopenharmony_ci{ 977bf215546Sopenharmony_ci D3D12_TEXTURE_COPY_LOCATION buf_loc = {0}; 978bf215546Sopenharmony_ci D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint; 979bf215546Sopenharmony_ci uint64_t offset = 0; 980bf215546Sopenharmony_ci auto descr = GetDesc(d3d12_resource_underlying(res, &offset)); 981bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 982bf215546Sopenharmony_ci ID3D12Device* dev = screen->dev; 983bf215546Sopenharmony_ci 984bf215546Sopenharmony_ci unsigned sub_resid = get_subresource_id(res, resid, z, trans->base.b.level); 985bf215546Sopenharmony_ci dev->GetCopyableFootprints(&descr, sub_resid, 1, 0, &footprint, nullptr, nullptr, nullptr); 986bf215546Sopenharmony_ci 987bf215546Sopenharmony_ci buf_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; 988bf215546Sopenharmony_ci buf_loc.pResource = d3d12_resource_underlying(staging_res, &offset); 989bf215546Sopenharmony_ci buf_loc.PlacedFootprint = footprint; 990bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Offset += offset; 991bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Offset += trans->base.b.offset; 992bf215546Sopenharmony_ci 993bf215546Sopenharmony_ci if (util_format_has_depth(util_format_description(res->base.b.format)) && 994bf215546Sopenharmony_ci screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) { 995bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Footprint.Width = res->base.b.width0; 996bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Footprint.Height = res->base.b.height0; 997bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Footprint.Depth = res->base.b.depth0; 998bf215546Sopenharmony_ci } else { 999bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Footprint.Width = ALIGN(trans->base.b.box.width, 1000bf215546Sopenharmony_ci util_format_get_blockwidth(res->base.b.format)); 1001bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Footprint.Height = ALIGN(trans->base.b.box.height, 1002bf215546Sopenharmony_ci util_format_get_blockheight(res->base.b.format)); 1003bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Footprint.Depth = ALIGN(depth, 1004bf215546Sopenharmony_ci util_format_get_blockdepth(res->base.b.format)); 1005bf215546Sopenharmony_ci } 1006bf215546Sopenharmony_ci 1007bf215546Sopenharmony_ci buf_loc.PlacedFootprint.Footprint.RowPitch = trans->base.b.stride; 1008bf215546Sopenharmony_ci 1009bf215546Sopenharmony_ci return buf_loc; 1010bf215546Sopenharmony_ci} 1011bf215546Sopenharmony_ci 1012bf215546Sopenharmony_cistruct copy_info { 1013bf215546Sopenharmony_ci struct d3d12_resource *dst; 1014bf215546Sopenharmony_ci D3D12_TEXTURE_COPY_LOCATION dst_loc; 1015bf215546Sopenharmony_ci UINT dst_x, dst_y, dst_z; 1016bf215546Sopenharmony_ci struct d3d12_resource *src; 1017bf215546Sopenharmony_ci D3D12_TEXTURE_COPY_LOCATION src_loc; 1018bf215546Sopenharmony_ci D3D12_BOX *src_box; 1019bf215546Sopenharmony_ci}; 1020bf215546Sopenharmony_ci 1021bf215546Sopenharmony_ci 1022bf215546Sopenharmony_cistatic void 1023bf215546Sopenharmony_cicopy_texture_region(struct d3d12_context *ctx, 1024bf215546Sopenharmony_ci struct copy_info& info) 1025bf215546Sopenharmony_ci{ 1026bf215546Sopenharmony_ci auto batch = d3d12_current_batch(ctx); 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, info.src, false); 1029bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, info.dst, true); 1030bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, info.src, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 1031bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, info.dst, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 1032bf215546Sopenharmony_ci d3d12_apply_resource_states(ctx, false); 1033bf215546Sopenharmony_ci ctx->cmdlist->CopyTextureRegion(&info.dst_loc, info.dst_x, info.dst_y, info.dst_z, 1034bf215546Sopenharmony_ci &info.src_loc, info.src_box); 1035bf215546Sopenharmony_ci} 1036bf215546Sopenharmony_ci 1037bf215546Sopenharmony_cistatic void 1038bf215546Sopenharmony_citransfer_buf_to_image_part(struct d3d12_context *ctx, 1039bf215546Sopenharmony_ci struct d3d12_resource *res, 1040bf215546Sopenharmony_ci struct d3d12_resource *staging_res, 1041bf215546Sopenharmony_ci struct d3d12_transfer *trans, 1042bf215546Sopenharmony_ci int z, int depth, int start_z, int dest_z, 1043bf215546Sopenharmony_ci int resid) 1044bf215546Sopenharmony_ci{ 1045bf215546Sopenharmony_ci if (D3D12_DEBUG_RESOURCE & d3d12_debug) { 1046bf215546Sopenharmony_ci debug_printf("D3D12: Copy %dx%dx%d + %dx%dx%d from buffer %s to image %s\n", 1047bf215546Sopenharmony_ci trans->base.b.box.x, trans->base.b.box.y, trans->base.b.box.z, 1048bf215546Sopenharmony_ci trans->base.b.box.width, trans->base.b.box.height, trans->base.b.box.depth, 1049bf215546Sopenharmony_ci util_format_name(staging_res->base.b.format), 1050bf215546Sopenharmony_ci util_format_name(res->base.b.format)); 1051bf215546Sopenharmony_ci } 1052bf215546Sopenharmony_ci 1053bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(res->base.b.screen); 1054bf215546Sopenharmony_ci struct copy_info copy_info; 1055bf215546Sopenharmony_ci copy_info.src = staging_res; 1056bf215546Sopenharmony_ci copy_info.src_loc = fill_buffer_location(ctx, res, staging_res, trans, depth, resid, z); 1057bf215546Sopenharmony_ci copy_info.src_loc.PlacedFootprint.Offset += (z - start_z) * trans->base.b.layer_stride; 1058bf215546Sopenharmony_ci copy_info.src_box = nullptr; 1059bf215546Sopenharmony_ci copy_info.dst = res; 1060bf215546Sopenharmony_ci copy_info.dst_loc = fill_texture_location(res, trans, resid, z); 1061bf215546Sopenharmony_ci if (util_format_has_depth(util_format_description(res->base.b.format)) && 1062bf215546Sopenharmony_ci screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) { 1063bf215546Sopenharmony_ci copy_info.dst_x = 0; 1064bf215546Sopenharmony_ci copy_info.dst_y = 0; 1065bf215546Sopenharmony_ci } else { 1066bf215546Sopenharmony_ci copy_info.dst_x = trans->base.b.box.x; 1067bf215546Sopenharmony_ci copy_info.dst_y = trans->base.b.box.y; 1068bf215546Sopenharmony_ci } 1069bf215546Sopenharmony_ci copy_info.dst_z = res->base.b.target == PIPE_TEXTURE_CUBE ? 0 : dest_z; 1070bf215546Sopenharmony_ci copy_info.src_box = nullptr; 1071bf215546Sopenharmony_ci 1072bf215546Sopenharmony_ci copy_texture_region(ctx, copy_info); 1073bf215546Sopenharmony_ci} 1074bf215546Sopenharmony_ci 1075bf215546Sopenharmony_cistatic bool 1076bf215546Sopenharmony_citransfer_buf_to_image(struct d3d12_context *ctx, 1077bf215546Sopenharmony_ci struct d3d12_resource *res, 1078bf215546Sopenharmony_ci struct d3d12_resource *staging_res, 1079bf215546Sopenharmony_ci struct d3d12_transfer *trans, int resid) 1080bf215546Sopenharmony_ci{ 1081bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_3D) { 1082bf215546Sopenharmony_ci assert(resid == 0); 1083bf215546Sopenharmony_ci transfer_buf_to_image_part(ctx, res, staging_res, trans, 1084bf215546Sopenharmony_ci 0, trans->base.b.box.depth, 0, 1085bf215546Sopenharmony_ci trans->base.b.box.z, 0); 1086bf215546Sopenharmony_ci } else { 1087bf215546Sopenharmony_ci int num_layers = trans->base.b.box.depth; 1088bf215546Sopenharmony_ci int start_z = trans->base.b.box.z; 1089bf215546Sopenharmony_ci 1090bf215546Sopenharmony_ci for (int z = start_z; z < start_z + num_layers; ++z) { 1091bf215546Sopenharmony_ci transfer_buf_to_image_part(ctx, res, staging_res, trans, 1092bf215546Sopenharmony_ci z, 1, start_z, 0, resid); 1093bf215546Sopenharmony_ci } 1094bf215546Sopenharmony_ci } 1095bf215546Sopenharmony_ci return true; 1096bf215546Sopenharmony_ci} 1097bf215546Sopenharmony_ci 1098bf215546Sopenharmony_cistatic void 1099bf215546Sopenharmony_citransfer_image_part_to_buf(struct d3d12_context *ctx, 1100bf215546Sopenharmony_ci struct d3d12_resource *res, 1101bf215546Sopenharmony_ci struct d3d12_resource *staging_res, 1102bf215546Sopenharmony_ci struct d3d12_transfer *trans, 1103bf215546Sopenharmony_ci unsigned resid, int z, int start_layer, 1104bf215546Sopenharmony_ci int start_box_z, int depth) 1105bf215546Sopenharmony_ci{ 1106bf215546Sopenharmony_ci struct pipe_box *box = &trans->base.b.box; 1107bf215546Sopenharmony_ci D3D12_BOX src_box = {}; 1108bf215546Sopenharmony_ci 1109bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(res->base.b.screen); 1110bf215546Sopenharmony_ci struct copy_info copy_info; 1111bf215546Sopenharmony_ci copy_info.src_box = nullptr; 1112bf215546Sopenharmony_ci copy_info.src = res; 1113bf215546Sopenharmony_ci copy_info.src_loc = fill_texture_location(res, trans, resid, z); 1114bf215546Sopenharmony_ci copy_info.dst = staging_res; 1115bf215546Sopenharmony_ci copy_info.dst_loc = fill_buffer_location(ctx, res, staging_res, trans, 1116bf215546Sopenharmony_ci depth, resid, z); 1117bf215546Sopenharmony_ci copy_info.dst_loc.PlacedFootprint.Offset += (z - start_layer) * trans->base.b.layer_stride; 1118bf215546Sopenharmony_ci copy_info.dst_x = copy_info.dst_y = copy_info.dst_z = 0; 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_ci bool whole_resource = util_texrange_covers_whole_level(&res->base.b, trans->base.b.level, 1121bf215546Sopenharmony_ci box->x, box->y, start_box_z, 1122bf215546Sopenharmony_ci box->width, box->height, depth); 1123bf215546Sopenharmony_ci if (util_format_has_depth(util_format_description(res->base.b.format)) && 1124bf215546Sopenharmony_ci screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) 1125bf215546Sopenharmony_ci whole_resource = true; 1126bf215546Sopenharmony_ci if (!whole_resource) { 1127bf215546Sopenharmony_ci src_box.left = box->x; 1128bf215546Sopenharmony_ci src_box.right = box->x + box->width; 1129bf215546Sopenharmony_ci src_box.top = box->y; 1130bf215546Sopenharmony_ci src_box.bottom = box->y + box->height; 1131bf215546Sopenharmony_ci src_box.front = start_box_z; 1132bf215546Sopenharmony_ci src_box.back = start_box_z + depth; 1133bf215546Sopenharmony_ci copy_info.src_box = &src_box; 1134bf215546Sopenharmony_ci } 1135bf215546Sopenharmony_ci 1136bf215546Sopenharmony_ci copy_texture_region(ctx, copy_info); 1137bf215546Sopenharmony_ci} 1138bf215546Sopenharmony_ci 1139bf215546Sopenharmony_cistatic bool 1140bf215546Sopenharmony_citransfer_image_to_buf(struct d3d12_context *ctx, 1141bf215546Sopenharmony_ci struct d3d12_resource *res, 1142bf215546Sopenharmony_ci struct d3d12_resource *staging_res, 1143bf215546Sopenharmony_ci struct d3d12_transfer *trans, 1144bf215546Sopenharmony_ci unsigned resid) 1145bf215546Sopenharmony_ci{ 1146bf215546Sopenharmony_ci 1147bf215546Sopenharmony_ci /* We only suppport loading from either an texture array 1148bf215546Sopenharmony_ci * or a ZS texture, so either resid is zero, or num_layers == 1) 1149bf215546Sopenharmony_ci */ 1150bf215546Sopenharmony_ci assert(resid == 0 || trans->base.b.box.depth == 1); 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci if (D3D12_DEBUG_RESOURCE & d3d12_debug) { 1153bf215546Sopenharmony_ci debug_printf("D3D12: Copy %dx%dx%d + %dx%dx%d from %s@%d to %s\n", 1154bf215546Sopenharmony_ci trans->base.b.box.x, trans->base.b.box.y, trans->base.b.box.z, 1155bf215546Sopenharmony_ci trans->base.b.box.width, trans->base.b.box.height, trans->base.b.box.depth, 1156bf215546Sopenharmony_ci util_format_name(res->base.b.format), resid, 1157bf215546Sopenharmony_ci util_format_name(staging_res->base.b.format)); 1158bf215546Sopenharmony_ci } 1159bf215546Sopenharmony_ci 1160bf215546Sopenharmony_ci struct pipe_resource *resolved_resource = nullptr; 1161bf215546Sopenharmony_ci if (res->base.b.nr_samples > 1) { 1162bf215546Sopenharmony_ci struct pipe_resource tmpl = res->base.b; 1163bf215546Sopenharmony_ci tmpl.nr_samples = 0; 1164bf215546Sopenharmony_ci resolved_resource = d3d12_resource_create(ctx->base.screen, &tmpl); 1165bf215546Sopenharmony_ci struct pipe_blit_info resolve_info = {}; 1166bf215546Sopenharmony_ci struct pipe_box box = {0,0,0, (int)res->base.b.width0, (int16_t)res->base.b.height0, (int16_t)res->base.b.depth0}; 1167bf215546Sopenharmony_ci resolve_info.dst.resource = resolved_resource; 1168bf215546Sopenharmony_ci resolve_info.dst.box = box; 1169bf215546Sopenharmony_ci resolve_info.dst.format = res->base.b.format; 1170bf215546Sopenharmony_ci resolve_info.src.resource = &res->base.b; 1171bf215546Sopenharmony_ci resolve_info.src.box = box; 1172bf215546Sopenharmony_ci resolve_info.src.format = res->base.b.format; 1173bf215546Sopenharmony_ci resolve_info.filter = PIPE_TEX_FILTER_NEAREST; 1174bf215546Sopenharmony_ci resolve_info.mask = util_format_get_mask(tmpl.format); 1175bf215546Sopenharmony_ci 1176bf215546Sopenharmony_ci 1177bf215546Sopenharmony_ci 1178bf215546Sopenharmony_ci d3d12_blit(&ctx->base, &resolve_info); 1179bf215546Sopenharmony_ci res = (struct d3d12_resource *)resolved_resource; 1180bf215546Sopenharmony_ci } 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci 1183bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_3D) { 1184bf215546Sopenharmony_ci transfer_image_part_to_buf(ctx, res, staging_res, trans, resid, 1185bf215546Sopenharmony_ci 0, 0, trans->base.b.box.z, trans->base.b.box.depth); 1186bf215546Sopenharmony_ci } else { 1187bf215546Sopenharmony_ci int start_layer = trans->base.b.box.z; 1188bf215546Sopenharmony_ci for (int z = start_layer; z < start_layer + trans->base.b.box.depth; ++z) { 1189bf215546Sopenharmony_ci transfer_image_part_to_buf(ctx, res, staging_res, trans, resid, 1190bf215546Sopenharmony_ci z, start_layer, 0, 1); 1191bf215546Sopenharmony_ci } 1192bf215546Sopenharmony_ci } 1193bf215546Sopenharmony_ci 1194bf215546Sopenharmony_ci pipe_resource_reference(&resolved_resource, NULL); 1195bf215546Sopenharmony_ci 1196bf215546Sopenharmony_ci return true; 1197bf215546Sopenharmony_ci} 1198bf215546Sopenharmony_ci 1199bf215546Sopenharmony_cistatic void 1200bf215546Sopenharmony_citransfer_buf_to_buf(struct d3d12_context *ctx, 1201bf215546Sopenharmony_ci struct d3d12_resource *src, 1202bf215546Sopenharmony_ci struct d3d12_resource *dst, 1203bf215546Sopenharmony_ci uint64_t src_offset, 1204bf215546Sopenharmony_ci uint64_t dst_offset, 1205bf215546Sopenharmony_ci uint64_t width) 1206bf215546Sopenharmony_ci{ 1207bf215546Sopenharmony_ci auto batch = d3d12_current_batch(ctx); 1208bf215546Sopenharmony_ci 1209bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, src, false); 1210bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, dst, true); 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_ci uint64_t src_offset_suballoc = 0; 1213bf215546Sopenharmony_ci uint64_t dst_offset_suballoc = 0; 1214bf215546Sopenharmony_ci auto src_d3d12 = d3d12_resource_underlying(src, &src_offset_suballoc); 1215bf215546Sopenharmony_ci auto dst_d3d12 = d3d12_resource_underlying(dst, &dst_offset_suballoc); 1216bf215546Sopenharmony_ci src_offset += src_offset_suballoc; 1217bf215546Sopenharmony_ci dst_offset += dst_offset_suballoc; 1218bf215546Sopenharmony_ci 1219bf215546Sopenharmony_ci // Same-resource copies not supported, since the resource would need to be in both states 1220bf215546Sopenharmony_ci assert(src_d3d12 != dst_d3d12); 1221bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, src, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 1222bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, dst, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 1223bf215546Sopenharmony_ci d3d12_apply_resource_states(ctx, false); 1224bf215546Sopenharmony_ci ctx->cmdlist->CopyBufferRegion(dst_d3d12, dst_offset, 1225bf215546Sopenharmony_ci src_d3d12, src_offset, 1226bf215546Sopenharmony_ci width); 1227bf215546Sopenharmony_ci} 1228bf215546Sopenharmony_ci 1229bf215546Sopenharmony_cistatic unsigned 1230bf215546Sopenharmony_cilinear_offset(int x, int y, int z, unsigned stride, unsigned layer_stride) 1231bf215546Sopenharmony_ci{ 1232bf215546Sopenharmony_ci return x + 1233bf215546Sopenharmony_ci y * stride + 1234bf215546Sopenharmony_ci z * layer_stride; 1235bf215546Sopenharmony_ci} 1236bf215546Sopenharmony_ci 1237bf215546Sopenharmony_cistatic D3D12_RANGE 1238bf215546Sopenharmony_cilinear_range(const struct pipe_box *box, unsigned stride, unsigned layer_stride) 1239bf215546Sopenharmony_ci{ 1240bf215546Sopenharmony_ci D3D12_RANGE range; 1241bf215546Sopenharmony_ci 1242bf215546Sopenharmony_ci range.Begin = linear_offset(box->x, box->y, box->z, 1243bf215546Sopenharmony_ci stride, layer_stride); 1244bf215546Sopenharmony_ci range.End = linear_offset(box->x + box->width, 1245bf215546Sopenharmony_ci box->y + box->height - 1, 1246bf215546Sopenharmony_ci box->z + box->depth - 1, 1247bf215546Sopenharmony_ci stride, layer_stride); 1248bf215546Sopenharmony_ci 1249bf215546Sopenharmony_ci return range; 1250bf215546Sopenharmony_ci} 1251bf215546Sopenharmony_ci 1252bf215546Sopenharmony_cistatic bool 1253bf215546Sopenharmony_cisynchronize(struct d3d12_context *ctx, 1254bf215546Sopenharmony_ci struct d3d12_resource *res, 1255bf215546Sopenharmony_ci unsigned usage, 1256bf215546Sopenharmony_ci D3D12_RANGE *range) 1257bf215546Sopenharmony_ci{ 1258bf215546Sopenharmony_ci assert(can_map_directly(&res->base.b)); 1259bf215546Sopenharmony_ci 1260bf215546Sopenharmony_ci /* Check whether that range contains valid data; if not, we might not need to sync */ 1261bf215546Sopenharmony_ci if (!(usage & PIPE_MAP_UNSYNCHRONIZED) && 1262bf215546Sopenharmony_ci usage & PIPE_MAP_WRITE && 1263bf215546Sopenharmony_ci !util_ranges_intersect(&res->valid_buffer_range, range->Begin, range->End)) { 1264bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 1265bf215546Sopenharmony_ci } 1266bf215546Sopenharmony_ci 1267bf215546Sopenharmony_ci if (!(usage & PIPE_MAP_UNSYNCHRONIZED) && resource_is_busy(ctx, res, usage & PIPE_MAP_WRITE)) { 1268bf215546Sopenharmony_ci if (usage & PIPE_MAP_DONTBLOCK) { 1269bf215546Sopenharmony_ci if (d3d12_batch_has_references(d3d12_current_batch(ctx), res->bo, usage & PIPE_MAP_WRITE)) 1270bf215546Sopenharmony_ci d3d12_flush_cmdlist(ctx); 1271bf215546Sopenharmony_ci return false; 1272bf215546Sopenharmony_ci } 1273bf215546Sopenharmony_ci 1274bf215546Sopenharmony_ci d3d12_resource_wait_idle(ctx, res, usage & PIPE_MAP_WRITE); 1275bf215546Sopenharmony_ci } 1276bf215546Sopenharmony_ci 1277bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) 1278bf215546Sopenharmony_ci util_range_add(&res->base.b, &res->valid_buffer_range, 1279bf215546Sopenharmony_ci range->Begin, range->End); 1280bf215546Sopenharmony_ci 1281bf215546Sopenharmony_ci return true; 1282bf215546Sopenharmony_ci} 1283bf215546Sopenharmony_ci 1284bf215546Sopenharmony_ci/* A wrapper to make sure local resources are freed and unmapped with 1285bf215546Sopenharmony_ci * any exit path */ 1286bf215546Sopenharmony_cistruct local_resource { 1287bf215546Sopenharmony_ci local_resource(pipe_screen *s, struct pipe_resource *tmpl) : 1288bf215546Sopenharmony_ci mapped(false) 1289bf215546Sopenharmony_ci { 1290bf215546Sopenharmony_ci res = d3d12_resource(d3d12_resource_create(s, tmpl)); 1291bf215546Sopenharmony_ci } 1292bf215546Sopenharmony_ci 1293bf215546Sopenharmony_ci ~local_resource() { 1294bf215546Sopenharmony_ci if (res) { 1295bf215546Sopenharmony_ci if (mapped) 1296bf215546Sopenharmony_ci d3d12_bo_unmap(res->bo, nullptr); 1297bf215546Sopenharmony_ci pipe_resource_reference((struct pipe_resource **)&res, NULL); 1298bf215546Sopenharmony_ci } 1299bf215546Sopenharmony_ci } 1300bf215546Sopenharmony_ci 1301bf215546Sopenharmony_ci void * 1302bf215546Sopenharmony_ci map() { 1303bf215546Sopenharmony_ci void *ptr; 1304bf215546Sopenharmony_ci ptr = d3d12_bo_map(res->bo, nullptr); 1305bf215546Sopenharmony_ci if (ptr) 1306bf215546Sopenharmony_ci mapped = true; 1307bf215546Sopenharmony_ci return ptr; 1308bf215546Sopenharmony_ci } 1309bf215546Sopenharmony_ci 1310bf215546Sopenharmony_ci void unmap() 1311bf215546Sopenharmony_ci { 1312bf215546Sopenharmony_ci if (mapped) 1313bf215546Sopenharmony_ci d3d12_bo_unmap(res->bo, nullptr); 1314bf215546Sopenharmony_ci mapped = false; 1315bf215546Sopenharmony_ci } 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci operator struct d3d12_resource *() { 1318bf215546Sopenharmony_ci return res; 1319bf215546Sopenharmony_ci } 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci bool operator !() { 1322bf215546Sopenharmony_ci return !res; 1323bf215546Sopenharmony_ci } 1324bf215546Sopenharmony_ciprivate: 1325bf215546Sopenharmony_ci struct d3d12_resource *res; 1326bf215546Sopenharmony_ci bool mapped; 1327bf215546Sopenharmony_ci}; 1328bf215546Sopenharmony_ci 1329bf215546Sopenharmony_ci/* Combined depth-stencil needs a special handling for reading back: DX handled 1330bf215546Sopenharmony_ci * depth and stencil parts as separate resources and handles copying them only 1331bf215546Sopenharmony_ci * by using seperate texture copy calls with different formats. So create two 1332bf215546Sopenharmony_ci * buffers, read back both resources and interleave the data. 1333bf215546Sopenharmony_ci */ 1334bf215546Sopenharmony_cistatic void 1335bf215546Sopenharmony_ciprepare_zs_layer_strides(struct d3d12_screen *screen, 1336bf215546Sopenharmony_ci struct d3d12_resource *res, 1337bf215546Sopenharmony_ci const struct pipe_box *box, 1338bf215546Sopenharmony_ci struct d3d12_transfer *trans) 1339bf215546Sopenharmony_ci{ 1340bf215546Sopenharmony_ci bool copy_whole_resource = screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED; 1341bf215546Sopenharmony_ci int width = copy_whole_resource ? res->base.b.width0 : box->width; 1342bf215546Sopenharmony_ci int height = copy_whole_resource ? res->base.b.height0 : box->height; 1343bf215546Sopenharmony_ci 1344bf215546Sopenharmony_ci trans->base.b.stride = align(util_format_get_stride(res->base.b.format, width), 1345bf215546Sopenharmony_ci D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); 1346bf215546Sopenharmony_ci trans->base.b.layer_stride = util_format_get_2d_size(res->base.b.format, 1347bf215546Sopenharmony_ci trans->base.b.stride, 1348bf215546Sopenharmony_ci height); 1349bf215546Sopenharmony_ci 1350bf215546Sopenharmony_ci if (copy_whole_resource) { 1351bf215546Sopenharmony_ci trans->zs_cpu_copy_stride = align(util_format_get_stride(res->base.b.format, box->width), 1352bf215546Sopenharmony_ci D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); 1353bf215546Sopenharmony_ci trans->zs_cpu_copy_layer_stride = util_format_get_2d_size(res->base.b.format, 1354bf215546Sopenharmony_ci trans->base.b.stride, 1355bf215546Sopenharmony_ci box->height); 1356bf215546Sopenharmony_ci } else { 1357bf215546Sopenharmony_ci trans->zs_cpu_copy_stride = trans->base.b.stride; 1358bf215546Sopenharmony_ci trans->zs_cpu_copy_layer_stride = trans->base.b.layer_stride; 1359bf215546Sopenharmony_ci } 1360bf215546Sopenharmony_ci} 1361bf215546Sopenharmony_ci 1362bf215546Sopenharmony_cistatic void * 1363bf215546Sopenharmony_ciread_zs_surface(struct d3d12_context *ctx, struct d3d12_resource *res, 1364bf215546Sopenharmony_ci const struct pipe_box *box, 1365bf215546Sopenharmony_ci struct d3d12_transfer *trans) 1366bf215546Sopenharmony_ci{ 1367bf215546Sopenharmony_ci pipe_screen *pscreen = ctx->base.screen; 1368bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pscreen); 1369bf215546Sopenharmony_ci 1370bf215546Sopenharmony_ci prepare_zs_layer_strides(screen, res, box, trans); 1371bf215546Sopenharmony_ci 1372bf215546Sopenharmony_ci struct pipe_resource tmpl; 1373bf215546Sopenharmony_ci memset(&tmpl, 0, sizeof tmpl); 1374bf215546Sopenharmony_ci tmpl.target = PIPE_BUFFER; 1375bf215546Sopenharmony_ci tmpl.format = PIPE_FORMAT_R32_UNORM; 1376bf215546Sopenharmony_ci tmpl.bind = 0; 1377bf215546Sopenharmony_ci tmpl.usage = PIPE_USAGE_STAGING; 1378bf215546Sopenharmony_ci tmpl.flags = 0; 1379bf215546Sopenharmony_ci tmpl.width0 = trans->base.b.layer_stride; 1380bf215546Sopenharmony_ci tmpl.height0 = 1; 1381bf215546Sopenharmony_ci tmpl.depth0 = 1; 1382bf215546Sopenharmony_ci tmpl.array_size = 1; 1383bf215546Sopenharmony_ci 1384bf215546Sopenharmony_ci local_resource depth_buffer(pscreen, &tmpl); 1385bf215546Sopenharmony_ci if (!depth_buffer) { 1386bf215546Sopenharmony_ci debug_printf("Allocating staging buffer for depth failed\n"); 1387bf215546Sopenharmony_ci return NULL; 1388bf215546Sopenharmony_ci } 1389bf215546Sopenharmony_ci 1390bf215546Sopenharmony_ci if (!transfer_image_to_buf(ctx, res, depth_buffer, trans, 0)) 1391bf215546Sopenharmony_ci return NULL; 1392bf215546Sopenharmony_ci 1393bf215546Sopenharmony_ci tmpl.format = PIPE_FORMAT_R8_UINT; 1394bf215546Sopenharmony_ci 1395bf215546Sopenharmony_ci local_resource stencil_buffer(pscreen, &tmpl); 1396bf215546Sopenharmony_ci if (!stencil_buffer) { 1397bf215546Sopenharmony_ci debug_printf("Allocating staging buffer for stencilfailed\n"); 1398bf215546Sopenharmony_ci return NULL; 1399bf215546Sopenharmony_ci } 1400bf215546Sopenharmony_ci 1401bf215546Sopenharmony_ci if (!transfer_image_to_buf(ctx, res, stencil_buffer, trans, 1)) 1402bf215546Sopenharmony_ci return NULL; 1403bf215546Sopenharmony_ci 1404bf215546Sopenharmony_ci d3d12_flush_cmdlist_and_wait(ctx); 1405bf215546Sopenharmony_ci 1406bf215546Sopenharmony_ci uint8_t *depth_ptr = (uint8_t *)depth_buffer.map(); 1407bf215546Sopenharmony_ci if (!depth_ptr) { 1408bf215546Sopenharmony_ci debug_printf("Mapping staging depth buffer failed\n"); 1409bf215546Sopenharmony_ci return NULL; 1410bf215546Sopenharmony_ci } 1411bf215546Sopenharmony_ci 1412bf215546Sopenharmony_ci uint8_t *stencil_ptr = (uint8_t *)stencil_buffer.map(); 1413bf215546Sopenharmony_ci if (!stencil_ptr) { 1414bf215546Sopenharmony_ci debug_printf("Mapping staging stencil buffer failed\n"); 1415bf215546Sopenharmony_ci return NULL; 1416bf215546Sopenharmony_ci } 1417bf215546Sopenharmony_ci 1418bf215546Sopenharmony_ci uint8_t *buf = (uint8_t *)malloc(trans->zs_cpu_copy_layer_stride); 1419bf215546Sopenharmony_ci if (!buf) 1420bf215546Sopenharmony_ci return NULL; 1421bf215546Sopenharmony_ci 1422bf215546Sopenharmony_ci trans->data = buf; 1423bf215546Sopenharmony_ci 1424bf215546Sopenharmony_ci switch (res->base.b.format) { 1425bf215546Sopenharmony_ci case PIPE_FORMAT_Z24_UNORM_S8_UINT: 1426bf215546Sopenharmony_ci if (screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) { 1427bf215546Sopenharmony_ci depth_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4; 1428bf215546Sopenharmony_ci stencil_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4; 1429bf215546Sopenharmony_ci } 1430bf215546Sopenharmony_ci util_format_z24_unorm_s8_uint_pack_separate(buf, trans->zs_cpu_copy_stride, 1431bf215546Sopenharmony_ci (uint32_t *)depth_ptr, trans->base.b.stride, 1432bf215546Sopenharmony_ci stencil_ptr, trans->base.b.stride, 1433bf215546Sopenharmony_ci trans->base.b.box.width, trans->base.b.box.height); 1434bf215546Sopenharmony_ci break; 1435bf215546Sopenharmony_ci case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 1436bf215546Sopenharmony_ci if (screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) { 1437bf215546Sopenharmony_ci depth_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4; 1438bf215546Sopenharmony_ci stencil_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x; 1439bf215546Sopenharmony_ci } 1440bf215546Sopenharmony_ci util_format_z32_float_s8x24_uint_pack_z_float(buf, trans->zs_cpu_copy_stride, 1441bf215546Sopenharmony_ci (float *)depth_ptr, trans->base.b.stride, 1442bf215546Sopenharmony_ci trans->base.b.box.width, trans->base.b.box.height); 1443bf215546Sopenharmony_ci util_format_z32_float_s8x24_uint_pack_s_8uint(buf, trans->zs_cpu_copy_stride, 1444bf215546Sopenharmony_ci stencil_ptr, trans->base.b.stride, 1445bf215546Sopenharmony_ci trans->base.b.box.width, trans->base.b.box.height); 1446bf215546Sopenharmony_ci break; 1447bf215546Sopenharmony_ci default: 1448bf215546Sopenharmony_ci unreachable("Unsupported depth steancil format"); 1449bf215546Sopenharmony_ci }; 1450bf215546Sopenharmony_ci 1451bf215546Sopenharmony_ci return trans->data; 1452bf215546Sopenharmony_ci} 1453bf215546Sopenharmony_ci 1454bf215546Sopenharmony_cistatic void * 1455bf215546Sopenharmony_ciprepare_write_zs_surface(struct d3d12_resource *res, 1456bf215546Sopenharmony_ci const struct pipe_box *box, 1457bf215546Sopenharmony_ci struct d3d12_transfer *trans) 1458bf215546Sopenharmony_ci{ 1459bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(res->base.b.screen); 1460bf215546Sopenharmony_ci prepare_zs_layer_strides(screen, res, box, trans); 1461bf215546Sopenharmony_ci uint32_t *buf = (uint32_t *)malloc(trans->base.b.layer_stride); 1462bf215546Sopenharmony_ci if (!buf) 1463bf215546Sopenharmony_ci return NULL; 1464bf215546Sopenharmony_ci 1465bf215546Sopenharmony_ci trans->data = buf; 1466bf215546Sopenharmony_ci return trans->data; 1467bf215546Sopenharmony_ci} 1468bf215546Sopenharmony_ci 1469bf215546Sopenharmony_cistatic void 1470bf215546Sopenharmony_ciwrite_zs_surface(struct pipe_context *pctx, struct d3d12_resource *res, 1471bf215546Sopenharmony_ci struct d3d12_transfer *trans) 1472bf215546Sopenharmony_ci{ 1473bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(res->base.b.screen); 1474bf215546Sopenharmony_ci struct pipe_resource tmpl; 1475bf215546Sopenharmony_ci memset(&tmpl, 0, sizeof tmpl); 1476bf215546Sopenharmony_ci tmpl.target = PIPE_BUFFER; 1477bf215546Sopenharmony_ci tmpl.format = PIPE_FORMAT_R32_UNORM; 1478bf215546Sopenharmony_ci tmpl.bind = 0; 1479bf215546Sopenharmony_ci tmpl.usage = PIPE_USAGE_STAGING; 1480bf215546Sopenharmony_ci tmpl.flags = 0; 1481bf215546Sopenharmony_ci tmpl.width0 = trans->base.b.layer_stride; 1482bf215546Sopenharmony_ci tmpl.height0 = 1; 1483bf215546Sopenharmony_ci tmpl.depth0 = 1; 1484bf215546Sopenharmony_ci tmpl.array_size = 1; 1485bf215546Sopenharmony_ci 1486bf215546Sopenharmony_ci local_resource depth_buffer(pctx->screen, &tmpl); 1487bf215546Sopenharmony_ci if (!depth_buffer) { 1488bf215546Sopenharmony_ci debug_printf("Allocating staging buffer for depth failed\n"); 1489bf215546Sopenharmony_ci return; 1490bf215546Sopenharmony_ci } 1491bf215546Sopenharmony_ci 1492bf215546Sopenharmony_ci local_resource stencil_buffer(pctx->screen, &tmpl); 1493bf215546Sopenharmony_ci if (!stencil_buffer) { 1494bf215546Sopenharmony_ci debug_printf("Allocating staging buffer for depth failed\n"); 1495bf215546Sopenharmony_ci return; 1496bf215546Sopenharmony_ci } 1497bf215546Sopenharmony_ci 1498bf215546Sopenharmony_ci uint8_t *depth_ptr = (uint8_t *)depth_buffer.map(); 1499bf215546Sopenharmony_ci if (!depth_ptr) { 1500bf215546Sopenharmony_ci debug_printf("Mapping staging depth buffer failed\n"); 1501bf215546Sopenharmony_ci return; 1502bf215546Sopenharmony_ci } 1503bf215546Sopenharmony_ci 1504bf215546Sopenharmony_ci uint8_t *stencil_ptr = (uint8_t *)stencil_buffer.map(); 1505bf215546Sopenharmony_ci if (!stencil_ptr) { 1506bf215546Sopenharmony_ci debug_printf("Mapping staging stencil buffer failed\n"); 1507bf215546Sopenharmony_ci return; 1508bf215546Sopenharmony_ci } 1509bf215546Sopenharmony_ci 1510bf215546Sopenharmony_ci switch (res->base.b.format) { 1511bf215546Sopenharmony_ci case PIPE_FORMAT_Z24_UNORM_S8_UINT: 1512bf215546Sopenharmony_ci if (screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) { 1513bf215546Sopenharmony_ci depth_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4; 1514bf215546Sopenharmony_ci stencil_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4; 1515bf215546Sopenharmony_ci } 1516bf215546Sopenharmony_ci util_format_z32_unorm_unpack_z_32unorm((uint32_t *)depth_ptr, trans->base.b.stride, (uint8_t*)trans->data, 1517bf215546Sopenharmony_ci trans->zs_cpu_copy_stride, trans->base.b.box.width, 1518bf215546Sopenharmony_ci trans->base.b.box.height); 1519bf215546Sopenharmony_ci util_format_z24_unorm_s8_uint_unpack_s_8uint(stencil_ptr, trans->base.b.stride, (uint8_t*)trans->data, 1520bf215546Sopenharmony_ci trans->zs_cpu_copy_stride, trans->base.b.box.width, 1521bf215546Sopenharmony_ci trans->base.b.box.height); 1522bf215546Sopenharmony_ci break; 1523bf215546Sopenharmony_ci case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 1524bf215546Sopenharmony_ci if (screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) { 1525bf215546Sopenharmony_ci depth_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4; 1526bf215546Sopenharmony_ci stencil_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x; 1527bf215546Sopenharmony_ci } 1528bf215546Sopenharmony_ci util_format_z32_float_s8x24_uint_unpack_z_float((float *)depth_ptr, trans->base.b.stride, (uint8_t*)trans->data, 1529bf215546Sopenharmony_ci trans->zs_cpu_copy_stride, trans->base.b.box.width, 1530bf215546Sopenharmony_ci trans->base.b.box.height); 1531bf215546Sopenharmony_ci util_format_z32_float_s8x24_uint_unpack_s_8uint(stencil_ptr, trans->base.b.stride, (uint8_t*)trans->data, 1532bf215546Sopenharmony_ci trans->zs_cpu_copy_stride, trans->base.b.box.width, 1533bf215546Sopenharmony_ci trans->base.b.box.height); 1534bf215546Sopenharmony_ci break; 1535bf215546Sopenharmony_ci default: 1536bf215546Sopenharmony_ci unreachable("Unsupported depth steancil format"); 1537bf215546Sopenharmony_ci }; 1538bf215546Sopenharmony_ci 1539bf215546Sopenharmony_ci stencil_buffer.unmap(); 1540bf215546Sopenharmony_ci depth_buffer.unmap(); 1541bf215546Sopenharmony_ci 1542bf215546Sopenharmony_ci transfer_buf_to_image(d3d12_context(pctx), res, depth_buffer, trans, 0); 1543bf215546Sopenharmony_ci transfer_buf_to_image(d3d12_context(pctx), res, stencil_buffer, trans, 1); 1544bf215546Sopenharmony_ci} 1545bf215546Sopenharmony_ci 1546bf215546Sopenharmony_ci#define BUFFER_MAP_ALIGNMENT 64 1547bf215546Sopenharmony_ci 1548bf215546Sopenharmony_cistatic void * 1549bf215546Sopenharmony_cid3d12_transfer_map(struct pipe_context *pctx, 1550bf215546Sopenharmony_ci struct pipe_resource *pres, 1551bf215546Sopenharmony_ci unsigned level, 1552bf215546Sopenharmony_ci unsigned usage, 1553bf215546Sopenharmony_ci const struct pipe_box *box, 1554bf215546Sopenharmony_ci struct pipe_transfer **transfer) 1555bf215546Sopenharmony_ci{ 1556bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1557bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(pres); 1558bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pres->screen); 1559bf215546Sopenharmony_ci 1560bf215546Sopenharmony_ci if (usage & PIPE_MAP_DIRECTLY || !res->bo) 1561bf215546Sopenharmony_ci return NULL; 1562bf215546Sopenharmony_ci 1563bf215546Sopenharmony_ci slab_child_pool* transfer_pool = (usage & TC_TRANSFER_MAP_THREADED_UNSYNC) ? 1564bf215546Sopenharmony_ci &ctx->transfer_pool_unsync : &ctx->transfer_pool; 1565bf215546Sopenharmony_ci struct d3d12_transfer *trans = (struct d3d12_transfer *)slab_zalloc(transfer_pool); 1566bf215546Sopenharmony_ci struct pipe_transfer *ptrans = &trans->base.b; 1567bf215546Sopenharmony_ci if (!trans) 1568bf215546Sopenharmony_ci return NULL; 1569bf215546Sopenharmony_ci 1570bf215546Sopenharmony_ci ptrans->level = level; 1571bf215546Sopenharmony_ci ptrans->usage = (enum pipe_map_flags)usage; 1572bf215546Sopenharmony_ci ptrans->box = *box; 1573bf215546Sopenharmony_ci 1574bf215546Sopenharmony_ci D3D12_RANGE range; 1575bf215546Sopenharmony_ci range.Begin = 0; 1576bf215546Sopenharmony_ci 1577bf215546Sopenharmony_ci void *ptr; 1578bf215546Sopenharmony_ci if (can_map_directly(&res->base.b)) { 1579bf215546Sopenharmony_ci if (pres->target == PIPE_BUFFER) { 1580bf215546Sopenharmony_ci ptrans->stride = 0; 1581bf215546Sopenharmony_ci ptrans->layer_stride = 0; 1582bf215546Sopenharmony_ci } else { 1583bf215546Sopenharmony_ci ptrans->stride = util_format_get_stride(pres->format, box->width); 1584bf215546Sopenharmony_ci ptrans->layer_stride = util_format_get_2d_size(pres->format, 1585bf215546Sopenharmony_ci ptrans->stride, 1586bf215546Sopenharmony_ci box->height); 1587bf215546Sopenharmony_ci } 1588bf215546Sopenharmony_ci 1589bf215546Sopenharmony_ci range = linear_range(box, ptrans->stride, ptrans->layer_stride); 1590bf215546Sopenharmony_ci if (!synchronize(ctx, res, usage, &range)) { 1591bf215546Sopenharmony_ci slab_free(transfer_pool, trans); 1592bf215546Sopenharmony_ci return NULL; 1593bf215546Sopenharmony_ci } 1594bf215546Sopenharmony_ci ptr = d3d12_bo_map(res->bo, &range); 1595bf215546Sopenharmony_ci } else if (unlikely(pres->format == PIPE_FORMAT_Z24_UNORM_S8_UINT || 1596bf215546Sopenharmony_ci pres->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)) { 1597bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) { 1598bf215546Sopenharmony_ci ptr = read_zs_surface(ctx, res, box, trans); 1599bf215546Sopenharmony_ci } else if (usage & PIPE_MAP_WRITE){ 1600bf215546Sopenharmony_ci ptr = prepare_write_zs_surface(res, box, trans); 1601bf215546Sopenharmony_ci } else { 1602bf215546Sopenharmony_ci ptr = nullptr; 1603bf215546Sopenharmony_ci } 1604bf215546Sopenharmony_ci } else if(util_format_is_yuv(res->overall_format)) { 1605bf215546Sopenharmony_ci 1606bf215546Sopenharmony_ci /* Get planes information*/ 1607bf215546Sopenharmony_ci 1608bf215546Sopenharmony_ci unsigned num_planes = util_format_get_num_planes(res->overall_format); 1609bf215546Sopenharmony_ci pipe_resource *planes[d3d12_max_planes]; 1610bf215546Sopenharmony_ci unsigned int strides[d3d12_max_planes]; 1611bf215546Sopenharmony_ci unsigned int layer_strides[d3d12_max_planes]; 1612bf215546Sopenharmony_ci unsigned int offsets[d3d12_max_planes]; 1613bf215546Sopenharmony_ci unsigned staging_res_size = 0; 1614bf215546Sopenharmony_ci 1615bf215546Sopenharmony_ci d3d12_resource_get_planes_info( 1616bf215546Sopenharmony_ci pres, 1617bf215546Sopenharmony_ci num_planes, 1618bf215546Sopenharmony_ci planes, 1619bf215546Sopenharmony_ci strides, 1620bf215546Sopenharmony_ci layer_strides, 1621bf215546Sopenharmony_ci offsets, 1622bf215546Sopenharmony_ci &staging_res_size 1623bf215546Sopenharmony_ci ); 1624bf215546Sopenharmony_ci 1625bf215546Sopenharmony_ci /* Allocate a buffer for all the planes to fit in adjacent memory*/ 1626bf215546Sopenharmony_ci 1627bf215546Sopenharmony_ci pipe_resource_usage staging_usage = (usage & (PIPE_MAP_READ | PIPE_MAP_READ_WRITE)) ? 1628bf215546Sopenharmony_ci PIPE_USAGE_STAGING : PIPE_USAGE_STREAM; 1629bf215546Sopenharmony_ci trans->staging_res = pipe_buffer_create(pctx->screen, 0, 1630bf215546Sopenharmony_ci staging_usage, 1631bf215546Sopenharmony_ci staging_res_size); 1632bf215546Sopenharmony_ci if (!trans->staging_res) 1633bf215546Sopenharmony_ci return NULL; 1634bf215546Sopenharmony_ci 1635bf215546Sopenharmony_ci struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res); 1636bf215546Sopenharmony_ci 1637bf215546Sopenharmony_ci /* Readback contents into the buffer allocation now if map was intended for read*/ 1638bf215546Sopenharmony_ci 1639bf215546Sopenharmony_ci /* Read all planes if readback needed*/ 1640bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) { 1641bf215546Sopenharmony_ci pipe_box original_box = ptrans->box; 1642bf215546Sopenharmony_ci for (uint plane_slice = 0; plane_slice < num_planes; ++plane_slice) { 1643bf215546Sopenharmony_ci /* Adjust strides, offsets, box to the corresponding plane for the copytexture operation*/ 1644bf215546Sopenharmony_ci d3d12_adjust_transfer_dimensions_for_plane(res, 1645bf215546Sopenharmony_ci plane_slice, 1646bf215546Sopenharmony_ci strides[plane_slice], 1647bf215546Sopenharmony_ci layer_strides[plane_slice], 1648bf215546Sopenharmony_ci offsets[plane_slice], 1649bf215546Sopenharmony_ci &original_box, 1650bf215546Sopenharmony_ci ptrans/*inout*/); 1651bf215546Sopenharmony_ci /* Perform the readback*/ 1652bf215546Sopenharmony_ci if(!transfer_image_to_buf(ctx, d3d12_resource(planes[plane_slice]), staging_res, trans, 0)){ 1653bf215546Sopenharmony_ci return NULL; 1654bf215546Sopenharmony_ci } 1655bf215546Sopenharmony_ci } 1656bf215546Sopenharmony_ci 1657bf215546Sopenharmony_ci d3d12_flush_cmdlist_and_wait(ctx); 1658bf215546Sopenharmony_ci } 1659bf215546Sopenharmony_ci 1660bf215546Sopenharmony_ci /* Map the whole staging buffer containing all the planes contiguously*/ 1661bf215546Sopenharmony_ci /* Just offset the resulting ptr to the according plane offset*/ 1662bf215546Sopenharmony_ci 1663bf215546Sopenharmony_ci range.End = staging_res_size - range.Begin; 1664bf215546Sopenharmony_ci uint8_t* all_planes_map = (uint8_t*) d3d12_bo_map(staging_res->bo, &range); 1665bf215546Sopenharmony_ci 1666bf215546Sopenharmony_ci ptrans->stride = strides[res->plane_slice]; 1667bf215546Sopenharmony_ci ptrans->layer_stride = layer_strides[res->plane_slice]; 1668bf215546Sopenharmony_ci ptr = all_planes_map + offsets[res->plane_slice]; 1669bf215546Sopenharmony_ci 1670bf215546Sopenharmony_ci } else { 1671bf215546Sopenharmony_ci ptrans->stride = align(util_format_get_stride(pres->format, box->width), 1672bf215546Sopenharmony_ci D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); 1673bf215546Sopenharmony_ci ptrans->layer_stride = util_format_get_2d_size(pres->format, 1674bf215546Sopenharmony_ci ptrans->stride, 1675bf215546Sopenharmony_ci box->height); 1676bf215546Sopenharmony_ci 1677bf215546Sopenharmony_ci if (res->base.b.target != PIPE_TEXTURE_3D) 1678bf215546Sopenharmony_ci ptrans->layer_stride = align(ptrans->layer_stride, 1679bf215546Sopenharmony_ci D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); 1680bf215546Sopenharmony_ci 1681bf215546Sopenharmony_ci if (util_format_has_depth(util_format_description(pres->format)) && 1682bf215546Sopenharmony_ci screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) { 1683bf215546Sopenharmony_ci trans->zs_cpu_copy_stride = ptrans->stride; 1684bf215546Sopenharmony_ci trans->zs_cpu_copy_layer_stride = ptrans->layer_stride; 1685bf215546Sopenharmony_ci 1686bf215546Sopenharmony_ci ptrans->stride = align(util_format_get_stride(pres->format, pres->width0), 1687bf215546Sopenharmony_ci D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); 1688bf215546Sopenharmony_ci ptrans->layer_stride = util_format_get_2d_size(pres->format, 1689bf215546Sopenharmony_ci ptrans->stride, 1690bf215546Sopenharmony_ci pres->height0); 1691bf215546Sopenharmony_ci 1692bf215546Sopenharmony_ci range.Begin = box->y * ptrans->stride + 1693bf215546Sopenharmony_ci box->x * util_format_get_blocksize(pres->format); 1694bf215546Sopenharmony_ci } 1695bf215546Sopenharmony_ci 1696bf215546Sopenharmony_ci unsigned staging_res_size = ptrans->layer_stride * box->depth; 1697bf215546Sopenharmony_ci if (res->base.b.target == PIPE_BUFFER) { 1698bf215546Sopenharmony_ci /* To properly support ARB_map_buffer_alignment, we need to return a pointer 1699bf215546Sopenharmony_ci * that's appropriately offset from a 64-byte-aligned base address. 1700bf215546Sopenharmony_ci */ 1701bf215546Sopenharmony_ci assert(box->x >= 0); 1702bf215546Sopenharmony_ci unsigned aligned_x = (unsigned)box->x % BUFFER_MAP_ALIGNMENT; 1703bf215546Sopenharmony_ci staging_res_size = align(box->width + aligned_x, 1704bf215546Sopenharmony_ci D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); 1705bf215546Sopenharmony_ci range.Begin = aligned_x; 1706bf215546Sopenharmony_ci } 1707bf215546Sopenharmony_ci 1708bf215546Sopenharmony_ci pipe_resource_usage staging_usage = (usage & (PIPE_MAP_DISCARD_RANGE | PIPE_MAP_DISCARD_WHOLE_RESOURCE)) ? 1709bf215546Sopenharmony_ci PIPE_USAGE_STREAM : PIPE_USAGE_STAGING; 1710bf215546Sopenharmony_ci 1711bf215546Sopenharmony_ci trans->staging_res = pipe_buffer_create(pctx->screen, 0, 1712bf215546Sopenharmony_ci staging_usage, 1713bf215546Sopenharmony_ci staging_res_size); 1714bf215546Sopenharmony_ci if (!trans->staging_res) { 1715bf215546Sopenharmony_ci slab_free(transfer_pool, trans); 1716bf215546Sopenharmony_ci return NULL; 1717bf215546Sopenharmony_ci } 1718bf215546Sopenharmony_ci 1719bf215546Sopenharmony_ci struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res); 1720bf215546Sopenharmony_ci 1721bf215546Sopenharmony_ci if ((usage & (PIPE_MAP_DISCARD_RANGE | PIPE_MAP_DISCARD_WHOLE_RESOURCE | TC_TRANSFER_MAP_THREADED_UNSYNC)) == 0) { 1722bf215546Sopenharmony_ci bool ret = true; 1723bf215546Sopenharmony_ci if (pres->target == PIPE_BUFFER) { 1724bf215546Sopenharmony_ci uint64_t src_offset = box->x; 1725bf215546Sopenharmony_ci uint64_t dst_offset = src_offset % BUFFER_MAP_ALIGNMENT; 1726bf215546Sopenharmony_ci transfer_buf_to_buf(ctx, res, staging_res, src_offset, dst_offset, box->width); 1727bf215546Sopenharmony_ci } else 1728bf215546Sopenharmony_ci ret = transfer_image_to_buf(ctx, res, staging_res, trans, 0); 1729bf215546Sopenharmony_ci if (!ret) 1730bf215546Sopenharmony_ci return NULL; 1731bf215546Sopenharmony_ci d3d12_flush_cmdlist_and_wait(ctx); 1732bf215546Sopenharmony_ci } 1733bf215546Sopenharmony_ci 1734bf215546Sopenharmony_ci range.End = staging_res_size - range.Begin; 1735bf215546Sopenharmony_ci 1736bf215546Sopenharmony_ci ptr = d3d12_bo_map(staging_res->bo, &range); 1737bf215546Sopenharmony_ci } 1738bf215546Sopenharmony_ci 1739bf215546Sopenharmony_ci pipe_resource_reference(&ptrans->resource, pres); 1740bf215546Sopenharmony_ci *transfer = ptrans; 1741bf215546Sopenharmony_ci return ptr; 1742bf215546Sopenharmony_ci} 1743bf215546Sopenharmony_ci 1744bf215546Sopenharmony_cistatic void 1745bf215546Sopenharmony_cid3d12_transfer_unmap(struct pipe_context *pctx, 1746bf215546Sopenharmony_ci struct pipe_transfer *ptrans) 1747bf215546Sopenharmony_ci{ 1748bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1749bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(ptrans->resource); 1750bf215546Sopenharmony_ci struct d3d12_transfer *trans = (struct d3d12_transfer *)ptrans; 1751bf215546Sopenharmony_ci D3D12_RANGE range = { 0, 0 }; 1752bf215546Sopenharmony_ci 1753bf215546Sopenharmony_ci if (trans->data != nullptr) { 1754bf215546Sopenharmony_ci if (trans->base.b.usage & PIPE_MAP_WRITE) 1755bf215546Sopenharmony_ci write_zs_surface(pctx, res, trans); 1756bf215546Sopenharmony_ci free(trans->data); 1757bf215546Sopenharmony_ci } else if (trans->staging_res) { 1758bf215546Sopenharmony_ci if(util_format_is_yuv(res->overall_format)) { 1759bf215546Sopenharmony_ci 1760bf215546Sopenharmony_ci /* Get planes information*/ 1761bf215546Sopenharmony_ci unsigned num_planes = util_format_get_num_planes(res->overall_format); 1762bf215546Sopenharmony_ci pipe_resource *planes[d3d12_max_planes]; 1763bf215546Sopenharmony_ci unsigned int strides[d3d12_max_planes]; 1764bf215546Sopenharmony_ci unsigned int layer_strides[d3d12_max_planes]; 1765bf215546Sopenharmony_ci unsigned int offsets[d3d12_max_planes]; 1766bf215546Sopenharmony_ci unsigned staging_res_size = 0; 1767bf215546Sopenharmony_ci 1768bf215546Sopenharmony_ci d3d12_resource_get_planes_info( 1769bf215546Sopenharmony_ci ptrans->resource, 1770bf215546Sopenharmony_ci num_planes, 1771bf215546Sopenharmony_ci planes, 1772bf215546Sopenharmony_ci strides, 1773bf215546Sopenharmony_ci layer_strides, 1774bf215546Sopenharmony_ci offsets, 1775bf215546Sopenharmony_ci &staging_res_size 1776bf215546Sopenharmony_ci ); 1777bf215546Sopenharmony_ci 1778bf215546Sopenharmony_ci /* Flush the changed contents into the GPU texture*/ 1779bf215546Sopenharmony_ci 1780bf215546Sopenharmony_ci /* In theory we should just flush only the contents for the plane*/ 1781bf215546Sopenharmony_ci /* requested in res->plane_slice, but the VAAPI frontend has this*/ 1782bf215546Sopenharmony_ci /* behaviour in which they assume that mapping the first plane of*/ 1783bf215546Sopenharmony_ci /* NV12, P010, etc resources will will give them a buffer containing*/ 1784bf215546Sopenharmony_ci /* both Y and UV planes contigously in vaDeriveImage and then vaMapBuffer*/ 1785bf215546Sopenharmony_ci /* so, flush them all*/ 1786bf215546Sopenharmony_ci 1787bf215546Sopenharmony_ci struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res); 1788bf215546Sopenharmony_ci if (trans->base.b.usage & PIPE_MAP_WRITE) { 1789bf215546Sopenharmony_ci assert(ptrans->box.x >= 0); 1790bf215546Sopenharmony_ci range.Begin = res->base.b.target == PIPE_BUFFER ? 1791bf215546Sopenharmony_ci (unsigned)ptrans->box.x % BUFFER_MAP_ALIGNMENT : 0; 1792bf215546Sopenharmony_ci range.End = staging_res->base.b.width0 - range.Begin; 1793bf215546Sopenharmony_ci 1794bf215546Sopenharmony_ci d3d12_bo_unmap(staging_res->bo, &range); 1795bf215546Sopenharmony_ci pipe_box original_box = ptrans->box; 1796bf215546Sopenharmony_ci for (uint plane_slice = 0; plane_slice < num_planes; ++plane_slice) { 1797bf215546Sopenharmony_ci /* Adjust strides, offsets to the corresponding plane for the copytexture operation*/ 1798bf215546Sopenharmony_ci d3d12_adjust_transfer_dimensions_for_plane(res, 1799bf215546Sopenharmony_ci plane_slice, 1800bf215546Sopenharmony_ci strides[plane_slice], 1801bf215546Sopenharmony_ci layer_strides[plane_slice], 1802bf215546Sopenharmony_ci offsets[plane_slice], 1803bf215546Sopenharmony_ci &original_box, 1804bf215546Sopenharmony_ci ptrans/*inout*/); 1805bf215546Sopenharmony_ci 1806bf215546Sopenharmony_ci transfer_buf_to_image(ctx, d3d12_resource(planes[plane_slice]), staging_res, trans, 0); 1807bf215546Sopenharmony_ci } 1808bf215546Sopenharmony_ci } 1809bf215546Sopenharmony_ci 1810bf215546Sopenharmony_ci pipe_resource_reference(&trans->staging_res, NULL); 1811bf215546Sopenharmony_ci } else { 1812bf215546Sopenharmony_ci struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res); 1813bf215546Sopenharmony_ci if (trans->base.b.usage & PIPE_MAP_WRITE) { 1814bf215546Sopenharmony_ci assert(ptrans->box.x >= 0); 1815bf215546Sopenharmony_ci range.Begin = res->base.b.target == PIPE_BUFFER ? 1816bf215546Sopenharmony_ci (unsigned)ptrans->box.x % BUFFER_MAP_ALIGNMENT : 0; 1817bf215546Sopenharmony_ci range.End = staging_res->base.b.width0 - range.Begin; 1818bf215546Sopenharmony_ci } 1819bf215546Sopenharmony_ci d3d12_bo_unmap(staging_res->bo, &range); 1820bf215546Sopenharmony_ci 1821bf215546Sopenharmony_ci if (trans->base.b.usage & PIPE_MAP_WRITE) { 1822bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1823bf215546Sopenharmony_ci if (res->base.b.target == PIPE_BUFFER) { 1824bf215546Sopenharmony_ci uint64_t dst_offset = trans->base.b.box.x; 1825bf215546Sopenharmony_ci uint64_t src_offset = dst_offset % BUFFER_MAP_ALIGNMENT; 1826bf215546Sopenharmony_ci transfer_buf_to_buf(ctx, staging_res, res, src_offset, dst_offset, ptrans->box.width); 1827bf215546Sopenharmony_ci } else 1828bf215546Sopenharmony_ci transfer_buf_to_image(ctx, res, staging_res, trans, 0); 1829bf215546Sopenharmony_ci } 1830bf215546Sopenharmony_ci 1831bf215546Sopenharmony_ci pipe_resource_reference(&trans->staging_res, NULL); 1832bf215546Sopenharmony_ci } 1833bf215546Sopenharmony_ci } else { 1834bf215546Sopenharmony_ci if (trans->base.b.usage & PIPE_MAP_WRITE) { 1835bf215546Sopenharmony_ci range.Begin = ptrans->box.x; 1836bf215546Sopenharmony_ci range.End = ptrans->box.x + ptrans->box.width; 1837bf215546Sopenharmony_ci } 1838bf215546Sopenharmony_ci d3d12_bo_unmap(res->bo, &range); 1839bf215546Sopenharmony_ci } 1840bf215546Sopenharmony_ci 1841bf215546Sopenharmony_ci pipe_resource_reference(&ptrans->resource, NULL); 1842bf215546Sopenharmony_ci slab_free(&d3d12_context(pctx)->transfer_pool, ptrans); 1843bf215546Sopenharmony_ci} 1844bf215546Sopenharmony_ci 1845bf215546Sopenharmony_civoid 1846bf215546Sopenharmony_cid3d12_context_resource_init(struct pipe_context *pctx) 1847bf215546Sopenharmony_ci{ 1848bf215546Sopenharmony_ci pctx->buffer_map = d3d12_transfer_map; 1849bf215546Sopenharmony_ci pctx->buffer_unmap = d3d12_transfer_unmap; 1850bf215546Sopenharmony_ci pctx->texture_map = d3d12_transfer_map; 1851bf215546Sopenharmony_ci pctx->texture_unmap = d3d12_transfer_unmap; 1852bf215546Sopenharmony_ci 1853bf215546Sopenharmony_ci pctx->transfer_flush_region = u_default_transfer_flush_region; 1854bf215546Sopenharmony_ci pctx->buffer_subdata = u_default_buffer_subdata; 1855bf215546Sopenharmony_ci pctx->texture_subdata = u_default_texture_subdata; 1856bf215546Sopenharmony_ci} 1857