Path: blob/21.2-virgl/src/gallium/drivers/swr/rasterizer/memory/TilingFunctions.h
4574 views
/****************************************************************************1* Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*22* @file TilingFunctions.h23*24* @brief Tiling functions.25*26******************************************************************************/27#pragma once2829#include "core/state.h"30#include "core/format_traits.h"31#include "memory/tilingtraits.h"32#include "memory/SurfaceState.h"3334#include <algorithm>3536#define MAX_NUM_LOD 153738#define GFX_ALIGN(x, a) (((x) + ((a) - 1)) - (((x) + ((a) - 1)) & ((a) - 1))) // Alt implementation with bitwise not (~) has issue with uint32 align used with 64-bit value, since ~'ed value will remain 32-bit.3940//////////////////////////////////////////////////////////////////////////41/// SimdTile SSE(2x2), AVX(4x2), or AVX-512(4x4?)42//////////////////////////////////////////////////////////////////////////43template<SWR_FORMAT HotTileFormat, SWR_FORMAT SrcOrDstFormat>44struct SimdTile45{46// SimdTile is SOA (e.g. rrrrrrrr gggggggg bbbbbbbb aaaaaaaa )47float color[FormatTraits<HotTileFormat>::numComps][KNOB_SIMD_WIDTH];4849//////////////////////////////////////////////////////////////////////////50/// @brief Retrieve color from simd.51/// @param index - linear index to color within simd.52/// @param outputColor - output color53INLINE void GetSwizzledColor(54uint32_t index,55float outputColor[4])56{57// SOA pattern for 2x2 is a subset of 4x2.58// 0 1 4 559// 2 3 6 760// The offset converts pattern to linear61#if (SIMD_TILE_X_DIM == 4)62static const uint32_t offset[] = { 0, 1, 4, 5, 2, 3, 6, 7 };63#elif (SIMD_TILE_X_DIM == 2)64static const uint32_t offset[] = { 0, 1, 2, 3 };65#endif6667for (uint32_t i = 0; i < FormatTraits<SrcOrDstFormat>::numComps; ++i)68{69outputColor[i] = this->color[FormatTraits<SrcOrDstFormat>::swizzle(i)][offset[index]];70}71}7273//////////////////////////////////////////////////////////////////////////74/// @brief Retrieve color from simd.75/// @param index - linear index to color within simd.76/// @param outputColor - output color77INLINE void SetSwizzledColor(78uint32_t index,79const float src[4])80{81// SOA pattern for 2x2 is a subset of 4x2.82// 0 1 4 583// 2 3 6 784// The offset converts pattern to linear85#if (SIMD_TILE_X_DIM == 4)86static const uint32_t offset[] = { 0, 1, 4, 5, 2, 3, 6, 7 };87#elif (SIMD_TILE_X_DIM == 2)88static const uint32_t offset[] = { 0, 1, 2, 3 };89#endif9091// Only loop over the components needed for destination.92for (uint32_t i = 0; i < FormatTraits<SrcOrDstFormat>::numComps; ++i)93{94this->color[i][offset[index]] = src[i];95}96}97};9899template<>100struct SimdTile <R8_UINT,R8_UINT>101{102// SimdTile is SOA (e.g. rrrrrrrr gggggggg bbbbbbbb aaaaaaaa )103uint8_t color[FormatTraits<R8_UINT>::numComps][KNOB_SIMD_WIDTH];104105//////////////////////////////////////////////////////////////////////////106/// @brief Retrieve color from simd.107/// @param index - linear index to color within simd.108/// @param outputColor - output color109INLINE void GetSwizzledColor(110uint32_t index,111float outputColor[4])112{113// SOA pattern for 2x2 is a subset of 4x2.114// 0 1 4 5115// 2 3 6 7116// The offset converts pattern to linear117#if (SIMD_TILE_X_DIM == 4)118static const uint32_t offset[] = { 0, 1, 4, 5, 2, 3, 6, 7 };119#elif (SIMD_TILE_X_DIM == 2)120static const uint32_t offset[] = { 0, 1, 2, 3 };121#endif122123for (uint32_t i = 0; i < FormatTraits<R8_UINT>::numComps; ++i)124{125uint32_t src = this->color[FormatTraits<R8_UINT>::swizzle(i)][offset[index]];126outputColor[i] = *(float*)&src;127}128}129130//////////////////////////////////////////////////////////////////////////131/// @brief Retrieve color from simd.132/// @param index - linear index to color within simd.133/// @param outputColor - output color134INLINE void SetSwizzledColor(135uint32_t index,136const float src[4])137{138// SOA pattern for 2x2 is a subset of 4x2.139// 0 1 4 5140// 2 3 6 7141// The offset converts pattern to linear142#if (SIMD_TILE_X_DIM == 4)143static const uint32_t offset[] = { 0, 1, 4, 5, 2, 3, 6, 7 };144#elif (SIMD_TILE_X_DIM == 2)145static const uint32_t offset[] = { 0, 1, 2, 3 };146#endif147148// Only loop over the components needed for destination.149for (uint32_t i = 0; i < FormatTraits<R8_UINT>::numComps; ++i)150{151this->color[i][offset[index]] = *(uint8_t*)&src[i];152}153}154};155156//////////////////////////////////////////////////////////////////////////157/// SimdTile 8x2 for AVX-512158//////////////////////////////////////////////////////////////////////////159160template<SWR_FORMAT HotTileFormat, SWR_FORMAT SrcOrDstFormat>161struct SimdTile_16162{163// SimdTile is SOA (e.g. rrrrrrrrrrrrrrrr gggggggggggggggg bbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaa )164float color[FormatTraits<HotTileFormat>::numComps][KNOB_SIMD16_WIDTH];165166//////////////////////////////////////////////////////////////////////////167/// @brief Retrieve color from simd.168/// @param index - linear index to color within simd.169/// @param outputColor - output color170INLINE void GetSwizzledColor(171uint32_t index,172float outputColor[4])173{174// SOA pattern for 8x2..175// 0 1 4 5 8 9 C D176// 2 3 6 7 A B E F177// The offset converts pattern to linear178static const uint32_t offset[KNOB_SIMD16_WIDTH] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 };179180for (uint32_t i = 0; i < FormatTraits<SrcOrDstFormat>::numComps; ++i)181{182outputColor[i] = this->color[FormatTraits<SrcOrDstFormat>::swizzle(i)][offset[index]];183}184}185186//////////////////////////////////////////////////////////////////////////187/// @brief Retrieve color from simd.188/// @param index - linear index to color within simd.189/// @param outputColor - output color190INLINE void SetSwizzledColor(191uint32_t index,192const float src[4])193{194// SOA pattern for 8x2..195// 0 1 4 5 8 9 C D196// 2 3 6 7 A B E F197// The offset converts pattern to linear198static const uint32_t offset[KNOB_SIMD16_WIDTH] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 };199200for (uint32_t i = 0; i < FormatTraits<SrcOrDstFormat>::numComps; ++i)201{202this->color[i][offset[index]] = src[i];203}204}205};206207template<>208struct SimdTile_16 <R8_UINT, R8_UINT>209{210// SimdTile is SOA (e.g. rrrrrrrrrrrrrrrr gggggggggggggggg bbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaa )211uint8_t color[FormatTraits<R8_UINT>::numComps][KNOB_SIMD16_WIDTH];212213//////////////////////////////////////////////////////////////////////////214/// @brief Retrieve color from simd.215/// @param index - linear index to color within simd.216/// @param outputColor - output color217INLINE void GetSwizzledColor(218uint32_t index,219float outputColor[4])220{221// SOA pattern for 8x2..222// 0 1 4 5 8 9 C D223// 2 3 6 7 A B E F224// The offset converts pattern to linear225static const uint32_t offset[KNOB_SIMD16_WIDTH] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 };226227for (uint32_t i = 0; i < FormatTraits<R8_UINT>::numComps; ++i)228{229uint32_t src = this->color[FormatTraits<R8_UINT>::swizzle(i)][offset[index]];230outputColor[i] = *(float*)&src;231}232}233234//////////////////////////////////////////////////////////////////////////235/// @brief Retrieve color from simd.236/// @param index - linear index to color within simd.237/// @param outputColor - output color238INLINE void SetSwizzledColor(239uint32_t index,240const float src[4])241{242// SOA pattern for 8x2..243// 0 1 4 5 8 9 C D244// 2 3 6 7 A B E F245// The offset converts pattern to linear246static const uint32_t offset[KNOB_SIMD16_WIDTH] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 };247248for (uint32_t i = 0; i < FormatTraits<R8_UINT>::numComps; ++i)249{250this->color[i][offset[index]] = *(uint8_t*)&src[i];251}252}253};254255//////////////////////////////////////////////////////////////////////////256/// @brief Computes lod offset for 1D surface at specified lod.257/// @param baseWidth - width of basemip (mip 0).258/// @param hAlign - horizontal alignment per miip, in texels259/// @param lod - lod index260/// @param offset - output offset.261INLINE void ComputeLODOffset1D(262const SWR_FORMAT_INFO& info,263uint32_t baseWidth,264uint32_t hAlign,265uint32_t lod,266uint32_t &offset)267{268if (lod == 0)269{270offset = 0;271}272else273{274uint32_t curWidth = baseWidth;275// @note hAlign is already in blocks for compressed formats so upconvert276// so that we have the desired alignment post-divide.277if (info.isBC)278{279hAlign *= info.bcWidth;280}281282offset = GFX_ALIGN(curWidth, hAlign);283for (uint32_t l = 1; l < lod; ++l)284{285curWidth = std::max<uint32_t>(curWidth >> 1, 1U);286offset += GFX_ALIGN(curWidth, hAlign);287}288289if (info.isSubsampled || info.isBC)290{291offset /= info.bcWidth;292}293}294}295296//////////////////////////////////////////////////////////////////////////297/// @brief Computes x lod offset for 2D surface at specified lod.298/// @param baseWidth - width of basemip (mip 0).299/// @param hAlign - horizontal alignment per mip, in texels300/// @param lod - lod index301/// @param offset - output offset.302INLINE void ComputeLODOffsetX(303const SWR_FORMAT_INFO& info,304uint32_t baseWidth,305uint32_t hAlign,306uint32_t lod,307uint32_t &offset)308{309if (lod < 2)310{311offset = 0;312}313else314{315uint32_t curWidth = baseWidth;316// @note hAlign is already in blocks for compressed formats so upconvert317// so that we have the desired alignment post-divide.318if (info.isBC)319{320hAlign *= info.bcWidth;321}322323curWidth = std::max<uint32_t>(curWidth >> 1, 1U);324curWidth = GFX_ALIGN(curWidth, hAlign);325326if (info.isSubsampled || info.isBC)327{328curWidth /= info.bcWidth;329}330331offset = curWidth;332}333}334335//////////////////////////////////////////////////////////////////////////336/// @brief Computes y lod offset for 2D surface at specified lod.337/// @param baseWidth - width of basemip (mip 0).338/// @param vAlign - vertical alignment per mip, in rows339/// @param lod - lod index340/// @param offset - output offset.341INLINE void ComputeLODOffsetY(342const SWR_FORMAT_INFO& info,343uint32_t baseHeight,344uint32_t vAlign,345uint32_t lod,346uint32_t &offset)347{348if (lod == 0)349{350offset = 0;351}352else353{354offset = 0;355uint32_t mipHeight = baseHeight;356357// @note vAlign is already in blocks for compressed formats so upconvert358// so that we have the desired alignment post-divide.359if (info.isBC)360{361vAlign *= info.bcHeight;362}363364for (uint32_t l = 1; l <= lod; ++l)365{366uint32_t alignedMipHeight = GFX_ALIGN(mipHeight, vAlign);367offset += ((l != 2) ? alignedMipHeight : 0);368mipHeight = std::max<uint32_t>(mipHeight >> 1, 1U);369}370371if (info.isBC)372{373offset /= info.bcHeight;374}375}376}377378//////////////////////////////////////////////////////////////////////////379/// @brief Computes 1D surface offset380/// @param x - offset from start of array slice at given lod.381/// @param array - array slice index382/// @param lod - lod index383/// @param pState - surface state384/// @param xOffsetBytes - output offset in bytes.385template<bool UseCachedOffsets>386INLINE void ComputeSurfaceOffset1D(387uint32_t x,388uint32_t array,389uint32_t lod,390const SWR_SURFACE_STATE *pState,391uint32_t &xOffsetBytes)392{393const SWR_FORMAT_INFO &info = GetFormatInfo(pState->format);394uint32_t lodOffset;395396if (UseCachedOffsets)397{398lodOffset = pState->lodOffsets[0][lod];399}400else401{402ComputeLODOffset1D(info, pState->width, pState->halign, lod, lodOffset);403}404405xOffsetBytes = (array * pState->qpitch + lodOffset + x) * info.Bpp;406}407408//////////////////////////////////////////////////////////////////////////409/// @brief Adjusts the array slice for legacy TileY MSAA410/// @param pState - surface state411/// @param array - array slice index412/// @param sampleNum - requested sample413INLINE void AdjustCoordsForMSAA(const SWR_SURFACE_STATE *pState, uint32_t& x, uint32_t& y, uint32_t& arrayIndex, uint32_t sampleNum)414{415/// @todo: might want to templatize adjusting for sample slices when we support tileYS/tileYF.416if((pState->tileMode == SWR_TILE_MODE_YMAJOR ||417pState->tileMode == SWR_TILE_MODE_WMAJOR) &&418pState->bInterleavedSamples)419{420uint32_t newX, newY, newSampleX, newSampleY;421switch(pState->numSamples)422{423case 1:424newX = x;425newY = y;426newSampleX = newSampleY = 0;427break;428case 2:429{430assert(pState->type == SURFACE_2D);431static const uint32_t xMask = 0xFFFFFFFD;432static const uint32_t sampleMaskX = 0x1;433newX = pdep_u32(x, xMask);434newY = y;435newSampleX = pext_u32(sampleNum, sampleMaskX);436newSampleY = 0;437}438break;439case 4:440{441assert(pState->type == SURFACE_2D);442static const uint32_t mask = 0xFFFFFFFD;443static const uint32_t sampleMaskX = 0x1;444static const uint32_t sampleMaskY = 0x2;445newX = pdep_u32(x, mask);446newY = pdep_u32(y, mask);447newSampleX = pext_u32(sampleNum, sampleMaskX);448newSampleY = pext_u32(sampleNum, sampleMaskY);449}450break;451case 8:452{453assert(pState->type == SURFACE_2D);454static const uint32_t xMask = 0xFFFFFFF9;455static const uint32_t yMask = 0xFFFFFFFD;456static const uint32_t sampleMaskX = 0x5;457static const uint32_t sampleMaskY = 0x2;458newX = pdep_u32(x, xMask);459newY = pdep_u32(y, yMask);460newSampleX = pext_u32(sampleNum, sampleMaskX);461newSampleY = pext_u32(sampleNum, sampleMaskY);462}463break;464case 16:465{466assert(pState->type == SURFACE_2D);467static const uint32_t mask = 0xFFFFFFF9;468static const uint32_t sampleMaskX = 0x5;469static const uint32_t sampleMaskY = 0xA;470newX = pdep_u32(x, mask);471newY = pdep_u32(y, mask);472newSampleX = pext_u32(sampleNum, sampleMaskX);473newSampleY = pext_u32(sampleNum, sampleMaskY);474}475break;476default:477assert(0 && "Unsupported sample count");478newX = newY = 0;479newSampleX = newSampleY = 0;480break;481}482x = newX | (newSampleX << 1);483y = newY | (newSampleY << 1);484}485else if(pState->tileMode == SWR_TILE_MODE_YMAJOR ||486pState->tileMode == SWR_TILE_NONE)487{488uint32_t sampleShift;489switch(pState->numSamples)490{491case 1:492assert(sampleNum == 0);493sampleShift = 0;494break;495case 2:496assert(pState->type == SURFACE_2D);497sampleShift = 1;498break;499case 4:500assert(pState->type == SURFACE_2D);501sampleShift = 2;502break;503case 8:504assert(pState->type == SURFACE_2D);505sampleShift = 3;506break;507case 16:508assert(pState->type == SURFACE_2D);509sampleShift = 4;510break;511default:512assert(0 && "Unsupported sample count");513sampleShift = 0;514break;515}516arrayIndex = (arrayIndex << sampleShift) | sampleNum;517}518}519520//////////////////////////////////////////////////////////////////////////521/// @brief Computes 2D surface offset522/// @param x - horizontal offset from start of array slice and lod.523/// @param y - vertical offset from start of array slice and lod.524/// @param array - array slice index525/// @param lod - lod index526/// @param pState - surface state527/// @param xOffsetBytes - output x offset in bytes.528/// @param yOffsetRows - output y offset in bytes.529template<bool UseCachedOffsets>530INLINE void ComputeSurfaceOffset2D(uint32_t x, uint32_t y, uint32_t array, uint32_t sampleNum, uint32_t lod, const SWR_SURFACE_STATE *pState, uint32_t &xOffsetBytes, uint32_t &yOffsetRows)531{532const SWR_FORMAT_INFO &info = GetFormatInfo(pState->format);533uint32_t lodOffsetX, lodOffsetY;534535if (UseCachedOffsets)536{537lodOffsetX = pState->lodOffsets[0][lod];538lodOffsetY = pState->lodOffsets[1][lod];539}540else541{542ComputeLODOffsetX(info, pState->width, pState->halign, lod, lodOffsetX);543ComputeLODOffsetY(info, pState->height, pState->valign, lod, lodOffsetY);544}545546AdjustCoordsForMSAA(pState, x, y, array, sampleNum);547xOffsetBytes = (x + lodOffsetX + pState->xOffset) * info.Bpp;548yOffsetRows = (array * pState->qpitch) + lodOffsetY + y + pState->yOffset;549}550551//////////////////////////////////////////////////////////////////////////552/// @brief Computes 3D surface offset553/// @param x - horizontal offset from start of array slice and lod.554/// @param y - vertical offset from start of array slice and lod.555/// @param z - depth offset from start of array slice and lod.556/// @param lod - lod index557/// @param pState - surface state558/// @param xOffsetBytes - output x offset in bytes.559/// @param yOffsetRows - output y offset in rows.560/// @param zOffsetSlices - output y offset in slices.561template<bool UseCachedOffsets>562INLINE void ComputeSurfaceOffset3D(uint32_t x, uint32_t y, uint32_t z, uint32_t lod, const SWR_SURFACE_STATE *pState, uint32_t &xOffsetBytes, uint32_t &yOffsetRows, uint32_t &zOffsetSlices)563{564const SWR_FORMAT_INFO &info = GetFormatInfo(pState->format);565uint32_t lodOffsetX, lodOffsetY;566567if (UseCachedOffsets)568{569lodOffsetX = pState->lodOffsets[0][lod];570lodOffsetY = pState->lodOffsets[1][lod];571}572else573{574ComputeLODOffsetX(info, pState->width, pState->halign, lod, lodOffsetX);575ComputeLODOffsetY(info, pState->height, pState->valign, lod, lodOffsetY);576}577578xOffsetBytes = (x + lodOffsetX) * info.Bpp;579yOffsetRows = lodOffsetY + y;580zOffsetSlices = z;581}582583//////////////////////////////////////////////////////////////////////////584/// @brief Swizzles the linear x,y offsets depending on surface tiling mode585/// and returns final surface address586/// @param xOffsetBytes - x offset from base of surface in bytes587/// @param yOffsetRows - y offset from base of surface in rows588/// @param pState - pointer to the surface state589template<typename TTraits>590INLINE uint32_t ComputeTileSwizzle2D(uint32_t xOffsetBytes, uint32_t yOffsetRows, const SWR_SURFACE_STATE *pState)591{592return ComputeOffset2D<TTraits>(pState->pitch, xOffsetBytes, yOffsetRows);593}594595//////////////////////////////////////////////////////////////////////////596/// @brief Swizzles the linear x,y offsets depending on surface tiling mode597/// and returns final surface address598/// @param xOffsetBytes - x offset from base of surface in bytes599/// @param yOffsetRows - y offset from base of surface in rows600/// @param pState - pointer to the surface state601template<typename TTraits>602INLINE uint32_t ComputeTileSwizzle3D(uint32_t xOffsetBytes, uint32_t yOffsetRows, uint32_t zOffsetSlices, const SWR_SURFACE_STATE *pState)603{604return ComputeOffset3D<TTraits>(pState->qpitch, pState->pitch, xOffsetBytes, yOffsetRows, zOffsetSlices);605}606607//////////////////////////////////////////////////////////////////////////608/// @brief Swizzles the linear x,y offsets depending on surface tiling mode609/// and returns final surface address610/// @param xOffsetBytes - x offset from base of surface in bytes611/// @param yOffsetRows - y offset from base of surface in rows612/// @param pState - pointer to the surface state613INLINE614uint32_t TileSwizzle2D(uint32_t xOffsetBytes, uint32_t yOffsetRows, const SWR_SURFACE_STATE *pState)615{616switch (pState->tileMode)617{618case SWR_TILE_NONE: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_NONE, 32> >(xOffsetBytes, yOffsetRows, pState);619case SWR_TILE_SWRZ: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_SWRZ, 32> >(xOffsetBytes, yOffsetRows, pState);620case SWR_TILE_MODE_XMAJOR: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_MODE_XMAJOR, 8> >(xOffsetBytes, yOffsetRows, pState);621case SWR_TILE_MODE_YMAJOR: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_MODE_YMAJOR, 32> >(xOffsetBytes, yOffsetRows, pState);622case SWR_TILE_MODE_WMAJOR: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_MODE_WMAJOR, 8> >(xOffsetBytes, yOffsetRows, pState);623default: SWR_INVALID("Unsupported tiling mode");624}625return 0;626}627628//////////////////////////////////////////////////////////////////////////629/// @brief Swizzles the linear x,y,z offsets depending on surface tiling mode630/// and returns final surface address631/// @param xOffsetBytes - x offset from base of surface in bytes632/// @param yOffsetRows - y offset from base of surface in rows633/// @param zOffsetSlices - z offset from base of surface in slices634/// @param pState - pointer to the surface state635INLINE636uint32_t TileSwizzle3D(uint32_t xOffsetBytes, uint32_t yOffsetRows, uint32_t zOffsetSlices, const SWR_SURFACE_STATE *pState)637{638switch (pState->tileMode)639{640case SWR_TILE_NONE: return ComputeTileSwizzle3D<TilingTraits<SWR_TILE_NONE, 32> >(xOffsetBytes, yOffsetRows, zOffsetSlices, pState);641case SWR_TILE_SWRZ: return ComputeTileSwizzle3D<TilingTraits<SWR_TILE_SWRZ, 32> >(xOffsetBytes, yOffsetRows, zOffsetSlices, pState);642case SWR_TILE_MODE_YMAJOR: return ComputeTileSwizzle3D<TilingTraits<SWR_TILE_MODE_YMAJOR, 32> >(xOffsetBytes, yOffsetRows, zOffsetSlices, pState);643default: SWR_INVALID("Unsupported tiling mode");644}645return 0;646}647648template<bool UseCachedOffsets>649INLINE650uint32_t ComputeSurfaceOffset(uint32_t x, uint32_t y, uint32_t z, uint32_t array, uint32_t sampleNum, uint32_t lod, const SWR_SURFACE_STATE *pState)651{652uint32_t offsetX = 0, offsetY = 0, offsetZ = 0;653switch (pState->type)654{655case SURFACE_BUFFER:656case SURFACE_STRUCTURED_BUFFER:657offsetX = x * pState->pitch;658return offsetX;659break;660case SURFACE_1D:661ComputeSurfaceOffset1D<UseCachedOffsets>(x, array, lod, pState, offsetX);662return TileSwizzle2D(offsetX, 0, pState);663break;664case SURFACE_2D:665ComputeSurfaceOffset2D<UseCachedOffsets>(x, y, array, sampleNum, lod, pState, offsetX, offsetY);666return TileSwizzle2D(offsetX, offsetY, pState);667case SURFACE_3D:668ComputeSurfaceOffset3D<UseCachedOffsets>(x, y, z, lod, pState, offsetX, offsetY, offsetZ);669return TileSwizzle3D(offsetX, offsetY, offsetZ, pState);670break;671case SURFACE_CUBE:672ComputeSurfaceOffset2D<UseCachedOffsets>(x, y, array, sampleNum, lod, pState, offsetX, offsetY);673return TileSwizzle2D(offsetX, offsetY, pState);674break;675default: SWR_INVALID("Unsupported format");676}677678return 0;679}680681typedef void*(*PFN_COMPUTESURFADDR)(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, const SWR_SURFACE_STATE*);682683//////////////////////////////////////////////////////////////////////////684/// @brief Computes surface address at the given location and lod685/// @param x - x location in pixels686/// @param y - y location in rows687/// @param z - z location for 3D surfaces688/// @param array - array slice for 1D and 2D surfaces689/// @param lod - level of detail690/// @param pState - pointer to the surface state691template<bool UseCachedOffsets, bool IsRead>692INLINE693void* ComputeSurfaceAddress(uint32_t x, uint32_t y, uint32_t z, uint32_t array, uint32_t sampleNum, uint32_t lod, const SWR_SURFACE_STATE *pState)694{695return (void*)(pState->xpBaseAddress + ComputeSurfaceOffset<UseCachedOffsets>(x, y, z, array, sampleNum, lod, pState));696}697698699