yum-mirror/slang

Making it easier to work with shaders

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

Ellie HermaszewskaCorrect include dir for libslang (#5539)7b570feed

master
6.6 KiB226 linesraw
1#include "core/slang-basic.h"
2#include "renderer-shared.h"
3
4namespace gfx
5{
6template<typename TDevice, typename TBufferResource>
7class StagingBufferPool
8{
9public:
10    struct StagingBufferPage
11    {
12        Slang::RefPtr<TBufferResource> resource;
13        size_t size;
14    };
15
16    struct Allocation
17    {
18        TBufferResource* resource;
19        size_t offset;
20    };
21
22    TDevice* m_device;
23    MemoryType m_memoryType;
24    uint32_t m_alignment;
25    ResourceStateSet m_allowedStates;
26
27    Slang::List<StagingBufferPage> m_pages;
28    Slang::List<Slang::RefPtr<TBufferResource>> m_largeAllocations;
29
30    Slang::Index m_pageAllocCounter = 0;
31    size_t m_offsetAllocCounter = 0;
32
33    const size_t kStagingBufferDefaultPageSize = 16 * 1024 * 1024;
34
35    void init(
36        TDevice* device,
37        MemoryType memoryType,
38        uint32_t alignment,
39        ResourceStateSet allowedStates)
40    {
41        m_device = device;
42        m_memoryType = memoryType;
43        m_alignment = alignment;
44        m_allowedStates = allowedStates;
45    }
46
47    static size_t alignUp(size_t value, uint32_t alignment)
48    {
49        return (value + alignment - 1) / alignment * alignment;
50    }
51
52    void reset()
53    {
54        m_pageAllocCounter = 0;
55        m_offsetAllocCounter = 0;
56        m_largeAllocations.clearAndDeallocate();
57    }
58
59    Result newStagingBufferPage()
60    {
61        StagingBufferPage page;
62        size_t pageSize = kStagingBufferDefaultPageSize;
63
64        Slang::ComPtr<IBufferResource> bufferPtr;
65        IBufferResource::Desc bufferDesc;
66        bufferDesc.type = IResource::Type::Buffer;
67        bufferDesc.defaultState = ResourceState::General;
68        bufferDesc.allowedStates = m_allowedStates;
69        bufferDesc.memoryType = m_memoryType;
70        bufferDesc.sizeInBytes = pageSize;
71        SLANG_RETURN_ON_FAIL(
72            m_device->createBufferResource(bufferDesc, nullptr, bufferPtr.writeRef()));
73
74        page.resource = static_cast<TBufferResource*>(bufferPtr.get());
75        page.size = pageSize;
76        m_pages.add(page);
77        return SLANG_OK;
78    }
79
80    Result newLargeBuffer(size_t size)
81    {
82        Slang::ComPtr<IBufferResource> bufferPtr;
83        IBufferResource::Desc bufferDesc;
84        bufferDesc.type = IResource::Type::Buffer;
85        bufferDesc.defaultState = ResourceState::General;
86        bufferDesc.allowedStates = m_allowedStates;
87        bufferDesc.memoryType = m_memoryType;
88        bufferDesc.sizeInBytes = size;
89        SLANG_RETURN_ON_FAIL(
90            m_device->createBufferResource(bufferDesc, nullptr, bufferPtr.writeRef()));
91        auto bufferImpl = static_cast<TBufferResource*>(bufferPtr.get());
92        m_largeAllocations.add(bufferImpl);
93        return SLANG_OK;
94    }
95
96    Allocation allocate(size_t size, bool forceLargePage)
97    {
98        if (forceLargePage || size >= (kStagingBufferDefaultPageSize >> 2))
99        {
100            newLargeBuffer(size);
101            Allocation result;
102            result.resource = m_largeAllocations.getLast();
103            result.offset = 0;
104            return result;
105        }
106
107        size_t bufferAllocOffset = alignUp(m_offsetAllocCounter, m_alignment);
108        Slang::Index bufferId = -1;
109        for (Slang::Index i = m_pageAllocCounter; i < m_pages.getCount(); i++)
110        {
111            auto cb = m_pages[i].resource.Ptr();
112            if (bufferAllocOffset + size <= cb->getDesc()->sizeInBytes)
113            {
114                bufferId = i;
115                break;
116            }
117            bufferAllocOffset = 0;
118        }
119        // If we cannot find an existing page with sufficient free space,
120        // create a new page.
121        if (bufferId == -1)
122        {
123            newStagingBufferPage();
124            bufferId = m_pages.getCount() - 1;
125        }
126        // Sub allocate from current page.
127        Allocation result;
128        result.resource = m_pages[bufferId].resource.Ptr();
129        result.offset = bufferAllocOffset;
130        m_pageAllocCounter = bufferId;
131        m_offsetAllocCounter = bufferAllocOffset + size;
132        return result;
133    }
134};
135
136template<typename TDevice, typename TBufferResource>
137class TransientResourceHeapBaseImpl : public TransientResourceHeapBase
138{
139public:
140    void breakStrongReferenceToDevice() { m_device.breakStrongReference(); }
141
142public:
143    BreakableReference<TDevice> m_device;
144    StagingBufferPool<TDevice, TBufferResource> m_constantBufferPool;
145    StagingBufferPool<TDevice, TBufferResource> m_uploadBufferPool;
146    StagingBufferPool<TDevice, TBufferResource> m_readbackBufferPool;
147
148    Result init(const ITransientResourceHeap::Desc& desc, uint32_t alignment, TDevice* device)
149    {
150        m_device = device;
151
152        m_constantBufferPool.init(
153            device,
154            MemoryType::Upload,
155            256,
156            ResourceStateSet(
157                ResourceState::ConstantBuffer,
158                ResourceState::CopySource,
159                ResourceState::CopyDestination));
160
161        m_uploadBufferPool.init(
162            device,
163            MemoryType::Upload,
164            256,
165            ResourceStateSet(ResourceState::CopySource, ResourceState::CopyDestination));
166
167        m_readbackBufferPool.init(
168            device,
169            MemoryType::ReadBack,
170            256,
171            ResourceStateSet(ResourceState::CopySource, ResourceState::CopyDestination));
172
173        m_version = getVersionCounter();
174        getVersionCounter()++;
175        return SLANG_OK;
176    }
177
178    Result allocateStagingBuffer(
179        size_t size,
180        IBufferResource*& outBufferWeakPtr,
181        size_t& offset,
182        MemoryType memoryType,
183        bool forceLargePage = false)
184    {
185        switch (memoryType)
186        {
187        case MemoryType::ReadBack:
188            {
189                auto allocation = m_readbackBufferPool.allocate(size, forceLargePage);
190                outBufferWeakPtr = allocation.resource;
191                offset = allocation.offset;
192            }
193            break;
194        default:
195            {
196                auto allocation = m_uploadBufferPool.allocate(size, forceLargePage);
197                outBufferWeakPtr = allocation.resource;
198                offset = allocation.offset;
199            }
200            break;
201        }
202        return SLANG_OK;
203    }
204
205    Result allocateConstantBuffer(
206        size_t size,
207        IBufferResource*& outBufferWeakPtr,
208        size_t& outOffset)
209    {
210        auto allocation = m_constantBufferPool.allocate(size, false);
211        outBufferWeakPtr = allocation.resource;
212        outOffset = allocation.offset;
213        return SLANG_OK;
214    }
215
216    void reset()
217    {
218        m_constantBufferPool.reset();
219        m_uploadBufferPool.reset();
220        m_readbackBufferPool.reset();
221        m_version = getVersionCounter();
222        getVersionCounter()++;
223    }
224};
225
226} // namespace gfx