diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/gpu-printing/main.cpp | 46 | ||||
| -rw-r--r-- | examples/hello-world/main.cpp | 52 | ||||
| -rw-r--r-- | examples/shader-object/main.cpp | 30 | ||||
| -rw-r--r-- | examples/shader-toy/main.cpp | 168 |
4 files changed, 157 insertions, 139 deletions
diff --git a/examples/gpu-printing/main.cpp b/examples/gpu-printing/main.cpp index e95233571..3fd1e460a 100644 --- a/examples/gpu-printing/main.cpp +++ b/examples/gpu-printing/main.cpp @@ -14,22 +14,9 @@ using namespace gfx; #include "gpu-printing.h" -ComPtr<slang::ISession> createSlangSession(gfx::IRenderer* renderer) +ComPtr<slang::ISession> createSlangSession(gfx::IDevice* device) { - ComPtr<slang::IGlobalSession> slangGlobalSession; - slangGlobalSession.attach(spCreateSession(NULL)); - - slang::TargetDesc targetDesc; - targetDesc.format = SLANG_DXBC; - targetDesc.profile = spFindProfile(slangGlobalSession, "sm_5_0"); - - slang::SessionDesc sessionDesc; - sessionDesc.targetCount = 1; - sessionDesc.targets = &targetDesc; - - ComPtr<slang::ISession> slangSession; - slangGlobalSession->createSession(sessionDesc, slangSession.writeRef()); - + ComPtr<slang::ISession> slangSession = device->getSlangSession(); return slangSession; } @@ -63,7 +50,7 @@ struct ExampleProgram int gWindowWidth = 640; int gWindowHeight = 480; -ComPtr<gfx::IRenderer> gRenderer; +ComPtr<gfx::IDevice> gDevice; ComPtr<slang::ISession> gSlangSession; ComPtr<slang::IModule> gSlangModule; @@ -103,19 +90,18 @@ ComPtr<gfx::IShaderProgram> loadComputeProgram(slang::IModule* slangModule, char programDesc.kernels = &kernelDescs[0]; programDesc.kernelCount = 2; - auto shaderProgram = gRenderer->createProgram(programDesc); + auto shaderProgram = gDevice->createProgram(programDesc); return shaderProgram; } Result execute() { - IRenderer::Desc rendererDesc; - rendererDesc.rendererType = gfx::RendererType::DirectX11; - Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef()); + IDevice::Desc deviceDesc; + Result res = gfxCreateDevice(&deviceDesc, gDevice.writeRef()); if(SLANG_FAILED(res)) return res; - gSlangSession = createSlangSession(gRenderer); + gSlangSession = createSlangSession(gDevice); gSlangModule = compileShaderModuleFromFile(gSlangSession, "kernels.slang"); gProgram = loadComputeProgram(gSlangModule, "computeMain"); @@ -128,7 +114,7 @@ Result execute() IDescriptorSetLayout::Desc descriptorSetLayoutDesc; descriptorSetLayoutDesc.slotRangeCount = 1; descriptorSetLayoutDesc.slotRanges = &slotRanges[0]; - auto descriptorSetLayout = gRenderer->createDescriptorSetLayout(descriptorSetLayoutDesc); + auto descriptorSetLayout = gDevice->createDescriptorSetLayout(descriptorSetLayoutDesc); if(!descriptorSetLayout) return SLANG_FAIL; IPipelineLayout::DescriptorSetDesc descriptorSets[] = @@ -139,7 +125,7 @@ Result execute() pipelineLayoutDesc.renderTargetCount = 1; pipelineLayoutDesc.descriptorSetCount = 1; pipelineLayoutDesc.descriptorSets = &descriptorSets[0]; - auto pipelineLayout = gRenderer->createPipelineLayout(pipelineLayoutDesc); + auto pipelineLayout = gDevice->createPipelineLayout(pipelineLayoutDesc); if(!pipelineLayout) return SLANG_FAIL; gPipelineLayout = pipelineLayout; @@ -147,7 +133,8 @@ Result execute() // Once we have the descriptor set layout, we can allocate // and fill in a descriptor set to hold our parameters. // - auto descriptorSet = gRenderer->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient); + auto descriptorSet = + gDevice->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient); if(!descriptorSet) return SLANG_FAIL; gDescriptorSet = descriptorSet; @@ -155,7 +142,7 @@ Result execute() ComputePipelineStateDesc desc; desc.pipelineLayout = gPipelineLayout; desc.program = gProgram; - auto pipelineState = gRenderer->createComputePipelineState(desc); + auto pipelineState = gDevice->createComputePipelineState(desc); if(!pipelineState) return SLANG_FAIL; gPipelineState = pipelineState; @@ -166,14 +153,15 @@ Result execute() printBufferDesc.init(printBufferSize); printBufferDesc.elementSize = sizeof(uint32_t); printBufferDesc.cpuAccessFlags = IResource::AccessFlag::Read; // | Resource::AccessFlag::Write; - auto printBuffer = gRenderer->createBufferResource(IResource::Usage::UnorderedAccess, printBufferDesc); + auto printBuffer = + gDevice->createBufferResource(IResource::Usage::UnorderedAccess, printBufferDesc); IResourceView::Desc printBufferViewDesc; printBufferViewDesc.type = IResourceView::Type::UnorderedAccess; - auto printBufferView = gRenderer->createBufferView(printBuffer, printBufferViewDesc); + auto printBufferView = gDevice->createBufferView(printBuffer, printBufferViewDesc); ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics}; - auto queue = gRenderer->createCommandQueue(queueDesc); + auto queue = gDevice->createCommandQueue(queueDesc); auto commandBuffer = queue->createCommandBuffer(); auto encoder = commandBuffer->encodeComputeCommands(); // TODO: need to copy a zero into the start of the print buffer! @@ -189,7 +177,7 @@ Result execute() // TODO: need to copy from the print buffer to a staging buffer... ComPtr<ISlangBlob> blob; - gRenderer->readBufferResource(printBuffer, 0, printBufferSize, blob.writeRef()); + gDevice->readBufferResource(printBuffer, 0, printBufferSize, blob.writeRef()); gGPUPrinting.processGPUPrintCommands(blob->getBufferPointer(), printBufferSize); diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp index 330b52a59..7b43abcab 100644 --- a/examples/hello-world/main.cpp +++ b/examples/hello-world/main.cpp @@ -87,7 +87,7 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) // about the program, which is what a `slang::ProgramLayout` provides. // gfx::Result loadShaderProgram( - gfx::IRenderer* renderer, + gfx::IDevice* device, gfx::IShaderProgram** outProgram) { // We need to obatin a compilation session (`slang::ISession`) that will provide @@ -96,7 +96,7 @@ gfx::Result loadShaderProgram( // Our example application uses the `gfx` graphics API abstraction layer, which already // creates a Slang compilation session for us, so we just grab and use it here. ComPtr<slang::ISession> slangSession; - slangSession = renderer->getSlangSession(); + slangSession = device->getSlangSession(); // We can now start loading code into the slang session. // @@ -182,7 +182,7 @@ gfx::Result loadShaderProgram( gfx::IShaderProgram::Desc programDesc = {}; programDesc.pipelineType = gfx::PipelineType::Graphics; programDesc.slangProgram = linkedProgram; - SLANG_RETURN_ON_FAIL(renderer->createProgram(programDesc, outProgram)); + SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); return SLANG_OK; } @@ -211,7 +211,7 @@ const uint32_t kSwapchainImageCount = 2; // building an example program. // RefPtr<platform::Window> gWindow; -Slang::ComPtr<gfx::IRenderer> gRenderer; +Slang::ComPtr<gfx::IDevice> gDevice; ComPtr<gfx::IPipelineState> gPipelineState; ComPtr<gfx::IShaderObject> gRootObject; @@ -233,6 +233,7 @@ Slang::Result initialize() windowDesc.title = "Hello, World!"; windowDesc.width = gWindowWidth; windowDesc.height = gWindowHeight; + windowDesc.style = platform::WindowStyle::FixedSize; gWindow = platform::Application::createWindow(windowDesc); gWindow->events.mainLoop = [this]() { renderFrame(); }; // Initialize the rendering layer. @@ -242,14 +243,13 @@ Slang::Result initialize() // A future version of this example may support multiple // platforms/APIs. // - IRenderer::Desc rendererDesc = {}; - rendererDesc.rendererType = gfx::RendererType::DirectX11; - gfx::Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef()); + IDevice::Desc deviceDesc = {}; + gfx::Result res = gfxCreateDevice(&deviceDesc, gDevice.writeRef()); if(SLANG_FAILED(res)) return res; ICommandQueue::Desc queueDesc = {}; queueDesc.type = ICommandQueue::QueueType::Graphics; - gQueue = gRenderer->createCommandQueue(queueDesc); + gQueue = gDevice->createCommandQueue(queueDesc); // Now we will create objects needed to configur the "input assembler" // (IA) stage of the D3D pipeline. @@ -260,7 +260,7 @@ Slang::Result initialize() { "POSITION", 0, Format::RGB_Float32, offsetof(Vertex, position) }, { "COLOR", 0, Format::RGB_Float32, offsetof(Vertex, color) }, }; - auto inputLayout = gRenderer->createInputLayout( + auto inputLayout = gDevice->createInputLayout( &inputElements[0], 2); if(!inputLayout) return SLANG_FAIL; @@ -271,7 +271,7 @@ Slang::Result initialize() IBufferResource::Desc vertexBufferDesc; vertexBufferDesc.init(kVertexCount * sizeof(Vertex)); vertexBufferDesc.setDefaults(IResource::Usage::VertexBuffer); - gVertexBuffer = gRenderer->createBufferResource( + gVertexBuffer = gDevice->createBufferResource( IResource::Usage::VertexBuffer, vertexBufferDesc, &kVertexData[0]); @@ -281,7 +281,7 @@ Slang::Result initialize() // the code from `shaders.slang` into the graphics API. // ComPtr<IShaderProgram> shaderProgram; - SLANG_RETURN_ON_FAIL(loadShaderProgram(gRenderer, shaderProgram.writeRef())); + SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, shaderProgram.writeRef())); // In order to bind shader parameters to the pipeline, we need // to know how those parameters were assigned to locations/bindings/registers @@ -312,7 +312,7 @@ Slang::Result initialize() // layout as being similar in spirit to a "root signature" or "pipeline layout." // ComPtr<IShaderObject> rootObject; - SLANG_RETURN_ON_FAIL(gRenderer->createRootShaderObject(shaderProgram, rootObject.writeRef())); + SLANG_RETURN_ON_FAIL(gDevice->createRootShaderObject(shaderProgram, rootObject.writeRef())); gRootObject = rootObject; // Create swapchain and framebuffers. @@ -324,7 +324,7 @@ Slang::Result initialize() swapchainDesc.queue = gQueue; gfx::WindowHandle windowHandle; memcpy(&windowHandle, &gWindow->getNativeHandle(), sizeof(windowHandle)); - gSwapchain = gRenderer->createSwapchain(swapchainDesc, windowHandle); + gSwapchain = gDevice->createSwapchain(swapchainDesc, windowHandle); IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1}; IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1}; @@ -334,7 +334,7 @@ Slang::Result initialize() framebufferLayoutDesc.depthStencil = &depthLayout; ComPtr<IFramebufferLayout> framebufferLayout; SLANG_RETURN_ON_FAIL( - gRenderer->createFramebufferLayout(framebufferLayoutDesc, framebufferLayout.writeRef())); + gDevice->createFramebufferLayout(framebufferLayoutDesc, framebufferLayout.writeRef())); for (uint32_t i = 0; i < kSwapchainImageCount; i++) { @@ -347,7 +347,7 @@ Slang::Result initialize() gSwapchain->getDesc().height, 0); - ComPtr<gfx::ITextureResource> depthBufferResource = gRenderer->createTextureResource( + ComPtr<gfx::ITextureResource> depthBufferResource = gDevice->createTextureResource( gfx::IResource::Usage::DepthWrite, depthBufferDesc, nullptr); ComPtr<gfx::ITextureResource> colorBuffer; gSwapchain->getImage(i, colorBuffer.writeRef()); @@ -357,21 +357,21 @@ Slang::Result initialize() colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget; ComPtr<gfx::IResourceView> rtv = - gRenderer->createTextureView(colorBuffer.get(), colorBufferViewDesc); + gDevice->createTextureView(colorBuffer.get(), colorBufferViewDesc); gfx::IResourceView::Desc depthBufferViewDesc = {}; depthBufferViewDesc.format = gfx::Format::D_Float32; depthBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; depthBufferViewDesc.type = gfx::IResourceView::Type::DepthStencil; ComPtr<gfx::IResourceView> dsv = - gRenderer->createTextureView(depthBufferResource.get(), depthBufferViewDesc); + gDevice->createTextureView(depthBufferResource.get(), depthBufferViewDesc); gfx::IFramebuffer::Desc framebufferDesc = {}; framebufferDesc.renderTargetCount = 1; framebufferDesc.depthStencilView = dsv.get(); framebufferDesc.renderTargetViews = rtv.readRef(); framebufferDesc.layout = framebufferLayout; - ComPtr<gfx::IFramebuffer> frameBuffer = gRenderer->createFramebuffer(framebufferDesc); + ComPtr<gfx::IFramebuffer> frameBuffer = gDevice->createFramebuffer(framebufferDesc); gFramebuffers.add(frameBuffer); } @@ -382,7 +382,7 @@ Slang::Result initialize() desc.inputLayout = inputLayout; desc.program = shaderProgram; desc.framebufferLayout = framebufferLayout; - auto pipelineState = gRenderer->createGraphicsPipelineState(desc); + auto pipelineState = gDevice->createGraphicsPipelineState(desc); if (!pipelineState) return SLANG_FAIL; @@ -403,7 +403,7 @@ Slang::Result initialize() depthStencilAccess.finalState = ResourceState::DepthWrite; renderPassDesc.renderTargetAccess = &renderTargetAccess; renderPassDesc.depthStencilAccess = &depthStencilAccess; - gRenderPass = gRenderer->createRenderPassLayout(renderPassDesc); + gRenderPass = gDevice->createRenderPassLayout(renderPassDesc); return SLANG_OK; } @@ -431,14 +431,7 @@ void renderFrame() // basis, even though the data that is loaded does not change // per-frame (we always use an identity matrix). // - float identityMatrix[] = - { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - }; - gfxGetIdentityProjection(gfxGetProjectionStyle(gRenderer->getRendererType()), identityMatrix); + auto deviceInfo = gDevice->getDeviceInfo(); // // We know that `gRootObject` is a root shader object created @@ -474,7 +467,8 @@ void renderFrame() // Once we have formed a cursor that "points" at the // model-view projection matrix, we can set its data directly. // - rootCursor["Uniforms"]["modelViewProjection"].setData(identityMatrix, sizeof(identityMatrix)); + rootCursor["Uniforms"]["modelViewProjection"].setData( + deviceInfo.identityProjectionMatrix, sizeof(float) * 16); // // Some readers might be concerned about the performance o // the above operations because of the use of strings. For diff --git a/examples/shader-object/main.cpp b/examples/shader-object/main.cpp index d368cd9aa..aaafc010a 100644 --- a/examples/shader-object/main.cpp +++ b/examples/shader-object/main.cpp @@ -30,7 +30,7 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) // Loads the shader code defined in `shader-object.slang` for use by the `gfx` layer. // Result loadShaderProgram( - gfx::IRenderer* renderer, + gfx::IDevice* device, ComPtr<gfx::IShaderProgram>& outShaderProgram, slang::ProgramLayout*& slangReflection) { @@ -40,7 +40,7 @@ Result loadShaderProgram( // Our example application uses the `gfx` graphics API abstraction layer, which already // creates a Slang compilation session for us, so we just grab and use it here. ComPtr<slang::ISession> slangSession; - SLANG_RETURN_ON_FAIL(renderer->getSlangSession(slangSession.writeRef())); + SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef())); // Once the session has been obtained, we can start loading code into it. // @@ -123,7 +123,7 @@ Result loadShaderProgram( programDesc.pipelineType = gfx::PipelineType::Compute; programDesc.slangProgram = composedProgram.get(); - auto shaderProgram = renderer->createProgram(programDesc); + auto shaderProgram = device->createProgram(programDesc); outShaderProgram = shaderProgram; return SLANG_OK; @@ -134,24 +134,23 @@ int main() { // Creates a `gfx` renderer, which provides the main interface for // interacting with the graphics API. - Slang::ComPtr<gfx::IRenderer> renderer; - IRenderer::Desc rendererDesc = {}; - rendererDesc.rendererType = RendererType::DirectX11; - SLANG_RETURN_ON_FAIL(gfxCreateRenderer(&rendererDesc, renderer.writeRef())); + Slang::ComPtr<gfx::IDevice> device; + IDevice::Desc deviceDesc = {}; + SLANG_RETURN_ON_FAIL(gfxCreateDevice(&deviceDesc, device.writeRef())); // Now we can load the shader code. // A `gfx::IShaderProgram` object for use in the `gfx` layer. ComPtr<gfx::IShaderProgram> shaderProgram; // A composed `IComponentType` that gives us reflection info on the shader code. slang::ProgramLayout* slangReflection; - SLANG_RETURN_ON_FAIL(loadShaderProgram(renderer, shaderProgram, slangReflection)); + SLANG_RETURN_ON_FAIL(loadShaderProgram(device, shaderProgram, slangReflection)); // Create a pipeline state with the loaded shader. gfx::ComputePipelineStateDesc pipelineDesc = {}; pipelineDesc.program = shaderProgram.get(); ComPtr<gfx::IPipelineState> pipelineState; SLANG_RETURN_ON_FAIL( - renderer->createComputePipelineState(pipelineDesc, pipelineState.writeRef())); + device->createComputePipelineState(pipelineDesc, pipelineState.writeRef())); // Create and initiate our input/output buffer. const int numberCount = 4; @@ -165,7 +164,7 @@ int main() bufferDesc.cpuAccessFlags = IResource::AccessFlag::Write | IResource::AccessFlag::Read; ComPtr<gfx::IBufferResource> numbersBuffer; - SLANG_RETURN_ON_FAIL(renderer->createBufferResource( + SLANG_RETURN_ON_FAIL(device->createBufferResource( gfx::IResource::Usage::UnorderedAccess, bufferDesc, (void*)initialData, @@ -176,7 +175,7 @@ int main() gfx::IResourceView::Desc viewDesc = {}; viewDesc.type = gfx::IResourceView::Type::UnorderedAccess; viewDesc.format = gfx::Format::Unknown; - SLANG_RETURN_ON_FAIL(renderer->createBufferView(numbersBuffer, viewDesc, bufferView.writeRef())); + SLANG_RETURN_ON_FAIL(device->createBufferView(numbersBuffer, viewDesc, bufferView.writeRef())); // Now comes the interesting part: binding the shader parameter for the // compute kernel that we about to launch. We would like to construct @@ -185,7 +184,7 @@ int main() // To start, we create a root shader object that represents the root level // scope of the shader parameters. ComPtr<gfx::IShaderObject> rootObject; - SLANG_RETURN_ON_FAIL(renderer->createRootShaderObject(shaderProgram, rootObject.writeRef())); + SLANG_RETURN_ON_FAIL(device->createRootShaderObject(shaderProgram, rootObject.writeRef())); // We can set parameters directly with `rootObject`, but that requires us to use // the Slang reflection API to obtain the proper offsets into the root object for each parameter. // We implemented these logic in the `ShaderCursor` helper class, which simplifies the user @@ -200,8 +199,7 @@ int main() // Now we can use this type to create a shader object that can be bound to the root object. ComPtr<gfx::IShaderObject> transformer; - SLANG_RETURN_ON_FAIL( - renderer->createShaderObject(addTransformerType, transformer.writeRef())); + SLANG_RETURN_ON_FAIL(device->createShaderObject(addTransformerType, transformer.writeRef())); // Set the `c` field of the `AddTransformer`. float c = 1.0f; gfx::ShaderCursor(transformer).getPath("c").setData(&c, sizeof(float)); @@ -213,7 +211,7 @@ int main() // to bind the pipeline and root object and launch the kernel. { ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics}; - auto queue = renderer->createCommandQueue(queueDesc); + auto queue = device->createCommandQueue(queueDesc); auto commandBuffer = queue->createCommandBuffer(); auto encoder = commandBuffer->encodeComputeCommands(); encoder->setPipelineState(pipelineState); @@ -226,7 +224,7 @@ int main() } // Read back the results. ComPtr<ISlangBlob> resultBlob; - SLANG_RETURN_ON_FAIL(renderer->readBufferResource( + SLANG_RETURN_ON_FAIL(device->readBufferResource( numbersBuffer, 0, numberCount * sizeof(float), resultBlob.writeRef())); auto result = reinterpret_cast<const float*>(resultBlob->getBufferPointer()); for (int i = 0; i < numberCount; i++) diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp index 7c22954c0..70bff13a8 100644 --- a/examples/shader-toy/main.cpp +++ b/examples/shader-toy/main.cpp @@ -92,7 +92,7 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) // The main interesting part of the host application code is where we // load, compile, inspect, and compose the Slang shader code. // -Result loadShaderProgram(gfx::IRenderer* renderer, ComPtr<gfx::IShaderProgram>& outShaderProgram) +Result loadShaderProgram(gfx::IDevice* device, ComPtr<gfx::IShaderProgram>& outShaderProgram) { // We need to obatin a compilation session (`slang::ISession`) that will provide // a scope to all the compilation and loading of code we do. @@ -100,7 +100,7 @@ Result loadShaderProgram(gfx::IRenderer* renderer, ComPtr<gfx::IShaderProgram>& // Our example application uses the `gfx` graphics API abstraction layer, which already // creates a Slang compilation session for us, so we just grab and use it here. ComPtr<slang::ISession> slangSession; - SLANG_RETURN_ON_FAIL(renderer->getSlangSession(slangSession.writeRef())); + SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef())); // Once the session has been obtained, we can start loading code into it. // @@ -322,7 +322,7 @@ Result loadShaderProgram(gfx::IRenderer* renderer, ComPtr<gfx::IShaderProgram>& programDesc.kernels = &kernelDescs[0]; programDesc.kernelCount = 2; - auto shaderProgram = renderer->createProgram(programDesc); + auto shaderProgram = device->createProgram(programDesc); outShaderProgram = shaderProgram; return SLANG_OK; @@ -333,9 +333,10 @@ int gWindowHeight = 768; const uint32_t kSwapchainImageCount = 2; Slang::RefPtr<platform::Window> gWindow; -Slang::ComPtr<gfx::IRenderer> gRenderer; +Slang::ComPtr<gfx::IDevice> gDevice; ComPtr<gfx::IBufferResource> gConstantBuffer; ComPtr<gfx::IPipelineLayout> gPipelineLayout; +ComPtr<gfx::IFramebufferLayout> gFramebufferLayout; ComPtr<gfx::IPipelineState> gPipelineState; ComPtr<gfx::IDescriptorSet> gDescriptorSet; ComPtr<gfx::IBufferResource> gVertexBuffer; @@ -347,7 +348,8 @@ ComPtr<gfx::ICommandQueue> gQueue; Result initialize() { platform::WindowDesc windowDesc; - windowDesc.title = "Slang Shader Toy"; + const char* title = "Slang Shader Toy"; + windowDesc.title = title; windowDesc.width = gWindowWidth; windowDesc.height = gWindowHeight; gWindow = platform::Application::createWindow(windowDesc); @@ -355,15 +357,21 @@ Result initialize() gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; + gWindow->events.sizeChanged = Slang::Action<>(this, &ShaderToyApp::windowSizeChanged); - IRenderer::Desc rendererDesc; - rendererDesc.rendererType = RendererType::DirectX11; - Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef()); + IDevice::Desc deviceDesc; + deviceDesc.deviceType = DeviceType::Vulkan; + Result res = gfxCreateDevice(&deviceDesc, gDevice.writeRef()); if(SLANG_FAILED(res)) return res; + auto deviceInfo = gDevice->getDeviceInfo(); + Slang::StringBuilder titleSb; + titleSb << title << " (" << deviceInfo.apiName << ": " << deviceInfo.adapterName << ")"; + gWindow->setText(titleSb.getBuffer()); + ICommandQueue::Desc queueDesc = {}; queueDesc.type = ICommandQueue::QueueType::Graphics; - gQueue = gRenderer->createCommandQueue(queueDesc); + gQueue = gDevice->createCommandQueue(queueDesc); int constantBufferSize = sizeof(Uniforms); @@ -372,15 +380,14 @@ Result initialize() constantBufferDesc.setDefaults(IResource::Usage::ConstantBuffer); constantBufferDesc.cpuAccessFlags = IResource::AccessFlag::Write; - gConstantBuffer = gRenderer->createBufferResource( - IResource::Usage::ConstantBuffer, - constantBufferDesc); + gConstantBuffer = + gDevice->createBufferResource(IResource::Usage::ConstantBuffer, constantBufferDesc); if(!gConstantBuffer) return SLANG_FAIL; InputElementDesc inputElements[] = { { "POSITION", 0, Format::RG_Float32, offsetof(FullScreenTriangle::Vertex, position) }, }; - auto inputLayout = gRenderer->createInputLayout( + auto inputLayout = gDevice->createInputLayout( &inputElements[0], SLANG_COUNT_OF(inputElements)); if(!inputLayout) return SLANG_FAIL; @@ -388,14 +395,14 @@ Result initialize() IBufferResource::Desc vertexBufferDesc; vertexBufferDesc.init(FullScreenTriangle::kVertexCount * sizeof(FullScreenTriangle::Vertex)); vertexBufferDesc.setDefaults(IResource::Usage::VertexBuffer); - gVertexBuffer = gRenderer->createBufferResource( + gVertexBuffer = gDevice->createBufferResource( IResource::Usage::VertexBuffer, vertexBufferDesc, &FullScreenTriangle::kVertices[0]); if(!gVertexBuffer) return SLANG_FAIL; ComPtr<IShaderProgram> shaderProgram; - SLANG_RETURN_ON_FAIL(loadShaderProgram(gRenderer, shaderProgram)); + SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, shaderProgram)); IDescriptorSetLayout::SlotRangeDesc slotRanges[] = { @@ -404,7 +411,7 @@ Result initialize() IDescriptorSetLayout::Desc descriptorSetLayoutDesc; descriptorSetLayoutDesc.slotRangeCount = 1; descriptorSetLayoutDesc.slotRanges = &slotRanges[0]; - auto descriptorSetLayout = gRenderer->createDescriptorSetLayout(descriptorSetLayoutDesc); + auto descriptorSetLayout = gDevice->createDescriptorSetLayout(descriptorSetLayoutDesc); if(!descriptorSetLayout) return SLANG_FAIL; IPipelineLayout::DescriptorSetDesc descriptorSets[] = @@ -415,12 +422,13 @@ Result initialize() pipelineLayoutDesc.renderTargetCount = 1; pipelineLayoutDesc.descriptorSetCount = 1; pipelineLayoutDesc.descriptorSets = &descriptorSets[0]; - auto pipelineLayout = gRenderer->createPipelineLayout(pipelineLayoutDesc); + auto pipelineLayout = gDevice->createPipelineLayout(pipelineLayoutDesc); if(!pipelineLayout) return SLANG_FAIL; gPipelineLayout = pipelineLayout; - auto descriptorSet = gRenderer->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient); + auto descriptorSet = + gDevice->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient); if(!descriptorSet) return SLANG_FAIL; descriptorSet->setConstantBuffer(0, 0, gConstantBuffer); @@ -436,7 +444,7 @@ Result initialize() swapchainDesc.queue = gQueue; gfx::WindowHandle windowHandle; memcpy(&windowHandle, &gWindow->getNativeHandle(), sizeof(windowHandle)); - gSwapchain = gRenderer->createSwapchain(swapchainDesc, windowHandle); + gSwapchain = gDevice->createSwapchain(swapchainDesc, windowHandle); IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1}; IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1}; @@ -444,58 +452,18 @@ Result initialize() framebufferLayoutDesc.renderTargetCount = 1; framebufferLayoutDesc.renderTargets = &renderTargetLayout; framebufferLayoutDesc.depthStencil = &depthLayout; - ComPtr<IFramebufferLayout> framebufferLayout; SLANG_RETURN_ON_FAIL( - gRenderer->createFramebufferLayout(framebufferLayoutDesc, framebufferLayout.writeRef())); - - for (uint32_t i = 0; i < kSwapchainImageCount; i++) - { - gfx::ITextureResource::Desc depthBufferDesc; - depthBufferDesc.setDefaults(gfx::IResource::Usage::DepthWrite); - depthBufferDesc.init2D( - gfx::IResource::Type::Texture2D, - gfx::Format::D_Float32, - gSwapchain->getDesc().width, - gSwapchain->getDesc().height, - 0); - - ComPtr<gfx::ITextureResource> depthBufferResource = gRenderer->createTextureResource( - gfx::IResource::Usage::DepthWrite, depthBufferDesc, nullptr); - ComPtr<gfx::ITextureResource> colorBuffer; - gSwapchain->getImage(i, colorBuffer.writeRef()); + gDevice->createFramebufferLayout(framebufferLayoutDesc, gFramebufferLayout.writeRef())); - gfx::IResourceView::Desc colorBufferViewDesc; - memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc)); - colorBufferViewDesc.format = gSwapchain->getDesc().format; - colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; - colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget; - ComPtr<gfx::IResourceView> rtv = - gRenderer->createTextureView(colorBuffer.get(), colorBufferViewDesc); - - gfx::IResourceView::Desc depthBufferViewDesc; - memset(&depthBufferViewDesc, 0, sizeof(depthBufferViewDesc)); - depthBufferViewDesc.format = gfx::Format::D_Float32; - depthBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; - depthBufferViewDesc.type = gfx::IResourceView::Type::DepthStencil; - ComPtr<gfx::IResourceView> dsv = - gRenderer->createTextureView(depthBufferResource.get(), depthBufferViewDesc); - - gfx::IFramebuffer::Desc framebufferDesc; - framebufferDesc.renderTargetCount = 1; - framebufferDesc.depthStencilView = dsv.get(); - framebufferDesc.renderTargetViews = rtv.readRef(); - framebufferDesc.layout = framebufferLayout; - ComPtr<gfx::IFramebuffer> frameBuffer = gRenderer->createFramebuffer(framebufferDesc); - gFramebuffers.add(frameBuffer); - } + createSwapchainFramebuffers(); // Create pipeline. GraphicsPipelineStateDesc desc; desc.inputLayout = inputLayout; desc.program = shaderProgram; - desc.framebufferLayout = framebufferLayout; + desc.framebufferLayout = gFramebufferLayout; desc.pipelineLayout = pipelineLayout; - auto pipelineState = gRenderer->createGraphicsPipelineState(desc); + auto pipelineState = gDevice->createGraphicsPipelineState(desc); if (!pipelineState) return SLANG_FAIL; @@ -503,7 +471,7 @@ Result initialize() // Create render pass. gfx::IRenderPassLayout::Desc renderPassDesc = {}; - renderPassDesc.framebufferLayout = framebufferLayout; + renderPassDesc.framebufferLayout = gFramebufferLayout; renderPassDesc.renderTargetCount = 1; IRenderPassLayout::AttachmentAccessDesc renderTargetAccess = {}; IRenderPassLayout::AttachmentAccessDesc depthStencilAccess = {}; @@ -517,7 +485,7 @@ Result initialize() depthStencilAccess.finalState = ResourceState::DepthWrite; renderPassDesc.renderTargetAccess = &renderTargetAccess; renderPassDesc.depthStencilAccess = &depthStencilAccess; - gRenderPass = gRenderer->createRenderPassLayout(renderPassDesc); + gRenderPass = gDevice->createRenderPassLayout(renderPassDesc); return SLANG_OK; } @@ -534,6 +502,9 @@ platform::TimePoint startTime; void renderFrame() { auto frameIndex = gSwapchain->acquireNextImage(); + if (frameIndex == -1) + return; + auto commandBuffer = gQueue->createCommandBuffer(); if( firstTime ) { @@ -599,6 +570,73 @@ void handleEvent(const platform::MouseEventArgs& event) lastMouseY = (float)event.y; } +void createSwapchainFramebuffers() +{ + gFramebuffers.clear(); + for (uint32_t i = 0; i < kSwapchainImageCount; i++) + { + gfx::ITextureResource::Desc depthBufferDesc; + depthBufferDesc.setDefaults(gfx::IResource::Usage::DepthWrite); + depthBufferDesc.init2D( + gfx::IResource::Type::Texture2D, + gfx::Format::D_Float32, + gSwapchain->getDesc().width, + gSwapchain->getDesc().height, + 0); + + ComPtr<gfx::ITextureResource> depthBufferResource = gDevice->createTextureResource( + gfx::IResource::Usage::DepthWrite, depthBufferDesc, nullptr); + ComPtr<gfx::ITextureResource> colorBuffer; + gSwapchain->getImage(i, colorBuffer.writeRef()); + + gfx::IResourceView::Desc colorBufferViewDesc; + memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc)); + colorBufferViewDesc.format = gSwapchain->getDesc().format; + colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; + colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget; + ComPtr<gfx::IResourceView> rtv = + gDevice->createTextureView(colorBuffer.get(), colorBufferViewDesc); + + gfx::IResourceView::Desc depthBufferViewDesc; + memset(&depthBufferViewDesc, 0, sizeof(depthBufferViewDesc)); + depthBufferViewDesc.format = gfx::Format::D_Float32; + depthBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; + depthBufferViewDesc.type = gfx::IResourceView::Type::DepthStencil; + ComPtr<gfx::IResourceView> dsv = + gDevice->createTextureView(depthBufferResource.get(), depthBufferViewDesc); + + gfx::IFramebuffer::Desc framebufferDesc; + framebufferDesc.renderTargetCount = 1; + framebufferDesc.depthStencilView = dsv.get(); + framebufferDesc.renderTargetViews = rtv.readRef(); + framebufferDesc.layout = gFramebufferLayout; + ComPtr<gfx::IFramebuffer> frameBuffer = gDevice->createFramebuffer(framebufferDesc); + gFramebuffers.add(frameBuffer); + } +} + +void windowSizeChanged() +{ + // Wait for the GPU to finish. + gQueue->wait(); + + auto clientRect = gWindow->getClientRect(); + if (clientRect.width > 0 && clientRect.height > 0) + { + // Free all framebuffers before resizing swapchain. + gFramebuffers = decltype(gFramebuffers)(); + + // Resize swapchain. + if (gSwapchain->resize(clientRect.width, clientRect.height) == SLANG_OK) + { + // Recreate framebuffers for each swapchain back buffer image. + createSwapchainFramebuffers(); + gWindowWidth = clientRect.width; + gWindowHeight = clientRect.height; + } + } +} + }; int innerMain() |
