yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
9.5 KiB317 linesraw
1// cpu-device.cpp
2#include "cpu-device.h"
3
4#include "cpu-buffer.h"
5#include "cpu-pipeline-state.h"
6#include "cpu-query.h"
7#include "cpu-resource-views.h"
8#include "cpu-shader-object.h"
9#include "cpu-shader-program.h"
10#include "cpu-texture.h"
11
12#include <chrono>
13
14namespace gfx
15{
16using namespace Slang;
17
18namespace cpu
19{
20DeviceImpl::~DeviceImpl()
21{
22    m_currentPipeline = nullptr;
23    m_currentRootObject = nullptr;
24}
25
26SLANG_NO_THROW Result SLANG_MCALL DeviceImpl::initialize(const Desc& desc)
27{
28    SLANG_RETURN_ON_FAIL(slangContext.initialize(
29        desc.slang,
30        desc.extendedDescCount,
31        desc.extendedDescs,
32        SLANG_SHADER_HOST_CALLABLE,
33        "sm_5_1",
34        makeArray(slang::PreprocessorMacroDesc{"__CPU__", "1"}).getView()));
35
36    SLANG_RETURN_ON_FAIL(RendererBase::initialize(desc));
37
38    // Initialize DeviceInfo
39    {
40        m_info.deviceType = DeviceType::CPU;
41        m_info.bindingStyle = BindingStyle::CUDA;
42        m_info.projectionStyle = ProjectionStyle::DirectX;
43        m_info.apiName = "CPU";
44        static const float kIdentity[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
45        ::memcpy(m_info.identityProjectionMatrix, kIdentity, sizeof(kIdentity));
46        m_info.adapterName = "CPU";
47        m_info.timestampFrequency = 1000000000;
48    }
49
50    // Can support pointers (or something akin to that)
51    {
52        m_features.add("has-ptr");
53    }
54
55    return SLANG_OK;
56}
57
58SLANG_NO_THROW Result SLANG_MCALL DeviceImpl::createTextureResource(
59    const ITextureResource::Desc& desc,
60    const ITextureResource::SubresourceData* initData,
61    ITextureResource** outResource)
62{
63    TextureResource::Desc srcDesc = fixupTextureDesc(desc);
64
65    RefPtr<TextureResourceImpl> texture = new TextureResourceImpl(srcDesc);
66
67    SLANG_RETURN_ON_FAIL(texture->init(initData));
68
69    returnComPtr(outResource, texture);
70    return SLANG_OK;
71}
72
73SLANG_NO_THROW Result SLANG_MCALL DeviceImpl::createBufferResource(
74    const IBufferResource::Desc& descIn,
75    const void* initData,
76    IBufferResource** outResource)
77{
78    auto desc = fixupBufferDesc(descIn);
79    RefPtr<BufferResourceImpl> resource = new BufferResourceImpl(desc);
80    SLANG_RETURN_ON_FAIL(resource->init());
81    if (initData)
82    {
83        SLANG_RETURN_ON_FAIL(resource->setData(0, desc.sizeInBytes, initData));
84    }
85    returnComPtr(outResource, resource);
86    return SLANG_OK;
87}
88
89SLANG_NO_THROW Result SLANG_MCALL DeviceImpl::createTextureView(
90    ITextureResource* inTexture,
91    IResourceView::Desc const& desc,
92    IResourceView** outView)
93{
94    auto texture = static_cast<TextureResourceImpl*>(inTexture);
95    RefPtr<TextureResourceViewImpl> view = new TextureResourceViewImpl(desc, texture);
96    returnComPtr(outView, view);
97    return SLANG_OK;
98}
99
100SLANG_NO_THROW Result SLANG_MCALL DeviceImpl::createBufferView(
101    IBufferResource* inBuffer,
102    IBufferResource* counterBuffer,
103    IResourceView::Desc const& desc,
104    IResourceView** outView)
105{
106    auto buffer = static_cast<BufferResourceImpl*>(inBuffer);
107    RefPtr<BufferResourceViewImpl> view = new BufferResourceViewImpl(desc, buffer);
108    returnComPtr(outView, view);
109    return SLANG_OK;
110}
111
112Result DeviceImpl::createShaderObjectLayout(
113    slang::ISession* session,
114    slang::TypeLayoutReflection* typeLayout,
115    ShaderObjectLayoutBase** outLayout)
116{
117    RefPtr<ShaderObjectLayoutImpl> cpuLayout =
118        new ShaderObjectLayoutImpl(this, session, typeLayout);
119    returnRefPtrMove(outLayout, cpuLayout);
120
121    return SLANG_OK;
122}
123
124Result DeviceImpl::createShaderObject(ShaderObjectLayoutBase* layout, IShaderObject** outObject)
125{
126    auto cpuLayout = static_cast<ShaderObjectLayoutImpl*>(layout);
127
128    RefPtr<ShaderObjectImpl> result = new ShaderObjectImpl();
129    SLANG_RETURN_ON_FAIL(result->init(this, cpuLayout));
130    returnComPtr(outObject, result);
131
132    return SLANG_OK;
133}
134
135Result DeviceImpl::createMutableShaderObject(
136    ShaderObjectLayoutBase* layout,
137    IShaderObject** outObject)
138{
139    auto cpuLayout = static_cast<ShaderObjectLayoutImpl*>(layout);
140
141    RefPtr<MutableShaderObjectImpl> result = new MutableShaderObjectImpl();
142    SLANG_RETURN_ON_FAIL(result->init(this, cpuLayout));
143    returnComPtr(outObject, result);
144
145    return SLANG_OK;
146}
147
148Result DeviceImpl::createRootShaderObject(IShaderProgram* program, ShaderObjectBase** outObject)
149{
150    auto cpuProgram = static_cast<ShaderProgramImpl*>(program);
151    auto cpuProgramLayout = cpuProgram->layout;
152
153    RefPtr<RootShaderObjectImpl> result = new RootShaderObjectImpl();
154    SLANG_RETURN_ON_FAIL(result->init(this, cpuProgramLayout));
155    returnRefPtrMove(outObject, result);
156    return SLANG_OK;
157}
158
159SLANG_NO_THROW Result SLANG_MCALL DeviceImpl::createProgram(
160    const IShaderProgram::Desc& desc,
161    IShaderProgram** outProgram,
162    ISlangBlob** outDiagnosticBlob)
163{
164    RefPtr<ShaderProgramImpl> cpuProgram = new ShaderProgramImpl();
165    cpuProgram->init(desc);
166    auto slangGlobalScope = cpuProgram->linkedProgram;
167    if (slangGlobalScope)
168    {
169        auto slangProgramLayout = slangGlobalScope->getLayout();
170        if (!slangProgramLayout)
171            return SLANG_FAIL;
172
173        RefPtr<RootShaderObjectLayoutImpl> cpuProgramLayout = new RootShaderObjectLayoutImpl(
174            this,
175            slangGlobalScope->getSession(),
176            slangProgramLayout);
177        cpuProgramLayout->m_programLayout = slangProgramLayout;
178
179        cpuProgram->layout = cpuProgramLayout;
180    }
181
182    returnComPtr(outProgram, cpuProgram);
183    return SLANG_OK;
184}
185
186SLANG_NO_THROW Result SLANG_MCALL DeviceImpl::createComputePipelineState(
187    const ComputePipelineStateDesc& desc,
188    IPipelineState** outState)
189{
190    RefPtr<PipelineStateImpl> state = new PipelineStateImpl();
191    state->init(desc);
192    returnComPtr(outState, state);
193    return Result();
194}
195
196SLANG_NO_THROW Result SLANG_MCALL
197DeviceImpl::createQueryPool(const IQueryPool::Desc& desc, IQueryPool** outPool)
198{
199    RefPtr<QueryPoolImpl> pool = new QueryPoolImpl();
200    pool->init(desc);
201    returnComPtr(outPool, pool);
202    return SLANG_OK;
203}
204
205void DeviceImpl::writeTimestamp(IQueryPool* pool, GfxIndex index)
206{
207    static_cast<QueryPoolImpl*>(pool)->m_queries[index] =
208        std::chrono::high_resolution_clock::now().time_since_epoch().count();
209}
210
211SLANG_NO_THROW const DeviceInfo& SLANG_MCALL DeviceImpl::getDeviceInfo() const
212{
213    return m_info;
214}
215
216SLANG_NO_THROW Result SLANG_MCALL
217DeviceImpl::createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler)
218{
219    SLANG_UNUSED(desc);
220    *outSampler = nullptr;
221    return SLANG_OK;
222}
223
224void* DeviceImpl::map(IBufferResource* buffer, MapFlavor flavor)
225{
226    SLANG_UNUSED(flavor);
227    auto bufferImpl = static_cast<BufferResourceImpl*>(buffer);
228    return bufferImpl->m_data;
229}
230void DeviceImpl::unmap(IBufferResource* buffer, size_t offsetWritten, size_t sizeWritten)
231{
232    SLANG_UNUSED(buffer);
233    SLANG_UNUSED(offsetWritten);
234    SLANG_UNUSED(sizeWritten);
235}
236
237void DeviceImpl::setPipelineState(IPipelineState* state)
238{
239    m_currentPipeline = static_cast<PipelineStateImpl*>(state);
240}
241
242void DeviceImpl::bindRootShaderObject(IShaderObject* object)
243{
244    m_currentRootObject = static_cast<RootShaderObjectImpl*>(object);
245}
246
247void DeviceImpl::dispatchCompute(int x, int y, int z)
248{
249    int entryPointIndex = 0;
250    int targetIndex = 0;
251
252    // Specialize the compute kernel based on the shader object bindings.
253    RefPtr<PipelineStateBase> newPipeline;
254    maybeSpecializePipeline(m_currentPipeline, m_currentRootObject, newPipeline);
255    m_currentPipeline = static_cast<PipelineStateImpl*>(newPipeline.Ptr());
256
257    auto program = m_currentPipeline->getProgram();
258    auto entryPointLayout = m_currentRootObject->getLayout()->getEntryPoint(entryPointIndex);
259    auto entryPointName = entryPointLayout->getEntryPointName();
260
261    auto entryPointObject = m_currentRootObject->getEntryPoint(entryPointIndex);
262
263    ComPtr<ISlangSharedLibrary> sharedLibrary;
264    ComPtr<ISlangBlob> diagnostics;
265    auto compileResult = program->slangGlobalScope->getEntryPointHostCallable(
266        entryPointIndex,
267        targetIndex,
268        sharedLibrary.writeRef(),
269        diagnostics.writeRef());
270    if (diagnostics)
271    {
272        getDebugCallback()->handleMessage(
273            compileResult == SLANG_OK ? DebugMessageType::Warning : DebugMessageType::Error,
274            DebugMessageSource::Slang,
275            (char*)diagnostics->getBufferPointer());
276    }
277    if (SLANG_FAILED(compileResult))
278        return;
279
280    auto func = (slang_prelude::ComputeFunc)sharedLibrary->findSymbolAddressByName(entryPointName);
281
282    slang_prelude::ComputeVaryingInput varyingInput;
283    varyingInput.startGroupID.x = 0;
284    varyingInput.startGroupID.y = 0;
285    varyingInput.startGroupID.z = 0;
286    varyingInput.endGroupID.x = x;
287    varyingInput.endGroupID.y = y;
288    varyingInput.endGroupID.z = z;
289
290    auto globalParamsData = m_currentRootObject->getDataBuffer();
291    auto entryPointParamsData = entryPointObject->getDataBuffer();
292    func(&varyingInput, entryPointParamsData, globalParamsData);
293}
294
295void DeviceImpl::copyBuffer(
296    IBufferResource* dst,
297    size_t dstOffset,
298    IBufferResource* src,
299    size_t srcOffset,
300    size_t size)
301{
302    auto dstImpl = static_cast<BufferResourceImpl*>(dst);
303    auto srcImpl = static_cast<BufferResourceImpl*>(src);
304    memcpy((uint8_t*)dstImpl->m_data + dstOffset, (uint8_t*)srcImpl->m_data + srcOffset, size);
305}
306
307} // namespace cpu
308
309Result SLANG_MCALL createCPUDevice(const IDevice::Desc* desc, IDevice** outDevice)
310{
311    RefPtr<cpu::DeviceImpl> result = new cpu::DeviceImpl();
312    SLANG_RETURN_ON_FAIL(result->initialize(*desc));
313    returnComPtr(outDevice, result);
314    return SLANG_OK;
315}
316
317} // namespace gfx