yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
4.3 KiB158 linesraw
1// metal-swap-chain.cpp
2#include "metal-swap-chain.h"
3
4#include "../apple/cocoa-util.h"
5#include "metal-util.h"
6
7namespace gfx
8{
9
10using namespace Slang;
11
12namespace metal
13{
14
15ISwapchain* SwapchainImpl::getInterface(const Guid& guid)
16{
17    if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
18        return static_cast<ISwapchain*>(this);
19    return nullptr;
20}
21
22void SwapchainImpl::getWindowSize(int& widthOut, int& heightOut) const
23{
24    CocoaUtil::getNSWindowContentSize((void*)m_windowHandle.handleValues[0], &widthOut, &heightOut);
25}
26
27void SwapchainImpl::createImages()
28{
29    m_images.setCount(m_desc.imageCount);
30    for (GfxCount i = 0; i < m_desc.imageCount; ++i)
31    {
32        ITextureResource::Desc imageDesc = {};
33        imageDesc.allowedStates = ResourceStateSet(
34            ResourceState::Present,
35            ResourceState::RenderTarget,
36            ResourceState::CopyDestination,
37            ResourceState::CopySource);
38        imageDesc.type = IResource::Type::Texture2D;
39        imageDesc.arraySize = 0;
40        imageDesc.format = m_desc.format;
41        imageDesc.size.width = m_desc.width;
42        imageDesc.size.height = m_desc.height;
43        imageDesc.size.depth = 1;
44        imageDesc.numMipLevels = 1;
45        imageDesc.defaultState = ResourceState::Present;
46        m_device->createTextureResource(
47            imageDesc,
48            nullptr,
49            (gfx::ITextureResource**)m_images[i].writeRef());
50    }
51}
52
53SwapchainImpl::~SwapchainImpl()
54{
55    m_images.clear();
56    CocoaUtil::destroyMetalLayer(m_metalLayer);
57}
58
59Result SwapchainImpl::init(DeviceImpl* device, const ISwapchain::Desc& desc, WindowHandle window)
60{
61    m_device = device;
62    m_desc = desc;
63    m_windowHandle = window;
64    m_metalFormat = MetalUtil::translatePixelFormat(desc.format);
65    m_currentImageIndex = -1;
66
67    getWindowSize(m_desc.width, m_desc.height);
68
69    m_metalLayer = (CA::MetalLayer*)CocoaUtil::createMetalLayer((void*)window.handleValues[0]);
70    if (!m_metalLayer)
71    {
72        return SLANG_FAIL;
73    }
74    m_metalLayer->setPixelFormat(m_metalFormat);
75    m_metalLayer->setDevice(m_device->m_device.get());
76    m_metalLayer->setDrawableSize(CGSize{(float)m_desc.width, (float)m_desc.height});
77    // We need to be able to copy from a texture.
78    m_metalLayer->setFramebufferOnly(false);
79
80    createImages();
81
82    return SLANG_OK;
83}
84
85Result SwapchainImpl::getImage(GfxIndex index, ITextureResource** outResource)
86{
87    if (index < 0 || index >= m_desc.imageCount)
88        return SLANG_FAIL;
89    returnComPtr(outResource, m_images[index]);
90    return SLANG_OK;
91}
92
93Result SwapchainImpl::resize(GfxCount width, GfxCount height)
94{
95    m_currentImageIndex = -1;
96    m_currentDrawable.reset();
97    getWindowSize(m_desc.width, m_desc.height);
98    m_metalLayer->setDrawableSize(CGSize{(float)m_desc.width, (float)m_desc.height});
99    createImages();
100    return SLANG_OK;
101}
102
103Result SwapchainImpl::present()
104{
105    AUTORELEASEPOOL
106
107    if (!m_currentDrawable)
108    {
109        return SLANG_FAIL;
110    }
111
112    MTL::CommandBuffer* commandBuffer = m_device->m_commandQueue->commandBuffer();
113    MTL::BlitCommandEncoder* encoder = commandBuffer->blitCommandEncoder();
114    encoder->copyFromTexture(
115        m_images[m_currentImageIndex]->m_texture.get(),
116        m_currentDrawable->texture());
117    encoder->endEncoding();
118    commandBuffer->presentDrawable(m_currentDrawable.get());
119    commandBuffer->commit();
120    m_currentDrawable.reset();
121    return SLANG_OK;
122
123    // // TODO: Expose controls via some other means
124    // static uint32_t frameCount = 0;
125    // static uint32_t maxFrameCount = 32;
126    // ++frameCount;
127    // if (m_device->captureEnabled() && frameCount == maxFrameCount)
128    // {
129    //     MTL::CaptureManager* captureManager = MTL::CaptureManager::sharedCaptureManager();
130    //     captureManager->stopCapture();
131    //     exit(1);
132    // }
133    // return SLANG_OK;
134}
135
136int SwapchainImpl::acquireNextImage()
137{
138    AUTORELEASEPOOL
139
140    m_currentDrawable = NS::RetainPtr(m_metalLayer->nextDrawable());
141    if (m_currentDrawable)
142    {
143        m_currentImageIndex = (m_currentImageIndex + 1) % m_desc.imageCount;
144    }
145    else
146    {
147        m_currentImageIndex = -1;
148    }
149    return m_currentImageIndex;
150}
151
152Result SwapchainImpl::setFullScreenMode(bool mode)
153{
154    return SLANG_E_NOT_AVAILABLE;
155}
156
157} // namespace metal
158} // namespace gfx