yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
6.7 KiB233 linesraw
1// cpu-texture.cpp
2#include "cpu-texture.h"
3
4namespace gfx
5{
6using namespace Slang;
7
8namespace cpu
9{
10
11static CPUTextureBaseShapeInfo const* _getBaseShapeInfo(ITextureResource::Type baseShape)
12{
13    return &kCPUTextureBaseShapeInfos[(int)baseShape];
14}
15
16template<int N>
17void _unpackFloatTexel(void const* texelData, void* outData, size_t outSize)
18{
19    auto input = (float const*)texelData;
20
21    float temp[4] = {0.0f, 0.0f, 0.0f, 1.0f};
22    for (int i = 0; i < N; ++i)
23        temp[i] = input[i];
24
25    memcpy(outData, temp, outSize);
26}
27
28template<int N>
29void _unpackFloat16Texel(void const* texelData, void* outData, size_t outSize)
30{
31    auto input = (int16_t const*)texelData;
32
33    float temp[4] = {0.0f, 0.0f, 0.0f, 1.0f};
34    for (int i = 0; i < N; ++i)
35        temp[i] = HalfToFloat(input[i]);
36
37    memcpy(outData, temp, outSize);
38}
39
40static inline float _unpackUnorm8Value(uint8_t value)
41{
42    return value / 255.0f;
43}
44
45template<int N>
46void _unpackUnorm8Texel(void const* texelData, void* outData, size_t outSize)
47{
48    auto input = (uint8_t const*)texelData;
49
50    float temp[4] = {0.0f, 0.0f, 0.0f, 1.0f};
51    for (int i = 0; i < N; ++i)
52        temp[i] = _unpackUnorm8Value(input[i]);
53
54    memcpy(outData, temp, outSize);
55}
56
57void _unpackUnormBGRA8Texel(void const* texelData, void* outData, size_t outSize)
58{
59    auto input = (uint8_t const*)texelData;
60
61    float temp[4];
62    temp[0] = _unpackUnorm8Value(input[2]);
63    temp[1] = _unpackUnorm8Value(input[1]);
64    temp[2] = _unpackUnorm8Value(input[0]);
65    temp[3] = _unpackUnorm8Value(input[3]);
66
67    memcpy(outData, temp, outSize);
68}
69
70template<int N>
71void _unpackUInt16Texel(void const* texelData, void* outData, size_t outSize)
72{
73    auto input = (uint16_t const*)texelData;
74
75    uint32_t temp[4] = {0, 0, 0, 0};
76    for (int i = 0; i < N; ++i)
77        temp[i] = input[i];
78
79    memcpy(outData, temp, outSize);
80}
81
82template<int N>
83void _unpackUInt32Texel(void const* texelData, void* outData, size_t outSize)
84{
85    auto input = (uint32_t const*)texelData;
86
87    uint32_t temp[4] = {0, 0, 0, 0};
88    for (int i = 0; i < N; ++i)
89        temp[i] = input[i];
90
91    memcpy(outData, temp, outSize);
92}
93
94TextureResourceImpl::~TextureResourceImpl()
95{
96    free(m_data);
97}
98
99Result TextureResourceImpl::init(ITextureResource::SubresourceData const* initData)
100{
101    auto desc = m_desc;
102
103    // The format of the texture will determine the
104    // size of the texels we allocate.
105    //
106    // TODO: Compressed formats usually work in terms
107    // of a fixed block size, so that we cannot actually
108    // compute a simple `texelSize` like this. Instead
109    // we should be computing a `blockSize` and then
110    // a `blockExtents` value that gives the extent
111    // in texels of each block. For uncompressed formats
112    // the block extents would be 1 along each axis.
113    //
114    auto format = desc.format;
115    FormatInfo texelInfo;
116    gfxGetFormatInfo(format, &texelInfo);
117    uint32_t texelSize = uint32_t(texelInfo.blockSizeInBytes / texelInfo.pixelsPerBlock);
118    m_texelSize = texelSize;
119
120    int32_t formatBlockSize[kMaxRank] = {1, 1, 1};
121
122    auto baseShapeInfo = _getBaseShapeInfo(desc.type);
123    m_baseShape = baseShapeInfo;
124    if (!baseShapeInfo)
125        return SLANG_FAIL;
126
127    auto formatInfo = _getFormatInfo(desc.format);
128    m_formatInfo = formatInfo;
129    if (!formatInfo)
130        return SLANG_FAIL;
131
132    int32_t rank = baseShapeInfo->rank;
133    int32_t effectiveArrayElementCount = desc.arraySize ? desc.arraySize : 1;
134    effectiveArrayElementCount *= baseShapeInfo->implicitArrayElementCount;
135    m_effectiveArrayElementCount = effectiveArrayElementCount;
136
137    int32_t extents[kMaxRank];
138    extents[0] = desc.size.width;
139    extents[1] = desc.size.height;
140    extents[2] = desc.size.depth;
141
142    for (int32_t axis = rank; axis < kMaxRank; ++axis)
143        extents[axis] = 1;
144
145    int32_t levelCount = desc.numMipLevels;
146
147    m_mipLevels.setCount(levelCount);
148
149    int64_t totalDataSize = 0;
150    for (int32_t levelIndex = 0; levelIndex < levelCount; ++levelIndex)
151    {
152        auto& level = m_mipLevels[levelIndex];
153
154        for (int32_t axis = 0; axis < kMaxRank; ++axis)
155        {
156            int32_t extent = extents[axis] >> levelIndex;
157            if (extent < 1)
158                extent = 1;
159            level.extents[axis] = extent;
160        }
161
162        level.strides[0] = texelSize;
163        for (int32_t axis = 1; axis < kMaxRank + 1; ++axis)
164        {
165            level.strides[axis] = level.strides[axis - 1] * level.extents[axis - 1];
166        }
167
168        int64_t levelDataSize = texelSize;
169        levelDataSize *= effectiveArrayElementCount;
170        for (int32_t axis = 0; axis < rank; ++axis)
171            levelDataSize *= int64_t(level.extents[axis]);
172
173        level.offset = totalDataSize;
174        totalDataSize += levelDataSize;
175    }
176
177    void* textureData = malloc((size_t)totalDataSize);
178    m_data = textureData;
179
180    if (initData)
181    {
182        int32_t subResourceCounter = 0;
183        for (int32_t arrayElementIndex = 0; arrayElementIndex < effectiveArrayElementCount;
184             ++arrayElementIndex)
185        {
186            for (int32_t mipLevel = 0; mipLevel < m_desc.numMipLevels; ++mipLevel)
187            {
188                int32_t subResourceIndex = subResourceCounter++;
189
190                auto dstRowStride = m_mipLevels[mipLevel].strides[1];
191                auto dstLayerStride = m_mipLevels[mipLevel].strides[2];
192                auto dstArrayStride = m_mipLevels[mipLevel].strides[3];
193
194                auto textureRowSize = m_mipLevels[mipLevel].extents[0] * texelSize;
195
196                auto rowCount = m_mipLevels[mipLevel].extents[1];
197                auto depthLayerCount = m_mipLevels[mipLevel].extents[2];
198
199                auto& srcImage = initData[subResourceIndex];
200                ptrdiff_t srcRowStride = ptrdiff_t(srcImage.strideY);
201                ptrdiff_t srcLayerStride = ptrdiff_t(srcImage.strideZ);
202
203                char* dstLevel = (char*)textureData + m_mipLevels[mipLevel].offset;
204                char* dstImage = dstLevel + dstArrayStride * arrayElementIndex;
205
206                const char* srcLayer = (const char*)srcImage.data;
207                char* dstLayer = dstImage;
208
209                for (int32_t depthLayer = 0; depthLayer < depthLayerCount; ++depthLayer)
210                {
211                    const char* srcRow = srcLayer;
212                    char* dstRow = dstLayer;
213
214                    for (int32_t row = 0; row < rowCount; ++row)
215                    {
216                        memcpy(dstRow, srcRow, textureRowSize);
217
218                        srcRow += srcRowStride;
219                        dstRow += dstRowStride;
220                    }
221
222                    srcLayer += srcLayerStride;
223                    dstLayer += dstLayerStride;
224                }
225            }
226        }
227    }
228
229    return SLANG_OK;
230}
231
232} // namespace cpu
233} // namespace gfx