yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1// cpu-resource-views.cpp 2#include "cpu-resource-views.h" 3 4namespace gfx 5{ 6using namespace Slang ; 7 8namespace cpu 9{ 10 11ResourceViewImpl ::ResourceViewImpl (Kind kind ,Desc const & desc ) 12 :m_kind (kind ) 13{ 14m_desc = desc ; 15} 16 17BufferResourceImpl * BufferResourceViewImpl ::getBuffer ()const 18{ 19return m_buffer ; 20} 21 22TextureResourceImpl * TextureResourceViewImpl ::getTexture ()const 23{ 24return m_texture ; 25} 26 27slang_prelude::TextureDimensions TextureResourceViewImpl ::GetDimensions (int mipLevel ) 28{ 29 slang_prelude::TextureDimensions dimensions = {}; 30 31TextureResourceImpl * texture = m_texture ; 32auto & desc = texture -> _getDesc (); 33auto baseShape = texture -> m_baseShape ; 34 35dimensions .arrayElementCount = desc .arraySize ; 36dimensions .numberOfLevels = desc .numMipLevels ; 37dimensions .shape = baseShape -> rank ; 38dimensions .width = desc .size .width ; 39dimensions .height = desc .size .height ; 40dimensions .depth = desc .size .depth ; 41 42return dimensions ; 43} 44 45void TextureResourceViewImpl ::Load (const int32_t * texelCoords ,void * outData ,size_t dataSize ) 46{ 47void * texelPtr = _getTexelPtr (texelCoords ); 48 49m_texture -> m_formatInfo -> unpackFunc (texelPtr ,outData ,dataSize ); 50} 51 52void TextureResourceViewImpl ::Sample ( 53 slang_prelude::SamplerState samplerState , 54const float * coords , 55void * outData , 56size_t dataSize ) 57{ 58// We have no access to information from fragment quads, so we cannot 59// compute the finite-difference derivatives needed from `coords`. 60// 61// The only reasonable thing to do is to sample mip level zero. 62// 63SampleLevel (samplerState ,coords ,0.0f ,outData ,dataSize ); 64} 65 66void TextureResourceViewImpl ::SampleLevel ( 67 slang_prelude::SamplerState samplerState , 68const float * coords , 69float level , 70void * outData , 71size_t dataSize ) 72{ 73TextureResourceImpl * texture = m_texture ; 74auto baseShape = texture -> m_baseShape ; 75auto & desc = texture -> _getDesc (); 76int32_t rank = baseShape -> rank ; 77int32_t baseCoordCount = baseShape -> baseCoordCount ; 78 79int32_t integerMipLevel = int32_t (level + 0.5f ); 80if (integerMipLevel >=desc .numMipLevels ) 81integerMipLevel = desc .numMipLevels - 1 ; 82if (integerMipLevel < 0 ) 83integerMipLevel = 0 ; 84 85auto & mipLevelInfo = texture -> m_mipLevels [integerMipLevel ]; 86 87bool isArray = (desc .arraySize != 0 )|| (desc .type == ITextureResource ::Type ::TextureCube ); 88int32_t effectiveArrayElementCount = texture -> m_effectiveArrayElementCount ; 89int32_t coordIndex = baseCoordCount ; 90int32_t elementIndex = 0 ; 91if (isArray ) 92 { 93elementIndex = int32_t (coords [coordIndex ++ ]+ 0.5f ); 94 } 95if (elementIndex >=effectiveArrayElementCount ) 96elementIndex = effectiveArrayElementCount - 1 ; 97if (elementIndex < 0 ) 98elementIndex = 0 ; 99 100// Note: for now we are just going to do nearest-neighbor sampling 101// 102int64_t texelOffset = mipLevelInfo .offset ; 103texelOffset += elementIndex * mipLevelInfo .strides [3 ]; 104for (int32_t axis = 0 ;axis < rank ;++ axis ) 105 { 106int32_t extent = mipLevelInfo .extents [axis ]; 107 108float coord = coords [axis ]; 109 110// TODO: deal with wrap/clamp/repeat if `coord < 0` or `coord > 1` 111 112int32_t integerCoord = int32_t (coord * (extent - 1 )+ 0.5f ); 113 114if (integerCoord >=extent ) 115integerCoord = extent - 1 ; 116if (integerCoord < 0 ) 117integerCoord = 0 ; 118 119texelOffset += integerCoord * mipLevelInfo .strides [axis ]; 120 } 121 122auto texelPtr = (char const * )texture -> m_data + texelOffset ; 123 124m_texture -> m_formatInfo -> unpackFunc (texelPtr ,outData ,dataSize ); 125} 126 127void * TextureResourceViewImpl ::refAt (const uint32_t * texelCoords ) 128{ 129return _getTexelPtr ((int32_t const * )texelCoords ); 130} 131 132void * TextureResourceViewImpl ::_getTexelPtr (int32_t const * texelCoords ) 133{ 134TextureResourceImpl * texture = m_texture ; 135auto baseShape = texture -> m_baseShape ; 136auto & desc = texture -> _getDesc (); 137 138int32_t rank = baseShape -> rank ; 139int32_t baseCoordCount = baseShape -> baseCoordCount ; 140 141bool isArray = (desc .arraySize != 0 )|| (desc .type == ITextureResource ::Type ::TextureCube ); 142bool isMultisample = desc .sampleDesc .numSamples > 1 ; 143bool isBuffer = desc .type == ITextureResource ::Type ::Buffer ; 144bool hasMipLevels = !(isMultisample || isBuffer ); 145 146int32_t effectiveArrayElementCount = texture -> m_effectiveArrayElementCount ; 147 148int32_t coordIndex = baseCoordCount ; 149int32_t elementIndex = 0 ; 150if (isArray ) 151 { 152elementIndex = texelCoords [coordIndex ++ ]; 153 } 154if (elementIndex >=effectiveArrayElementCount ) 155elementIndex = effectiveArrayElementCount - 1 ; 156if (elementIndex < 0 ) 157elementIndex = 0 ; 158 159int32_t mipLevel = 0 ; 160if (!hasMipLevels ) 161 { 162mipLevel = texelCoords [coordIndex ++ ]; 163 } 164if (mipLevel >=desc .numMipLevels ) 165mipLevel = desc .numMipLevels - 1 ; 166if (mipLevel < 0 ) 167mipLevel = 0 ; 168 169auto & mipLevelInfo = texture -> m_mipLevels [mipLevel ]; 170 171int64_t texelOffset = mipLevelInfo .offset ; 172texelOffset += elementIndex * mipLevelInfo .strides [3 ]; 173for (int32_t axis = 0 ;axis < rank ;++ axis ) 174 { 175int32_t coord = texelCoords [axis ]; 176if (coord >=mipLevelInfo .extents [axis ]) 177coord = mipLevelInfo .extents [axis ]- 1 ; 178if (coord < 0 ) 179coord = 0 ; 180 181texelOffset += texelCoords [axis ]* mipLevelInfo .strides [axis ]; 182 } 183 184return (char * )texture -> m_data + texelOffset ; 185} 186 187}// namespace cpu 188}// namespace gfx