diff options
author | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-05-10 20:36:03 +0200 |
---|---|---|
committer | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-05-18 11:48:51 +0200 |
commit | 8aabed64c37c70b0914e5628f0168264ed7e21c7 (patch) | |
tree | e8d495e77696a700dec93e15d8014ce6555270a4 /src/amd/common/ac_surface.c | |
parent | db77cd879b7996fcf423090b776f6f96708818c3 (diff) |
ac/radeonsi: move the bulk of gfx9_surface_init to ac_surface
We can now merge the two *_surface_init functions.
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Diffstat (limited to 'src/amd/common/ac_surface.c')
-rw-r--r-- | src/amd/common/ac_surface.c | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c index cf741049db..8b6d3b10a2 100644 --- a/src/amd/common/ac_surface.c +++ b/src/amd/common/ac_surface.c @@ -630,3 +630,383 @@ int gfx6_compute_surface(ADDR_HANDLE addrlib, surf->is_linear = surf->u.legacy.level[0].mode == RADEON_SURF_MODE_LINEAR_ALIGNED; return 0; } + +/* This is only called when expecting a tiled layout. */ +static int +gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib, + ADDR2_COMPUTE_SURFACE_INFO_INPUT *in, + bool is_fmask, AddrSwizzleMode *swizzle_mode) +{ + ADDR_E_RETURNCODE ret; + ADDR2_GET_PREFERRED_SURF_SETTING_INPUT sin = {0}; + ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT sout = {0}; + + sin.size = sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_INPUT); + sout.size = sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT); + + sin.flags = in->flags; + sin.resourceType = in->resourceType; + sin.format = in->format; + sin.resourceLoction = ADDR_RSRC_LOC_INVIS; + /* TODO: We could allow some of these: */ + sin.forbiddenBlock.micro = 1; /* don't allow the 256B swizzle modes */ + sin.forbiddenBlock.var = 1; /* don't allow the variable-sized swizzle modes */ + sin.forbiddenBlock.linear = 1; /* don't allow linear swizzle modes */ + sin.bpp = in->bpp; + sin.width = in->width; + sin.height = in->height; + sin.numSlices = in->numSlices; + sin.numMipLevels = in->numMipLevels; + sin.numSamples = in->numSamples; + sin.numFrags = in->numFrags; + + if (is_fmask) { + sin.flags.color = 0; + sin.flags.fmask = 1; + } + + ret = Addr2GetPreferredSurfaceSetting(addrlib, &sin, &sout); + if (ret != ADDR_OK) + return ret; + + *swizzle_mode = sout.swizzleMode; + return 0; +} + +static int gfx9_compute_miptree(ADDR_HANDLE addrlib, + struct radeon_surf *surf, bool compressed, + ADDR2_COMPUTE_SURFACE_INFO_INPUT *in) +{ + ADDR2_MIP_INFO mip_info[RADEON_SURF_MAX_LEVELS] = {}; + ADDR2_COMPUTE_SURFACE_INFO_OUTPUT out = {0}; + ADDR_E_RETURNCODE ret; + + out.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT); + out.pMipInfo = mip_info; + + ret = Addr2ComputeSurfaceInfo(addrlib, in, &out); + if (ret != ADDR_OK) + return ret; + + if (in->flags.stencil) { + surf->u.gfx9.stencil.swizzle_mode = in->swizzleMode; + surf->u.gfx9.stencil.epitch = out.epitchIsHeight ? out.mipChainHeight - 1 : + out.mipChainPitch - 1; + surf->surf_alignment = MAX2(surf->surf_alignment, out.baseAlign); + surf->u.gfx9.stencil_offset = align(surf->surf_size, out.baseAlign); + surf->surf_size = surf->u.gfx9.stencil_offset + out.surfSize; + return 0; + } + + surf->u.gfx9.surf.swizzle_mode = in->swizzleMode; + surf->u.gfx9.surf.epitch = out.epitchIsHeight ? out.mipChainHeight - 1 : + out.mipChainPitch - 1; + + /* CMASK fast clear uses these even if FMASK isn't allocated. + * FMASK only supports the Z swizzle modes, whose numbers are multiples of 4. + */ + surf->u.gfx9.fmask.swizzle_mode = surf->u.gfx9.surf.swizzle_mode & ~0x3; + surf->u.gfx9.fmask.epitch = surf->u.gfx9.surf.epitch; + + surf->u.gfx9.surf_slice_size = out.sliceSize; + surf->u.gfx9.surf_pitch = out.pitch; + surf->u.gfx9.surf_height = out.height; + surf->surf_size = out.surfSize; + surf->surf_alignment = out.baseAlign; + + if (in->swizzleMode == ADDR_SW_LINEAR) { + for (unsigned i = 0; i < in->numMipLevels; i++) + surf->u.gfx9.offset[i] = mip_info[i].offset; + } + + if (in->flags.depth) { + assert(in->swizzleMode != ADDR_SW_LINEAR); + + /* HTILE */ + ADDR2_COMPUTE_HTILE_INFO_INPUT hin = {0}; + ADDR2_COMPUTE_HTILE_INFO_OUTPUT hout = {0}; + + hin.size = sizeof(ADDR2_COMPUTE_HTILE_INFO_INPUT); + hout.size = sizeof(ADDR2_COMPUTE_HTILE_INFO_OUTPUT); + + hin.hTileFlags.pipeAligned = 1; + hin.hTileFlags.rbAligned = 1; + hin.depthFlags = in->flags; + hin.swizzleMode = in->swizzleMode; + hin.unalignedWidth = in->width; + hin.unalignedHeight = in->height; + hin.numSlices = in->numSlices; + hin.numMipLevels = in->numMipLevels; + + ret = Addr2ComputeHtileInfo(addrlib, &hin, &hout); + if (ret != ADDR_OK) + return ret; + + surf->u.gfx9.htile.rb_aligned = hin.hTileFlags.rbAligned; + surf->u.gfx9.htile.pipe_aligned = hin.hTileFlags.pipeAligned; + surf->htile_size = hout.htileBytes; + surf->htile_alignment = hout.baseAlign; + } else { + /* DCC */ + if (!(surf->flags & RADEON_SURF_DISABLE_DCC) && + !(surf->flags & RADEON_SURF_SCANOUT) && + !compressed && + in->swizzleMode != ADDR_SW_LINEAR && + /* TODO: We could support DCC with MSAA. */ + in->numSamples == 1) { + ADDR2_COMPUTE_DCCINFO_INPUT din = {0}; + ADDR2_COMPUTE_DCCINFO_OUTPUT dout = {0}; + + din.size = sizeof(ADDR2_COMPUTE_DCCINFO_INPUT); + dout.size = sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT); + + din.dccKeyFlags.pipeAligned = 1; + din.dccKeyFlags.rbAligned = 1; + din.colorFlags = in->flags; + din.resourceType = in->resourceType; + din.swizzleMode = in->swizzleMode; + din.bpp = in->bpp; + din.unalignedWidth = in->width; + din.unalignedHeight = in->height; + din.numSlices = in->numSlices; + din.numFrags = in->numFrags; + din.numMipLevels = in->numMipLevels; + din.dataSurfaceSize = out.surfSize; + + ret = Addr2ComputeDccInfo(addrlib, &din, &dout); + if (ret != ADDR_OK) + return ret; + + surf->u.gfx9.dcc.rb_aligned = din.dccKeyFlags.rbAligned; + surf->u.gfx9.dcc.pipe_aligned = din.dccKeyFlags.pipeAligned; + surf->u.gfx9.dcc_pitch_max = dout.pitch - 1; + surf->dcc_size = dout.dccRamSize; + surf->dcc_alignment = dout.dccRamBaseAlign; + } + + /* FMASK */ + if (in->numSamples > 1) { + ADDR2_COMPUTE_FMASK_INFO_INPUT fin = {0}; + ADDR2_COMPUTE_FMASK_INFO_OUTPUT fout = {0}; + + fin.size = sizeof(ADDR2_COMPUTE_FMASK_INFO_INPUT); + fout.size = sizeof(ADDR2_COMPUTE_FMASK_INFO_OUTPUT); + + ret = gfx9_get_preferred_swizzle_mode(addrlib, in, true, &fin.swizzleMode); + if (ret != ADDR_OK) + return ret; + + fin.unalignedWidth = in->width; + fin.unalignedHeight = in->height; + fin.numSlices = in->numSlices; + fin.numSamples = in->numSamples; + fin.numFrags = in->numFrags; + + ret = Addr2ComputeFmaskInfo(addrlib, &fin, &fout); + if (ret != ADDR_OK) + return ret; + + surf->u.gfx9.fmask.swizzle_mode = fin.swizzleMode; + surf->u.gfx9.fmask.epitch = fout.pitch - 1; + surf->u.gfx9.fmask_size = fout.fmaskBytes; + surf->u.gfx9.fmask_alignment = fout.baseAlign; + } + + /* CMASK */ + if (in->swizzleMode != ADDR_SW_LINEAR) { + ADDR2_COMPUTE_CMASK_INFO_INPUT cin = {0}; + ADDR2_COMPUTE_CMASK_INFO_OUTPUT cout = {0}; + + cin.size = sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT); + cout.size = sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT); + + cin.cMaskFlags.pipeAligned = 1; + cin.cMaskFlags.rbAligned = 1; + cin.colorFlags = in->flags; + cin.resourceType = in->resourceType; + cin.unalignedWidth = in->width; + cin.unalignedHeight = in->height; + cin.numSlices = in->numSlices; + + if (in->numSamples > 1) + cin.swizzleMode = surf->u.gfx9.fmask.swizzle_mode; + else + cin.swizzleMode = in->swizzleMode; + + ret = Addr2ComputeCmaskInfo(addrlib, &cin, &cout); + if (ret != ADDR_OK) + return ret; + + surf->u.gfx9.cmask.rb_aligned = cin.cMaskFlags.rbAligned; + surf->u.gfx9.cmask.pipe_aligned = cin.cMaskFlags.pipeAligned; + surf->u.gfx9.cmask_size = cout.cmaskBytes; + surf->u.gfx9.cmask_alignment = cout.baseAlign; + } + } + + return 0; +} + +int gfx9_compute_surface(ADDR_HANDLE addrlib, + const struct ac_surf_config *config, + enum radeon_surf_mode mode, + struct radeon_surf *surf) +{ + bool compressed; + ADDR2_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn = {0}; + int r; + + assert(!(surf->flags & RADEON_SURF_FMASK)); + + AddrSurfInfoIn.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT); + + compressed = surf->blk_w == 4 && surf->blk_h == 4; + + /* The format must be set correctly for the allocation of compressed + * textures to work. In other cases, setting the bpp is sufficient. */ + if (compressed) { + switch (surf->bpe) { + case 8: + AddrSurfInfoIn.format = ADDR_FMT_BC1; + break; + case 16: + AddrSurfInfoIn.format = ADDR_FMT_BC3; + break; + default: + assert(0); + } + } else { + AddrSurfInfoIn.bpp = surf->bpe * 8; + } + + AddrSurfInfoIn.flags.color = !(surf->flags & RADEON_SURF_Z_OR_SBUFFER); + AddrSurfInfoIn.flags.depth = (surf->flags & RADEON_SURF_ZBUFFER) != 0; + AddrSurfInfoIn.flags.display = (surf->flags & RADEON_SURF_SCANOUT) != 0; + AddrSurfInfoIn.flags.texture = 1; + AddrSurfInfoIn.flags.opt4space = 1; + + AddrSurfInfoIn.numMipLevels = config->info.levels; + AddrSurfInfoIn.numSamples = config->info.samples ? config->info.samples : 1; + AddrSurfInfoIn.numFrags = AddrSurfInfoIn.numSamples; + + /* GFX9 doesn't support 1D depth textures, so allocate all 1D textures + * as 2D to avoid having shader variants for 1D vs 2D, so all shaders + * must sample 1D textures as 2D. */ + if (config->is_3d) + AddrSurfInfoIn.resourceType = ADDR_RSRC_TEX_3D; + else + AddrSurfInfoIn.resourceType = ADDR_RSRC_TEX_2D; + + AddrSurfInfoIn.width = config->info.width; + AddrSurfInfoIn.height = config->info.height; + + if (config->is_3d) + AddrSurfInfoIn.numSlices = config->info.depth; + else if (config->is_cube) + AddrSurfInfoIn.numSlices = 6; + else + AddrSurfInfoIn.numSlices = config->info.array_size; + + switch (mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + assert(config->info.samples <= 1); + assert(!(surf->flags & RADEON_SURF_Z_OR_SBUFFER)); + AddrSurfInfoIn.swizzleMode = ADDR_SW_LINEAR; + break; + + case RADEON_SURF_MODE_1D: + case RADEON_SURF_MODE_2D: + r = gfx9_get_preferred_swizzle_mode(addrlib, &AddrSurfInfoIn, false, + &AddrSurfInfoIn.swizzleMode); + if (r) + return r; + break; + + default: + assert(0); + } + + surf->u.gfx9.resource_type = AddrSurfInfoIn.resourceType; + + surf->surf_size = 0; + surf->dcc_size = 0; + surf->htile_size = 0; + surf->u.gfx9.surf_offset = 0; + surf->u.gfx9.stencil_offset = 0; + surf->u.gfx9.fmask_size = 0; + surf->u.gfx9.cmask_size = 0; + + /* Calculate texture layout information. */ + r = gfx9_compute_miptree(addrlib, surf, compressed, &AddrSurfInfoIn); + if (r) + return r; + + /* Calculate texture layout information for stencil. */ + if (surf->flags & RADEON_SURF_SBUFFER) { + AddrSurfInfoIn.bpp = 8; + AddrSurfInfoIn.flags.depth = 0; + AddrSurfInfoIn.flags.stencil = 1; + + r = gfx9_compute_miptree(addrlib, surf, compressed, &AddrSurfInfoIn); + if (r) + return r; + } + + surf->is_linear = surf->u.gfx9.surf.swizzle_mode == ADDR_SW_LINEAR; + surf->num_dcc_levels = surf->dcc_size ? config->info.levels : 0; + + switch (surf->u.gfx9.surf.swizzle_mode) { + /* S = standard. */ + case ADDR_SW_256B_S: + case ADDR_SW_4KB_S: + case ADDR_SW_64KB_S: + case ADDR_SW_VAR_S: + case ADDR_SW_64KB_S_T: + case ADDR_SW_4KB_S_X: + case ADDR_SW_64KB_S_X: + case ADDR_SW_VAR_S_X: + surf->micro_tile_mode = RADEON_MICRO_MODE_THIN; + break; + + /* D = display. */ + case ADDR_SW_LINEAR: + case ADDR_SW_256B_D: + case ADDR_SW_4KB_D: + case ADDR_SW_64KB_D: + case ADDR_SW_VAR_D: + case ADDR_SW_64KB_D_T: + case ADDR_SW_4KB_D_X: + case ADDR_SW_64KB_D_X: + case ADDR_SW_VAR_D_X: + surf->micro_tile_mode = RADEON_MICRO_MODE_DISPLAY; + break; + + /* R = rotated. */ + case ADDR_SW_256B_R: + case ADDR_SW_4KB_R: + case ADDR_SW_64KB_R: + case ADDR_SW_VAR_R: + case ADDR_SW_64KB_R_T: + case ADDR_SW_4KB_R_X: + case ADDR_SW_64KB_R_X: + case ADDR_SW_VAR_R_X: + surf->micro_tile_mode = RADEON_MICRO_MODE_ROTATED; + break; + + /* Z = depth. */ + case ADDR_SW_4KB_Z: + case ADDR_SW_64KB_Z: + case ADDR_SW_VAR_Z: + case ADDR_SW_64KB_Z_T: + case ADDR_SW_4KB_Z_X: + case ADDR_SW_64KB_Z_X: + case ADDR_SW_VAR_Z_X: + surf->micro_tile_mode = RADEON_MICRO_MODE_DEPTH; + break; + + default: + assert(0); + } + + return 0; +} |