summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-03-10 10:58:15 -0800
committerGitHub <noreply@github.com>2021-03-10 10:58:15 -0800
commit6ef4054f8a8aea4ec61481057fa7e16aaecde6d7 (patch)
tree66edcae112faff7276c2595865463698bde277fd /examples
parent2765861cdc104e6104a31cf9e20800b8d1dfae26 (diff)
Swapchain resize and rename to `IDevice` (#1741)
* Swapchain resize * Fix.
Diffstat (limited to 'examples')
-rw-r--r--examples/gpu-printing/main.cpp46
-rw-r--r--examples/hello-world/main.cpp52
-rw-r--r--examples/shader-object/main.cpp30
-rw-r--r--examples/shader-toy/main.cpp168
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()