summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-02-24 15:43:43 -0800
committerGitHub <noreply@github.com>2021-02-24 15:43:43 -0800
commit9b7a007c31072bc9aebd1134aa4f1bfd28a4c541 (patch)
treeb71a48eb30b3b09ab4e77e40dc1c68ecd854ef82
parentd66b30729029bdb43892e05c9c80fd56ac95a24f (diff)
Explicit swapchain interface in `gfx`. (#1726)
* Explicit swapchain interface in `gfx`. * Correctly return nullptr when `IRenderer` creation failed. * Fix crashes on CUDA tests. * Cleanups.
-rw-r--r--build/visual-studio/core/core.vcxproj1
-rw-r--r--build/visual-studio/core/core.vcxproj.filters3
-rw-r--r--build/visual-studio/gfx/gfx.vcxproj2
-rw-r--r--build/visual-studio/gfx/gfx.vcxproj.filters6
-rw-r--r--examples/gpu-printing/main.cpp13
-rw-r--r--examples/hello-world/main.cpp102
-rw-r--r--examples/heterogeneous-hello-world/main.cpp7
-rw-r--r--examples/model-viewer/main.cpp135
-rw-r--r--examples/shader-object/main.cpp5
-rw-r--r--examples/shader-toy/main.cpp98
-rw-r--r--external/wglext.h1056
-rw-r--r--slang-gfx.h180
-rw-r--r--source/core/slang-virtual-object-pool.h119
-rw-r--r--tools/gfx/cuda/render-cuda.cpp64
-rw-r--r--tools/gfx/cuda/render-cuda.h2
-rw-r--r--tools/gfx/d3d/d3d-util.cpp2
-rw-r--r--tools/gfx/d3d11/render-d3d11.cpp623
-rw-r--r--tools/gfx/d3d11/render-d3d11.h2
-rw-r--r--tools/gfx/d3d12/descriptor-heap-d3d12.h50
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp957
-rw-r--r--tools/gfx/d3d12/render-d3d12.h2
-rw-r--r--tools/gfx/open-gl/render-gl.cpp614
-rw-r--r--tools/gfx/open-gl/render-gl.h2
-rw-r--r--tools/gfx/render-graphics-common.cpp3
-rw-r--r--tools/gfx/render.cpp13
-rw-r--r--tools/gfx/renderer-shared.cpp9
-rw-r--r--tools/gfx/renderer-shared.h7
-rw-r--r--tools/gfx/vulkan/render-vk.cpp1121
-rw-r--r--tools/gfx/vulkan/render-vk.h2
-rw-r--r--tools/gfx/vulkan/vk-api.h10
-rw-r--r--tools/gfx/vulkan/vk-descriptor-allocator.cpp70
-rw-r--r--tools/gfx/vulkan/vk-descriptor-allocator.h43
-rw-r--r--tools/gfx/vulkan/vk-device-queue.cpp50
-rw-r--r--tools/gfx/vulkan/vk-device-queue.h13
-rw-r--r--tools/gfx/vulkan/vk-swap-chain.cpp135
-rw-r--r--tools/gfx/vulkan/vk-swap-chain.h25
-rw-r--r--tools/gfx/vulkan/vk-util.cpp1
-rw-r--r--tools/graphics-app-framework/gui.cpp6
-rw-r--r--tools/graphics-app-framework/gui.h2
-rw-r--r--tools/render-test/render-test-main.cpp127
-rw-r--r--tools/render-test/shader-renderer-util.cpp2
-rw-r--r--tools/slang-test/test-reporter.cpp48
42 files changed, 4063 insertions, 1669 deletions
diff --git a/build/visual-studio/core/core.vcxproj b/build/visual-studio/core/core.vcxproj
index 2bf02ecdd..01a7e3eb2 100644
--- a/build/visual-studio/core/core.vcxproj
+++ b/build/visual-studio/core/core.vcxproj
@@ -219,6 +219,7 @@
<ClInclude Include="..\..\..\source\core\slang-type-text-util.h" />
<ClInclude Include="..\..\..\source\core\slang-type-traits.h" />
<ClInclude Include="..\..\..\source\core\slang-uint-set.h" />
+ <ClInclude Include="..\..\..\source\core\slang-virtual-object-pool.h" />
<ClInclude Include="..\..\..\source\core\slang-visual-studio-compiler-util.h" />
<ClInclude Include="..\..\..\source\core\slang-writer.h" />
<ClInclude Include="..\..\..\source\core\slang-zip-file-system.h" />
diff --git a/build/visual-studio/core/core.vcxproj.filters b/build/visual-studio/core/core.vcxproj.filters
index 99cc6ba6a..3c2a7371d 100644
--- a/build/visual-studio/core/core.vcxproj.filters
+++ b/build/visual-studio/core/core.vcxproj.filters
@@ -156,6 +156,9 @@
<ClInclude Include="..\..\..\source\core\slang-uint-set.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\core\slang-virtual-object-pool.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\core\slang-visual-studio-compiler-util.h">
<Filter>Header Files</Filter>
</ClInclude>
diff --git a/build/visual-studio/gfx/gfx.vcxproj b/build/visual-studio/gfx/gfx.vcxproj
index 91c6a9441..0968e8c6c 100644
--- a/build/visual-studio/gfx/gfx.vcxproj
+++ b/build/visual-studio/gfx/gfx.vcxproj
@@ -196,6 +196,7 @@
<ClInclude Include="..\..\..\tools\gfx\slang-context.h" />
<ClInclude Include="..\..\..\tools\gfx\vulkan\render-vk.h" />
<ClInclude Include="..\..\..\tools\gfx\vulkan\vk-api.h" />
+ <ClInclude Include="..\..\..\tools\gfx\vulkan\vk-descriptor-allocator.h" />
<ClInclude Include="..\..\..\tools\gfx\vulkan\vk-device-queue.h" />
<ClInclude Include="..\..\..\tools\gfx\vulkan\vk-module.h" />
<ClInclude Include="..\..\..\tools\gfx\vulkan\vk-swap-chain.h" />
@@ -217,6 +218,7 @@
<ClCompile Include="..\..\..\tools\gfx\renderer-shared.cpp" />
<ClCompile Include="..\..\..\tools\gfx\vulkan\render-vk.cpp" />
<ClCompile Include="..\..\..\tools\gfx\vulkan\vk-api.cpp" />
+ <ClCompile Include="..\..\..\tools\gfx\vulkan\vk-descriptor-allocator.cpp" />
<ClCompile Include="..\..\..\tools\gfx\vulkan\vk-device-queue.cpp" />
<ClCompile Include="..\..\..\tools\gfx\vulkan\vk-module.cpp" />
<ClCompile Include="..\..\..\tools\gfx\vulkan\vk-swap-chain.cpp" />
diff --git a/build/visual-studio/gfx/gfx.vcxproj.filters b/build/visual-studio/gfx/gfx.vcxproj.filters
index cf800961a..1dc6581d6 100644
--- a/build/visual-studio/gfx/gfx.vcxproj.filters
+++ b/build/visual-studio/gfx/gfx.vcxproj.filters
@@ -60,6 +60,9 @@
<ClInclude Include="..\..\..\tools\gfx\vulkan\vk-api.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\tools\gfx\vulkan\vk-descriptor-allocator.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\tools\gfx\vulkan\vk-device-queue.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -119,6 +122,9 @@
<ClCompile Include="..\..\..\tools\gfx\vulkan\vk-api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\tools\gfx\vulkan\vk-descriptor-allocator.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\tools\gfx\vulkan\vk-device-queue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/examples/gpu-printing/main.cpp b/examples/gpu-printing/main.cpp
index 63b1939a6..4f79147f6 100644
--- a/examples/gpu-printing/main.cpp
+++ b/examples/gpu-printing/main.cpp
@@ -64,7 +64,6 @@ int gWindowWidth = 640;
int gWindowHeight = 480;
gfx::ApplicationContext* gAppContext;
-gfx::Window* gWindow;
ComPtr<gfx::IRenderer> gRenderer;
ComPtr<slang::ISession> gSlangSession;
@@ -112,17 +111,9 @@ ComPtr<gfx::IShaderProgram> loadComputeProgram(slang::IModule* slangModule, char
Result execute()
{
- WindowDesc windowDesc;
- windowDesc.title = "GPU Printing";
- windowDesc.width = gWindowWidth;
- windowDesc.height = gWindowHeight;
- gWindow = createWindow(windowDesc);
-
IRenderer::Desc rendererDesc;
rendererDesc.rendererType = gfx::RendererType::DirectX11;
- rendererDesc.width = gWindowWidth;
- rendererDesc.height = gWindowHeight;
- Result res = gfxCreateRenderer(&rendererDesc, getPlatformWindowHandle(gWindow), gRenderer.writeRef());
+ Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef());
if(SLANG_FAILED(res)) return res;
gSlangSession = createSlangSession(gRenderer);
@@ -157,7 +148,7 @@ 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);
+ auto descriptorSet = gRenderer->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient);
if(!descriptorSet) return SLANG_FAIL;
// descriptorSet->setConstantBuffer(0, 0, gConstantBuffer);
diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp
index 49fe2ec67..f0ea3eb2a 100644
--- a/examples/hello-world/main.cpp
+++ b/examples/hello-world/main.cpp
@@ -201,6 +201,7 @@ gfx::Result loadShaderProgram(
//
int gWindowWidth = 1024;
int gWindowHeight = 768;
+const uint32_t kSwapchainImageCount = 2;
// We will define global variables for the various platform and
// graphics API objects that our application needs:
@@ -213,10 +214,10 @@ gfx::ApplicationContext* gAppContext;
gfx::Window* gWindow;
Slang::ComPtr<gfx::IRenderer> gRenderer;
-//ComPtr<gfx::IShaderObjectLayout> gRootLayout;
ComPtr<gfx::IPipelineState> gPipelineState;
ComPtr<gfx::IShaderObject> gRootObject;
-
+ComPtr<gfx::ISwapchain> gSwapchain;
+List<ComPtr<gfx::IFramebuffer>> gFramebuffers;
ComPtr<gfx::IBufferResource> gVertexBuffer;
// Now that we've covered the function that actually loads and
@@ -242,9 +243,7 @@ Slang::Result initialize()
//
IRenderer::Desc rendererDesc = {};
rendererDesc.rendererType = gfx::RendererType::DirectX11;
- rendererDesc.width = gWindowWidth;
- rendererDesc.height = gWindowHeight;
- gfx::Result res = gfxCreateRenderer(&rendererDesc, getPlatformWindowHandle(gWindow), gRenderer.writeRef());
+ gfx::Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef());
if(SLANG_FAILED(res)) return res;
// Now we will create objects needed to configur the "input assembler"
@@ -311,15 +310,76 @@ Slang::Result initialize()
SLANG_RETURN_ON_FAIL(gRenderer->createRootShaderObject(shaderProgram, rootObject.writeRef()));
gRootObject = rootObject;
+ // Create swapchain and framebuffers.
+ gfx::ISwapchain::Desc swapchainDesc = {};
+ swapchainDesc.format = gfx::Format::RGBA_Unorm_UInt8;
+ swapchainDesc.width = gWindowWidth;
+ swapchainDesc.height = gWindowHeight;
+ swapchainDesc.imageCount = kSwapchainImageCount;
+ gSwapchain = gRenderer->createSwapchain(
+ swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow)));
+
+ IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1};
+ IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1};
+ IFramebufferLayout::Desc framebufferLayoutDesc;
+ 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());
+
+ 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);
+ }
+
// Following the D3D12/Vulkan style of API, we need a pipeline state object
// (PSO) to encapsulate the configuration of the overall graphics pipeline.
//
GraphicsPipelineStateDesc desc;
desc.inputLayout = inputLayout;
desc.program = shaderProgram;
- desc.renderTargetCount = 1;
+ desc.framebufferLayout = framebufferLayout;
auto pipelineState = gRenderer->createGraphicsPipelineState(desc);
- if(!pipelineState) return SLANG_FAIL;
+ if (!pipelineState)
+ return SLANG_FAIL;
gPipelineState = pipelineState;
@@ -338,6 +398,17 @@ Slang::Result initialize()
//
void renderFrame()
{
+ gRenderer->beginFrame();
+ uint32_t frameBufferIndex = gSwapchain->acquireNextImage();
+ gRenderer->setFramebuffer(gFramebuffers[frameBufferIndex]);
+
+ gfx::Viewport viewport = {};
+ viewport.maxZ = 1.0f;
+ viewport.extentX = (float)gWindowWidth;
+ viewport.extentY = (float)gWindowHeight;
+ gRenderer->setViewportAndScissor(viewport);
+
+
// We start by clearing our framebuffer, which only has a color target.
//
static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
@@ -349,13 +420,15 @@ void renderFrame()
// basis, even though the data that is loaded does not change
// per-frame (we always use an identity matrix).
//
- static const float kIdentity[] =
+ float identityMatrix[] =
{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
};
+ gfxGetIdentityProjection(gfxGetProjectionStyle(gRenderer->getRendererType()), identityMatrix);
+
//
// We know that `gRootObject` is a root shader object created
// from our program, and that it is set up to hold values for
@@ -390,7 +463,7 @@ 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(kIdentity, sizeof(kIdentity));
+ rootCursor["Uniforms"]["modelViewProjection"].setData(identityMatrix, sizeof(identityMatrix));
//
// Some readers might be concerned about the performance o
// the above operations because of the use of strings. For
@@ -427,14 +500,17 @@ void renderFrame()
// With that, we are done drawing for one frame, and ready for the next.
//
- gRenderer->presentFrame();
+ gRenderer->makeSwapchainImagePresentable(gSwapchain);
+
+ gRenderer->endFrame();
+
+ gSwapchain->present();
}
void finalize()
{
- // All of our graphics API objects are reference-counted,
- // so there isn't any additional cleanup work that needs
- // to be done in this simple example.
+ gRenderer->waitForGpu();
+ destroyWindow(gWindow);
}
};
diff --git a/examples/heterogeneous-hello-world/main.cpp b/examples/heterogeneous-hello-world/main.cpp
index ff44ecc45..010434bfa 100644
--- a/examples/heterogeneous-hello-world/main.cpp
+++ b/examples/heterogeneous-hello-world/main.cpp
@@ -124,9 +124,8 @@ gfx::IRenderer* createRenderer(
//
IRenderer::Desc rendererDesc = {};
rendererDesc.rendererType = gfx::RendererType::DirectX11;
- rendererDesc.width = windowWidth;
- rendererDesc.height = windowHeight;
- Result res = gfxCreateRenderer(&rendererDesc, getPlatformWindowHandle(window), gRenderer.writeRef());
+ Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef());
+
if (SLANG_FAILED(res)) return nullptr;
return gRenderer;
}
@@ -196,7 +195,7 @@ gfx::IDescriptorSet* buildDescriptorSet(
// Once we have the descriptor set layout, we can allocate
// and fill in a descriptor set to hold our parameters.
//
- gDescriptorSet = renderer->createDescriptorSet(descriptorSetLayout);
+ gDescriptorSet = renderer->createDescriptorSet(descriptorSetLayout, gfx::IDescriptorSet::Flag::Transient);
if(!gDescriptorSet) return nullptr;
// Once we have the bufferResource created, we can fill in
diff --git a/examples/model-viewer/main.cpp b/examples/model-viewer/main.cpp
index f18a2cc58..c9693e529 100644
--- a/examples/model-viewer/main.cpp
+++ b/examples/model-viewer/main.cpp
@@ -548,7 +548,7 @@ struct ParameterBlockEncoder
// A top-level encoder will unmap the underlying constant
// buffer (if any) when it goes out of scope.
//
- ~ParameterBlockEncoder();
+ void finishEncoding();
// The underlying descriptor set being filled in.
//
@@ -669,7 +669,7 @@ RefPtr<ParameterBlock> allocateParameterBlockImpl(
// resource parameters (including the primary constant buffer, if any).
//
auto descriptorSet = renderer->createDescriptorSet(
- layout->descriptorSetLayout);
+ layout->descriptorSetLayout, gfx::IDescriptorSet::Flag::Transient);
// If the parameter block has any ordinary data, then it requires
// a "primary" constant buffer to hold that data.
@@ -743,10 +743,7 @@ ParameterBlockEncoder ParameterBlock::beginEncoding()
return encoder;
}
-// When a "top-level" encoder goes out of scope,
-// we need to unmap the parameter block.
-//
-ParameterBlockEncoder::~ParameterBlockEncoder()
+void ParameterBlockEncoder::finishEncoding()
{
if (parameterBlock && uniformData)
{
@@ -801,7 +798,8 @@ struct EffectVariant : RefObject
RefPtr<EffectVariant> createEffectVaraint(
Effect* effect,
UInt parameterBlockCount,
- ParameterBlockLayout* const* parameterBlockLayouts)
+ ParameterBlockLayout* const* parameterBlockLayouts,
+ IFramebufferLayout* framebufferLayout)
{
// One note to make at the very start is that the creation
// of a specialized variant is based on the *layout* of
@@ -982,7 +980,7 @@ RefPtr<EffectVariant> createEffectVaraint(
pipelineStateDesc.program = specializedProgram;
pipelineStateDesc.pipelineLayout = pipelineLayout;
pipelineStateDesc.inputLayout = effect->inputLayout;
- pipelineStateDesc.renderTargetCount = effect->renderTargetCount;
+ pipelineStateDesc.framebufferLayout = framebufferLayout;
auto pipelineState = renderer->createGraphicsPipelineState(pipelineStateDesc);
RefPtr<EffectVariant> variant = new EffectVariant();
@@ -1040,7 +1038,8 @@ struct ShaderCache : RefObject
// on demand in case of a miss.
//
RefPtr<EffectVariant> getEffectVariant(
- VariantKey const& key)
+ VariantKey const& key,
+ IFramebufferLayout* framebufferLayout)
{
RefPtr<EffectVariant> variant;
if(variants.TryGetValue(key, variant))
@@ -1049,7 +1048,8 @@ struct ShaderCache : RefObject
variant = createEffectVaraint(
key.effect,
key.parameterBlockCount,
- key.parameterBlockLayouts);
+ key.parameterBlockLayouts,
+ framebufferLayout);
variants.Add(key, variant);
return variant;
@@ -1224,7 +1224,7 @@ public:
pipelineStateDirty = true;
}
- void flushState()
+ void flushState(IFramebufferLayout* framebufferLayout)
{
// The `flushState()` operation must be used by the application
// any time it binds a different effect or parameter block(s),
@@ -1248,7 +1248,7 @@ public:
// be present in the cache, and this function returns
// without much effort.
//
- auto variant = shaderCache->getEffectVariant(variantKey);
+ auto variant = shaderCache->getEffectVariant(variantKey, framebufferLayout);
// In order to adapt to a change in shader variant,
// we simply bind its PSO into the GPU state, and
@@ -1342,6 +1342,7 @@ struct SimpleMaterial : Material
encoder.writeField(0, diffuseColor);
encoder.writeField(1, specularColor);
encoder.writeField(2, specularity);
+ encoder.finishEncoding();
return parameterBlock;
}
@@ -1811,6 +1812,7 @@ struct LightEnv : public RefObject
ParameterBlockEncoder encoder = parameterBlock->beginEncoding();
fillInParameterBlock(encoder);
+ encoder.finishEncoding();
return parameterBlock;
}
@@ -1911,7 +1913,9 @@ struct ModelViewer {
Window* gWindow;
Slang::ComPtr<gfx::IRenderer> gRenderer;
-ComPtr<gfx::IResourceView> gDepthTarget;
+ComPtr<gfx::ISwapchain> gSwapchain;
+ComPtr<IFramebufferLayout> gFramebufferLayout;
+Slang::List<ComPtr<gfx::IFramebuffer>> gFramebuffers;
// We keep a pointer to the one effect we are using (for a forward
// rendering pass), plus the parameter-block layouts for our `PerView`
@@ -1946,6 +1950,7 @@ void loadAndAddModel(
int gWindowWidth = 1024;
int gWindowHeight = 768;
+const uint32_t kSwapchainImageCount = 2;
// Our "simulation" state consists of just a few values.
//
@@ -2052,9 +2057,7 @@ Result initialize()
IRenderer::Desc rendererDesc = {};
rendererDesc.rendererType = gfx::RendererType::DirectX11;
- rendererDesc.width = gWindowWidth;
- rendererDesc.height = gWindowHeight;
- gfxCreateRenderer(&rendererDesc, getPlatformWindowHandle(gWindow), gRenderer.writeRef());
+ gfxCreateRenderer(&rendererDesc, gRenderer.writeRef());
InputElementDesc inputElements[] = {
{"POSITION", 0, Format::RGB_Float32, offsetof(Model::Vertex, position) },
@@ -2066,23 +2069,64 @@ Result initialize()
3);
if(!inputLayout) return SLANG_FAIL;
- // Because we are rendering more than a single triangle this time, we
- // require a depth buffer to resolve visibility.
- //
- ITextureResource::Desc depthBufferDesc = gRenderer->getSwapChainTextureDesc();
- depthBufferDesc.format = Format::D_Float32;
- depthBufferDesc.setDefaults(IResource::Usage::DepthWrite);
- auto depthTexture = gRenderer->createTextureResource(
- IResource::Usage::DepthWrite,
- depthBufferDesc);
- if(!depthTexture) return SLANG_FAIL;
-
- IResourceView::Desc textureViewDesc;
- textureViewDesc.type = IResourceView::Type::DepthStencil;
- auto depthTarget = gRenderer->createTextureView(depthTexture, textureViewDesc);
- if (!depthTarget) return SLANG_FAIL;
-
- gDepthTarget = depthTarget;
+ // Create swapchain and framebuffers.
+ gfx::ISwapchain::Desc swapchainDesc = {};
+ swapchainDesc.format = gfx::Format::RGBA_Unorm_UInt8;
+ swapchainDesc.width = gWindowWidth;
+ swapchainDesc.height = gWindowHeight;
+ swapchainDesc.imageCount = kSwapchainImageCount;
+ gSwapchain = gRenderer->createSwapchain(
+ swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow)));
+
+ IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1};
+ IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1};
+ IFramebufferLayout::Desc framebufferLayoutDesc;
+ framebufferLayoutDesc.renderTargetCount = 1;
+ framebufferLayoutDesc.renderTargets = &renderTargetLayout;
+ framebufferLayoutDesc.depthStencil = &depthLayout;
+ SLANG_RETURN_ON_FAIL(
+ gRenderer->createFramebufferLayout(framebufferLayoutDesc, gFramebufferLayout.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());
+
+ 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 = gFramebufferLayout;
+ ComPtr<gfx::IFramebuffer> frameBuffer = gRenderer->createFramebuffer(framebufferDesc);
+ gFramebuffers.add(frameBuffer);
+ }
// Unlike the earlier example, we will not generate final shader kernel
// code during initialization. Instead, we simply load the shader module
@@ -2157,7 +2201,7 @@ Result initialize()
// We will do some GUI rendering in this app, using "Dear, IMGUI",
// so we need to do the appropriate initialization work here.
- gui = new GUI(gWindow, gRenderer);
+ gui = new GUI(gWindow, gRenderer, gFramebufferLayout);
showWindow(gWindow);
@@ -2170,6 +2214,7 @@ Result initialize()
//
void renderFrame()
{
+ gRenderer->beginFrame();
gui->beginFrame();
// In order to see that things are rendering properly we need some
@@ -2213,7 +2258,15 @@ void renderFrame()
// Some of the basic rendering setup is identical to the previous example.
//
- gRenderer->setDepthStencilTarget(gDepthTarget);
+ auto frameIndex = gSwapchain->acquireNextImage();
+ gRenderer->setFramebuffer(gFramebuffers[frameIndex]);
+
+ gfx::Viewport viewport = {};
+ viewport.maxZ = 1.0f;
+ viewport.extentX = (float)gWindowWidth;
+ viewport.extentY = (float)gWindowHeight;
+ gRenderer->setViewportAndScissor(viewport);
+
static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
gRenderer->setClearColor(kClearColor);
gRenderer->clearFrame();
@@ -2245,6 +2298,7 @@ void renderFrame()
auto encoder = viewParameterBlock->beginEncoding();
encoder.writeField(0, viewProjection);
encoder.writeField(1, cameraPosition);
+ encoder.finishEncoding();
}
//
// Note: the assignment of indices to parameter blocks is driven
@@ -2288,6 +2342,7 @@ void renderFrame()
auto encoder = modelParameterBlock->beginEncoding();
encoder.writeField(0, modelTransform);
encoder.writeField(1, inverseTransposeModelTransform);
+ encoder.finishEncoding();
}
context.setParameterBlock(1, modelParameterBlock);
@@ -2321,7 +2376,7 @@ void renderFrame()
// material changed, a shader switch might be
// required).
//
- context.flushState();
+ context.flushState(gFramebufferLayout);
gRenderer->drawIndexed(mesh->indexCount, mesh->firstIndex);
}
@@ -2348,7 +2403,11 @@ void renderFrame()
ImGui::End();
gui->endFrame();
- gRenderer->presentFrame();
+
+ gRenderer->makeSwapchainImagePresentable(gSwapchain);
+ gRenderer->endFrame();
+ gSwapchain->present();
+
}
void finalize()
@@ -2359,7 +2418,9 @@ void finalize()
// that we aren't relying on C++ global destructors to tear
// down our application cleanly.
//
+ gRenderer->waitForGpu();
SimpleMaterial::gParameterBlockLayout = nullptr;
+ destroyWindow(gWindow);
}
};
diff --git a/examples/shader-object/main.cpp b/examples/shader-object/main.cpp
index b61cf30e4..9b1b4de72 100644
--- a/examples/shader-object/main.cpp
+++ b/examples/shader-object/main.cpp
@@ -137,7 +137,7 @@ int main()
Slang::ComPtr<gfx::IRenderer> renderer;
IRenderer::Desc rendererDesc = {};
rendererDesc.rendererType = RendererType::CUDA;
- SLANG_RETURN_ON_FAIL(gfxCreateRenderer(&rendererDesc, nullptr, renderer.writeRef()));
+ SLANG_RETURN_ON_FAIL(gfxCreateRenderer(&rendererDesc, renderer.writeRef()));
// Now we can load the shader code.
// A `gfx::IShaderProgram` object for use in the `gfx` layer.
@@ -211,10 +211,11 @@ int main()
// We have set up all required parameters in entry-point object, now it is time
// to bind the pipeline and root object and launch the kernel.
+ renderer->beginFrame();
renderer->setPipelineState(pipelineState);
SLANG_RETURN_ON_FAIL(renderer->bindRootShaderObject(gfx::PipelineType::Compute, rootObject));
renderer->dispatchCompute(1, 1, 1);
-
+ renderer->endFrame();
// Read back the results.
renderer->waitForGpu();
float* result = (float*)renderer->map(numbersBuffer, gfx::MapFlavor::HostRead);
diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp
index 89aa74ccb..697bb1044 100644
--- a/examples/shader-toy/main.cpp
+++ b/examples/shader-toy/main.cpp
@@ -327,6 +327,7 @@ Result loadShaderProgram(gfx::IRenderer* renderer, ComPtr<gfx::IShaderProgram>&
int gWindowWidth = 1024;
int gWindowHeight = 768;
+const uint32_t kSwapchainImageCount = 2;
gfx::ApplicationContext* gAppContext;
gfx::Window* gWindow;
@@ -336,6 +337,8 @@ ComPtr<gfx::IPipelineLayout> gPipelineLayout;
ComPtr<gfx::IPipelineState> gPipelineState;
ComPtr<gfx::IDescriptorSet> gDescriptorSet;
ComPtr<gfx::IBufferResource> gVertexBuffer;
+ComPtr<gfx::ISwapchain> gSwapchain;
+Slang::List<ComPtr<gfx::IFramebuffer>> gFramebuffers;
Result initialize()
{
@@ -349,9 +352,7 @@ Result initialize()
IRenderer::Desc rendererDesc;
rendererDesc.rendererType = RendererType::DirectX11;
- rendererDesc.width = gWindowWidth;
- rendererDesc.height = gWindowHeight;
- Result res = gfxCreateRenderer(&rendererDesc, getPlatformWindowHandle(gWindow), gRenderer.writeRef());
+ Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef());
if(SLANG_FAILED(res)) return res;
int constantBufferSize = sizeof(Uniforms);
@@ -409,20 +410,82 @@ Result initialize()
gPipelineLayout = pipelineLayout;
- auto descriptorSet = gRenderer->createDescriptorSet(descriptorSetLayout);
+ auto descriptorSet = gRenderer->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient);
if(!descriptorSet) return SLANG_FAIL;
descriptorSet->setConstantBuffer(0, 0, gConstantBuffer);
gDescriptorSet = descriptorSet;
+ // Create swapchain and framebuffers.
+ gfx::ISwapchain::Desc swapchainDesc = {};
+ swapchainDesc.format = gfx::Format::RGBA_Unorm_UInt8;
+ swapchainDesc.width = gWindowWidth;
+ swapchainDesc.height = gWindowHeight;
+ swapchainDesc.imageCount = kSwapchainImageCount;
+ gSwapchain = gRenderer->createSwapchain(
+ swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow)));
+
+ IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1};
+ IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1};
+ IFramebufferLayout::Desc framebufferLayoutDesc;
+ 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());
+
+ 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);
+ }
+
+ // Create pipeline.
GraphicsPipelineStateDesc desc;
- desc.pipelineLayout = gPipelineLayout;
desc.inputLayout = inputLayout;
desc.program = shaderProgram;
- desc.renderTargetCount = 1;
+ desc.framebufferLayout = framebufferLayout;
+ desc.pipelineLayout = pipelineLayout;
auto pipelineState = gRenderer->createGraphicsPipelineState(desc);
- if(!pipelineState) return SLANG_FAIL;
+ if (!pipelineState)
+ return SLANG_FAIL;
gPipelineState = pipelineState;
@@ -443,12 +506,21 @@ uint64_t startTime = 0;
void renderFrame()
{
+ gRenderer->beginFrame();
+ auto frameIndex = gSwapchain->acquireNextImage();
+ gRenderer->setFramebuffer(gFramebuffers[frameIndex]);
if( firstTime )
{
startTime = getCurrentTime();
firstTime = false;
}
+ gfx::Viewport viewport = {};
+ viewport.maxZ = 1.0f;
+ viewport.extentX = (float)gWindowWidth;
+ viewport.extentY = (float)gWindowHeight;
+ gRenderer->setViewportAndScissor(viewport);
+
static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
gRenderer->setClearColor(kClearColor);
gRenderer->clearFrame();
@@ -483,10 +555,18 @@ void renderFrame()
gRenderer->draw(3);
- gRenderer->presentFrame();
+ gRenderer->makeSwapchainImagePresentable(gSwapchain);
+
+ gRenderer->endFrame();
+
+ gSwapchain->present();
}
-void finalize() { destroyWindow(gWindow); }
+void finalize()
+{
+ gRenderer->waitForGpu();
+ destroyWindow(gWindow);
+}
void handleEvent(Event const& event)
{
diff --git a/external/wglext.h b/external/wglext.h
new file mode 100644
index 000000000..a25543ad8
--- /dev/null
+++ b/external/wglext.h
@@ -0,0 +1,1056 @@
+#ifndef __wgl_wglext_h_
+#define __wgl_wglext_h_ 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ** Copyright 2013-2020 The Khronos Group Inc.
+ ** SPDX-License-Identifier: MIT
+ **
+ ** This header is generated from the Khronos OpenGL / OpenGL ES XML
+ ** API Registry. The current version of the Registry, generator scripts
+ ** used to make the header, and the header can be found at
+ ** https://github.com/KhronosGroup/OpenGL-Registry
+ */
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+# define WIN32_LEAN_AND_MEAN 1
+# include <windows.h>
+#endif
+
+#define WGL_WGLEXT_VERSION 20200813
+
+ /* Generated C header for:
+ * API: wgl
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: wgl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef WGL_ARB_buffer_region
+# define WGL_ARB_buffer_region 1
+# define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
+# define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002
+# define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004
+# define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008
+ typedef HANDLE(WINAPI* PFNWGLCREATEBUFFERREGIONARBPROC)(HDC hDC, int iLayerPlane, UINT uType);
+ typedef VOID(WINAPI* PFNWGLDELETEBUFFERREGIONARBPROC)(HANDLE hRegion);
+ typedef BOOL(WINAPI* PFNWGLSAVEBUFFERREGIONARBPROC)(
+ HANDLE hRegion, int x, int y, int width, int height);
+ typedef BOOL(WINAPI* PFNWGLRESTOREBUFFERREGIONARBPROC)(
+ HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ HANDLE WINAPI wglCreateBufferRegionARB(HDC hDC, int iLayerPlane, UINT uType);
+ VOID WINAPI wglDeleteBufferRegionARB(HANDLE hRegion);
+ BOOL WINAPI wglSaveBufferRegionARB(HANDLE hRegion, int x, int y, int width, int height);
+ BOOL WINAPI wglRestoreBufferRegionARB(
+ HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+# endif
+#endif /* WGL_ARB_buffer_region */
+
+#ifndef WGL_ARB_context_flush_control
+# define WGL_ARB_context_flush_control 1
+# define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+# define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+# define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#endif /* WGL_ARB_context_flush_control */
+
+#ifndef WGL_ARB_create_context
+# define WGL_ARB_create_context 1
+# define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
+# define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+# define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+# define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+# define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+# define WGL_CONTEXT_FLAGS_ARB 0x2094
+# define ERROR_INVALID_VERSION_ARB 0x2095
+ typedef HGLRC(WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC)(
+ HDC hDC, HGLRC hShareContext, const int* attribList);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ HGLRC WINAPI wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int* attribList);
+# endif
+#endif /* WGL_ARB_create_context */
+
+#ifndef WGL_ARB_create_context_no_error
+# define WGL_ARB_create_context_no_error 1
+# define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
+#endif /* WGL_ARB_create_context_no_error */
+
+#ifndef WGL_ARB_create_context_profile
+# define WGL_ARB_create_context_profile 1
+# define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+# define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+# define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+# define ERROR_INVALID_PROFILE_ARB 0x2096
+#endif /* WGL_ARB_create_context_profile */
+
+#ifndef WGL_ARB_create_context_robustness
+# define WGL_ARB_create_context_robustness 1
+# define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+# define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+# define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+# define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
+#endif /* WGL_ARB_create_context_robustness */
+
+#ifndef WGL_ARB_extensions_string
+# define WGL_ARB_extensions_string 1
+ typedef const char*(WINAPI* PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC hdc);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ const char* WINAPI wglGetExtensionsStringARB(HDC hdc);
+# endif
+#endif /* WGL_ARB_extensions_string */
+
+#ifndef WGL_ARB_framebuffer_sRGB
+# define WGL_ARB_framebuffer_sRGB 1
+# define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
+#endif /* WGL_ARB_framebuffer_sRGB */
+
+#ifndef WGL_ARB_make_current_read
+# define WGL_ARB_make_current_read 1
+# define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043
+# define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
+ typedef BOOL(WINAPI* PFNWGLMAKECONTEXTCURRENTARBPROC)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+ typedef HDC(WINAPI* PFNWGLGETCURRENTREADDCARBPROC)(void);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+ HDC WINAPI wglGetCurrentReadDCARB(void);
+# endif
+#endif /* WGL_ARB_make_current_read */
+
+#ifndef WGL_ARB_multisample
+# define WGL_ARB_multisample 1
+# define WGL_SAMPLE_BUFFERS_ARB 0x2041
+# define WGL_SAMPLES_ARB 0x2042
+#endif /* WGL_ARB_multisample */
+
+#ifndef WGL_ARB_pbuffer
+# define WGL_ARB_pbuffer 1
+ DECLARE_HANDLE(HPBUFFERARB);
+# define WGL_DRAW_TO_PBUFFER_ARB 0x202D
+# define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
+# define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
+# define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
+# define WGL_PBUFFER_LARGEST_ARB 0x2033
+# define WGL_PBUFFER_WIDTH_ARB 0x2034
+# define WGL_PBUFFER_HEIGHT_ARB 0x2035
+# define WGL_PBUFFER_LOST_ARB 0x2036
+ typedef HPBUFFERARB(WINAPI* PFNWGLCREATEPBUFFERARBPROC)(
+ HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+ typedef HDC(WINAPI* PFNWGLGETPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer);
+ typedef int(WINAPI* PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer, HDC hDC);
+ typedef BOOL(WINAPI* PFNWGLDESTROYPBUFFERARBPROC)(HPBUFFERARB hPbuffer);
+ typedef BOOL(WINAPI* PFNWGLQUERYPBUFFERARBPROC)(
+ HPBUFFERARB hPbuffer, int iAttribute, int* piValue);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ HPBUFFERARB WINAPI wglCreatePbufferARB(
+ HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+ HDC WINAPI wglGetPbufferDCARB(HPBUFFERARB hPbuffer);
+ int WINAPI wglReleasePbufferDCARB(HPBUFFERARB hPbuffer, HDC hDC);
+ BOOL WINAPI wglDestroyPbufferARB(HPBUFFERARB hPbuffer);
+ BOOL WINAPI wglQueryPbufferARB(HPBUFFERARB hPbuffer, int iAttribute, int* piValue);
+# endif
+#endif /* WGL_ARB_pbuffer */
+
+#ifndef WGL_ARB_pixel_format
+# define WGL_ARB_pixel_format 1
+# define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+# define WGL_DRAW_TO_WINDOW_ARB 0x2001
+# define WGL_DRAW_TO_BITMAP_ARB 0x2002
+# define WGL_ACCELERATION_ARB 0x2003
+# define WGL_NEED_PALETTE_ARB 0x2004
+# define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
+# define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
+# define WGL_SWAP_METHOD_ARB 0x2007
+# define WGL_NUMBER_OVERLAYS_ARB 0x2008
+# define WGL_NUMBER_UNDERLAYS_ARB 0x2009
+# define WGL_TRANSPARENT_ARB 0x200A
+# define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
+# define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
+# define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
+# define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
+# define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
+# define WGL_SHARE_DEPTH_ARB 0x200C
+# define WGL_SHARE_STENCIL_ARB 0x200D
+# define WGL_SHARE_ACCUM_ARB 0x200E
+# define WGL_SUPPORT_GDI_ARB 0x200F
+# define WGL_SUPPORT_OPENGL_ARB 0x2010
+# define WGL_DOUBLE_BUFFER_ARB 0x2011
+# define WGL_STEREO_ARB 0x2012
+# define WGL_PIXEL_TYPE_ARB 0x2013
+# define WGL_COLOR_BITS_ARB 0x2014
+# define WGL_RED_BITS_ARB 0x2015
+# define WGL_RED_SHIFT_ARB 0x2016
+# define WGL_GREEN_BITS_ARB 0x2017
+# define WGL_GREEN_SHIFT_ARB 0x2018
+# define WGL_BLUE_BITS_ARB 0x2019
+# define WGL_BLUE_SHIFT_ARB 0x201A
+# define WGL_ALPHA_BITS_ARB 0x201B
+# define WGL_ALPHA_SHIFT_ARB 0x201C
+# define WGL_ACCUM_BITS_ARB 0x201D
+# define WGL_ACCUM_RED_BITS_ARB 0x201E
+# define WGL_ACCUM_GREEN_BITS_ARB 0x201F
+# define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+# define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+# define WGL_DEPTH_BITS_ARB 0x2022
+# define WGL_STENCIL_BITS_ARB 0x2023
+# define WGL_AUX_BUFFERS_ARB 0x2024
+# define WGL_NO_ACCELERATION_ARB 0x2025
+# define WGL_GENERIC_ACCELERATION_ARB 0x2026
+# define WGL_FULL_ACCELERATION_ARB 0x2027
+# define WGL_SWAP_EXCHANGE_ARB 0x2028
+# define WGL_SWAP_COPY_ARB 0x2029
+# define WGL_SWAP_UNDEFINED_ARB 0x202A
+# define WGL_TYPE_RGBA_ARB 0x202B
+# define WGL_TYPE_COLORINDEX_ARB 0x202C
+ typedef BOOL(WINAPI* PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int* piAttributes,
+ int* piValues);
+ typedef BOOL(WINAPI* PFNWGLGETPIXELFORMATATTRIBFVARBPROC)(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int* piAttributes,
+ FLOAT* pfValues);
+ typedef BOOL(WINAPI* PFNWGLCHOOSEPIXELFORMATARBPROC)(
+ HDC hdc,
+ const int* piAttribIList,
+ const FLOAT* pfAttribFList,
+ UINT nMaxFormats,
+ int* piFormats,
+ UINT* nNumFormats);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglGetPixelFormatAttribivARB(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int* piAttributes,
+ int* piValues);
+ BOOL WINAPI wglGetPixelFormatAttribfvARB(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int* piAttributes,
+ FLOAT* pfValues);
+ BOOL WINAPI wglChoosePixelFormatARB(
+ HDC hdc,
+ const int* piAttribIList,
+ const FLOAT* pfAttribFList,
+ UINT nMaxFormats,
+ int* piFormats,
+ UINT* nNumFormats);
+# endif
+#endif /* WGL_ARB_pixel_format */
+
+#ifndef WGL_ARB_pixel_format_float
+# define WGL_ARB_pixel_format_float 1
+# define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
+#endif /* WGL_ARB_pixel_format_float */
+
+#ifndef WGL_ARB_render_texture
+# define WGL_ARB_render_texture 1
+# define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
+# define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
+# define WGL_TEXTURE_FORMAT_ARB 0x2072
+# define WGL_TEXTURE_TARGET_ARB 0x2073
+# define WGL_MIPMAP_TEXTURE_ARB 0x2074
+# define WGL_TEXTURE_RGB_ARB 0x2075
+# define WGL_TEXTURE_RGBA_ARB 0x2076
+# define WGL_NO_TEXTURE_ARB 0x2077
+# define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
+# define WGL_TEXTURE_1D_ARB 0x2079
+# define WGL_TEXTURE_2D_ARB 0x207A
+# define WGL_MIPMAP_LEVEL_ARB 0x207B
+# define WGL_CUBE_MAP_FACE_ARB 0x207C
+# define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+# define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
+# define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
+# define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
+# define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
+# define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
+# define WGL_FRONT_LEFT_ARB 0x2083
+# define WGL_FRONT_RIGHT_ARB 0x2084
+# define WGL_BACK_LEFT_ARB 0x2085
+# define WGL_BACK_RIGHT_ARB 0x2086
+# define WGL_AUX0_ARB 0x2087
+# define WGL_AUX1_ARB 0x2088
+# define WGL_AUX2_ARB 0x2089
+# define WGL_AUX3_ARB 0x208A
+# define WGL_AUX4_ARB 0x208B
+# define WGL_AUX5_ARB 0x208C
+# define WGL_AUX6_ARB 0x208D
+# define WGL_AUX7_ARB 0x208E
+# define WGL_AUX8_ARB 0x208F
+# define WGL_AUX9_ARB 0x2090
+ typedef BOOL(WINAPI* PFNWGLBINDTEXIMAGEARBPROC)(HPBUFFERARB hPbuffer, int iBuffer);
+ typedef BOOL(WINAPI* PFNWGLRELEASETEXIMAGEARBPROC)(HPBUFFERARB hPbuffer, int iBuffer);
+ typedef BOOL(WINAPI* PFNWGLSETPBUFFERATTRIBARBPROC)(
+ HPBUFFERARB hPbuffer, const int* piAttribList);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer);
+ BOOL WINAPI wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer);
+ BOOL WINAPI wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int* piAttribList);
+# endif
+#endif /* WGL_ARB_render_texture */
+
+#ifndef WGL_ARB_robustness_application_isolation
+# define WGL_ARB_robustness_application_isolation 1
+# define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+#endif /* WGL_ARB_robustness_application_isolation */
+
+#ifndef WGL_ARB_robustness_share_group_isolation
+# define WGL_ARB_robustness_share_group_isolation 1
+#endif /* WGL_ARB_robustness_share_group_isolation */
+
+#ifndef WGL_3DFX_multisample
+# define WGL_3DFX_multisample 1
+# define WGL_SAMPLE_BUFFERS_3DFX 0x2060
+# define WGL_SAMPLES_3DFX 0x2061
+#endif /* WGL_3DFX_multisample */
+
+#ifndef WGL_3DL_stereo_control
+# define WGL_3DL_stereo_control 1
+# define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055
+# define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056
+# define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057
+# define WGL_STEREO_POLARITY_INVERT_3DL 0x2058
+ typedef BOOL(WINAPI* PFNWGLSETSTEREOEMITTERSTATE3DLPROC)(HDC hDC, UINT uState);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglSetStereoEmitterState3DL(HDC hDC, UINT uState);
+# endif
+#endif /* WGL_3DL_stereo_control */
+
+#ifndef WGL_AMD_gpu_association
+# define WGL_AMD_gpu_association 1
+# define WGL_GPU_VENDOR_AMD 0x1F00
+# define WGL_GPU_RENDERER_STRING_AMD 0x1F01
+# define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+# define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
+# define WGL_GPU_RAM_AMD 0x21A3
+# define WGL_GPU_CLOCK_AMD 0x21A4
+# define WGL_GPU_NUM_PIPES_AMD 0x21A5
+# define WGL_GPU_NUM_SIMD_AMD 0x21A6
+# define WGL_GPU_NUM_RB_AMD 0x21A7
+# define WGL_GPU_NUM_SPI_AMD 0x21A8
+ typedef UINT(WINAPI* PFNWGLGETGPUIDSAMDPROC)(UINT maxCount, UINT* ids);
+ typedef INT(WINAPI* PFNWGLGETGPUINFOAMDPROC)(
+ UINT id, INT property, GLenum dataType, UINT size, void* data);
+ typedef UINT(WINAPI* PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc);
+ typedef HGLRC(WINAPI* PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC)(UINT id);
+ typedef HGLRC(WINAPI* PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)(
+ UINT id, HGLRC hShareContext, const int* attribList);
+ typedef BOOL(WINAPI* PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC)(HGLRC hglrc);
+ typedef BOOL(WINAPI* PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)(HGLRC hglrc);
+ typedef HGLRC(WINAPI* PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC)(void);
+ typedef VOID(WINAPI* PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)(
+ HGLRC dstCtx,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ UINT WINAPI wglGetGPUIDsAMD(UINT maxCount, UINT* ids);
+ INT WINAPI wglGetGPUInfoAMD(UINT id, INT property, GLenum dataType, UINT size, void* data);
+ UINT WINAPI wglGetContextGPUIDAMD(HGLRC hglrc);
+ HGLRC WINAPI wglCreateAssociatedContextAMD(UINT id);
+ HGLRC WINAPI
+ wglCreateAssociatedContextAttribsAMD(UINT id, HGLRC hShareContext, const int* attribList);
+ BOOL WINAPI wglDeleteAssociatedContextAMD(HGLRC hglrc);
+ BOOL WINAPI wglMakeAssociatedContextCurrentAMD(HGLRC hglrc);
+ HGLRC WINAPI wglGetCurrentAssociatedContextAMD(void);
+ VOID WINAPI wglBlitContextFramebufferAMD(
+ HGLRC dstCtx,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+# endif
+#endif /* WGL_AMD_gpu_association */
+
+#ifndef WGL_ATI_pixel_format_float
+# define WGL_ATI_pixel_format_float 1
+# define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0
+#endif /* WGL_ATI_pixel_format_float */
+
+#ifndef WGL_ATI_render_texture_rectangle
+# define WGL_ATI_render_texture_rectangle 1
+# define WGL_TEXTURE_RECTANGLE_ATI 0x21A5
+#endif /* WGL_ATI_render_texture_rectangle */
+
+#ifndef WGL_EXT_colorspace
+# define WGL_EXT_colorspace 1
+# define WGL_COLORSPACE_EXT 0x309D
+# define WGL_COLORSPACE_SRGB_EXT 0x3089
+# define WGL_COLORSPACE_LINEAR_EXT 0x308A
+#endif /* WGL_EXT_colorspace */
+
+#ifndef WGL_EXT_create_context_es2_profile
+# define WGL_EXT_create_context_es2_profile 1
+# define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#endif /* WGL_EXT_create_context_es2_profile */
+
+#ifndef WGL_EXT_create_context_es_profile
+# define WGL_EXT_create_context_es_profile 1
+# define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#endif /* WGL_EXT_create_context_es_profile */
+
+#ifndef WGL_EXT_depth_float
+# define WGL_EXT_depth_float 1
+# define WGL_DEPTH_FLOAT_EXT 0x2040
+#endif /* WGL_EXT_depth_float */
+
+#ifndef WGL_EXT_display_color_table
+# define WGL_EXT_display_color_table 1
+ typedef GLboolean(WINAPI* PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC)(GLushort id);
+ typedef GLboolean(WINAPI* PFNWGLLOADDISPLAYCOLORTABLEEXTPROC)(
+ const GLushort* table, GLuint length);
+ typedef GLboolean(WINAPI* PFNWGLBINDDISPLAYCOLORTABLEEXTPROC)(GLushort id);
+ typedef VOID(WINAPI* PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC)(GLushort id);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ GLboolean WINAPI wglCreateDisplayColorTableEXT(GLushort id);
+ GLboolean WINAPI wglLoadDisplayColorTableEXT(const GLushort* table, GLuint length);
+ GLboolean WINAPI wglBindDisplayColorTableEXT(GLushort id);
+ VOID WINAPI wglDestroyDisplayColorTableEXT(GLushort id);
+# endif
+#endif /* WGL_EXT_display_color_table */
+
+#ifndef WGL_EXT_extensions_string
+# define WGL_EXT_extensions_string 1
+ typedef const char*(WINAPI* PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ const char* WINAPI wglGetExtensionsStringEXT(void);
+# endif
+#endif /* WGL_EXT_extensions_string */
+
+#ifndef WGL_EXT_framebuffer_sRGB
+# define WGL_EXT_framebuffer_sRGB 1
+# define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
+#endif /* WGL_EXT_framebuffer_sRGB */
+
+#ifndef WGL_EXT_make_current_read
+# define WGL_EXT_make_current_read 1
+# define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043
+ typedef BOOL(WINAPI* PFNWGLMAKECONTEXTCURRENTEXTPROC)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+ typedef HDC(WINAPI* PFNWGLGETCURRENTREADDCEXTPROC)(void);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglMakeContextCurrentEXT(HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+ HDC WINAPI wglGetCurrentReadDCEXT(void);
+# endif
+#endif /* WGL_EXT_make_current_read */
+
+#ifndef WGL_EXT_multisample
+# define WGL_EXT_multisample 1
+# define WGL_SAMPLE_BUFFERS_EXT 0x2041
+# define WGL_SAMPLES_EXT 0x2042
+#endif /* WGL_EXT_multisample */
+
+#ifndef WGL_EXT_pbuffer
+# define WGL_EXT_pbuffer 1
+ DECLARE_HANDLE(HPBUFFEREXT);
+# define WGL_DRAW_TO_PBUFFER_EXT 0x202D
+# define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E
+# define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F
+# define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030
+# define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031
+# define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032
+# define WGL_PBUFFER_LARGEST_EXT 0x2033
+# define WGL_PBUFFER_WIDTH_EXT 0x2034
+# define WGL_PBUFFER_HEIGHT_EXT 0x2035
+ typedef HPBUFFEREXT(WINAPI* PFNWGLCREATEPBUFFEREXTPROC)(
+ HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+ typedef HDC(WINAPI* PFNWGLGETPBUFFERDCEXTPROC)(HPBUFFEREXT hPbuffer);
+ typedef int(WINAPI* PFNWGLRELEASEPBUFFERDCEXTPROC)(HPBUFFEREXT hPbuffer, HDC hDC);
+ typedef BOOL(WINAPI* PFNWGLDESTROYPBUFFEREXTPROC)(HPBUFFEREXT hPbuffer);
+ typedef BOOL(WINAPI* PFNWGLQUERYPBUFFEREXTPROC)(
+ HPBUFFEREXT hPbuffer, int iAttribute, int* piValue);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ HPBUFFEREXT WINAPI wglCreatePbufferEXT(
+ HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+ HDC WINAPI wglGetPbufferDCEXT(HPBUFFEREXT hPbuffer);
+ int WINAPI wglReleasePbufferDCEXT(HPBUFFEREXT hPbuffer, HDC hDC);
+ BOOL WINAPI wglDestroyPbufferEXT(HPBUFFEREXT hPbuffer);
+ BOOL WINAPI wglQueryPbufferEXT(HPBUFFEREXT hPbuffer, int iAttribute, int* piValue);
+# endif
+#endif /* WGL_EXT_pbuffer */
+
+#ifndef WGL_EXT_pixel_format
+# define WGL_EXT_pixel_format 1
+# define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000
+# define WGL_DRAW_TO_WINDOW_EXT 0x2001
+# define WGL_DRAW_TO_BITMAP_EXT 0x2002
+# define WGL_ACCELERATION_EXT 0x2003
+# define WGL_NEED_PALETTE_EXT 0x2004
+# define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005
+# define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006
+# define WGL_SWAP_METHOD_EXT 0x2007
+# define WGL_NUMBER_OVERLAYS_EXT 0x2008
+# define WGL_NUMBER_UNDERLAYS_EXT 0x2009
+# define WGL_TRANSPARENT_EXT 0x200A
+# define WGL_TRANSPARENT_VALUE_EXT 0x200B
+# define WGL_SHARE_DEPTH_EXT 0x200C
+# define WGL_SHARE_STENCIL_EXT 0x200D
+# define WGL_SHARE_ACCUM_EXT 0x200E
+# define WGL_SUPPORT_GDI_EXT 0x200F
+# define WGL_SUPPORT_OPENGL_EXT 0x2010
+# define WGL_DOUBLE_BUFFER_EXT 0x2011
+# define WGL_STEREO_EXT 0x2012
+# define WGL_PIXEL_TYPE_EXT 0x2013
+# define WGL_COLOR_BITS_EXT 0x2014
+# define WGL_RED_BITS_EXT 0x2015
+# define WGL_RED_SHIFT_EXT 0x2016
+# define WGL_GREEN_BITS_EXT 0x2017
+# define WGL_GREEN_SHIFT_EXT 0x2018
+# define WGL_BLUE_BITS_EXT 0x2019
+# define WGL_BLUE_SHIFT_EXT 0x201A
+# define WGL_ALPHA_BITS_EXT 0x201B
+# define WGL_ALPHA_SHIFT_EXT 0x201C
+# define WGL_ACCUM_BITS_EXT 0x201D
+# define WGL_ACCUM_RED_BITS_EXT 0x201E
+# define WGL_ACCUM_GREEN_BITS_EXT 0x201F
+# define WGL_ACCUM_BLUE_BITS_EXT 0x2020
+# define WGL_ACCUM_ALPHA_BITS_EXT 0x2021
+# define WGL_DEPTH_BITS_EXT 0x2022
+# define WGL_STENCIL_BITS_EXT 0x2023
+# define WGL_AUX_BUFFERS_EXT 0x2024
+# define WGL_NO_ACCELERATION_EXT 0x2025
+# define WGL_GENERIC_ACCELERATION_EXT 0x2026
+# define WGL_FULL_ACCELERATION_EXT 0x2027
+# define WGL_SWAP_EXCHANGE_EXT 0x2028
+# define WGL_SWAP_COPY_EXT 0x2029
+# define WGL_SWAP_UNDEFINED_EXT 0x202A
+# define WGL_TYPE_RGBA_EXT 0x202B
+# define WGL_TYPE_COLORINDEX_EXT 0x202C
+ typedef BOOL(WINAPI* PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ int* piAttributes,
+ int* piValues);
+ typedef BOOL(WINAPI* PFNWGLGETPIXELFORMATATTRIBFVEXTPROC)(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ int* piAttributes,
+ FLOAT* pfValues);
+ typedef BOOL(WINAPI* PFNWGLCHOOSEPIXELFORMATEXTPROC)(
+ HDC hdc,
+ const int* piAttribIList,
+ const FLOAT* pfAttribFList,
+ UINT nMaxFormats,
+ int* piFormats,
+ UINT* nNumFormats);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglGetPixelFormatAttribivEXT(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ int* piAttributes,
+ int* piValues);
+ BOOL WINAPI wglGetPixelFormatAttribfvEXT(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ int* piAttributes,
+ FLOAT* pfValues);
+ BOOL WINAPI wglChoosePixelFormatEXT(
+ HDC hdc,
+ const int* piAttribIList,
+ const FLOAT* pfAttribFList,
+ UINT nMaxFormats,
+ int* piFormats,
+ UINT* nNumFormats);
+# endif
+#endif /* WGL_EXT_pixel_format */
+
+#ifndef WGL_EXT_pixel_format_packed_float
+# define WGL_EXT_pixel_format_packed_float 1
+# define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
+#endif /* WGL_EXT_pixel_format_packed_float */
+
+#ifndef WGL_EXT_swap_control
+# define WGL_EXT_swap_control 1
+ typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval);
+ typedef int(WINAPI* PFNWGLGETSWAPINTERVALEXTPROC)(void);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglSwapIntervalEXT(int interval);
+ int WINAPI wglGetSwapIntervalEXT(void);
+# endif
+#endif /* WGL_EXT_swap_control */
+
+#ifndef WGL_EXT_swap_control_tear
+# define WGL_EXT_swap_control_tear 1
+#endif /* WGL_EXT_swap_control_tear */
+
+#ifndef WGL_I3D_digital_video_control
+# define WGL_I3D_digital_video_control 1
+# define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
+# define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
+# define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
+# define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
+ typedef BOOL(WINAPI* PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC)(
+ HDC hDC, int iAttribute, int* piValue);
+ typedef BOOL(WINAPI* PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC)(
+ HDC hDC, int iAttribute, const int* piValue);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglGetDigitalVideoParametersI3D(HDC hDC, int iAttribute, int* piValue);
+ BOOL WINAPI wglSetDigitalVideoParametersI3D(HDC hDC, int iAttribute, const int* piValue);
+# endif
+#endif /* WGL_I3D_digital_video_control */
+
+#ifndef WGL_I3D_gamma
+# define WGL_I3D_gamma 1
+# define WGL_GAMMA_TABLE_SIZE_I3D 0x204E
+# define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F
+ typedef BOOL(WINAPI* PFNWGLGETGAMMATABLEPARAMETERSI3DPROC)(
+ HDC hDC, int iAttribute, int* piValue);
+ typedef BOOL(WINAPI* PFNWGLSETGAMMATABLEPARAMETERSI3DPROC)(
+ HDC hDC, int iAttribute, const int* piValue);
+ typedef BOOL(WINAPI* PFNWGLGETGAMMATABLEI3DPROC)(
+ HDC hDC, int iEntries, USHORT* puRed, USHORT* puGreen, USHORT* puBlue);
+ typedef BOOL(WINAPI* PFNWGLSETGAMMATABLEI3DPROC)(
+ HDC hDC, int iEntries, const USHORT* puRed, const USHORT* puGreen, const USHORT* puBlue);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglGetGammaTableParametersI3D(HDC hDC, int iAttribute, int* piValue);
+ BOOL WINAPI wglSetGammaTableParametersI3D(HDC hDC, int iAttribute, const int* piValue);
+ BOOL WINAPI
+ wglGetGammaTableI3D(HDC hDC, int iEntries, USHORT* puRed, USHORT* puGreen, USHORT* puBlue);
+ BOOL WINAPI wglSetGammaTableI3D(
+ HDC hDC, int iEntries, const USHORT* puRed, const USHORT* puGreen, const USHORT* puBlue);
+# endif
+#endif /* WGL_I3D_gamma */
+
+#ifndef WGL_I3D_genlock
+# define WGL_I3D_genlock 1
+# define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
+# define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045
+# define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046
+# define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047
+# define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
+# define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
+# define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
+# define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
+# define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
+ typedef BOOL(WINAPI* PFNWGLENABLEGENLOCKI3DPROC)(HDC hDC);
+ typedef BOOL(WINAPI* PFNWGLDISABLEGENLOCKI3DPROC)(HDC hDC);
+ typedef BOOL(WINAPI* PFNWGLISENABLEDGENLOCKI3DPROC)(HDC hDC, BOOL* pFlag);
+ typedef BOOL(WINAPI* PFNWGLGENLOCKSOURCEI3DPROC)(HDC hDC, UINT uSource);
+ typedef BOOL(WINAPI* PFNWGLGETGENLOCKSOURCEI3DPROC)(HDC hDC, UINT* uSource);
+ typedef BOOL(WINAPI* PFNWGLGENLOCKSOURCEEDGEI3DPROC)(HDC hDC, UINT uEdge);
+ typedef BOOL(WINAPI* PFNWGLGETGENLOCKSOURCEEDGEI3DPROC)(HDC hDC, UINT* uEdge);
+ typedef BOOL(WINAPI* PFNWGLGENLOCKSAMPLERATEI3DPROC)(HDC hDC, UINT uRate);
+ typedef BOOL(WINAPI* PFNWGLGETGENLOCKSAMPLERATEI3DPROC)(HDC hDC, UINT* uRate);
+ typedef BOOL(WINAPI* PFNWGLGENLOCKSOURCEDELAYI3DPROC)(HDC hDC, UINT uDelay);
+ typedef BOOL(WINAPI* PFNWGLGETGENLOCKSOURCEDELAYI3DPROC)(HDC hDC, UINT* uDelay);
+ typedef BOOL(WINAPI* PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC)(
+ HDC hDC, UINT* uMaxLineDelay, UINT* uMaxPixelDelay);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglEnableGenlockI3D(HDC hDC);
+ BOOL WINAPI wglDisableGenlockI3D(HDC hDC);
+ BOOL WINAPI wglIsEnabledGenlockI3D(HDC hDC, BOOL* pFlag);
+ BOOL WINAPI wglGenlockSourceI3D(HDC hDC, UINT uSource);
+ BOOL WINAPI wglGetGenlockSourceI3D(HDC hDC, UINT* uSource);
+ BOOL WINAPI wglGenlockSourceEdgeI3D(HDC hDC, UINT uEdge);
+ BOOL WINAPI wglGetGenlockSourceEdgeI3D(HDC hDC, UINT* uEdge);
+ BOOL WINAPI wglGenlockSampleRateI3D(HDC hDC, UINT uRate);
+ BOOL WINAPI wglGetGenlockSampleRateI3D(HDC hDC, UINT* uRate);
+ BOOL WINAPI wglGenlockSourceDelayI3D(HDC hDC, UINT uDelay);
+ BOOL WINAPI wglGetGenlockSourceDelayI3D(HDC hDC, UINT* uDelay);
+ BOOL WINAPI
+ wglQueryGenlockMaxSourceDelayI3D(HDC hDC, UINT* uMaxLineDelay, UINT* uMaxPixelDelay);
+# endif
+#endif /* WGL_I3D_genlock */
+
+#ifndef WGL_I3D_image_buffer
+# define WGL_I3D_image_buffer 1
+# define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001
+# define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002
+ typedef LPVOID(WINAPI* PFNWGLCREATEIMAGEBUFFERI3DPROC)(HDC hDC, DWORD dwSize, UINT uFlags);
+ typedef BOOL(WINAPI* PFNWGLDESTROYIMAGEBUFFERI3DPROC)(HDC hDC, LPVOID pAddress);
+ typedef BOOL(WINAPI* PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC)(
+ HDC hDC, const HANDLE* pEvent, const LPVOID* pAddress, const DWORD* pSize, UINT count);
+ typedef BOOL(WINAPI* PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC)(
+ HDC hDC, const LPVOID* pAddress, UINT count);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ LPVOID WINAPI wglCreateImageBufferI3D(HDC hDC, DWORD dwSize, UINT uFlags);
+ BOOL WINAPI wglDestroyImageBufferI3D(HDC hDC, LPVOID pAddress);
+ BOOL WINAPI wglAssociateImageBufferEventsI3D(
+ HDC hDC, const HANDLE* pEvent, const LPVOID* pAddress, const DWORD* pSize, UINT count);
+ BOOL WINAPI wglReleaseImageBufferEventsI3D(HDC hDC, const LPVOID* pAddress, UINT count);
+# endif
+#endif /* WGL_I3D_image_buffer */
+
+#ifndef WGL_I3D_swap_frame_lock
+# define WGL_I3D_swap_frame_lock 1
+ typedef BOOL(WINAPI* PFNWGLENABLEFRAMELOCKI3DPROC)(void);
+ typedef BOOL(WINAPI* PFNWGLDISABLEFRAMELOCKI3DPROC)(void);
+ typedef BOOL(WINAPI* PFNWGLISENABLEDFRAMELOCKI3DPROC)(BOOL* pFlag);
+ typedef BOOL(WINAPI* PFNWGLQUERYFRAMELOCKMASTERI3DPROC)(BOOL* pFlag);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglEnableFrameLockI3D(void);
+ BOOL WINAPI wglDisableFrameLockI3D(void);
+ BOOL WINAPI wglIsEnabledFrameLockI3D(BOOL* pFlag);
+ BOOL WINAPI wglQueryFrameLockMasterI3D(BOOL* pFlag);
+# endif
+#endif /* WGL_I3D_swap_frame_lock */
+
+#ifndef WGL_I3D_swap_frame_usage
+# define WGL_I3D_swap_frame_usage 1
+ typedef BOOL(WINAPI* PFNWGLGETFRAMEUSAGEI3DPROC)(float* pUsage);
+ typedef BOOL(WINAPI* PFNWGLBEGINFRAMETRACKINGI3DPROC)(void);
+ typedef BOOL(WINAPI* PFNWGLENDFRAMETRACKINGI3DPROC)(void);
+ typedef BOOL(WINAPI* PFNWGLQUERYFRAMETRACKINGI3DPROC)(
+ DWORD* pFrameCount, DWORD* pMissedFrames, float* pLastMissedUsage);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglGetFrameUsageI3D(float* pUsage);
+ BOOL WINAPI wglBeginFrameTrackingI3D(void);
+ BOOL WINAPI wglEndFrameTrackingI3D(void);
+ BOOL WINAPI
+ wglQueryFrameTrackingI3D(DWORD* pFrameCount, DWORD* pMissedFrames, float* pLastMissedUsage);
+# endif
+#endif /* WGL_I3D_swap_frame_usage */
+
+#ifndef WGL_NV_DX_interop
+# define WGL_NV_DX_interop 1
+# define WGL_ACCESS_READ_ONLY_NV 0x00000000
+# define WGL_ACCESS_READ_WRITE_NV 0x00000001
+# define WGL_ACCESS_WRITE_DISCARD_NV 0x00000002
+ typedef BOOL(WINAPI* PFNWGLDXSETRESOURCESHAREHANDLENVPROC)(void* dxObject, HANDLE shareHandle);
+ typedef HANDLE(WINAPI* PFNWGLDXOPENDEVICENVPROC)(void* dxDevice);
+ typedef BOOL(WINAPI* PFNWGLDXCLOSEDEVICENVPROC)(HANDLE hDevice);
+ typedef HANDLE(WINAPI* PFNWGLDXREGISTEROBJECTNVPROC)(
+ HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access);
+ typedef BOOL(WINAPI* PFNWGLDXUNREGISTEROBJECTNVPROC)(HANDLE hDevice, HANDLE hObject);
+ typedef BOOL(WINAPI* PFNWGLDXOBJECTACCESSNVPROC)(HANDLE hObject, GLenum access);
+ typedef BOOL(WINAPI* PFNWGLDXLOCKOBJECTSNVPROC)(HANDLE hDevice, GLint count, HANDLE* hObjects);
+ typedef BOOL(WINAPI* PFNWGLDXUNLOCKOBJECTSNVPROC)(
+ HANDLE hDevice, GLint count, HANDLE* hObjects);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglDXSetResourceShareHandleNV(void* dxObject, HANDLE shareHandle);
+ HANDLE WINAPI wglDXOpenDeviceNV(void* dxDevice);
+ BOOL WINAPI wglDXCloseDeviceNV(HANDLE hDevice);
+ HANDLE WINAPI wglDXRegisterObjectNV(
+ HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access);
+ BOOL WINAPI wglDXUnregisterObjectNV(HANDLE hDevice, HANDLE hObject);
+ BOOL WINAPI wglDXObjectAccessNV(HANDLE hObject, GLenum access);
+ BOOL WINAPI wglDXLockObjectsNV(HANDLE hDevice, GLint count, HANDLE* hObjects);
+ BOOL WINAPI wglDXUnlockObjectsNV(HANDLE hDevice, GLint count, HANDLE* hObjects);
+# endif
+#endif /* WGL_NV_DX_interop */
+
+#ifndef WGL_NV_DX_interop2
+# define WGL_NV_DX_interop2 1
+#endif /* WGL_NV_DX_interop2 */
+
+#ifndef WGL_NV_copy_image
+# define WGL_NV_copy_image 1
+ typedef BOOL(WINAPI* PFNWGLCOPYIMAGESUBDATANVPROC)(
+ HGLRC hSrcRC,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ HGLRC hDstRC,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglCopyImageSubDataNV(
+ HGLRC hSrcRC,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ HGLRC hDstRC,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+# endif
+#endif /* WGL_NV_copy_image */
+
+#ifndef WGL_NV_delay_before_swap
+# define WGL_NV_delay_before_swap 1
+ typedef BOOL(WINAPI* PFNWGLDELAYBEFORESWAPNVPROC)(HDC hDC, GLfloat seconds);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglDelayBeforeSwapNV(HDC hDC, GLfloat seconds);
+# endif
+#endif /* WGL_NV_delay_before_swap */
+
+#ifndef WGL_NV_float_buffer
+# define WGL_NV_float_buffer 1
+# define WGL_FLOAT_COMPONENTS_NV 0x20B0
+# define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
+# define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
+# define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
+# define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
+# define WGL_TEXTURE_FLOAT_R_NV 0x20B5
+# define WGL_TEXTURE_FLOAT_RG_NV 0x20B6
+# define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7
+# define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8
+#endif /* WGL_NV_float_buffer */
+
+#ifndef WGL_NV_gpu_affinity
+# define WGL_NV_gpu_affinity 1
+ DECLARE_HANDLE(HGPUNV);
+ struct _GPU_DEVICE
+ {
+ DWORD cb;
+ CHAR DeviceName[32];
+ CHAR DeviceString[128];
+ DWORD Flags;
+ RECT rcVirtualScreen;
+ };
+ typedef struct _GPU_DEVICE* PGPU_DEVICE;
+# define ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0
+# define ERROR_MISSING_AFFINITY_MASK_NV 0x20D1
+ typedef BOOL(WINAPI* PFNWGLENUMGPUSNVPROC)(UINT iGpuIndex, HGPUNV* phGpu);
+ typedef BOOL(WINAPI* PFNWGLENUMGPUDEVICESNVPROC)(
+ HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
+ typedef HDC(WINAPI* PFNWGLCREATEAFFINITYDCNVPROC)(const HGPUNV* phGpuList);
+ typedef BOOL(WINAPI* PFNWGLENUMGPUSFROMAFFINITYDCNVPROC)(
+ HDC hAffinityDC, UINT iGpuIndex, HGPUNV* hGpu);
+ typedef BOOL(WINAPI* PFNWGLDELETEDCNVPROC)(HDC hdc);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglEnumGpusNV(UINT iGpuIndex, HGPUNV* phGpu);
+ BOOL WINAPI wglEnumGpuDevicesNV(HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
+ HDC WINAPI wglCreateAffinityDCNV(const HGPUNV* phGpuList);
+ BOOL WINAPI wglEnumGpusFromAffinityDCNV(HDC hAffinityDC, UINT iGpuIndex, HGPUNV* hGpu);
+ BOOL WINAPI wglDeleteDCNV(HDC hdc);
+# endif
+#endif /* WGL_NV_gpu_affinity */
+
+#ifndef WGL_NV_multigpu_context
+# define WGL_NV_multigpu_context 1
+# define WGL_CONTEXT_MULTIGPU_ATTRIB_NV 0x20AA
+# define WGL_CONTEXT_MULTIGPU_ATTRIB_SINGLE_NV 0x20AB
+# define WGL_CONTEXT_MULTIGPU_ATTRIB_AFR_NV 0x20AC
+# define WGL_CONTEXT_MULTIGPU_ATTRIB_MULTICAST_NV 0x20AD
+# define WGL_CONTEXT_MULTIGPU_ATTRIB_MULTI_DISPLAY_MULTICAST_NV 0x20AE
+#endif /* WGL_NV_multigpu_context */
+
+#ifndef WGL_NV_multisample_coverage
+# define WGL_NV_multisample_coverage 1
+# define WGL_COVERAGE_SAMPLES_NV 0x2042
+# define WGL_COLOR_SAMPLES_NV 0x20B9
+#endif /* WGL_NV_multisample_coverage */
+
+#ifndef WGL_NV_present_video
+# define WGL_NV_present_video 1
+ DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
+# define WGL_NUM_VIDEO_SLOTS_NV 0x20F0
+ typedef int(WINAPI* PFNWGLENUMERATEVIDEODEVICESNVPROC)(
+ HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList);
+ typedef BOOL(WINAPI* PFNWGLBINDVIDEODEVICENVPROC)(
+ HDC hDc,
+ unsigned int uVideoSlot,
+ HVIDEOOUTPUTDEVICENV hVideoDevice,
+ const int* piAttribList);
+ typedef BOOL(WINAPI* PFNWGLQUERYCURRENTCONTEXTNVPROC)(int iAttribute, int* piValue);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ int WINAPI wglEnumerateVideoDevicesNV(HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList);
+ BOOL WINAPI wglBindVideoDeviceNV(
+ HDC hDc,
+ unsigned int uVideoSlot,
+ HVIDEOOUTPUTDEVICENV hVideoDevice,
+ const int* piAttribList);
+ BOOL WINAPI wglQueryCurrentContextNV(int iAttribute, int* piValue);
+# endif
+#endif /* WGL_NV_present_video */
+
+#ifndef WGL_NV_render_depth_texture
+# define WGL_NV_render_depth_texture 1
+# define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3
+# define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
+# define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5
+# define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
+# define WGL_DEPTH_COMPONENT_NV 0x20A7
+#endif /* WGL_NV_render_depth_texture */
+
+#ifndef WGL_NV_render_texture_rectangle
+# define WGL_NV_render_texture_rectangle 1
+# define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
+# define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
+# define WGL_TEXTURE_RECTANGLE_NV 0x20A2
+#endif /* WGL_NV_render_texture_rectangle */
+
+#ifndef WGL_NV_swap_group
+# define WGL_NV_swap_group 1
+ typedef BOOL(WINAPI* PFNWGLJOINSWAPGROUPNVPROC)(HDC hDC, GLuint group);
+ typedef BOOL(WINAPI* PFNWGLBINDSWAPBARRIERNVPROC)(GLuint group, GLuint barrier);
+ typedef BOOL(WINAPI* PFNWGLQUERYSWAPGROUPNVPROC)(HDC hDC, GLuint* group, GLuint* barrier);
+ typedef BOOL(WINAPI* PFNWGLQUERYMAXSWAPGROUPSNVPROC)(
+ HDC hDC, GLuint* maxGroups, GLuint* maxBarriers);
+ typedef BOOL(WINAPI* PFNWGLQUERYFRAMECOUNTNVPROC)(HDC hDC, GLuint* count);
+ typedef BOOL(WINAPI* PFNWGLRESETFRAMECOUNTNVPROC)(HDC hDC);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglJoinSwapGroupNV(HDC hDC, GLuint group);
+ BOOL WINAPI wglBindSwapBarrierNV(GLuint group, GLuint barrier);
+ BOOL WINAPI wglQuerySwapGroupNV(HDC hDC, GLuint* group, GLuint* barrier);
+ BOOL WINAPI wglQueryMaxSwapGroupsNV(HDC hDC, GLuint* maxGroups, GLuint* maxBarriers);
+ BOOL WINAPI wglQueryFrameCountNV(HDC hDC, GLuint* count);
+ BOOL WINAPI wglResetFrameCountNV(HDC hDC);
+# endif
+#endif /* WGL_NV_swap_group */
+
+#ifndef WGL_NV_vertex_array_range
+# define WGL_NV_vertex_array_range 1
+ typedef void*(WINAPI* PFNWGLALLOCATEMEMORYNVPROC)(
+ GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
+ typedef void(WINAPI* PFNWGLFREEMEMORYNVPROC)(void* pointer);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ void* WINAPI
+ wglAllocateMemoryNV(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
+ void WINAPI wglFreeMemoryNV(void* pointer);
+# endif
+#endif /* WGL_NV_vertex_array_range */
+
+#ifndef WGL_NV_video_capture
+# define WGL_NV_video_capture 1
+ DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
+# define WGL_UNIQUE_ID_NV 0x20CE
+# define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
+ typedef BOOL(WINAPI* PFNWGLBINDVIDEOCAPTUREDEVICENVPROC)(
+ UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
+ typedef UINT(WINAPI* PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC)(
+ HDC hDc, HVIDEOINPUTDEVICENV* phDeviceList);
+ typedef BOOL(WINAPI* PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC)(HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+ typedef BOOL(WINAPI* PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC)(
+ HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int* piValue);
+ typedef BOOL(WINAPI* PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC)(
+ HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglBindVideoCaptureDeviceNV(UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
+ UINT WINAPI wglEnumerateVideoCaptureDevicesNV(HDC hDc, HVIDEOINPUTDEVICENV* phDeviceList);
+ BOOL WINAPI wglLockVideoCaptureDeviceNV(HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+ BOOL WINAPI wglQueryVideoCaptureDeviceNV(
+ HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int* piValue);
+ BOOL WINAPI wglReleaseVideoCaptureDeviceNV(HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+# endif
+#endif /* WGL_NV_video_capture */
+
+#ifndef WGL_NV_video_output
+# define WGL_NV_video_output 1
+ DECLARE_HANDLE(HPVIDEODEV);
+# define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0
+# define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1
+# define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2
+# define WGL_VIDEO_OUT_COLOR_NV 0x20C3
+# define WGL_VIDEO_OUT_ALPHA_NV 0x20C4
+# define WGL_VIDEO_OUT_DEPTH_NV 0x20C5
+# define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+# define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+# define WGL_VIDEO_OUT_FRAME 0x20C8
+# define WGL_VIDEO_OUT_FIELD_1 0x20C9
+# define WGL_VIDEO_OUT_FIELD_2 0x20CA
+# define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB
+# define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC
+ typedef BOOL(WINAPI* PFNWGLGETVIDEODEVICENVPROC)(
+ HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice);
+ typedef BOOL(WINAPI* PFNWGLRELEASEVIDEODEVICENVPROC)(HPVIDEODEV hVideoDevice);
+ typedef BOOL(WINAPI* PFNWGLBINDVIDEOIMAGENVPROC)(
+ HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
+ typedef BOOL(WINAPI* PFNWGLRELEASEVIDEOIMAGENVPROC)(HPBUFFERARB hPbuffer, int iVideoBuffer);
+ typedef BOOL(WINAPI* PFNWGLSENDPBUFFERTOVIDEONVPROC)(
+ HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock);
+ typedef BOOL(WINAPI* PFNWGLGETVIDEOINFONVPROC)(
+ HPVIDEODEV hpVideoDevice,
+ unsigned long* pulCounterOutputPbuffer,
+ unsigned long* pulCounterOutputVideo);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglGetVideoDeviceNV(HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice);
+ BOOL WINAPI wglReleaseVideoDeviceNV(HPVIDEODEV hVideoDevice);
+ BOOL WINAPI
+ wglBindVideoImageNV(HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
+ BOOL WINAPI wglReleaseVideoImageNV(HPBUFFERARB hPbuffer, int iVideoBuffer);
+ BOOL WINAPI wglSendPbufferToVideoNV(
+ HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock);
+ BOOL WINAPI wglGetVideoInfoNV(
+ HPVIDEODEV hpVideoDevice,
+ unsigned long* pulCounterOutputPbuffer,
+ unsigned long* pulCounterOutputVideo);
+# endif
+#endif /* WGL_NV_video_output */
+
+#ifndef WGL_OML_sync_control
+# define WGL_OML_sync_control 1
+ typedef BOOL(WINAPI* PFNWGLGETSYNCVALUESOMLPROC)(HDC hdc, INT64* ust, INT64* msc, INT64* sbc);
+ typedef BOOL(WINAPI* PFNWGLGETMSCRATEOMLPROC)(HDC hdc, INT32* numerator, INT32* denominator);
+ typedef INT64(WINAPI* PFNWGLSWAPBUFFERSMSCOMLPROC)(
+ HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+ typedef INT64(WINAPI* PFNWGLSWAPLAYERBUFFERSMSCOMLPROC)(
+ HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+ typedef BOOL(WINAPI* PFNWGLWAITFORMSCOMLPROC)(
+ HDC hdc,
+ INT64 target_msc,
+ INT64 divisor,
+ INT64 remainder,
+ INT64* ust,
+ INT64* msc,
+ INT64* sbc);
+ typedef BOOL(WINAPI* PFNWGLWAITFORSBCOMLPROC)(
+ HDC hdc, INT64 target_sbc, INT64* ust, INT64* msc, INT64* sbc);
+# ifdef WGL_WGLEXT_PROTOTYPES
+ BOOL WINAPI wglGetSyncValuesOML(HDC hdc, INT64* ust, INT64* msc, INT64* sbc);
+ BOOL WINAPI wglGetMscRateOML(HDC hdc, INT32* numerator, INT32* denominator);
+ INT64 WINAPI wglSwapBuffersMscOML(HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+ INT64 WINAPI wglSwapLayerBuffersMscOML(
+ HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+ BOOL WINAPI wglWaitForMscOML(
+ HDC hdc,
+ INT64 target_msc,
+ INT64 divisor,
+ INT64 remainder,
+ INT64* ust,
+ INT64* msc,
+ INT64* sbc);
+ BOOL WINAPI wglWaitForSbcOML(HDC hdc, INT64 target_sbc, INT64* ust, INT64* msc, INT64* sbc);
+# endif
+#endif /* WGL_OML_sync_control */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/slang-gfx.h b/slang-gfx.h
index 7b77650e8..5fad16e8f 100644
--- a/slang-gfx.h
+++ b/slang-gfx.h
@@ -160,6 +160,7 @@ enum class Format
R_Float32,
RGBA_Unorm_UInt8,
+ BGRA_Unorm_UInt8,
R_UInt16,
R_UInt32,
@@ -594,6 +595,7 @@ public:
int numMipLevels; ///< Number of mip levels - if 0 will create all mip levels
Format format; ///< The resources format
SampleDesc sampleDesc; ///< How the resource is sampled
+ float optimalClearValue[4] = {0.0f, 0.0f, 0.0f, 0.0f};
};
/// The ordering of the subResources is
@@ -795,10 +797,23 @@ public:
UnorderedAccess,
};
+ struct RenderTargetDesc
+ {
+ // The resource shape of this render target view.
+ IResource::Type shape;
+ uint32_t mipSlice;
+ uint32_t arrayIndex;
+ uint32_t arraySize;
+ uint32_t planeIndex;
+ };
+
struct Desc
{
Type type;
Format format;
+
+ // Fields for `RenderTarget` and `DepthStencil` views.
+ RenderTargetDesc renderTarget;
};
};
#define SLANG_UUID_IResourceView \
@@ -810,6 +825,15 @@ public:
class IDescriptorSet : public ISlangUnknown
{
public:
+ struct Flag
+ {
+ enum Enum
+ {
+ None = 0,
+ Transient = 1,
+ Persistent = 2
+ };
+ };
virtual SLANG_NO_THROW void SLANG_MCALL setConstantBuffer(UInt range, UInt index, IBufferResource* buffer) = 0;
virtual SLANG_NO_THROW void SLANG_MCALL
setResource(UInt range, UInt index, IResourceView* view) = 0;
@@ -917,6 +941,9 @@ struct DepthStencilOpDesc
StencilOp stencilDepthFailOp = StencilOp::Keep;
StencilOp stencilPassOp = StencilOp::Keep;
ComparisonFunc stencilFunc = ComparisonFunc::Always;
+ uint32_t stencilCompareMask = 0xFFFFFFFF;
+ uint32_t stencilWriteMask = 0xFFFFFFFF;
+ uint32_t stencilReference = 0;
};
struct DepthStencilDesc
@@ -1022,6 +1049,26 @@ struct BlendDesc
bool alphaToCoverateEnable = false;
};
+class IFramebufferLayout : public ISlangUnknown
+{
+public:
+ struct AttachmentLayout
+ {
+ Format format;
+ int sampleCount;
+ };
+ struct Desc
+ {
+ uint32_t renderTargetCount;
+ AttachmentLayout* renderTargets;
+ AttachmentLayout* depthStencil;
+ };
+};
+#define SLANG_UUID_IFramebufferLayout \
+ { \
+ 0xa838785, 0xc13a, 0x4832, { 0xad, 0x88, 0x64, 0x6, 0xb5, 0x4b, 0x5e, 0xba } \
+ }
+
struct GraphicsPipelineStateDesc
{
IShaderProgram* program;
@@ -1030,8 +1077,8 @@ struct GraphicsPipelineStateDesc
// from `program`, which must have been created with Slang reflection info.
IPipelineLayout* pipelineLayout = nullptr;
- IInputLayout* inputLayout;
- UInt renderTargetCount = 0; // Only used if `pipelineLayout` is non-null
+ IInputLayout* inputLayout;
+ IFramebufferLayout* framebufferLayout;
DepthStencilDesc depthStencil;
RasterizerDesc rasterizer;
BlendDesc blend;
@@ -1073,6 +1120,69 @@ struct Viewport
float maxZ = 1.0f;
};
+class IFramebuffer : public ISlangUnknown
+{
+public:
+ struct Desc
+ {
+ uint32_t renderTargetCount;
+ IResourceView* const* renderTargetViews;
+ IResourceView* depthStencilView;
+ IFramebufferLayout* layout;
+ };
+};
+#define SLANG_UUID_IFrameBuffer \
+ { \
+ 0xf0c0d9a, 0x4ef3, 0x4e18, { 0x9b, 0xa9, 0x34, 0x60, 0xea, 0x69, 0x87, 0x95 } \
+ }
+
+class ISwapchain : public ISlangUnknown
+{
+public:
+ struct Desc
+ {
+ Format format;
+ uint32_t width, height;
+ uint32_t imageCount;
+ bool enableVSync;
+ };
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0;
+ virtual SLANG_NO_THROW Result getImage(uint32_t index, ITextureResource** outResource) = 0;
+ virtual SLANG_NO_THROW Result present() = 0;
+ virtual SLANG_NO_THROW uint32_t acquireNextImage() = 0;
+};
+#define SLANG_UUID_ISwapchain \
+ { \
+ 0xbe91ba6c, 0x784, 0x4308, { 0xa1, 0x0, 0x19, 0xc3, 0x66, 0x83, 0x44, 0xb2 } \
+ }
+
+struct WindowHandle
+{
+ enum class Type
+ {
+ Unknown,
+ Win32Handle,
+ XLibHandle,
+ };
+ Type type;
+ intptr_t handleValues[2];
+ static WindowHandle FromHwnd(void* hwnd)
+ {
+ WindowHandle handle = {};
+ handle.type = WindowHandle::Type::Win32Handle;
+ handle.handleValues[0] = (intptr_t)(hwnd);
+ return handle;
+ }
+ static WindowHandle FromXWindow(void* xdisplay, uint32_t xwindow)
+ {
+ WindowHandle handle = {};
+ handle.type = WindowHandle::Type::XLibHandle;
+ handle.handleValues[0] = (intptr_t)(xdisplay);
+ handle.handleValues[1] = xwindow;
+ return handle;
+ }
+};
+
class IRenderer: public ISlangUnknown
{
public:
@@ -1096,8 +1206,6 @@ public:
struct Desc
{
RendererType rendererType; // The underlying API/Platform of the renderer.
- int width = 0; // Width in pixels
- int height = 0; // height in pixels
const char* adapter = nullptr; // Name to identify the adapter to use
int requiredFeatureCount = 0; // Number of required features.
const char** requiredFeatures = nullptr; // Array of required feature names, whose size is `requiredFeatureCount`.
@@ -1122,10 +1230,10 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) = 0;
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() = 0;
-
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() = 0;
-
- virtual SLANG_NO_THROW ITextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() = 0;
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() = 0;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) = 0;
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() = 0;
/// Create a texture resource. initData holds the initialize data to set the contents of the texture when constructed.
virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
@@ -1192,6 +1300,33 @@ public:
return view;
}
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebufferLayout(IFramebufferLayout::Desc const& desc, IFramebufferLayout** outFrameBuffer) = 0;
+ inline ComPtr<IFramebufferLayout> createFramebufferLayout(IFramebufferLayout::Desc const& desc)
+ {
+ ComPtr<IFramebufferLayout> fb;
+ SLANG_RETURN_NULL_ON_FAIL(createFramebufferLayout(desc, fb.writeRef()));
+ return fb;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) = 0;
+ inline ComPtr<IFramebuffer> createFramebuffer(IFramebuffer::Desc const& desc)
+ {
+ ComPtr<IFramebuffer> fb;
+ SLANG_RETURN_NULL_ON_FAIL(createFramebuffer(desc, fb.writeRef()));
+ return fb;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ ISwapchain::Desc const& desc, WindowHandle window, ISwapchain** outSwapchain) = 0;
+ inline ComPtr<ISwapchain> createSwapchain(ISwapchain::Desc const& desc, WindowHandle window)
+ {
+ ComPtr<ISwapchain> swapchain;
+ SLANG_RETURN_NULL_ON_FAIL(createSwapchain(desc, window, swapchain.writeRef()));
+ return swapchain;
+ }
+
virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout(
const InputElementDesc* inputElements, UInt inputElementCount, IInputLayout** outLayout) = 0;
@@ -1241,12 +1376,12 @@ public:
return layout;
}
- virtual SLANG_NO_THROW Result SLANG_MCALL createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) = 0;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet) = 0;
- inline ComPtr<IDescriptorSet> createDescriptorSet(IDescriptorSetLayout* layout)
+ inline ComPtr<IDescriptorSet> createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag)
{
ComPtr<IDescriptorSet> descriptorSet;
- SLANG_RETURN_NULL_ON_FAIL(createDescriptorSet(layout, descriptorSet.writeRef()));
+ SLANG_RETURN_NULL_ON_FAIL(createDescriptorSet(layout, flag, descriptorSet.writeRef()));
return descriptorSet;
}
@@ -1283,8 +1418,12 @@ public:
return state;
}
- /// Captures the back buffer and stores the result in surfaceOut. If the surface contains data - it will either be overwritten (if same size and format), or freed and a re-allocated.
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(void* buffer, size_t *inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) = 0;
+ /// Read back texture resource and stores the result in `outBlob`.
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* resource,
+ ISlangBlob** outBlob,
+ size_t* outRowPitch,
+ size_t* outPixelSize) = 0;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) = 0;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) = 0;
@@ -1308,8 +1447,6 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL
setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset = 0) = 0;
- virtual SLANG_NO_THROW void SLANG_MCALL setDepthStencilTarget(IResourceView* depthStencilView) = 0;
-
virtual SLANG_NO_THROW void SLANG_MCALL setViewports(UInt count, Viewport const* viewports) = 0;
inline void setViewport(Viewport const& viewport)
{
@@ -1321,8 +1458,17 @@ public:
{
setScissorRects(1, &rect);
}
-
+ /// Sets the viewport, and sets the scissor rect to match the viewport.
+ inline void setViewportAndScissor(Viewport const& viewport)
+ {
+ setViewports(1, &viewport);
+ ScissorRect rect = {};
+ rect.maxX = static_cast<gfx::Int>(viewport.extentX);
+ rect.maxY = static_cast<gfx::Int>(viewport.extentY);
+ setScissorRects(1, &rect);
+ }
virtual SLANG_NO_THROW void SLANG_MCALL setPipelineState(IPipelineState* state) = 0;
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* framebuffer) = 0;
virtual SLANG_NO_THROW void SLANG_MCALL draw(UInt vertexCount, UInt startVertex = 0) = 0;
virtual SLANG_NO_THROW void SLANG_MCALL drawIndexed(UInt indexCount, UInt startIndex = 0, UInt baseVertex = 0) = 0;
@@ -1372,7 +1518,7 @@ extern "C"
SLANG_GFX_API const char* SLANG_MCALL gfxGetRendererName(RendererType type);
/// Given a type returns a function that can construct it, or nullptr if there isn't one
- SLANG_GFX_API SlangResult SLANG_MCALL gfxCreateRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer);
+ SLANG_GFX_API SlangResult SLANG_MCALL gfxCreateRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer);
}
}// renderer_test
diff --git a/source/core/slang-virtual-object-pool.h b/source/core/slang-virtual-object-pool.h
new file mode 100644
index 000000000..c1247acb7
--- /dev/null
+++ b/source/core/slang-virtual-object-pool.h
@@ -0,0 +1,119 @@
+#ifndef SLANG_VIRTUAL_POOL_ALLOCATOR_H
+#define SLANG_VIRTUAL_POOL_ALLOCATOR_H
+
+namespace Slang
+{
+
+ /// A virtual free-list allocater.
+ /// This class doesn't actually allocates memory, instead it operates on a
+ /// virtual integer space. Can be used to implement various types of object pools
+ /// that needs to support contiguous allocations of more than one elements.
+class VirtualObjectPool
+{
+public:
+ struct FreeListNode
+ {
+ int Offset;
+ int Length;
+ FreeListNode* prev;
+ FreeListNode* next;
+ };
+ FreeListNode* freeListHead = nullptr;
+
+public:
+ void destroy()
+ {
+ auto list = freeListHead;
+ while (list)
+ {
+ auto next = list->next;
+ delete list;
+ list = next;
+ }
+ freeListHead = nullptr;
+ }
+
+ ~VirtualObjectPool() { destroy(); }
+
+ void initPool(int numElements)
+ {
+ freeListHead = new FreeListNode();
+ freeListHead->prev = freeListHead->next = nullptr;
+ freeListHead->Offset = 0;
+ freeListHead->Length = numElements;
+ }
+
+ int alloc(int size)
+ {
+ if (!freeListHead)
+ return -1;
+ auto freeBlock = freeListHead;
+ while (freeBlock && freeBlock->Length < size)
+ freeBlock = freeBlock->next;
+ if (!freeBlock || freeBlock->Length < size)
+ return -1;
+ int result = freeBlock->Offset;
+ freeBlock->Offset += size;
+ freeBlock->Length -= size;
+ if (freeBlock->Length == 0)
+ {
+ if (freeBlock->prev)
+ freeBlock->prev->next = freeBlock->next;
+ if (freeBlock->next)
+ freeBlock->next->prev = freeBlock->prev;
+ if (freeBlock == freeListHead)
+ freeListHead = freeBlock->next;
+ delete freeBlock;
+ }
+ return result;
+ }
+ void free(int offset, int size)
+ {
+ if (!freeListHead)
+ {
+ freeListHead = new FreeListNode();
+ freeListHead->next = freeListHead->prev = nullptr;
+ freeListHead->Length = size;
+ freeListHead->Offset = offset;
+ return;
+ }
+ auto freeListNode = freeListHead;
+ FreeListNode* prevFreeNode = nullptr;
+ while (freeListNode && freeListNode->Offset < offset + size)
+ {
+ prevFreeNode = freeListNode;
+ freeListNode = freeListNode->next;
+ }
+ FreeListNode* newNode = new FreeListNode();
+ newNode->Offset = offset;
+ newNode->Length = size;
+ newNode->prev = prevFreeNode;
+ newNode->next = freeListNode;
+ if (freeListNode)
+ freeListNode->prev = newNode;
+ if (prevFreeNode)
+ prevFreeNode->next = newNode;
+ if (freeListNode == freeListHead)
+ freeListHead = newNode;
+ if (prevFreeNode && prevFreeNode->Offset + prevFreeNode->Length == newNode->Offset)
+ {
+ prevFreeNode->Length += newNode->Length;
+ prevFreeNode->next = freeListNode;
+ if (freeListNode)
+ freeListNode->prev = prevFreeNode;
+ delete newNode;
+ newNode = prevFreeNode;
+ }
+ if (freeListNode && newNode->Offset + newNode->Length == freeListNode->Offset)
+ {
+ newNode->Length += freeListNode->Length;
+ newNode->next = freeListNode->next;
+ if (freeListNode->next)
+ freeListNode->next->prev = newNode;
+ delete freeListNode;
+ }
+ }
+};
+
+} // namespace Slang
+#endif
diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp
index 4673cda6e..eabb2d301 100644
--- a/tools/gfx/cuda/render-cuda.cpp
+++ b/tools/gfx/cuda/render-cuda.cpp
@@ -878,11 +878,11 @@ private:
cuCtxDestroy(m_context);
}
}
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override
{
SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_PTX, "sm_5_1"));
- SLANG_RETURN_ON_FAIL(RendererBase::initialize(desc, inWindowHandle));
+ SLANG_RETURN_ON_FAIL(RendererBase::initialize(desc));
SLANG_RETURN_ON_FAIL(_initCuda(reportType));
@@ -950,6 +950,7 @@ private:
switch (desc.format)
{
case Format::R_Float32:
+ case Format::D_Float32:
{
format = CU_AD_FORMAT_FLOAT;
numChannels = 1;
@@ -1362,7 +1363,6 @@ private:
ShaderObjectLayoutBase* layout,
IShaderObject** outObject) override
{
-
RefPtr<CUDAShaderObject> result = new CUDAShaderObject();
SLANG_RETURN_ON_FAIL(result->init(this, dynamic_cast<CUDAShaderObjectLayout*>(layout)));
*outObject = result.detach();
@@ -1560,12 +1560,39 @@ public:
SLANG_UNUSED(color);
}
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() override {}
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() override {}
- virtual SLANG_NO_THROW TextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() override
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() override {}
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() override {}
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) override
{
- return TextureResource::Desc();
+ SLANG_UNUSED(swapchain);
+ }
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) override
+ {
+ SLANG_UNUSED(desc);
+ SLANG_UNUSED(window);
+ SLANG_UNUSED(outSwapchain);
+ return SLANG_FAIL;
+ }
+ virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout) override
+ {
+ SLANG_UNUSED(desc);
+ SLANG_UNUSED(outLayout);
+ return SLANG_FAIL;
+ }
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer) override
+ {
+ SLANG_UNUSED(desc);
+ SLANG_UNUSED(outFramebuffer);
+ return SLANG_FAIL;
+ }
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* frameBuffer) override
+ {
+ SLANG_UNUSED(frameBuffer);
}
-
virtual SLANG_NO_THROW Result SLANG_MCALL
createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) override
{
@@ -1599,9 +1626,10 @@ public:
return SLANG_E_NOT_AVAILABLE;
}
virtual SLANG_NO_THROW Result SLANG_MCALL
- createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) override
+ createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flags, IDescriptorSet** outDescriptorSet) override
{
SLANG_UNUSED(layout);
+ SLANG_UNUSED(flags);
SLANG_UNUSED(outDescriptorSet);
return SLANG_E_NOT_AVAILABLE;
}
@@ -1612,11 +1640,11 @@ public:
SLANG_UNUSED(outState);
return SLANG_E_NOT_AVAILABLE;
}
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override
{
- SLANG_UNUSED(buffer);
- SLANG_UNUSED(inOutBufferSize);
+ SLANG_UNUSED(texture);
+ SLANG_UNUSED(outBlob);
SLANG_UNUSED(outRowPitch);
SLANG_UNUSED(outPixelSize);
@@ -1659,11 +1687,6 @@ public:
SLANG_UNUSED(offset);
}
virtual SLANG_NO_THROW void SLANG_MCALL
- setDepthStencilTarget(IResourceView* depthStencilView) override
- {
- SLANG_UNUSED(depthStencilView);
- }
- virtual SLANG_NO_THROW void SLANG_MCALL
setViewports(UInt count, Viewport const* viewports) override
{
SLANG_UNUSED(count);
@@ -1760,18 +1783,17 @@ SlangResult CUDARootShaderObject::init(IRenderer* renderer, CUDAShaderObjectLayo
return SLANG_OK;
}
-SlangResult SLANG_MCALL createCUDARenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+SlangResult SLANG_MCALL createCUDARenderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
RefPtr<CUDARenderer> result = new CUDARenderer();
- SLANG_RETURN_ON_FAIL(result->initialize(*desc, windowHandle));
+ SLANG_RETURN_ON_FAIL(result->initialize(*desc));
*outRenderer = result.detach();
return SLANG_OK;
}
#else
-SlangResult SLANG_MCALL createCUDARenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+SlangResult SLANG_MCALL createCUDARenderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
SLANG_UNUSED(desc);
- SLANG_UNUSED(windowHandle);
*outRenderer = nullptr;
return SLANG_OK;
}
diff --git a/tools/gfx/cuda/render-cuda.h b/tools/gfx/cuda/render-cuda.h
index 39d5b60f8..cd8482e37 100644
--- a/tools/gfx/cuda/render-cuda.h
+++ b/tools/gfx/cuda/render-cuda.h
@@ -5,5 +5,5 @@
namespace gfx
{
-SlangResult SLANG_MCALL createCUDARenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer);
+SlangResult SLANG_MCALL createCUDARenderer(const IRenderer::Desc* desc, IRenderer** outRenderer);
}
diff --git a/tools/gfx/d3d/d3d-util.cpp b/tools/gfx/d3d/d3d-util.cpp
index f60bd9d3f..cb96c6211 100644
--- a/tools/gfx/d3d/d3d-util.cpp
+++ b/tools/gfx/d3d/d3d-util.cpp
@@ -35,6 +35,8 @@ using namespace Slang;
case Format::RG_Float32: return DXGI_FORMAT_R32G32_FLOAT;
case Format::R_Float32: return DXGI_FORMAT_R32_FLOAT;
case Format::RGBA_Unorm_UInt8: return DXGI_FORMAT_R8G8B8A8_UNORM;
+ case Format::BGRA_Unorm_UInt8: return DXGI_FORMAT_B8G8R8A8_UNORM;
+
case Format::R_UInt16: return DXGI_FORMAT_R16_UINT;
case Format::R_UInt32: return DXGI_FORMAT_R32_UINT;
diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp
index 49fe101fb..c64b1c3bd 100644
--- a/tools/gfx/d3d11/render-d3d11.cpp
+++ b/tools/gfx/d3d11/render-d3d11.cpp
@@ -1,9 +1,9 @@
// render-d3d11.cpp
-
#define _CRT_SECURE_NO_WARNINGS
#include "render-d3d11.h"
#include "core/slang-basic.h"
+#include "core/slang-blob.h"
//WORKING: #include "options.h"
#include "../renderer-shared.h"
@@ -63,11 +63,23 @@ public:
~D3D11Renderer() {}
// Renderer implementation
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override;
virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) override;
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() override;
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() override;
- virtual SLANG_NO_THROW TextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) override
+ {
+ SLANG_UNUSED(swapchain);
+ }
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* frameBuffer) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
IResource::Usage initialUsage,
@@ -96,8 +108,10 @@ public:
const IDescriptorSetLayout::Desc& desc, IDescriptorSetLayout** outLayout) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createPipelineLayout(const IPipelineLayout::Desc& desc, IPipelineLayout** outLayout) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createDescriptorSet(
+ IDescriptorSetLayout* layout,
+ IDescriptorSet::Flag::Enum flag,
+ IDescriptorSet** outDescriptorSet) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override;
@@ -106,8 +120,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -129,8 +143,6 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL
setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override;
virtual SLANG_NO_THROW void SLANG_MCALL
- setDepthStencilTarget(IResourceView* depthStencilView) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
setViewports(UInt count, Viewport const* viewports) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setScissorRects(UInt count, ScissorRect const* rects) override;
@@ -432,6 +444,175 @@ public:
ComPtr<ID3D11RenderTargetView> m_rtv;
};
+ class FramebufferLayoutImpl
+ : public IFramebufferLayout
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebufferLayout* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout)
+ return static_cast<IFramebufferLayout*>(this);
+ return nullptr;
+ }
+
+ public:
+ ShortList<IFramebufferLayout::AttachmentLayout> m_renderTargets;
+ bool m_hasDepthStencil = false;
+ IFramebufferLayout::AttachmentLayout m_depthStencil;
+ };
+
+ class FramebufferImpl
+ : public IFramebuffer
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebuffer* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebuffer)
+ return static_cast<IFramebuffer*>(this);
+ return nullptr;
+ }
+
+ public:
+ ShortList<RefPtr<RenderTargetViewImpl>, kMaxRTVs> renderTargetViews;
+ ShortList<ID3D11RenderTargetView*, kMaxRTVs> d3dRenderTargetViews;
+ RefPtr<DepthStencilViewImpl> depthStencilView;
+ ID3D11DepthStencilView* d3dDepthStencilView;
+ };
+
+ class SwapchainImpl
+ : public ISwapchain
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ISwapchain* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
+ return static_cast<ISwapchain*>(this);
+ return nullptr;
+ }
+
+ public:
+ Result init(D3D11Renderer* renderer, const ISwapchain::Desc& desc, WindowHandle window)
+ {
+ // Return fail on non-supported platforms.
+ switch (window.type)
+ {
+ case WindowHandle::Type::Win32Handle:
+ break;
+ default:
+ return SLANG_FAIL;
+ }
+
+ m_renderer = renderer;
+ m_desc = desc;
+
+ // Describe the swap chain.
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = desc.imageCount;
+ swapChainDesc.BufferDesc.Width = desc.width;
+ swapChainDesc.BufferDesc.Height = desc.height;
+ swapChainDesc.BufferDesc.Format = D3DUtil::getMapFormat(desc.format);
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.OutputWindow = (HWND)window.handleValues[0];
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.Windowed = TRUE;
+
+ if (!desc.enableVSync)
+ {
+ swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
+ }
+
+ // Swap chain needs the queue so that it can force a flush on it.
+ ComPtr<IDXGISwapChain> swapChain;
+ SLANG_RETURN_ON_FAIL(m_renderer->m_dxgiFactory->CreateSwapChain(
+ m_renderer->m_device, &swapChainDesc, swapChain.writeRef()));
+ SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(m_swapChain.writeRef()));
+
+ if (!desc.enableVSync)
+ {
+ m_swapChainWaitableObject = m_swapChain->GetFrameLatencyWaitableObject();
+
+ int maxLatency = desc.imageCount - 2;
+
+ // Make sure the maximum latency is in the range required by dx12 runtime
+ maxLatency = (maxLatency < 1) ? 1 : maxLatency;
+ maxLatency = (maxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS)
+ ? DXGI_MAX_SWAP_CHAIN_BUFFERS
+ : maxLatency;
+
+ m_swapChain->SetMaximumFrameLatency(maxLatency);
+ }
+
+ SLANG_RETURN_ON_FAIL(m_renderer->m_dxgiFactory->MakeWindowAssociation(
+ (HWND)window.handleValues[0], DXGI_MWA_NO_ALT_ENTER));
+
+ for (uint32_t i = 0; i < desc.imageCount; i++)
+ {
+ ComPtr<ID3D11Resource> d3dResource;
+ m_swapChain->GetBuffer(0, IID_PPV_ARGS(d3dResource.writeRef()));
+ ITextureResource::Desc imageDesc = {};
+ imageDesc.init2D(
+ IResource::Type::Texture2D, desc.format, desc.width, desc.height, 0);
+ RefPtr<TextureResourceImpl> image = new TextureResourceImpl(imageDesc, IResource::Usage::RenderTarget);
+ image->m_resource = d3dResource;
+ m_images.add(image);
+ }
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
+ virtual SLANG_NO_THROW Result
+ getImage(uint32_t index, ITextureResource** outResource) override
+ {
+ m_images[index]->addRef();
+ *outResource = m_images[index].Ptr();
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW Result present() override
+ {
+ if (m_swapChainWaitableObject)
+ {
+ // check if now is good time to present
+ // This doesn't wait - because the wait time is 0. If it returns WAIT_TIMEOUT it
+ // means that no frame is waiting to be be displayed so there is no point doing a
+ // present.
+ const bool shouldPresent =
+ (WaitForSingleObjectEx(m_swapChainWaitableObject, 0, TRUE) != WAIT_TIMEOUT);
+ if (shouldPresent)
+ {
+ m_swapChain->Present(0, 0);
+ }
+ }
+ else
+ {
+ if (SLANG_FAILED(m_swapChain->Present(1, 0)))
+ {
+ return SLANG_FAIL;
+ }
+ }
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW uint32_t acquireNextImage() override
+ {
+ uint32_t count;
+ m_swapChain->GetLastPresentCount(&count);
+ return count % m_images.getCount();
+ }
+
+ public:
+ D3D11Renderer* m_renderer = nullptr;
+ ISwapchain::Desc m_desc;
+ HANDLE m_swapChainWaitableObject = nullptr;
+ ComPtr<IDXGISwapChain2> m_swapChain;
+ ShortList<RefPtr<TextureResourceImpl>> m_images;
+ };
+
class InputLayoutImpl: public IInputLayout, public RefObject
{
public:
@@ -489,16 +670,6 @@ public:
}
};
- /// Capture a texture to a file
- static HRESULT captureTextureToSurface(
- ID3D11Device* device,
- ID3D11DeviceContext* context,
- TextureResourceImpl* texture,
- void* buffer,
- size_t* inOutBufferSize,
- size_t* outRowPitch,
- size_t* outPixelSize);
-
void _flushGraphicsState();
void _flushComputeState();
@@ -506,21 +677,16 @@ public:
ComPtr<ID3D11Device> m_device;
ComPtr<ID3D11DeviceContext> m_immediateContext;
ComPtr<ID3D11Texture2D> m_backBufferTexture;
+ ComPtr<IDXGIFactory> m_dxgiFactory;
- RefPtr<TextureResourceImpl> m_primaryRenderTargetTexture;
- RefPtr<RenderTargetViewImpl> m_primaryRenderTargetView;
-
-// List<ComPtr<ID3D11RenderTargetView> > m_renderTargetViews;
-// List<ComPtr<ID3D11Texture2D> > m_renderTargetTextures;
-
- bool m_renderTargetBindingsDirty = false;
+ RefPtr<FramebufferImpl> m_currentFramebuffer;
ComPtr<PipelineStateImpl> m_currentPipelineState;
- ComPtr<ID3D11RenderTargetView> m_rtvBindings[kMaxRTVs];
- ComPtr<ID3D11DepthStencilView> m_dsvBinding;
ComPtr<ID3D11UnorderedAccessView> m_uavBindings[int(PipelineType::CountOf)][kMaxUAVs];
- bool m_targetBindingsDirty[int(PipelineType::CountOf)];
+
+ bool m_framebufferBindingDirty = true;
+ bool m_shaderBindingDirty = true;
Desc m_desc;
@@ -529,10 +695,10 @@ public:
bool m_nvapi = false;
};
-SlangResult SLANG_MCALL createD3D11Renderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+SlangResult SLANG_MCALL createD3D11Renderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
RefPtr<D3D11Renderer> result = new D3D11Renderer();
- SLANG_RETURN_ON_FAIL(result->initialize(*desc, windowHandle));
+ SLANG_RETURN_ON_FAIL(result->initialize(*desc));
*outRenderer = result.detach();
return SLANG_OK;
}
@@ -575,87 +741,6 @@ D3D11Renderer::ScopeNVAPI::~ScopeNVAPI()
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!D3D11Renderer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-/* static */ HRESULT D3D11Renderer::captureTextureToSurface(
- ID3D11Device* device,
- ID3D11DeviceContext* context,
- TextureResourceImpl* texture,
- void* buffer,
- size_t* inOutBufferSize,
- size_t* outRowPitch,
- size_t* outPixelSize)
-{
- if (!context) return E_INVALIDARG;
- if (!texture) return E_INVALIDARG;
-
- // Don't bother supporting MSAA for right now
- if (texture->getDesc()->sampleDesc.numSamples > 1)
- {
- fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
- return E_INVALIDARG;
- }
-
- size_t bytesPerPixel = sizeof(uint32_t);
- size_t rowPitch = int(texture->getDesc()->size.width) * bytesPerPixel;
- size_t bufferSize = rowPitch * int(texture->getDesc()->size.height);
- if (outRowPitch)
- *outRowPitch = rowPitch;
- if (outPixelSize)
- *outPixelSize = bytesPerPixel;
- if (!buffer || *inOutBufferSize == 0)
- {
- *inOutBufferSize = bufferSize;
- return S_OK;
- }
- if (*inOutBufferSize < bufferSize)
- return SLANG_ERROR_INSUFFICIENT_BUFFER;
-
- D3D11_TEXTURE2D_DESC textureDesc;
- auto d3d11Texture = ((ID3D11Texture2D*)texture->m_resource.get());
- d3d11Texture->GetDesc(&textureDesc);
-
- HRESULT hr = S_OK;
- ComPtr<ID3D11Texture2D> stagingTexture;
-
- if (textureDesc.Usage == D3D11_USAGE_STAGING && (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
- {
- stagingTexture = d3d11Texture;
- }
- else
- {
- // Modify the descriptor to give us a staging texture
- textureDesc.BindFlags = 0;
- textureDesc.MiscFlags &= ~D3D11_RESOURCE_MISC_TEXTURECUBE;
- textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- textureDesc.Usage = D3D11_USAGE_STAGING;
-
- hr = device->CreateTexture2D(&textureDesc, 0, stagingTexture.writeRef());
- if (FAILED(hr))
- {
- fprintf(stderr, "ERROR: failed to create staging texture\n");
- return hr;
- }
-
- context->CopyResource(stagingTexture, d3d11Texture);
- }
-
- // Now just read back texels from the staging textures
- {
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- SLANG_RETURN_ON_FAIL(context->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource));
-
- for (size_t y = 0; y < textureDesc.Height; y++)
- {
- memcpy(
- (char*)buffer + y * (*outRowPitch),
- (char*)mappedResource.pData + y * mappedResource.RowPitch,
- *outRowPitch);
- }
- // Make sure to unmap
- context->Unmap(stagingTexture, 0);
- return SLANG_OK;
- }
-}
-
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
static bool _isSupportedNVAPIOp(IUnknown* dev, uint32_t op)
@@ -671,13 +756,12 @@ static bool _isSupportedNVAPIOp(IUnknown* dev, uint32_t op)
#endif
}
-SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
+SlangResult D3D11Renderer::initialize(const Desc& desc)
{
SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_DXBC, "sm_5_0"));
- SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc, inWindowHandle));
+ SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc));
- auto windowHandle = (HWND)inWindowHandle;
m_desc = desc;
// Rather than statically link against D3D, we load it dynamically.
@@ -706,24 +790,6 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
return SLANG_FAIL;
}
- // Our swap chain uses RGBA8 with sRGB, with double buffering.
- DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-
- // Note(tfoley): Disabling sRGB for DX back buffer for now, so that we
- // can get consistent output with OpenGL, where setting up sRGB will
- // probably be more involved.
- // swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
- swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.BufferCount = 2;
- swapChainDesc.OutputWindow = windowHandle;
- swapChainDesc.Windowed = TRUE;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
- swapChainDesc.Flags = 0;
-
// We will ask for the highest feature level that can be supported.
const D3D_FEATURE_LEVEL featureLevels[] = {
D3D_FEATURE_LEVEL_11_1,
@@ -757,11 +823,13 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
combiner.add(DeviceCheckFlag::UseHardwareDevice, ChangeType::OnOff); ///< First try hardware, then reference
combiner.add(DeviceCheckFlag::UseFullFeatureLevel, ChangeType::OnOff); ///< First try fully featured, then degrade features
+
const int numCombinations = combiner.getNumCombinations();
Result res = SLANG_FAIL;
for (int i = 0; i < numCombinations; ++i)
{
const auto deviceCheckFlags = combiner.getCombination(i);
+ D3DUtil::createFactory(deviceCheckFlags, m_dxgiFactory);
// If we have an adapter set on the desc, look it up. We only need to do so for hardware
ComPtr<IDXGIAdapter> adapter;
@@ -787,36 +855,17 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
const int startFeatureIndex = (deviceCheckFlags & DeviceCheckFlag::UseFullFeatureLevel) ? 0 : 1;
const UINT deviceFlags = (deviceCheckFlags & DeviceCheckFlag::UseDebug) ? D3D11_CREATE_DEVICE_DEBUG : 0;
- if (windowHandle)
- {
- res = D3D11CreateDeviceAndSwapChain_(
- adapter,
- driverType,
- nullptr, // software
- deviceFlags,
- &featureLevels[startFeatureIndex],
- totalNumFeatureLevels - startFeatureIndex,
- D3D11_SDK_VERSION,
- &swapChainDesc,
- m_swapChain.writeRef(),
- m_device.writeRef(),
- &featureLevel,
- m_immediateContext.writeRef());
- }
- else
- {
- res = D3D11CreateDevice_(
- adapter,
- driverType,
- nullptr,
- deviceFlags,
- &featureLevels[startFeatureIndex],
- totalNumFeatureLevels - startFeatureIndex,
- D3D11_SDK_VERSION,
- m_device.writeRef(),
- &featureLevel,
- m_immediateContext.writeRef());
- }
+ res = D3D11CreateDevice_(
+ adapter,
+ driverType,
+ nullptr,
+ deviceFlags,
+ &featureLevels[startFeatureIndex],
+ totalNumFeatureLevels - startFeatureIndex,
+ D3D11_SDK_VERSION,
+ m_device.writeRef(),
+ &featureLevel,
+ m_immediateContext.writeRef());
// Check if successfully constructed - if so we are done.
if (SLANG_SUCCEEDED(res))
{
@@ -830,7 +879,6 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
}
// Check we have a swap chain, context and device
SLANG_ASSERT(m_immediateContext && m_device);
- SLANG_ASSERT(!windowHandle || m_swapChain);
}
// NVAPI
@@ -859,68 +907,6 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
m_nvapi = true;
#endif
}
-
- // TODO: Add support for debugging to help detect leaks:
- //
- // ComPtr<ID3D11Debug> gDebug;
- // m_device->QueryInterface(IID_PPV_ARGS(gDebug.writeRef()));
- //
-
- // After we've created the swap chain, we can request a pointer to the
- // back buffer as a D3D11 texture, and create a render-target view from it.
-
- static const IID kIID_ID3D11Texture2D = {
- 0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48,
- 0x95, 0x35, 0xd3, 0x4f, 0x9c };
- if (m_swapChain)
- {
- SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(0, kIID_ID3D11Texture2D, (void**)m_backBufferTexture.writeRef()));
-
- // for (int i = 0; i < 8; i++)
- {
- ComPtr<ID3D11Texture2D> texture;
- D3D11_TEXTURE2D_DESC textureDesc;
- m_backBufferTexture->GetDesc(&textureDesc);
- SLANG_RETURN_ON_FAIL(m_device->CreateTexture2D(&textureDesc, nullptr, texture.writeRef()));
-
- ComPtr<ID3D11RenderTargetView> rtv;
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- rtvDesc.Texture2D.MipSlice = 0;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
- SLANG_RETURN_ON_FAIL(m_device->CreateRenderTargetView(texture, &rtvDesc, rtv.writeRef()));
-
- TextureResource::Desc resourceDesc;
- resourceDesc.init2D(IResource::Type::Texture2D, Format::RGBA_Unorm_UInt8, textureDesc.Width, textureDesc.Height, 1);
-
- ComPtr<ITextureResource> primaryRenderTargetTexture;
- SLANG_RETURN_ON_FAIL(createTextureResource(IResource::Usage::RenderTarget, resourceDesc, nullptr, primaryRenderTargetTexture.writeRef()));
-
- IResourceView::Desc viewDesc;
- viewDesc.format = resourceDesc.format;
- viewDesc.type = IResourceView::Type::RenderTarget;
- ComPtr<IResourceView> primaryRenderTargetView;
- SLANG_RETURN_ON_FAIL(createTextureView(primaryRenderTargetTexture, viewDesc, primaryRenderTargetView.writeRef()));
-
- m_primaryRenderTargetTexture = dynamic_cast<TextureResourceImpl*>(primaryRenderTargetTexture.get());
- m_primaryRenderTargetView = dynamic_cast<RenderTargetViewImpl*>(primaryRenderTargetView.get());
- }
-
- // m_immediateContext->OMSetRenderTargets(1, m_primaryRenderTargetView->m_rtv.readRef(), nullptr);
- m_rtvBindings[0] = m_primaryRenderTargetView->m_rtv;
- m_targetBindingsDirty[int(PipelineType::Graphics)] = true;
-
- // Similarly, we are going to set up a viewport once, and then never
- // switch, since this is a simple test app.
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = (float)desc.width;
- viewport.Height = (float)desc.height;
- viewport.MaxDepth = 1; // TODO(tfoley): use reversed depth
- viewport.MinDepth = 0;
- m_immediateContext->RSSetViewports(1, &viewport);
- }
return SLANG_OK;
}
@@ -931,42 +917,146 @@ void D3D11Renderer::setClearColor(const float color[4])
void D3D11Renderer::clearFrame()
{
- m_immediateContext->ClearRenderTargetView(m_primaryRenderTargetView->m_rtv, m_clearColor);
+ for (auto rtv : m_currentFramebuffer->renderTargetViews)
+ m_immediateContext->ClearRenderTargetView(rtv->m_rtv, m_clearColor);
- if(m_dsvBinding)
+ if (m_currentFramebuffer->depthStencilView)
{
- m_immediateContext->ClearDepthStencilView(m_dsvBinding, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
+ m_immediateContext->ClearDepthStencilView(
+ m_currentFramebuffer->depthStencilView->m_dsv,
+ D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL,
+ 1.0f,
+ 0);
}
}
-void D3D11Renderer::presentFrame()
+void D3D11Renderer::beginFrame() { }
+
+void D3D11Renderer::endFrame() {}
+
+Result D3D11Renderer::createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain)
{
- m_immediateContext->CopyResource(m_backBufferTexture, m_primaryRenderTargetTexture->m_resource);
- m_swapChain->Present(0, 0);
+ RefPtr<SwapchainImpl> swapchain = new SwapchainImpl();
+ SLANG_RETURN_ON_FAIL(swapchain->init(this, desc, window));
+ *outSwapchain = swapchain.detach();
+ return SLANG_OK;
}
-TextureResource::Desc D3D11Renderer::getSwapChainTextureDesc()
+Result D3D11Renderer::createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout)
{
- D3D11_TEXTURE2D_DESC dxDesc;
- ((ID3D11Texture2D*)m_primaryRenderTargetTexture->m_resource.get())->GetDesc(&dxDesc);
+ RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl();
+ layout->m_renderTargets.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ layout->m_renderTargets[i] = desc.renderTargets[i];
+ }
- TextureResource::Desc desc;
- desc.init2D(IResource::Type::Texture2D, Format::Unknown, dxDesc.Width, dxDesc.Height, 1);
+ if (desc.depthStencil)
+ {
+ layout->m_hasDepthStencil = true;
+ layout->m_depthStencil = *desc.depthStencil;
+ }
+ else
+ {
+ layout->m_hasDepthStencil = false;
+ }
+ *outLayout = layout.detach();
+ return SLANG_OK;
+}
+
+Result D3D11Renderer::createFramebuffer(
+ const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer)
+{
+ RefPtr<FramebufferImpl> framebuffer = new FramebufferImpl();
+ framebuffer->renderTargetViews.setCount(desc.renderTargetCount);
+ framebuffer->d3dRenderTargetViews.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ framebuffer->renderTargetViews[i] = static_cast<RenderTargetViewImpl*>(desc.renderTargetViews[i]);
+ framebuffer->d3dRenderTargetViews[i] = framebuffer->renderTargetViews[i]->m_rtv;
+ }
+ framebuffer->depthStencilView = static_cast<DepthStencilViewImpl*>(desc.depthStencilView);
+ framebuffer->d3dDepthStencilView = framebuffer->depthStencilView->m_dsv;
+ *outFramebuffer = framebuffer.detach();
+ return SLANG_OK;
+}
- return desc;
+void D3D11Renderer::setFramebuffer(IFramebuffer* frameBuffer)
+{
+ m_framebufferBindingDirty = true;
+ m_currentFramebuffer = static_cast<FramebufferImpl*>(frameBuffer);
}
-SlangResult D3D11Renderer::captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
+SlangResult D3D11Renderer::readTextureResource(
+ ITextureResource* resource, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize)
{
- return captureTextureToSurface(
- m_device,
- m_immediateContext,
- m_primaryRenderTargetTexture.Ptr(),
- buffer,
- inOutBufferSize,
- outRowPitch,
- outPixelSize);
+ auto texture = static_cast<TextureResourceImpl*>(resource);
+ // Don't bother supporting MSAA for right now
+ if (texture->getDesc()->sampleDesc.numSamples > 1)
+ {
+ fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
+ return E_INVALIDARG;
+ }
+
+ size_t bytesPerPixel = sizeof(uint32_t);
+ size_t rowPitch = int(texture->getDesc()->size.width) * bytesPerPixel;
+ size_t bufferSize = rowPitch * int(texture->getDesc()->size.height);
+ if (outRowPitch)
+ *outRowPitch = rowPitch;
+ if (outPixelSize)
+ *outPixelSize = bytesPerPixel;
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ auto d3d11Texture = ((ID3D11Texture2D*)texture->m_resource.get());
+ d3d11Texture->GetDesc(&textureDesc);
+
+ HRESULT hr = S_OK;
+ ComPtr<ID3D11Texture2D> stagingTexture;
+
+ if (textureDesc.Usage == D3D11_USAGE_STAGING &&
+ (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
+ {
+ stagingTexture = d3d11Texture;
+ }
+ else
+ {
+ // Modify the descriptor to give us a staging texture
+ textureDesc.BindFlags = 0;
+ textureDesc.MiscFlags &= ~D3D11_RESOURCE_MISC_TEXTURECUBE;
+ textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ textureDesc.Usage = D3D11_USAGE_STAGING;
+
+ hr = m_device->CreateTexture2D(&textureDesc, 0, stagingTexture.writeRef());
+ if (FAILED(hr))
+ {
+ fprintf(stderr, "ERROR: failed to create staging texture\n");
+ return hr;
+ }
+
+ m_immediateContext->CopyResource(stagingTexture, d3d11Texture);
+ }
+
+ // Now just read back texels from the staging textures
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ SLANG_RETURN_ON_FAIL(m_immediateContext->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource));
+ RefPtr<ListBlob> blob = new ListBlob();
+ blob->m_data.setCount(bufferSize);
+ char* buffer = (char*)blob->m_data.begin();
+ for (size_t y = 0; y < textureDesc.Height; y++)
+ {
+ memcpy(
+ (char*)buffer + y * (*outRowPitch),
+ (char*)mappedResource.pData + y * mappedResource.RowPitch,
+ *outRowPitch);
+ }
+ // Make sure to unmap
+ m_immediateContext->Unmap(stagingTexture, 0);
+ *outBlob = blob.detach();
+ return SLANG_OK;
+ }
}
static D3D11_BIND_FLAG _calcResourceFlag(IResource::BindFlag::Enum bindFlag)
@@ -1661,12 +1751,6 @@ void D3D11Renderer::setIndexBuffer(IBufferResource* buffer, Format indexFormat,
m_immediateContext->IASetIndexBuffer(((BufferResourceImpl*)buffer)->m_buffer, dxFormat, UINT(offset));
}
-void D3D11Renderer::setDepthStencilTarget(IResourceView* depthStencilView)
-{
- m_dsvBinding = ((DepthStencilViewImpl*) depthStencilView)->m_dsv;
- m_targetBindingsDirty[int(PipelineType::Graphics)] = true;
-}
-
void D3D11Renderer::setViewports(UInt count, Viewport const* viewports)
{
static const int kMaxViewports = D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX + 1;
@@ -2097,9 +2181,10 @@ Result D3D11Renderer::createGraphicsPipelineState(const GraphicsPipelineStateDes
state->m_depthStencilState = depthStencilState;
state->m_rasterizerState = rasterizerState;
state->m_blendState = blendState;
- state->m_pipelineLayout = (PipelineLayoutImpl*) desc.pipelineLayout;
- state->m_inputLayout = (InputLayoutImpl*) desc.inputLayout;
- state->m_rtvCount = UINT(desc.renderTargetCount);
+ state->m_pipelineLayout = static_cast<PipelineLayoutImpl*>(desc.pipelineLayout);
+ state->m_inputLayout = static_cast<InputLayoutImpl*>(desc.inputLayout);
+ state->m_rtvCount = (UINT) static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout)
+ ->m_renderTargets.getCount();
state->m_blendColor[0] = 0;
state->m_blendColor[1] = 0;
state->m_blendColor[2] = 0;
@@ -2258,8 +2343,10 @@ Result D3D11Renderer::createPipelineLayout(const IPipelineLayout::Desc& desc, IP
return SLANG_OK;
}
-Result D3D11Renderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet)
+Result D3D11Renderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet)
{
+ SLANG_UNUSED(flag);
+
auto layoutImpl = (DescriptorSetLayoutImpl*)layout;
RefPtr<DescriptorSetImpl> descriptorSetImpl = new DescriptorSetImpl();
@@ -2321,19 +2408,19 @@ Result D3D11Renderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescrip
void D3D11Renderer::_flushGraphicsState()
{
auto pipelineType = int(PipelineType::Graphics);
- if(m_targetBindingsDirty[pipelineType])
+ if (m_framebufferBindingDirty || m_shaderBindingDirty)
{
- m_targetBindingsDirty[pipelineType] = false;
+ m_framebufferBindingDirty = false;
+ m_shaderBindingDirty = false;
auto pipelineState = static_cast<GraphicsPipelineStateImpl*>(m_currentPipelineState.get());
- auto rtvCount = pipelineState->m_rtvCount;
+ auto rtvCount = (UINT)m_currentFramebuffer->renderTargetViews.getCount();
auto uavCount = pipelineState->m_pipelineLayout->m_uavCount;
-
m_immediateContext->OMSetRenderTargetsAndUnorderedAccessViews(
rtvCount,
- m_rtvBindings[0].readRef(),
- m_dsvBinding,
+ m_currentFramebuffer->d3dRenderTargetViews.getArrayView().getBuffer(),
+ m_currentFramebuffer->d3dDepthStencilView,
rtvCount,
uavCount,
m_uavBindings[pipelineType][0].readRef(),
@@ -2344,9 +2431,9 @@ void D3D11Renderer::_flushGraphicsState()
void D3D11Renderer::_flushComputeState()
{
auto pipelineType = int(PipelineType::Compute);
- if(m_targetBindingsDirty[pipelineType])
+ if (m_shaderBindingDirty)
{
- m_targetBindingsDirty[pipelineType] = false;
+ m_shaderBindingDirty = false;
auto pipelineState = static_cast<ComputePipelineStateImpl*>(m_currentPipelineState.get());
@@ -2568,7 +2655,7 @@ void D3D11Renderer::setDescriptorSet(PipelineType pipelineType, IPipelineLayout*
{
m_uavBindings[int(pipelineType)][startSlot + ii] = uavs[ii];
}
- m_targetBindingsDirty[int(pipelineType)] = true;
+ m_shaderBindingDirty = true;
}
}
}
diff --git a/tools/gfx/d3d11/render-d3d11.h b/tools/gfx/d3d11/render-d3d11.h
index 1c81b688c..42887ed1b 100644
--- a/tools/gfx/d3d11/render-d3d11.h
+++ b/tools/gfx/d3d11/render-d3d11.h
@@ -6,6 +6,6 @@
namespace gfx
{
-SlangResult SLANG_MCALL createD3D11Renderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer);
+SlangResult SLANG_MCALL createD3D11Renderer(const IRenderer::Desc* desc, IRenderer** outRenderer);
} // gfx
diff --git a/tools/gfx/d3d12/descriptor-heap-d3d12.h b/tools/gfx/d3d12/descriptor-heap-d3d12.h
index 642ff59db..20d867155 100644
--- a/tools/gfx/d3d12/descriptor-heap-d3d12.h
+++ b/tools/gfx/d3d12/descriptor-heap-d3d12.h
@@ -6,6 +6,7 @@
#include "slang-com-ptr.h"
#include "core/slang-list.h"
+#include "core/slang-virtual-object-pool.h"
namespace gfx {
@@ -76,8 +77,6 @@ struct D3D12HostVisibleDescriptor
///
/// Unlike the `D3D12DescriptorHeap` type, this class allows for both
/// allocation and freeing of descriptors, by maintaining a free list.
-/// In order to keep the implementation simple, this class only supports
-/// allocation of single descriptors and not ranges.
///
class D3D12HostVisibleDescriptorAllocator
{
@@ -86,8 +85,7 @@ class D3D12HostVisibleDescriptorAllocator
D3D12_DESCRIPTOR_HEAP_TYPE m_type;
D3D12DescriptorHeap m_heap;
- Slang::List<D3D12HostVisibleDescriptor> m_freeList;
- Slang::List<D3D12DescriptorHeap> m_heaps;
+ Slang::VirtualObjectPool m_allocator;
public:
D3D12HostVisibleDescriptorAllocator()
@@ -100,36 +98,29 @@ public:
m_type = type;
SLANG_RETURN_ON_FAIL(m_heap.init(m_device, m_chunkSize, m_type, D3D12_DESCRIPTOR_HEAP_FLAG_NONE));
-
+ m_allocator.initPool(m_chunkSize);
return SLANG_OK;
}
- Slang::Result allocate(D3D12HostVisibleDescriptor* outDescriptor)
+ SLANG_FORCE_INLINE D3D12_CPU_DESCRIPTOR_HANDLE getCpuHandle(int index) const
{
- // TODO: this allocator would take some work to make thread-safe
+ return m_heap.getCpuHandle(index);
+ }
- if(m_freeList.getCount() > 0)
- {
- auto descriptor = m_freeList[0];
- m_freeList.fastRemoveAt(0);
+ int allocate(int count)
+ {
+ return m_allocator.alloc(count);
+ }
- *outDescriptor = descriptor;
- return SLANG_OK;
- }
+ Slang::Result allocate(D3D12HostVisibleDescriptor* outDescriptor)
+ {
+ // TODO: this allocator would take some work to make thread-safe
- int index = m_heap.allocate();
+ int index = m_allocator.alloc(1);
if(index < 0)
{
- // Allocate a new heap and try again.
- m_heaps.add(m_heap);
- SLANG_RETURN_ON_FAIL(m_heap.init(m_device, m_chunkSize, m_type, D3D12_DESCRIPTOR_HEAP_FLAG_NONE));
-
- int index = m_heap.allocate();
- if(index < 0)
- {
- assert(!"descriptor allocation failed on fresh heap");
- return SLANG_FAIL;
- }
+ assert(!"descriptor allocation failed");
+ return SLANG_FAIL;
}
D3D12HostVisibleDescriptor descriptor;
@@ -139,9 +130,16 @@ public:
return SLANG_OK;
}
+ void free(int index, int count)
+ {
+ m_allocator.free(index, count);
+ }
+
void free(D3D12HostVisibleDescriptor descriptor)
{
- m_freeList.add(descriptor);
+ auto index =
+ (int)(descriptor.cpuHandle.ptr - m_heap.getCpuStart().ptr) / m_heap.getDescriptorSize();
+ free(index, 1);
}
};
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp
index 2e1959bde..4e80ff47a 100644
--- a/tools/gfx/d3d12/render-d3d12.cpp
+++ b/tools/gfx/d3d12/render-d3d12.cpp
@@ -6,7 +6,7 @@
//WORKING:#include "options.h"
#include "../renderer-shared.h"
#include "../render-graphics-common.h"
-
+#include "core/slang-blob.h"
#include "core/slang-basic.h"
// In order to use the Slang API, we need to include its header
@@ -66,11 +66,17 @@ class D3D12Renderer : public GraphicsAPIRenderer
{
public:
// Renderer implementation
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override;
virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) override;
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() override;
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() override;
- virtual SLANG_NO_THROW ITextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ const ISwapchain::Desc& desc,
+ WindowHandle window,
+ ISwapchain** outSwapchain) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
IResource::Usage initialUsage,
@@ -92,6 +98,12 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView(
IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebufferLayout(IFramebufferLayout::Desc const& desc, IFramebufferLayout** outLayout) override;
+
virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout(
const InputElementDesc* inputElements,
UInt inputElementCount,
@@ -102,7 +114,9 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createPipelineLayout(
const IPipelineLayout::Desc& desc, IPipelineLayout** outLayout) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createDescriptorSet(
- IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) override;
+ IDescriptorSetLayout* layout,
+ IDescriptorSet::Flag::Enum flag,
+ IDescriptorSet** outDescriptorSet) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override;
@@ -111,8 +125,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* resource, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL
map(IBufferResource* buffer, MapFlavor flavor) override;
@@ -135,12 +149,12 @@ public:
const UInt* offsets) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override;
- virtual void SLANG_MCALL setDepthStencilTarget(IResourceView* depthStencilView) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setViewports(UInt count, Viewport const* viewports) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setScissorRects(UInt count, ScissorRect const* rects) override;
virtual SLANG_NO_THROW void SLANG_MCALL setPipelineState(IPipelineState* state) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* frameBuffer) override;
virtual SLANG_NO_THROW void SLANG_MCALL draw(UInt vertexCount, UInt startVertex) override;
virtual SLANG_NO_THROW void SLANG_MCALL
drawIndexed(UInt indexCount, UInt startIndex, UInt baseVertex) override;
@@ -202,6 +216,18 @@ protected:
}
ComPtr<ID3D12CommandAllocator> m_commandAllocator; ///< The command allocator for this frame
UINT64 m_fenceValue; ///< The fence value when rendering this Frame is complete
+
+ // During command submission, we need all the descriptor tables that get
+ // used to come from a single heap (for each descriptor heap type).
+ //
+ // We will thus keep a single heap of each type that we hope will hold
+ // all the descriptors that actually get needed in a frame.
+ //
+ // TODO: we need an allocation policy to reallocate and resize these
+ // if/when we run out of space during a frame.
+ //
+ D3D12DescriptorHeap m_viewHeap; ///< Cbv, Srv, Uav
+ D3D12DescriptorHeap m_samplerHeap; ///< Heap for samplers
};
class ShaderProgramImpl : public GraphicsCommonShaderProgram
@@ -315,7 +341,12 @@ protected:
return nullptr;
}
public:
- D3D12_CPU_DESCRIPTOR_HANDLE m_cpuHandle;
+ D3D12HostVisibleDescriptor m_descriptor;
+ D3D12Renderer* m_renderer;
+ ~SamplerStateImpl()
+ {
+ m_renderer->m_samplerAllocator.free(m_descriptor);
+ }
};
class ResourceViewImpl : public IResourceView, public RefObject
@@ -333,6 +364,189 @@ protected:
D3D12HostVisibleDescriptor m_descriptor;
};
+ class FramebufferLayoutImpl
+ : public IFramebufferLayout
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebufferLayout* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout)
+ return static_cast<IFramebufferLayout*>(this);
+ return nullptr;
+ }
+
+ public:
+ ShortList<IFramebufferLayout::AttachmentLayout> m_renderTargets;
+ bool m_hasDepthStencil = false;
+ IFramebufferLayout::AttachmentLayout m_depthStencil;
+ };
+
+ class FramebufferImpl
+ : public IFramebuffer
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebuffer* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebuffer)
+ return static_cast<IFramebuffer*>(this);
+ return nullptr;
+ }
+
+ public:
+ ShortList<ComPtr<IResourceView>> renderTargetViews;
+ ComPtr<IResourceView> depthStencilView;
+ ShortList<D3D12_CPU_DESCRIPTOR_HANDLE> renderTargetDescriptors;
+ D3D12_CPU_DESCRIPTOR_HANDLE depthStencilDescriptor;
+ };
+
+ class SwapchainImpl
+ : public ISwapchain
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ISwapchain* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
+ return static_cast<ISwapchain*>(this);
+ return nullptr;
+ }
+
+ public:
+ Result init(D3D12Renderer* renderer, const ISwapchain::Desc& desc, WindowHandle window)
+ {
+ // Return fail on non-supported platforms.
+ switch (window.type)
+ {
+ case WindowHandle::Type::Win32Handle:
+ break;
+ default:
+ return SLANG_FAIL;
+ }
+
+ m_renderer = renderer;
+ m_desc = desc;
+
+ // Describe the swap chain.
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = desc.imageCount;
+ swapChainDesc.BufferDesc.Width = desc.width;
+ swapChainDesc.BufferDesc.Height = desc.height;
+ swapChainDesc.BufferDesc.Format = D3DUtil::getMapFormat(desc.format);
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ swapChainDesc.OutputWindow = (HWND)window.handleValues[0];
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.Windowed = TRUE;
+
+ if (!desc.enableVSync)
+ {
+ swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
+ }
+
+ // Swap chain needs the queue so that it can force a flush on it.
+ ComPtr<IDXGISwapChain> swapChain;
+ SLANG_RETURN_ON_FAIL(m_renderer->m_deviceInfo.m_dxgiFactory->CreateSwapChain(
+ m_renderer->m_commandQueue, &swapChainDesc, swapChain.writeRef()));
+ SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(m_swapChain.writeRef()));
+
+ if (!desc.enableVSync)
+ {
+ m_swapChainWaitableObject = m_swapChain->GetFrameLatencyWaitableObject();
+
+ int maxLatency = desc.imageCount - 2;
+
+ // Make sure the maximum latency is in the range required by dx12 runtime
+ maxLatency = (maxLatency < 1) ? 1 : maxLatency;
+ maxLatency = (maxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS)
+ ? DXGI_MAX_SWAP_CHAIN_BUFFERS
+ : maxLatency;
+
+ m_swapChain->SetMaximumFrameLatency(maxLatency);
+ }
+
+ // This sample does not support fullscreen transitions.
+ SLANG_RETURN_ON_FAIL(m_renderer->m_deviceInfo.m_dxgiFactory->MakeWindowAssociation(
+ (HWND)window.handleValues[0], DXGI_MWA_NO_ALT_ENTER));
+
+ m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
+
+ for (uint32_t i = 0; i < desc.imageCount; i++)
+ {
+ ComPtr<ID3D12Resource> d3dResource;
+ m_swapChain->GetBuffer(i, IID_PPV_ARGS(d3dResource.writeRef()));
+ ITextureResource::Desc imageDesc = {};
+ imageDesc.init2D(
+ IResource::Type::Texture2D, desc.format, desc.width, desc.height, 0);
+ RefPtr<TextureResourceImpl> image = new TextureResourceImpl(imageDesc);
+ image->m_resource.setResource(d3dResource.get(), D3D12_RESOURCE_STATE_COMMON);
+ m_images.add(image);
+ }
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
+ virtual SLANG_NO_THROW Result getImage(uint32_t index, ITextureResource** outResource) override
+ {
+ m_images[index]->addRef();
+ *outResource = m_images[index].Ptr();
+ return SLANG_OK;
+ }
+ void makeBackbufferPresentable()
+ {
+ D3D12BarrierSubmitter submitter(m_renderer->m_commandList);
+ m_images[m_renderTargetIndex]->m_resource.transition(
+ D3D12_RESOURCE_STATE_PRESENT, submitter);
+ }
+ virtual SLANG_NO_THROW Result present() override
+ {
+ if (m_swapChainWaitableObject)
+ {
+ // check if now is good time to present
+ // This doesn't wait - because the wait time is 0. If it returns WAIT_TIMEOUT it
+ // means that no frame is waiting to be be displayed so there is no point doing a
+ // present.
+ const bool shouldPresent =
+ (WaitForSingleObjectEx(m_swapChainWaitableObject, 0, TRUE) != WAIT_TIMEOUT);
+ if (shouldPresent)
+ {
+ m_swapChain->Present(0, 0);
+ }
+ }
+ else
+ {
+ if (SLANG_FAILED(m_swapChain->Present(1, 0)))
+ {
+ return SLANG_FAIL;
+ }
+ }
+ // Update the render target index.
+ m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW uint32_t acquireNextImage() override
+ {
+ // `IRenderer::beginFrame()` must be called before `acquireNextImage`.
+ SLANG_RELEASE_ASSERT(m_renderer->m_commandListOpenCount == 1);
+
+ D3D12BarrierSubmitter submitter(m_renderer->m_commandList);
+ m_images[m_renderTargetIndex]->m_resource.transition(
+ D3D12_RESOURCE_STATE_RENDER_TARGET, submitter);
+ return m_renderTargetIndex;
+ }
+ public:
+ D3D12Renderer* m_renderer = nullptr;
+ ISwapchain::Desc m_desc;
+ HANDLE m_swapChainWaitableObject = nullptr;
+ ComPtr<IDXGISwapChain3> m_swapChain;
+ uint32_t m_renderTargetIndex;
+ ShortList<RefPtr<TextureResourceImpl>> m_images;
+ };
+
class InputLayoutImpl: public IInputLayout, public RefObject
{
public:
@@ -495,8 +709,8 @@ protected:
D3D12Renderer* m_renderer = nullptr; ///< Weak pointer - must be because if set on Renderer, will have a circular reference
RefPtr<DescriptorSetLayoutImpl> m_layout;
- D3D12DescriptorHeap* m_resourceHeap = nullptr;
- D3D12DescriptorHeap* m_samplerHeap = nullptr;
+ D3D12HostVisibleDescriptorAllocator* m_resourceHeap = nullptr;
+ D3D12HostVisibleDescriptorAllocator* m_samplerHeap = nullptr;
Int m_resourceTable = 0;
Int m_samplerTable = 0;
@@ -514,20 +728,15 @@ protected:
/// Backing storage for root constant ranges in this descriptor set.
List<char> m_rootConstantData;
- };
-
- // During command submission, we need all the descriptor tables that get
- // used to come from a single heap (for each descriptor heap type).
- //
- // We will thus keep a single heap of each type that we hope will hold
- // all the descriptors that actually get needed in a frame.
- //
- // TODO: we need an allocation policy to reallocate and resize these
- // if/when we run out of space during a frame.
- //
- D3D12DescriptorHeap m_viewHeap; ///< Cbv, Srv, Uav
- D3D12DescriptorHeap m_samplerHeap; ///< Heap for samplers
+ ~DescriptorSetImpl()
+ {
+ if (m_resourceObjects.getCount())
+ m_resourceHeap->free((int)m_resourceTable, (int)m_resourceObjects.getCount());
+ if (m_samplerObjects.getCount())
+ m_samplerHeap->free((int)m_samplerTable, (int)m_samplerObjects.getCount());
+ }
+ };
D3D12HostVisibleDescriptorAllocator m_rtvAllocator;
D3D12HostVisibleDescriptorAllocator m_dsvAllocator;
@@ -539,8 +748,8 @@ protected:
// around CPU-visible heaps for storing descriptors in a format
// that is ready for copying into the GPU-visible heaps as needed.
//
- D3D12DescriptorHeap m_cpuViewHeap; ///< Cbv, Srv, Uav
- D3D12DescriptorHeap m_cpuSamplerHeap; ///< Heap for samplers
+ D3D12HostVisibleDescriptorAllocator m_cpuViewHeap; ///< Cbv, Srv, Uav
+ D3D12HostVisibleDescriptorAllocator m_cpuSamplerHeap; ///< Heap for samplers
class PipelineStateImpl : public PipelineStateBase
{
@@ -639,17 +848,12 @@ protected:
Result createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, const void* srcData, size_t srcDataSize, D3D12Resource& uploadResource, D3D12_RESOURCE_STATES finalState, D3D12Resource& resourceOut);
- void beginRender();
-
- void endRender();
-
void submitGpuWorkAndWait();
void _resetCommandList();
Result captureTextureToSurface(
D3D12Resource& resource,
- void* buffer,
- size_t* inOutBufferSize,
+ ISlangBlob** blob,
size_t* outRowPitch,
size_t* outPixelSize);
@@ -658,21 +862,10 @@ protected:
ID3D12GraphicsCommandList* getCommandList() const { return m_commandList; }
-// RenderState* calcRenderState();
-
- /// From current bindings calculate the root signature and pipeline state
-// Result calcGraphicsPipelineState(ComPtr<ID3D12RootSignature>& sigOut, ComPtr<ID3D12PipelineState>& pipelineStateOut);
-// Result calcComputePipelineState(ComPtr<ID3D12RootSignature>& signatureOut, ComPtr<ID3D12PipelineState>& pipelineStateOut);
-
Result _bindRenderState(PipelineStateImpl* pipelineStateImpl, ID3D12GraphicsCommandList* commandList, Submitter* submitter);
-// Result _calcBindParameters(BindParameters& params);
-// RenderState* findRenderState(PipelineType pipelineType);
-
Result _createDevice(DeviceCheckFlags deviceCheckFlags, const UnownedStringSlice& nameMatch, D3D_FEATURE_LEVEL featureLevel, DeviceInfo& outDeviceInfo);
- D3D12CircularResourceHeap m_circularResourceHeap;
-
int m_commandListOpenCount = 0; ///< If >0 the command list should be open
List<BoundVertexBuffer> m_boundVertexBuffers;
@@ -683,21 +876,8 @@ protected:
RefPtr<PipelineStateImpl> m_currentPipelineState;
-// RefPtr<ShaderProgramImpl> m_boundShaderProgram;
-// RefPtr<InputLayoutImpl> m_boundInputLayout;
-
-// RefPtr<BindingStateImpl> m_boundBindingState;
RefPtr<DescriptorSetImpl> m_boundDescriptorSets[int(PipelineType::CountOf)][kMaxDescriptorSetCount];
- DXGI_FORMAT m_targetFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
- DXGI_FORMAT m_depthStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
- bool m_hasVsync = true;
- bool m_isFullSpeed = false;
- bool m_allowFullScreen = false;
- bool m_isMultiSampled = false;
- int m_numTargetSamples = 1; ///< The number of multi sample samples
- int m_targetSampleQuality = 0; ///< The multi sample quality
-
Desc m_desc;
bool m_isInitialized = false;
@@ -707,26 +887,20 @@ protected:
float m_clearColor[4] = { 0, 0, 0, 0 };
- D3D12_VIEWPORT m_viewport = {};
+ D3D12_VIEWPORT m_viewports[kMaxRTVCount] = {};
ComPtr<ID3D12Debug> m_dxDebug;
DeviceInfo m_deviceInfo;
ID3D12Device* m_device = nullptr;
- ComPtr<IDXGISwapChain3> m_swapChain;
ComPtr<ID3D12CommandQueue> m_commandQueue;
-// ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
ComPtr<ID3D12GraphicsCommandList> m_commandList;
- D3D12_RECT m_scissorRect = {};
-
-// List<RefPtr<RenderState> > m_renderStates; ///< Holds list of all render state combinations
-// RenderState* m_currentRenderState = nullptr; ///< The current combination
+ D3D12_RECT m_scissorRects[kMaxRTVCount] = {};
UINT m_rtvDescriptorSize = 0;
-// ComPtr<ID3D12DescriptorHeap> m_dsvHeap;
UINT m_dsvDescriptorSize = 0;
// Synchronization objects.
@@ -740,17 +914,8 @@ protected:
FrameInfo m_frameInfos[kMaxNumRenderFrames];
int m_numRenderTargets = 2;
- int m_renderTargetIndex = 0;
-
- D3D12Resource* m_backBuffers[kMaxNumRenderTargets];
- D3D12Resource* m_renderTargets[kMaxNumRenderTargets];
-
- D3D12Resource m_backBufferResources[kMaxNumRenderTargets];
- D3D12Resource m_renderTargetResources[kMaxNumRenderTargets];
-
- RefPtr<ResourceViewImpl> m_rtvs[kMaxRTVCount];
- RefPtr<ResourceViewImpl> m_dsv;
+ RefPtr<FramebufferImpl> m_frameBuffer;
int32_t m_depthStencilUsageFlags = 0; ///< D3DUtil::UsageFlag combination for depth stencil
int32_t m_targetUsageFlags = 0; ///< D3DUtil::UsageFlag combination for target
@@ -760,15 +925,13 @@ protected:
PFN_D3D12_CREATE_DEVICE m_D3D12CreateDevice = nullptr;
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE m_D3D12SerializeRootSignature = nullptr;
- HWND m_hwnd = nullptr;
-
bool m_nvapi = false;
};
-SlangResult SLANG_MCALL createD3D12Renderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+SlangResult SLANG_MCALL createD3D12Renderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
RefPtr<D3D12Renderer> result = new D3D12Renderer();
- SLANG_RETURN_ON_FAIL(result->initialize(*desc, windowHandle));
+ SLANG_RETURN_ON_FAIL(result->initialize(*desc));
*outRenderer = result.detach();
return SLANG_OK;
}
@@ -786,22 +949,12 @@ SlangResult SLANG_MCALL createD3D12Renderer(const IRenderer::Desc* desc, void* w
void D3D12Renderer::releaseFrameResources()
{
- // https://msdn.microsoft.com/en-us/library/windows/desktop/bb174577%28v=vs.85%29.aspx
-
- // Release the resources holding references to the swap chain (requirement of
- // IDXGISwapChain::ResizeBuffers) and reset the frame fence values to the
- // current fence value.
for (int i = 0; i < m_numRenderFrames; i++)
{
FrameInfo& info = m_frameInfos[i];
info.reset();
info.m_fenceValue = m_fence.getCurrentValue();
}
- for (int i = 0; i < m_numRenderTargets; i++)
- {
- m_backBuffers[i]->setResourceNull();
- m_renderTargets[i]->setResourceNull();
- }
}
void D3D12Renderer::waitForGpu()
@@ -965,75 +1118,21 @@ void D3D12Renderer::_resetCommandList()
ID3D12GraphicsCommandList* commandList = getCommandList();
commandList->Reset(frame.m_commandAllocator, nullptr);
-
- // TIM: when should this get set?
-// commandList->OMSetRenderTargets(
-// 1,
-// &m_rtvs[0]->m_descriptor.cpuHandle,
-// FALSE,
-// m_dsv ? &m_dsv->m_descriptor.cpuHandle : nullptr);
-
- // Set necessary state.
- commandList->RSSetViewports(1, &m_viewport);
- commandList->RSSetScissorRects(1, &m_scissorRect);
}
-void D3D12Renderer::beginRender()
+void D3D12Renderer::beginFrame()
{
- // Should currently not be open!
- assert(m_commandListOpenCount == 0);
-
- m_circularResourceHeap.updateCompleted();
-
- getFrame().m_commandAllocator->Reset();
-
- _resetCommandList();
-
- // Indicate that the render target needs to be writable
- if (m_swapChain)
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- m_renderTargets[m_renderTargetIndex]->transition(D3D12_RESOURCE_STATE_RENDER_TARGET, submitter);
- }
+}
- m_commandListOpenCount = 1;
+void D3D12Renderer::makeSwapchainImagePresentable(ISwapchain* swapchain)
+{
+ static_cast<SwapchainImpl*>(swapchain)->makeBackbufferPresentable();
}
-void D3D12Renderer::endRender()
+void D3D12Renderer::endFrame()
{
assert(m_commandListOpenCount == 1);
-
- {
- const UInt64 signalValue = m_fence.nextSignal(m_commandQueue);
- m_circularResourceHeap.addSync(signalValue);
- }
- if (m_swapChain)
- {
- D3D12Resource& backBuffer = *m_backBuffers[m_renderTargetIndex];
- if (m_isMultiSampled)
- {
- // MSAA resolve
- D3D12Resource& renderTarget = *m_renderTargets[m_renderTargetIndex];
- assert(&renderTarget != &backBuffer);
- // Barriers to wait for the render target, and the backbuffer to be in correct state
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- renderTarget.transition(D3D12_RESOURCE_STATE_RESOLVE_SOURCE, submitter);
- backBuffer.transition(D3D12_RESOURCE_STATE_RESOLVE_DEST, submitter);
- }
-
- // Do the resolve...
- m_commandList->ResolveSubresource(backBuffer, 0, renderTarget, 0, m_targetFormat);
- }
-
- // Make the back buffer presentable
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- backBuffer.transition(D3D12_RESOURCE_STATE_PRESENT, submitter);
- }
- }
SLANG_ASSERT_VOID_ON_FAIL(m_commandList->Close());
-
{
// Execute the command list.
ID3D12CommandList* commandLists[] = { m_commandList };
@@ -1043,6 +1142,30 @@ void D3D12Renderer::endRender()
assert(m_commandListOpenCount == 1);
// Must be 0
m_commandListOpenCount = 0;
+
+
+ // Increment the fence value. Save on the frame - we'll know that frame is done when the fence
+ // value >=
+ m_frameInfos[m_frameIndex].m_fenceValue = m_fence.nextSignal(m_commandQueue);
+
+ // increment frame index after signal
+ m_frameIndex = (m_frameIndex + 1) % m_numRenderFrames;
+
+ // On the current frame wait until it is completed
+ {
+ FrameInfo& frame = m_frameInfos[m_frameIndex];
+ // If the next frame is not ready to be rendered yet, wait until it is ready.
+ m_fence.waitUntilCompleted(frame.m_fenceValue);
+ }
+
+ getFrame().m_commandAllocator->Reset();
+
+ _resetCommandList();
+
+ m_commandListOpenCount = 1;
+
+ getFrame().m_viewHeap.deallocateAll();
+ getFrame().m_samplerHeap.deallocateAll();
}
void D3D12Renderer::submitGpuWork()
@@ -1069,8 +1192,7 @@ void D3D12Renderer::submitGpuWorkAndWait()
Result D3D12Renderer::captureTextureToSurface(
D3D12Resource& resource,
- void* buffer,
- size_t* inOutBufferSize,
+ ISlangBlob** outBlob,
size_t* outRowPitch,
size_t* outPixelSize)
{
@@ -1092,13 +1214,7 @@ Result D3D12Renderer::captureTextureToSurface(
*outRowPitch = rowPitch;
if (outPixelSize)
*outPixelSize = bytesPerPixel;
- if (!buffer || *inOutBufferSize == 0)
- {
- *inOutBufferSize = bufferSize;
- return SLANG_OK;
- }
- if (*inOutBufferSize < bufferSize)
- return SLANG_ERROR_INSUFFICIENT_BUFFER;
+
D3D12Resource stagingResource;
{
D3D12_RESOURCE_DESC stagingDesc;
@@ -1155,9 +1271,11 @@ Result D3D12Renderer::captureTextureToSurface(
SLANG_RETURN_ON_FAIL(dxResource->Map(0, &readRange, reinterpret_cast<void**>(&data)));
- memcpy(buffer, data, bufferSize);
-
+ RefPtr<Slang::ListBlob> resultBlob = new Slang::ListBlob();
+ resultBlob->m_data.setCount(bufferSize);
+ memcpy(resultBlob->m_data.getBuffer(), data, bufferSize);
dxResource->Unmap(0, nullptr);
+ *outBlob = resultBlob.detach();
return SLANG_OK;
}
}
@@ -1174,8 +1292,8 @@ Result D3D12Renderer::_bindRenderState(PipelineStateImpl* pipelineStateImpl, ID3
ID3D12DescriptorHeap* heaps[] =
{
- m_viewHeap.getHeap(),
- m_samplerHeap.getHeap(),
+ getFrame().m_viewHeap.getHeap(),
+ getFrame().m_samplerHeap.getHeap(),
};
commandList->SetDescriptorHeaps(SLANG_COUNT_OF(heaps), heaps);
@@ -1196,7 +1314,7 @@ Result D3D12Renderer::_bindRenderState(PipelineStateImpl* pipelineStateImpl, ID3
{
if(auto descriptorCount = descriptorSetLayout->m_resourceCount)
{
- auto& gpuHeap = m_viewHeap;
+ auto& gpuHeap = getFrame().m_viewHeap;
auto gpuDescriptorTable = gpuHeap.allocate(int(descriptorCount));
auto& cpuHeap = *descriptorSet->m_resourceHeap;
@@ -1214,7 +1332,7 @@ Result D3D12Renderer::_bindRenderState(PipelineStateImpl* pipelineStateImpl, ID3
{
if(auto descriptorCount = descriptorSetLayout->m_samplerCount)
{
- auto& gpuHeap = m_samplerHeap;
+ auto& gpuHeap = getFrame().m_samplerHeap;
auto gpuDescriptorTable = gpuHeap.allocate(int(descriptorCount));
auto& cpuHeap = *descriptorSet->m_samplerHeap;
@@ -1352,14 +1470,12 @@ static bool _isSupportedNVAPIOp(ID3D12Device* dev, uint32_t op)
#endif
}
-Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
+Result D3D12Renderer::initialize(const Desc& desc)
{
SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_DXBC, "sm_5_1"));
- SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc, inWindowHandle));
+ SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc));
- m_hwnd = (HWND)inWindowHandle;
-
// Rather than statically link against D3D, we load it dynamically.
HMODULE d3dModule = LoadLibraryA("d3d12.dll");
@@ -1505,23 +1621,6 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
m_desc = desc;
- // set viewport
- {
- m_viewport.Width = float(m_desc.width);
- m_viewport.Height = float(m_desc.height);
- m_viewport.MinDepth = 0;
- m_viewport.MaxDepth = 1;
- m_viewport.TopLeftX = 0;
- m_viewport.TopLeftY = 0;
- }
-
- {
- m_scissorRect.left = 0;
- m_scissorRect.top = 0;
- m_scissorRect.right = m_desc.width;
- m_scissorRect.bottom = m_desc.height;
- }
-
// Describe and create the command queue.
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
@@ -1529,62 +1628,22 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
SLANG_RETURN_ON_FAIL(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(m_commandQueue.writeRef())));
- if (inWindowHandle)
+ // Create descriptor heaps.
+ for (int i = 0; i < m_numRenderFrames; i++)
{
- // Describe the swap chain.
- DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
- swapChainDesc.BufferCount = m_numRenderTargets;
- swapChainDesc.BufferDesc.Width = m_desc.width;
- swapChainDesc.BufferDesc.Height = m_desc.height;
- swapChainDesc.BufferDesc.Format = m_targetFormat;
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
- swapChainDesc.OutputWindow = m_hwnd;
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.Windowed = TRUE;
-
- if (m_isFullSpeed)
- {
- m_hasVsync = false;
- m_allowFullScreen = false;
- }
-
- if (!m_hasVsync)
- {
- swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
- }
-
- // Swap chain needs the queue so that it can force a flush on it.
- ComPtr<IDXGISwapChain> swapChain;
- SLANG_RETURN_ON_FAIL(m_deviceInfo.m_dxgiFactory->CreateSwapChain(m_commandQueue, &swapChainDesc, swapChain.writeRef()));
- SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(m_swapChain.writeRef()));
-
- if (!m_hasVsync)
- {
- m_swapChainWaitableObject = m_swapChain->GetFrameLatencyWaitableObject();
-
- int maxLatency = m_numRenderTargets - 2;
-
- // Make sure the maximum latency is in the range required by dx12 runtime
- maxLatency = (maxLatency < 1) ? 1 : maxLatency;
- maxLatency = (maxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS) ? DXGI_MAX_SWAP_CHAIN_BUFFERS : maxLatency;
-
- m_swapChain->SetMaximumFrameLatency(maxLatency);
- }
-
- // This sample does not support fullscreen transitions.
- SLANG_RETURN_ON_FAIL(m_deviceInfo.m_dxgiFactory->MakeWindowAssociation(m_hwnd, DXGI_MWA_NO_ALT_ENTER));
-
- m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
+ SLANG_RETURN_ON_FAIL(m_frameInfos[i].m_viewHeap.init(
+ m_device,
+ 256,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+ D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
+ SLANG_RETURN_ON_FAIL(m_frameInfos[i].m_samplerHeap.init(
+ m_device,
+ 16,
+ D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
+ D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
}
-
- // Create descriptor heaps.
-
- SLANG_RETURN_ON_FAIL(m_viewHeap.init (m_device, 256, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
- SLANG_RETURN_ON_FAIL(m_samplerHeap.init(m_device, 16, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
-
- SLANG_RETURN_ON_FAIL(m_cpuViewHeap.init (m_device, 1024, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE));
- SLANG_RETURN_ON_FAIL(m_cpuSamplerHeap.init(m_device, 64, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE));
+ SLANG_RETURN_ON_FAIL(m_cpuViewHeap.init (m_device, 1024, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));
+ SLANG_RETURN_ON_FAIL(m_cpuSamplerHeap.init(m_device, 64, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER));
SLANG_RETURN_ON_FAIL(m_rtvAllocator.init (m_device, 16, D3D12_DESCRIPTOR_HEAP_TYPE_RTV));
SLANG_RETURN_ON_FAIL(m_dsvAllocator.init (m_device, 16, D3D12_DESCRIPTOR_HEAP_TYPE_DSV));
@@ -1603,17 +1662,9 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
m_commandList->Close();
}
- {
- D3D12CircularResourceHeap::Desc desc;
- desc.init();
- // Define size
- desc.m_blockSize = 65536;
- // Set up the heap
- m_circularResourceHeap.init(m_device, desc, &m_fence);
- }
+ _resetCommandList();
- // Setup for rendering
- beginRender();
+ m_commandListOpenCount = 1;
m_isInitialized = true;
return SLANG_OK;
@@ -1628,133 +1679,6 @@ Result D3D12Renderer::createFrameResources()
SLANG_RETURN_ON_FAIL(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(frame.m_commandAllocator.writeRef())));
}
- // Create back buffers
- if (m_swapChain)
- {
-// D3D12_CPU_DESCRIPTOR_HANDLE rtvStart(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
-
- // Work out target format
- D3D12_RESOURCE_DESC resourceDesc;
- {
- ComPtr<ID3D12Resource> backBuffer;
- SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(0, IID_PPV_ARGS(backBuffer.writeRef())));
- resourceDesc = backBuffer->GetDesc();
- }
- const DXGI_FORMAT resourceFormat = D3DUtil::calcResourceFormat(D3DUtil::USAGE_TARGET, m_targetUsageFlags, resourceDesc.Format);
- const DXGI_FORMAT targetFormat = D3DUtil::calcFormat(D3DUtil::USAGE_TARGET, resourceFormat);
-
- // Set the target format
- m_targetFormat = targetFormat;
-
- // Create a RTV, and a command allocator for each frame.
- for (int i = 0; i < m_numRenderTargets; i++)
- {
- // Get the back buffer
- ComPtr<ID3D12Resource> backBuffer;
- SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(UINT(i), IID_PPV_ARGS(backBuffer.writeRef())));
-
- // Set up resource for back buffer
- m_backBufferResources[i].setResource(backBuffer, D3D12_RESOURCE_STATE_COMMON);
- m_backBuffers[i] = &m_backBufferResources[i];
- // Assume they are the same thing for now...
- m_renderTargets[i] = &m_backBufferResources[i];
-
- // If we are multi-sampling - create a render target separate from the back buffer
- if (m_isMultiSampled)
- {
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
- D3D12_CLEAR_VALUE clearValue = {};
- clearValue.Format = m_targetFormat;
-
- // Don't know targets alignment, so just memory copy
- ::memcpy(clearValue.Color, m_clearColor, sizeof(m_clearColor));
-
- D3D12_RESOURCE_DESC desc(resourceDesc);
-
- desc.Format = resourceFormat;
- desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- desc.SampleDesc.Count = m_numTargetSamples;
- desc.SampleDesc.Quality = m_targetSampleQuality;
- desc.Alignment = 0;
-
- SLANG_RETURN_ON_FAIL(m_renderTargetResources[i].initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clearValue));
- m_renderTargets[i] = &m_renderTargetResources[i];
- }
-
- D3D12HostVisibleDescriptor rtvDescriptor;
- SLANG_RETURN_ON_FAIL(m_rtvAllocator.allocate(&rtvDescriptor));
-
- m_device->CreateRenderTargetView(*m_renderTargets[i], nullptr, rtvDescriptor.cpuHandle);
- }
- }
-
- if (m_swapChain)
- {
- D3D12_RESOURCE_DESC desc = m_backBuffers[0]->getResource()->GetDesc();
- assert(desc.Width == UINT64(m_desc.width) && desc.Height == UINT64(m_desc.height));
- }
-
- // Create the depth stencil view.
- {
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- DXGI_FORMAT resourceFormat = D3DUtil::calcResourceFormat(D3DUtil::USAGE_DEPTH_STENCIL, m_depthStencilUsageFlags, m_depthStencilFormat);
- DXGI_FORMAT depthStencilFormat = D3DUtil::calcFormat(D3DUtil::USAGE_DEPTH_STENCIL, resourceFormat);
-
- // Set the depth stencil format
- m_depthStencilFormat = depthStencilFormat;
-
- // Setup default clear
- D3D12_CLEAR_VALUE clearValue = {};
- clearValue.Format = depthStencilFormat;
- clearValue.DepthStencil.Depth = 1.0f;
- clearValue.DepthStencil.Stencil = 0;
-
- D3D12_RESOURCE_DESC resourceDesc = {};
- resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- resourceDesc.Format = resourceFormat;
- resourceDesc.Width = m_desc.width;
- resourceDesc.Height = m_desc.height;
- resourceDesc.DepthOrArraySize = 1;
- resourceDesc.MipLevels = 1;
- resourceDesc.SampleDesc.Count = m_numTargetSamples;
- resourceDesc.SampleDesc.Quality = m_targetSampleQuality;
- resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
- resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
- resourceDesc.Alignment = 0;
-
-#if 0
- SLANG_RETURN_ON_FAIL(m_depthStencil.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue));
-
- // Set the depth stencil
- D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
- depthStencilDesc.Format = depthStencilFormat;
- depthStencilDesc.ViewDimension = m_isMultiSampled ? D3D12_DSV_DIMENSION_TEXTURE2DMS : D3D12_DSV_DIMENSION_TEXTURE2D;
- depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE;
-
- // Set up as the depth stencil view
- m_device->CreateDepthStencilView(m_depthStencil, &depthStencilDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
- m_depthStencilView = m_dsvHeap->GetCPUDescriptorHandleForHeapStart();
-#endif
- }
-
- m_viewport.Width = static_cast<float>(m_desc.width);
- m_viewport.Height = static_cast<float>(m_desc.height);
- m_viewport.MaxDepth = 1.0f;
-
- m_scissorRect.right = static_cast<LONG>(m_desc.width);
- m_scissorRect.bottom = static_cast<LONG>(m_desc.height);
-
return SLANG_OK;
}
@@ -1766,72 +1690,35 @@ void D3D12Renderer::setClearColor(const float color[4])
void D3D12Renderer::clearFrame()
{
// Record commands
- if(auto rtv = m_rtvs[0])
+ if (!m_frameBuffer)
+ return;
+ for (auto rtv : m_frameBuffer->renderTargetDescriptors)
{
- m_commandList->ClearRenderTargetView(rtv->m_descriptor.cpuHandle, m_clearColor, 0, nullptr);
+ m_commandList->ClearRenderTargetView(rtv, m_clearColor, 0, nullptr);
}
- if (m_dsv)
+ if (m_frameBuffer->depthStencilView)
{
- m_commandList->ClearDepthStencilView(m_dsv->m_descriptor.cpuHandle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
+ m_commandList->ClearDepthStencilView(
+ m_frameBuffer->depthStencilDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
}
}
-void D3D12Renderer::presentFrame()
+SLANG_NO_THROW Result SLANG_MCALL D3D12Renderer::createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain)
{
- endRender();
-
- if (m_swapChainWaitableObject)
- {
- // check if now is good time to present
- // This doesn't wait - because the wait time is 0. If it returns WAIT_TIMEOUT it means that no frame is waiting to be be displayed
- // so there is no point doing a present.
- const bool shouldPresent = (WaitForSingleObjectEx(m_swapChainWaitableObject, 0, TRUE) != WAIT_TIMEOUT);
- if (shouldPresent)
- {
- m_swapChain->Present(0, 0);
- }
- }
- else
- {
- if (SLANG_FAILED(m_swapChain->Present(1, 0)))
- {
- assert(!"Problem presenting");
- beginRender();
- return;
- }
- }
-
- // Increment the fence value. Save on the frame - we'll know that frame is done when the fence value >=
- m_frameInfos[m_frameIndex].m_fenceValue = m_fence.nextSignal(m_commandQueue);
-
- // increment frame index after signal
- m_frameIndex = (m_frameIndex + 1) % m_numRenderFrames;
- // Update the render target index.
- m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
-
- // On the current frame wait until it is completed
- {
- FrameInfo& frame = m_frameInfos[m_frameIndex];
- // If the next frame is not ready to be rendered yet, wait until it is ready.
- m_fence.waitUntilCompleted(frame.m_fenceValue);
- }
-
- // Setup such that rendering can restart
- beginRender();
-}
-
-TextureResource::Desc D3D12Renderer::getSwapChainTextureDesc()
-{
- TextureResource::Desc desc;
- desc.init2D(IResource::Type::Texture2D, Format::Unknown, m_desc.width, m_desc.height, 1);
-
- return desc;
+ RefPtr<SwapchainImpl> swapchain = new SwapchainImpl();
+ SLANG_RETURN_ON_FAIL(swapchain->init(this, desc, window));
+ *outSwapchain = swapchain.detach();
+ return SLANG_OK;
}
-SlangResult D3D12Renderer::captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
+SlangResult D3D12Renderer::readTextureResource(
+ ITextureResource* resource,
+ ISlangBlob** outBlob,
+ size_t* outRowPitch,
+ size_t* outPixelSize)
{
- return captureTextureToSurface(*m_renderTargets[m_renderTargetIndex], buffer, inOutBufferSize, outRowPitch, outPixelSize);
+ return captureTextureToSurface(static_cast<TextureResourceImpl*>(resource)->m_resource, outBlob, outRowPitch, outPixelSize);
}
static D3D12_RESOURCE_STATES _calcResourceState(IResource::Usage usage)
@@ -1934,6 +1821,22 @@ Result D3D12Renderer::createTextureResource(IResource::Usage initialUsage, const
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+
+ switch (initialUsage)
+ {
+ case IResource::Usage::RenderTarget:
+ resourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+ break;
+ case IResource::Usage::DepthWrite:
+ resourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
+ break;
+ case IResource::Usage::UnorderedAccess:
+ resourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+ break;
+ default:
+ break;
+ }
+
resourceDesc.Alignment = 0;
RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(srcDesc));
@@ -1948,7 +1851,22 @@ Result D3D12Renderer::createTextureResource(IResource::Usage initialUsage, const
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
- SLANG_RETURN_ON_FAIL(texture->m_resource.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
+ D3D12_CLEAR_VALUE clearValue;
+ D3D12_CLEAR_VALUE* clearValuePtr = &clearValue;
+ if ((resourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |
+ D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) == 0)
+ {
+ clearValuePtr = nullptr;
+ }
+ clearValue.Format = pixelFormat;
+ memcpy(clearValue.Color, descIn.optimalClearValue, sizeof(clearValue.Color));
+ SLANG_RETURN_ON_FAIL(texture->m_resource.initCommitted(
+ m_device,
+ heapProps,
+ D3D12_HEAP_FLAG_NONE,
+ resourceDesc,
+ D3D12_RESOURCE_STATE_COPY_DEST,
+ clearValuePtr));
texture->m_resource.setDebugName(L"Texture");
}
@@ -1961,17 +1879,13 @@ Result D3D12Renderer::createTextureResource(IResource::Usage initialUsage, const
List<UInt32> mipNumRows;
mipNumRows.setCount(numMipMaps);
- // Since textures are effectively immutable currently initData must be set
- assert(initData);
- // We should have this many sub resources
- assert(initData->numSubResources == numMipMaps * srcDesc.size.depth * arraySize);
-
// NOTE! This is just the size for one array upload -> not for the whole texture
UInt64 requiredSize = 0;
m_device->GetCopyableFootprints(&resourceDesc, 0, numMipMaps, 0, layouts.begin(), mipNumRows.begin(), mipRowSizeInBytes.begin(), &requiredSize);
// Sub resource indexing
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn705766(v=vs.85).aspx#subresource_indexing
+ if (initData)
{
// Create the upload texture
D3D12Resource uploadTexture;
@@ -2242,27 +2156,17 @@ Result D3D12Renderer::createSamplerState(ISamplerState::Desc const& desc, ISampl
auto samplerHeap = &m_cpuSamplerHeap;
- int indexInSamplerHeap = samplerHeap->allocate();
- if(indexInSamplerHeap < 0)
- {
- // We ran out of room in our CPU sampler heap.
- //
- // TODO: this should not be a catastrophic failure, because
- // we should just allocate another CPU sampler heap that
- // can service subsequent allocation.
- //
- return SLANG_FAIL;
- }
- auto cpuDescriptorHandle = samplerHeap->getCpuHandle(indexInSamplerHeap);
-
- m_device->CreateSampler(&dxDesc, cpuDescriptorHandle);
+ D3D12HostVisibleDescriptor cpuDescriptor;
+ samplerHeap->allocate(&cpuDescriptor);
+ m_device->CreateSampler(&dxDesc, cpuDescriptor.cpuHandle);
// TODO: We really ought to have a free-list of sampler-heap
// entries that we check before we go to the heap, and then
// when we are done with a sampler we simply add it to the free list.
//
RefPtr<SamplerStateImpl> samplerImpl = new SamplerStateImpl();
- samplerImpl->m_cpuHandle = cpuDescriptorHandle;
+ samplerImpl->m_renderer = this;
+ samplerImpl->m_descriptor = cpuDescriptor;
*outSampler = samplerImpl.detach();
return SLANG_OK;
}
@@ -2282,14 +2186,53 @@ Result D3D12Renderer::createTextureView(ITextureResource* texture, IResourceView
case IResourceView::Type::RenderTarget:
{
SLANG_RETURN_ON_FAIL(m_rtvAllocator.allocate(&viewImpl->m_descriptor));
- m_device->CreateRenderTargetView(resourceImpl->m_resource, nullptr, viewImpl->m_descriptor.cpuHandle);
+ D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
+ rtvDesc.Format = D3DUtil::getMapFormat(desc.format);
+ switch (desc.renderTarget.shape)
+ {
+ case IResource::Type::Texture1D:
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1D;
+ rtvDesc.Texture1D.MipSlice = desc.renderTarget.mipSlice;
+ break;
+ case IResource::Type::Texture2D:
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = desc.renderTarget.mipSlice;
+ rtvDesc.Texture2D.PlaneSlice = desc.renderTarget.planeIndex;
+ break;
+ case IResource::Type::Texture3D:
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = desc.renderTarget.mipSlice;
+ rtvDesc.Texture3D.FirstWSlice = desc.renderTarget.arrayIndex;
+ rtvDesc.Texture3D.WSize = desc.renderTarget.arraySize;
+ break;
+ default:
+ return SLANG_FAIL;
+ }
+ m_device->CreateRenderTargetView(
+ resourceImpl->m_resource, &rtvDesc, viewImpl->m_descriptor.cpuHandle);
}
break;
case IResourceView::Type::DepthStencil:
{
SLANG_RETURN_ON_FAIL(m_dsvAllocator.allocate(&viewImpl->m_descriptor));
- m_device->CreateDepthStencilView(resourceImpl->m_resource, nullptr, viewImpl->m_descriptor.cpuHandle);
+ D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
+ dsvDesc.Format = D3DUtil::getMapFormat(desc.format);
+ switch (desc.renderTarget.shape)
+ {
+ case IResource::Type::Texture1D:
+ dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE1D;
+ dsvDesc.Texture1D.MipSlice = desc.renderTarget.mipSlice;
+ break;
+ case IResource::Type::Texture2D:
+ dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
+ dsvDesc.Texture2D.MipSlice = desc.renderTarget.mipSlice;
+ break;
+ default:
+ return SLANG_FAIL;
+ }
+ m_device->CreateDepthStencilView(
+ resourceImpl->m_resource, &dsvDesc, viewImpl->m_descriptor.cpuHandle);
}
break;
@@ -2403,6 +2346,54 @@ Result D3D12Renderer::createBufferView(IBufferResource* buffer, IResourceView::D
return SLANG_OK;
}
+Result D3D12Renderer::createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFb)
+{
+ RefPtr<FramebufferImpl> framebuffer = new FramebufferImpl();
+ framebuffer->renderTargetViews.setCount(desc.renderTargetCount);
+ framebuffer->renderTargetDescriptors.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ framebuffer->renderTargetViews[i] = desc.renderTargetViews[i];
+ framebuffer->renderTargetDescriptors[i] =
+ static_cast<ResourceViewImpl*>(desc.renderTargetViews[i])->m_descriptor.cpuHandle;
+ }
+ framebuffer->depthStencilView = desc.depthStencilView;
+ if (desc.depthStencilView)
+ {
+ framebuffer->depthStencilDescriptor =
+ static_cast<ResourceViewImpl*>(desc.depthStencilView)->m_descriptor.cpuHandle;
+ }
+ else
+ {
+ framebuffer->depthStencilDescriptor.ptr = 0;
+ }
+ *outFb = framebuffer.detach();
+ return SLANG_OK;
+}
+
+Result D3D12Renderer::createFramebufferLayout(
+ IFramebufferLayout::Desc const& desc, IFramebufferLayout** outLayout)
+{
+ RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl();
+ layout->m_renderTargets.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ layout->m_renderTargets[i] = desc.renderTargets[i];
+ }
+
+ if (desc.depthStencil)
+ {
+ layout->m_hasDepthStencil = true;
+ layout->m_depthStencil = *desc.depthStencil;
+ }
+ else
+ {
+ layout->m_hasDepthStencil = false;
+ }
+ *outLayout = layout.detach();
+ return SLANG_OK;
+}
+
Result D3D12Renderer::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount, IInputLayout** outLayout)
{
RefPtr<InputLayoutImpl> layout(new InputLayoutImpl);
@@ -2655,20 +2646,14 @@ void D3D12Renderer::setIndexBuffer(IBufferResource* buffer, Format indexFormat,
m_boundIndexOffset = UINT(offset);
}
-void D3D12Renderer::setDepthStencilTarget(IResourceView* depthStencilView)
-{
-}
-
void D3D12Renderer::setViewports(UInt count, Viewport const* viewports)
{
static const int kMaxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
- assert(count <= kMaxViewports);
-
- D3D12_VIEWPORT dxViewports[kMaxViewports];
+ assert(count <= kMaxViewports && count <= kMaxRTVCount);
for(UInt ii = 0; ii < count; ++ii)
{
auto& inViewport = viewports[ii];
- auto& dxViewport = dxViewports[ii];
+ auto& dxViewport = m_viewports[ii];
dxViewport.TopLeftX = inViewport.originX;
dxViewport.TopLeftY = inViewport.originY;
@@ -2677,20 +2662,18 @@ void D3D12Renderer::setViewports(UInt count, Viewport const* viewports)
dxViewport.MinDepth = inViewport.minZ;
dxViewport.MaxDepth = inViewport.maxZ;
}
-
- m_commandList->RSSetViewports(UINT(count), dxViewports);
+ m_commandList->RSSetViewports(UINT(count), m_viewports);
}
void D3D12Renderer::setScissorRects(UInt count, ScissorRect const* rects)
{
static const int kMaxScissorRects = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
- assert(count <= kMaxScissorRects);
+ assert(count <= kMaxScissorRects && count <= kMaxRTVCount);
- D3D12_RECT dxRects[kMaxScissorRects];
for(UInt ii = 0; ii < count; ++ii)
{
auto& inRect = rects[ii];
- auto& dxRect = dxRects[ii];
+ auto& dxRect = m_scissorRects[ii];
dxRect.left = LONG(inRect.minX);
dxRect.top = LONG(inRect.minY);
@@ -2698,7 +2681,7 @@ void D3D12Renderer::setScissorRects(UInt count, ScissorRect const* rects)
dxRect.bottom = LONG(inRect.maxY);
}
- m_commandList->RSSetScissorRects(UINT(count), dxRects);
+ m_commandList->RSSetScissorRects(UINT(count), m_scissorRects);
}
void D3D12Renderer::setPipelineState(IPipelineState* state)
@@ -2706,6 +2689,19 @@ void D3D12Renderer::setPipelineState(IPipelineState* state)
m_currentPipelineState = (PipelineStateImpl*)state;
}
+void D3D12Renderer::setFramebuffer(IFramebuffer* frameBuffer)
+{
+ ID3D12GraphicsCommandList* commandList = m_commandList;
+ auto framebufferImpl = static_cast<FramebufferImpl*>(frameBuffer);
+ commandList->OMSetRenderTargets(
+ (UINT)framebufferImpl->renderTargetViews.getCount(),
+ framebufferImpl->renderTargetDescriptors.getArrayView().getBuffer(),
+ FALSE,
+ framebufferImpl->depthStencilView ? &framebufferImpl->depthStencilDescriptor : nullptr);
+ m_frameBuffer = framebufferImpl;
+}
+
+
void D3D12Renderer::draw(UInt vertexCount, UInt startVertex)
{
ID3D12GraphicsCommandList* commandList = m_commandList;
@@ -2864,7 +2860,7 @@ void D3D12Renderer::DescriptorSetImpl::setSampler(UInt range, UInt index, ISampl
dxDevice->CopyDescriptorsSimple(
1,
m_samplerHeap->getCpuHandle(int(descriptorIndex)),
- samplerImpl->m_cpuHandle,
+ samplerImpl->m_descriptor.cpuHandle,
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
}
@@ -2908,7 +2904,7 @@ void D3D12Renderer::DescriptorSetImpl::setCombinedTextureSampler(
dxDevice->CopyDescriptorsSimple(
1,
m_samplerHeap->getCpuHandle(int(samplerDescriptorIndex)),
- samplerImpl->m_cpuHandle,
+ samplerImpl->m_descriptor.cpuHandle,
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
}
@@ -3601,7 +3597,10 @@ Result D3D12Renderer::createPipelineLayout(const IPipelineLayout::Desc& desc, IP
return SLANG_OK;
}
-Result D3D12Renderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet)
+Result D3D12Renderer::createDescriptorSet(
+ IDescriptorSetLayout* layout,
+ IDescriptorSet::Flag::Enum flag,
+ IDescriptorSet** outDescriptorSet)
{
auto layoutImpl = (DescriptorSetLayoutImpl*) layout;
@@ -3660,13 +3659,22 @@ Result D3D12Renderer::createGraphicsPipelineState(const GraphicsPipelineStateDes
psoDesc.PrimitiveTopologyType = m_primitiveTopologyType;
{
- const int numRenderTargets = int(desc.renderTargetCount);
+ auto framebufferLayout = static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout);
+ const int numRenderTargets = int(framebufferLayout->m_renderTargets.getCount());
- psoDesc.DSVFormat = m_depthStencilFormat;
+ if (framebufferLayout->m_hasDepthStencil)
+ {
+ psoDesc.DSVFormat = D3DUtil::getMapFormat(framebufferLayout->m_depthStencil.format);
+ }
+ else
+ {
+ psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
+ }
psoDesc.NumRenderTargets = numRenderTargets;
for (Int i = 0; i < numRenderTargets; i++)
{
- psoDesc.RTVFormats[i] = m_targetFormat;
+ psoDesc.RTVFormats[i] =
+ D3DUtil::getMapFormat(framebufferLayout->m_renderTargets[i].format);
}
psoDesc.SampleDesc.Count = 1;
@@ -3735,6 +3743,7 @@ Result D3D12Renderer::createGraphicsPipelineState(const GraphicsPipelineStateDes
RefPtr<PipelineStateImpl> pipelineStateImpl = new PipelineStateImpl();
pipelineStateImpl->m_pipelineLayout = pipelineLayoutImpl;
pipelineStateImpl->m_pipelineState = pipelineState;
+ pipelineStateImpl->m_program = programImpl;
pipelineStateImpl->init(desc);
*outState = pipelineStateImpl.detach();
return SLANG_OK;
diff --git a/tools/gfx/d3d12/render-d3d12.h b/tools/gfx/d3d12/render-d3d12.h
index 3304d92dc..4e9dc3f78 100644
--- a/tools/gfx/d3d12/render-d3d12.h
+++ b/tools/gfx/d3d12/render-d3d12.h
@@ -6,6 +6,6 @@
namespace gfx
{
-SlangResult SLANG_MCALL createD3D12Renderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer);
+SlangResult SLANG_MCALL createD3D12Renderer(const IRenderer::Desc* desc, IRenderer** outRenderer);
} // gfx
diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp
index 4251abe98..34ea70eef 100644
--- a/tools/gfx/open-gl/render-gl.cpp
+++ b/tools/gfx/open-gl/render-gl.cpp
@@ -3,13 +3,11 @@
#include "../nvapi/nvapi-util.h"
-//WORKING:#include "options.h"
#include "../renderer-shared.h"
#include "../render-graphics-common.h"
-#include <stdio.h>
-#include <stdlib.h>
#include "core/slang-basic.h"
+#include "core/slang-blob.h"
#include "core/slang-secure-crt.h"
#include "external/stb/stb_image_write.h"
@@ -33,6 +31,7 @@
#include <GL/GL.h>
#include "external/glext.h"
+#include "external/wglext.h"
// We define an "X-macro" for mapping over loadable OpenGL
// extension entry point that we will use, so that we can
@@ -69,8 +68,21 @@
F(glBindSampler, PFNGLBINDSAMPLERPROC) \
F(glTexImage3D, PFNGLTEXIMAGE3DPROC) \
F(glSamplerParameteri, PFNGLSAMPLERPARAMETERIPROC) \
+ F(glGenFramebuffers, PFNGLGENFRAMEBUFFERSPROC) \
+ F(glDeleteFramebuffers, PFNGLDELETEFRAMEBUFFERSPROC) \
+ F(glBindFramebuffer, PFNGLBINDFRAMEBUFFERPROC) \
+ F(glFramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC) \
+ F(glFramebufferTextureLayer, PFNGLFRAMEBUFFERTEXTURELAYERPROC) \
+ F(glBlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC) \
+ F(glCheckFramebufferStatus, PFNGLCHECKFRAMEBUFFERSTATUSPROC) \
+ F(glGenVertexArrays, PFNGLGENVERTEXARRAYSPROC) \
+ F(glBindVertexArray, PFNGLBINDVERTEXARRAYPROC) \
+ F(glDeleteVertexArrays, PFNGLDELETEVERTEXARRAYSPROC) \
/* end */
+#define MAP_WGL_EXTENSION_FUNCS(F) \
+ F(wglCreateContextAttribsARB, PFNWGLCREATECONTEXTATTRIBSARBPROC) \
+ /* end */
using namespace Slang;
namespace gfx {
@@ -78,13 +90,24 @@ namespace gfx {
class GLRenderer : public GraphicsAPIRenderer
{
public:
-
// Renderer implementation
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override;
virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) override;
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() override;
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() override;
- virtual SLANG_NO_THROW ITextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) override
+ {
+ SLANG_UNUSED(swapchain);
+ }
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* frameBuffer) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
IResource::Usage initialUsage,
@@ -114,7 +137,7 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL
createPipelineLayout(const IPipelineLayout::Desc& desc, IPipelineLayout** outLayout) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
- createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) override;
+ createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override;
@@ -123,8 +146,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -146,8 +169,6 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL
setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override;
virtual SLANG_NO_THROW void SLANG_MCALL
- setDepthStencilTarget(IResourceView* depthStencilView) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
setViewports(UInt count, Viewport const* viewports) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setScissorRects(UInt count, ScissorRect const* rects) override;
@@ -166,6 +187,7 @@ public:
{
return m_currentPipelineState.Ptr();
}
+ HGLRC createGLContext(HDC hdc);
GLRenderer();
~GLRenderer();
@@ -298,6 +320,200 @@ public:
GLuint m_bufferID;
};
+ class FramebufferLayoutImpl
+ : public IFramebufferLayout
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebufferLayout* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout)
+ return static_cast<IFramebufferLayout*>(this);
+ return nullptr;
+ }
+
+ public:
+ ShortList<IFramebufferLayout::AttachmentLayout> m_renderTargets;
+ bool m_hasDepthStencil = false;
+ IFramebufferLayout::AttachmentLayout m_depthStencil;
+ };
+
+ class FramebufferImpl
+ : public IFramebuffer
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebuffer* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebuffer)
+ return static_cast<IFramebuffer*>(this);
+ return nullptr;
+ }
+
+ public:
+ GLuint m_framebuffer;
+ WeakSink<GLRenderer>* m_renderer;
+ ShortList<RefPtr<TextureViewImpl>> renderTargetViews;
+ RefPtr<TextureViewImpl> depthStencilView;
+ FramebufferImpl(WeakSink<GLRenderer>* renderer) :m_renderer(renderer) {}
+ ~FramebufferImpl()
+ {
+ if (auto renderer = m_renderer->get())
+ {
+ renderer->glDeleteFramebuffers(1, &m_framebuffer);
+ }
+ }
+ void createGLFramebuffer()
+ {
+ auto renderer = m_renderer->get();
+ renderer->glGenFramebuffers(1, &m_framebuffer);
+ renderer->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
+ for (Index i = 0; i < renderTargetViews.getCount(); i++)
+ {
+ auto rtv = renderTargetViews[i].Ptr();
+ renderer->glFramebufferTexture2D(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + (uint32_t)i, GL_TEXTURE_2D, rtv->m_textureID, 0);
+ }
+ if (depthStencilView)
+ {
+ renderer->glFramebufferTexture2D(
+ GL_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D,
+ depthStencilView->m_textureID,
+ 0);
+ }
+ auto error = renderer->glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (error != GL_FRAMEBUFFER_COMPLETE)
+ {
+ return;
+ }
+ }
+ };
+
+ class SwapchainImpl
+ : public ISwapchain
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ISwapchain* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
+ return static_cast<ISwapchain*>(this);
+ return nullptr;
+ }
+
+ public:
+ ~SwapchainImpl()
+ {
+ for (auto image : m_images)
+ image->m_handle = 0;
+ if (auto rendererRef = m_renderer->get())
+ {
+ rendererRef->glDeleteFramebuffers(1, &m_framebuffer);
+ glDeleteTextures(1, &m_backBuffer);
+ }
+ wglMakeCurrent(m_hdc, 0);
+ wglDeleteContext(m_glrc);
+ ::ReleaseDC(m_hwnd, m_hdc);
+ }
+ Result init(GLRenderer* renderer, const ISwapchain::Desc& desc, WindowHandle window)
+ {
+ m_renderer = renderer->m_weakRenderer.Ptr();
+
+ m_hwnd = (HWND)window.handleValues[0];
+ m_hdc = ::GetDC(m_hwnd);
+ m_glrc = renderer->createGLContext(m_hdc);
+ wglMakeCurrent(renderer->m_hdc, renderer->m_glContext);
+
+ m_desc = desc;
+
+ glGenTextures(1, &m_backBuffer);
+ glBindTexture(GL_TEXTURE_2D, m_backBuffer);
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGBA8,
+ desc.width,
+ desc.height,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ nullptr);
+
+ wglMakeCurrent(m_hdc, m_glrc);
+ renderer->glGenFramebuffers(1, &m_framebuffer);
+ renderer->glBindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer);
+ renderer->glFramebufferTexture2D(
+ GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_backBuffer, 0);
+
+ for (uint32_t i = 0; i < desc.imageCount; i++)
+ {
+ ITextureResource::Desc texDesc = {};
+ texDesc.init2D(
+ IResource::Type::Texture2D,
+ gfx::Format::RGBA_Unorm_UInt8,
+ desc.width,
+ desc.height,
+ 1);
+ RefPtr<TextureResourceImpl> tex =
+ new TextureResourceImpl(IResource::Usage::RenderTarget, texDesc, m_renderer);
+ tex->m_handle = m_backBuffer;
+ m_images.add(tex);
+ }
+ wglMakeCurrent(renderer->m_hdc, renderer->m_glContext);
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
+ virtual SLANG_NO_THROW Result
+ getImage(uint32_t index, ITextureResource** outResource) override
+ {
+ m_images[index]->addRef();
+ *outResource = m_images[index].Ptr();
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW Result present() override
+ {
+ glFlush();
+ wglMakeCurrent(m_hdc, m_glrc);
+ auto renderer = m_renderer->get();
+ renderer->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ renderer->glBindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer);
+ renderer->glBlitFramebuffer(
+ 0,
+ 0,
+ m_desc.width,
+ m_desc.height,
+ 0,
+ 0,
+ m_desc.width,
+ m_desc.height,
+ GL_COLOR_BUFFER_BIT,
+ GL_NEAREST);
+ SwapBuffers(m_hdc);
+ wglMakeCurrent(renderer->m_hdc, renderer->m_glContext);
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW uint32_t acquireNextImage() override
+ {
+ return 0;
+ }
+
+ public:
+ WeakSink<GLRenderer>* m_renderer = nullptr;
+ GLuint m_framebuffer;
+ GLuint m_backBuffer;
+ HGLRC m_glrc;
+ HWND m_hwnd;
+ HDC m_hdc;
+ ISwapchain::Desc m_desc;
+ ShortList<RefPtr<TextureResourceImpl>> m_images;
+ };
+
enum class GLDescriptorSlotType
{
ConstantBuffer,
@@ -429,6 +645,8 @@ public:
{
Unknown,
RGBA_Unorm_UInt8,
+ D_Float32,
+ D_Unorm24_S8,
CountOf,
};
@@ -455,10 +673,11 @@ public:
static void compileTimeAsserts();
HDC m_hdc;
- HGLRC m_glContext;
+ HGLRC m_glContext = 0;
float m_clearColor[4] = { 0, 0, 0, 0 };
-
+ GLuint m_vao;
RefPtr<PipelineStateImpl> m_currentPipelineState;
+ RefPtr<FramebufferImpl> m_currentFramebuffer;
RefPtr<WeakSink<GLRenderer> > m_weakRenderer;
RefPtr<DescriptorSetImpl> m_boundDescriptorSets[kMaxDescriptorSetCount];
@@ -469,11 +688,12 @@ public:
UInt m_boundVertexStreamOffsets[kMaxVertexStreams];
Desc m_desc;
-
+ WindowHandle m_windowHandle;
// Declare a function pointer for each OpenGL
// extension function we need to load
#define DECLARE_GL_EXTENSION_FUNC(NAME, TYPE) TYPE NAME;
MAP_GL_EXTENSION_FUNCS(DECLARE_GL_EXTENSION_FUNC)
+ MAP_WGL_EXTENSION_FUNCS(DECLARE_GL_EXTENSION_FUNC)
#undef DECLARE_GL_EXTENSION_FUNC
static const GlPixelFormatInfo s_pixelFormatInfos[]; /// Maps GlPixelFormat to a format info
@@ -484,6 +704,9 @@ public:
switch (format)
{
case Format::RGBA_Unorm_UInt8: return GlPixelFormat::RGBA_Unorm_UInt8;
+ case Format::D_Float32: return GlPixelFormat::D_Float32;
+ case Format::D_Unorm24_S8: return GlPixelFormat::D_Unorm24_S8;
+
default: return GlPixelFormat::Unknown;
}
}
@@ -493,6 +716,9 @@ public:
// internalType, format, formatType
{ 0, 0, 0}, // GlPixelFormat::Unknown
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, // GlPixelFormat::RGBA_Unorm_UInt8
+ { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE}, // GlPixelFormat::D_Float32
+ { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE}, // GlPixelFormat::D_Unorm24_S8
+
};
/* static */void GLRenderer::compileTimeAsserts()
@@ -500,10 +726,10 @@ public:
SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_pixelFormatInfos) == int(GlPixelFormat::CountOf));
}
-SlangResult SLANG_MCALL createGLRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+SlangResult SLANG_MCALL createGLRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
RefPtr<GLRenderer> result = new GLRenderer();
- SLANG_RETURN_ON_FAIL(result->initialize(*desc, windowHandle));
+ SLANG_RETURN_ON_FAIL(result->initialize(*desc));
*outRenderer = result.detach();
return SLANG_OK;
}
@@ -523,26 +749,6 @@ void GLRenderer::debugCallback(GLenum source, GLenum type, GLuint id, GLenum sev
}
}
-
-GLRenderer::GLRenderer()
-{
- m_weakRenderer = new WeakSink<GLRenderer>(this);
-}
-
-GLRenderer::~GLRenderer()
-{
- // We can destroy things whilst in this state
- m_currentPipelineState.setNull();
-
- // By resetting the weak pointer, other objects accessing through WeakSink<GLRenderer> will no longer
- // be able to access this object which is entering a 'being destroyed' to 'destroyed' state
- if (m_weakRenderer)
- {
- SLANG_ASSERT(m_weakRenderer->get() == this);
- m_weakRenderer->detach();
- }
-}
-
/* static */void APIENTRY GLRenderer::staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
((GLRenderer*)userParam)->debugCallback(source, type, id, severity, length, message);
@@ -582,6 +788,11 @@ void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buff
void GLRenderer::flushStateForDraw()
{
+ if (m_currentFramebuffer)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, m_currentFramebuffer->m_framebuffer);
+ }
+ glBindVertexArray(m_vao);
auto inputLayout = m_currentPipelineState->m_inputLayout.Ptr();
auto attrCount = Index(inputLayout->m_attributeCount);
for (Index ii = 0; ii < attrCount; ++ii)
@@ -606,7 +817,6 @@ void GLRenderer::flushStateForDraw()
{
glDisableVertexAttribArray((GLuint)ii);
}
-
// Next bind the descriptor sets as required by the layout
auto pipelineLayout = m_currentPipelineState->m_pipelineLayout;
auto descriptorSetCount = pipelineLayout->m_sets.getCount();
@@ -770,36 +980,126 @@ GLuint GLRenderer::loadShader(GLenum stage, const char* source)
return shaderID;
}
-#if 0
-void GLRenderer::destroyBindingEntries(const BindingState::Desc& desc, const BindingDetail* details)
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
+
+#ifdef _WIN32
+LRESULT CALLBACK WindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
- const auto& bindings = desc.m_bindings;
- const int numBindings = int(bindings.Count());
- for (int i = 0; i < numBindings; ++i)
- {
- const auto& binding = bindings[i];
- const auto& detail = details[i];
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+#endif
- if (binding.bindingType == BindingType::Sampler && detail.m_samplerHandle != 0)
- {
- glDeleteSamplers(1, &detail.m_samplerHandle);
- }
- }
+WindowHandle createWindow()
+{
+ WindowHandle window = {};
+#ifdef _WIN32
+ const wchar_t className[] = L"OpenGLContextWindow";
+ static bool windowClassRegistered = false;
+ HINSTANCE hInstance = GetModuleHandle(NULL);
+ if (!windowClassRegistered)
+ {
+ windowClassRegistered = true;
+ WNDCLASS wc = {};
+ wc.lpfnWndProc = WindowProc;
+ wc.hInstance = hInstance;
+ wc.lpszClassName = className;
+ RegisterClass(&wc);
+ }
+
+ HWND hwnd = CreateWindowEx(
+ 0, // Optional window styles.
+ className, // Window class
+ L"GLWindow", // Window text
+ WS_OVERLAPPEDWINDOW, // Window style
+ // Size and position
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL, // Parent window
+ NULL, // Menu
+ hInstance, // Instance handle
+ NULL // Additional application data
+ );
+
+ if (hwnd == NULL)
+ {
+ return window;
+ }
+ window = WindowHandle::FromHwnd(hwnd);
+#endif
+ return window;
}
+
+void destroyWindow(WindowHandle window)
+{
+#ifdef _WIN32
+ DestroyWindow((HWND)window.handleValues[0]);
#endif
+}
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
+GLRenderer::GLRenderer() { m_weakRenderer = new WeakSink<GLRenderer>(this); }
-SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc, void* inWindowHandle)
+GLRenderer::~GLRenderer()
+{
+ // We can destroy things whilst in this state
+ m_currentPipelineState.setNull();
+ m_currentFramebuffer.setNull();
+ if (glDeleteVertexArrays)
+ {
+ glDeleteVertexArrays(1, &m_vao);
+ }
+ if (m_glContext)
+ {
+ wglDeleteContext(m_glContext);
+ }
+ destroyWindow(m_windowHandle);
+
+ // By resetting the weak pointer, other objects accessing through WeakSink<GLRenderer> will no
+ // longer be able to access this object which is entering a 'being destroyed' to 'destroyed'
+ // state
+ if (m_weakRenderer)
+ {
+ SLANG_ASSERT(m_weakRenderer->get() == this);
+ m_weakRenderer->detach();
+ }
+}
+
+HGLRC GLRenderer::createGLContext(HDC hdc)
+{
+ PIXELFORMATDESCRIPTOR pixelFormatDesc = {sizeof(PIXELFORMATDESCRIPTOR)};
+ pixelFormatDesc.nVersion = 1;
+ pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
+ pixelFormatDesc.cColorBits = 32;
+ pixelFormatDesc.cDepthBits = 24;
+ pixelFormatDesc.cStencilBits = 8;
+ pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
+ int pixelFormatIndex = ChoosePixelFormat(hdc, &pixelFormatDesc);
+ SetPixelFormat(hdc, pixelFormatIndex, &pixelFormatDesc);
+
+ int attributeList[5];
+
+ attributeList[0] = WGL_CONTEXT_MAJOR_VERSION_ARB;
+ attributeList[1] = 4;
+ attributeList[2] = WGL_CONTEXT_MINOR_VERSION_ARB;
+ attributeList[3] = 3;
+ attributeList[4] = 0;
+
+ HGLRC newGLContext = wglCreateContextAttribsARB(hdc, m_glContext, attributeList);
+ return newGLContext;
+}
+
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc)
{
SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_GLSL, "glsl_440"));
- SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc, inWindowHandle));
+ SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc));
- auto windowHandle = (HWND)inWindowHandle;
+ m_windowHandle = createWindow();
m_desc = desc;
- m_hdc = ::GetDC(windowHandle);
+ m_hdc = ::GetDC((HWND)m_windowHandle.handleValues[0]);
PIXELFORMATDESCRIPTOR pixelFormatDesc = { sizeof(PIXELFORMATDESCRIPTOR) };
pixelFormatDesc.nVersion = 1;
@@ -812,7 +1112,6 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc, void*
int pixelFormatIndex = ChoosePixelFormat(m_hdc, &pixelFormatDesc);
SetPixelFormat(m_hdc, pixelFormatIndex, &pixelFormatDesc);
-
m_glContext = wglCreateContext(m_hdc);
wglMakeCurrent(m_hdc, m_glContext);
@@ -844,19 +1143,39 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc, void*
#define LOAD_GL_EXTENSION_FUNC(NAME, TYPE) NAME = (TYPE) wglGetProcAddress(#NAME);
MAP_GL_EXTENSION_FUNCS(LOAD_GL_EXTENSION_FUNC)
+ MAP_WGL_EXTENSION_FUNCS(LOAD_GL_EXTENSION_FUNC)
#undef LOAD_GL_EXTENSION_FUNC
+ wglMakeCurrent(m_hdc, 0);
+ wglDeleteContext(m_glContext);
+ m_glContext = 0;
+
+ if (!wglCreateContextAttribsARB)
+ {
+ return SLANG_FAIL;
+ }
+
+ m_glContext = createGLContext(m_hdc);
+
+ if (m_glContext == NULL)
+ {
+ return SLANG_FAIL;
+ }
+ wglMakeCurrent(m_hdc, m_glContext);
+
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
- glViewport(0, 0, desc.width, desc.height);
+ if (!glGenVertexArrays)
+ return SLANG_FAIL;
+
+ glGenVertexArrays(1, &m_vao);
if (glDebugMessageCallback)
{
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(staticDebugCallback, this);
}
-
return SLANG_OK;
}
@@ -870,49 +1189,97 @@ SLANG_NO_THROW void SLANG_MCALL GLRenderer::clearFrame()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
-SLANG_NO_THROW void SLANG_MCALL GLRenderer::presentFrame()
+SLANG_NO_THROW void SLANG_MCALL GLRenderer::beginFrame() { }
+
+SLANG_NO_THROW void SLANG_MCALL GLRenderer::endFrame()
{
glFlush();
- ::SwapBuffers(m_hdc);
}
-SLANG_NO_THROW TextureResource::Desc SLANG_MCALL GLRenderer::getSwapChainTextureDesc()
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain)
{
- TextureResource::Desc desc;
- desc.init2D(IResource::Type::Texture2D, Format::Unknown, m_desc.width, m_desc.height, 1);
- return desc;
+ RefPtr<SwapchainImpl> swapchain = new SwapchainImpl();
+ SLANG_RETURN_ON_FAIL(swapchain->init(this, desc, window));
+ *outSwapchain = swapchain.detach();
+ wglMakeCurrent(m_hdc, m_glContext);
+ return SLANG_OK;
}
-SLANG_NO_THROW Result SLANG_MCALL GLRenderer::captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout)
{
- size_t requiredSize = m_desc.width * m_desc.height * sizeof(uint32_t);
- if (outRowPitch)
- *outRowPitch = m_desc.width * sizeof(uint32_t);
- if (outPixelSize)
- *outPixelSize = sizeof(uint32_t);
+ RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl();
+ layout->m_renderTargets.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ layout->m_renderTargets[i] = desc.renderTargets[i];
+ }
- if (!buffer || *inOutBufferSize == 0)
+ if (desc.depthStencil)
{
- *inOutBufferSize = requiredSize;
- return SLANG_OK;
+ layout->m_hasDepthStencil = true;
+ layout->m_depthStencil = *desc.depthStencil;
+ }
+ else
+ {
+ layout->m_hasDepthStencil = false;
+ }
+ *outLayout = layout.detach();
+ return SLANG_OK;
+}
+
+SLANG_NO_THROW Result SLANG_MCALL
+ GLRenderer::createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer)
+{
+ RefPtr<FramebufferImpl> framebuffer = new FramebufferImpl(m_weakRenderer);
+ framebuffer->renderTargetViews.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ framebuffer->renderTargetViews[i] =
+ static_cast<TextureViewImpl*>(desc.renderTargetViews[i]);
}
- if (*inOutBufferSize < requiredSize)
- return SLANG_ERROR_INSUFFICIENT_BUFFER;
+ framebuffer->depthStencilView = static_cast<TextureViewImpl*>(desc.depthStencilView);
+ framebuffer->createGLFramebuffer();
+ *outFramebuffer = framebuffer.detach();
+ return SLANG_OK;
+}
- glReadPixels(0, 0, m_desc.width, m_desc.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+SLANG_NO_THROW void SLANG_MCALL GLRenderer::setFramebuffer(IFramebuffer* frameBuffer)
+{
+ m_currentFramebuffer = static_cast<FramebufferImpl*>(frameBuffer);
+}
+
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize)
+{
+ auto resource = static_cast<TextureResourceImpl*>(texture);
+ auto size = resource->getDesc()->size;
+ size_t requiredSize = size.width * size.height * sizeof(uint32_t);
+ if (outRowPitch)
+ *outRowPitch = size.width * sizeof(uint32_t);
+ if (outPixelSize)
+ *outPixelSize = sizeof(uint32_t);
+
+ RefPtr<ListBlob> blob = new ListBlob();
+ blob->m_data.setCount(requiredSize);
+ auto buffer = blob->m_data.begin();
+ glBindTexture(resource->m_target, resource->m_handle);
+ glGetTexImage(resource->m_target, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Flip pixels vertically in-place.
- for (int y = 0; y < m_desc.height / 2; y++)
+ for (int y = 0; y < size.height / 2; y++)
{
- for (int x = 0; x < m_desc.width; x++)
+ for (int x = 0; x < size.width; x++)
{
std::swap(
- *((uint32_t*)buffer + y * m_desc.width + x),
- *((uint32_t*)buffer + (m_desc.height - y - 1) * m_desc.width + x));
+ *((uint32_t*)buffer + y * size.width + x),
+ *((uint32_t*)buffer + (size.height - y - 1) * size.width + x));
}
}
+ *outBlob = blob.detach();
+
return SLANG_OK;
}
@@ -945,12 +1312,8 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
const int effectiveArraySize = srcDesc.calcEffectiveArraySize();
- assert(initData);
- assert(initData->numSubResources == srcDesc.numMipLevels * srcDesc.size.depth * effectiveArraySize);
-
// Set on texture so will be freed if failure
texture->m_handle = handle;
- const void*const*const data = initData->subResources;
switch (srcDesc.type)
{
@@ -966,7 +1329,16 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
{
for (int j = 0; j < srcDesc.numMipLevels; j++)
{
- glTexImage2D(target, j, internalFormat, srcDesc.size.width, i, 0, format, formatType, data[slice++]);
+ glTexImage2D(
+ target,
+ j,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> j),
+ i,
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[slice++] : nullptr);
}
}
}
@@ -976,7 +1348,15 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
glBindTexture(target, handle);
for (int i = 0; i < srcDesc.numMipLevels; i++)
{
- glTexImage1D(target, i, internalFormat, srcDesc.size.width, 0, format, formatType, data[i]);
+ glTexImage1D(
+ target,
+ i,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> i),
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[i] : nullptr);
}
}
break;
@@ -1002,7 +1382,17 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
{
for (int j = 0; j < srcDesc.numMipLevels; j++)
{
- glTexImage3D(target, j, internalFormat, srcDesc.size.width, srcDesc.size.height, slice, 0, format, formatType, data[slice++]);
+ glTexImage3D(
+ target,
+ j,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> j),
+ Math::Max(1, srcDesc.size.height >> j),
+ slice,
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[slice++] : nullptr);
}
}
}
@@ -1018,7 +1408,16 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
{
for (int i = 0; i < srcDesc.numMipLevels; i++)
{
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, internalFormat, srcDesc.size.width, srcDesc.size.height, 0, format, formatType, data[slice++]);
+ glTexImage2D(
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X + j,
+ i,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> i),
+ Math::Max(1, srcDesc.size.height >> i),
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[slice++] : nullptr);
}
}
}
@@ -1028,7 +1427,16 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
glBindTexture(target, handle);
for (int i = 0; i < srcDesc.numMipLevels; i++)
{
- glTexImage2D(target, i, internalFormat, srcDesc.size.width, srcDesc.size.height, 0, format, formatType, data[i]);
+ glTexImage2D(
+ target,
+ i,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> i),
+ Math::Max(1, srcDesc.size.height >> i),
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[i] : nullptr);
}
}
}
@@ -1040,7 +1448,17 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
glBindTexture(target, handle);
for (int i = 0; i < srcDesc.numMipLevels; i++)
{
- glTexImage3D(target, i, internalFormat, srcDesc.size.width, srcDesc.size.height, srcDesc.size.depth, 0, format, formatType, data[i]);
+ glTexImage3D(
+ target,
+ i,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> i),
+ Math::Max(1, srcDesc.size.height >> i),
+ Math::Max(1, srcDesc.size.depth >> i),
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[i] : nullptr);
}
break;
}
@@ -1122,14 +1540,14 @@ SLANG_NO_THROW Result SLANG_MCALL
SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureView(
ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView)
{
- auto resourceImpl = (TextureResourceImpl*) texture;
+ auto resourceImpl = static_cast<TextureResourceImpl*>(texture);
// TODO: actually do something?
RefPtr<TextureViewImpl> viewImpl = new TextureViewImpl();
viewImpl->m_resource = resourceImpl;
viewImpl->m_textureID = resourceImpl->m_handle;
- *outView = viewImpl;
+ *outView = viewImpl.detach();
return SLANG_OK;
}
@@ -1235,10 +1653,6 @@ SLANG_NO_THROW void SLANG_MCALL
{
}
-SLANG_NO_THROW void SLANG_MCALL GLRenderer::setDepthStencilTarget(IResourceView* depthStencilView)
-{
-}
-
SLANG_NO_THROW void SLANG_MCALL GLRenderer::setViewports(UInt count, Viewport const* viewports)
{
assert(count == 1);
@@ -1455,8 +1869,10 @@ SLANG_NO_THROW Result SLANG_MCALL
}
SLANG_NO_THROW Result SLANG_MCALL
- GLRenderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet)
+ GLRenderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet)
{
+ SLANG_UNUSED(flag);
+
auto layoutImpl = (DescriptorSetLayoutImpl*) layout;
RefPtr<DescriptorSetImpl> descriptorSetImpl = new DescriptorSetImpl();
diff --git a/tools/gfx/open-gl/render-gl.h b/tools/gfx/open-gl/render-gl.h
index ef8bb318c..7d0d0f3dd 100644
--- a/tools/gfx/open-gl/render-gl.h
+++ b/tools/gfx/open-gl/render-gl.h
@@ -5,6 +5,6 @@
namespace gfx {
-SlangResult SLANG_MCALL createGLRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer);
+SlangResult SLANG_MCALL createGLRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer);
} // gfx
diff --git a/tools/gfx/render-graphics-common.cpp b/tools/gfx/render-graphics-common.cpp
index 3e38b8b5a..068669136 100644
--- a/tools/gfx/render-graphics-common.cpp
+++ b/tools/gfx/render-graphics-common.cpp
@@ -962,7 +962,7 @@ protected:
{
ComPtr<IDescriptorSet> descriptorSet;
SLANG_RETURN_ON_FAIL(
- renderer->createDescriptorSet(descriptorSetInfo->layout, descriptorSet.writeRef()));
+ renderer->createDescriptorSet(descriptorSetInfo->layout, IDescriptorSet::Flag::Transient, descriptorSet.writeRef()));
descriptorSets.add(descriptorSet);
}
@@ -1474,7 +1474,6 @@ void GraphicsAPIRenderer::preparePipelineDesc(GraphicsPipelineStateDesc& desc)
{
auto program = dynamic_cast<GraphicsCommonShaderProgram*>(desc.program);
auto rootLayout = program->getLayout();
- desc.renderTargetCount = rootLayout->getRenderTargetCount();
desc.pipelineLayout = rootLayout->getPipelineLayout();
}
}
diff --git a/tools/gfx/render.cpp b/tools/gfx/render.cpp
index dc3928454..3a886aaa4 100644
--- a/tools/gfx/render.cpp
+++ b/tools/gfx/render.cpp
@@ -25,6 +25,7 @@ static const uint8_t s_formatSize[] = {
uint8_t(sizeof(float) * 1), // R_Float32,
uint8_t(sizeof(uint32_t)), // RGBA_Unorm_UInt8,
+ uint8_t(sizeof(uint32_t)), // BGRA_Unorm_UInt8,
uint8_t(sizeof(uint16_t)), // R_UInt16,
uint8_t(sizeof(uint32_t)), // R_UInt32,
@@ -85,30 +86,30 @@ extern "C"
}
}
- SLANG_GFX_API SlangResult SLANG_MCALL gfxCreateRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+ SLANG_GFX_API SlangResult SLANG_MCALL gfxCreateRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
switch (desc->rendererType)
{
#if SLANG_WINDOWS_FAMILY
case RendererType::DirectX11:
{
- return createD3D11Renderer(desc, windowHandle, outRenderer);
+ return createD3D11Renderer(desc, outRenderer);
}
case RendererType::DirectX12:
{
- return createD3D12Renderer(desc, windowHandle, outRenderer);
+ return createD3D12Renderer(desc, outRenderer);
}
case RendererType::OpenGl:
{
- return createGLRenderer(desc, windowHandle, outRenderer);
+ return createGLRenderer(desc, outRenderer);
}
case RendererType::Vulkan:
{
- return createVKRenderer(desc, windowHandle, outRenderer);
+ return createVKRenderer(desc, outRenderer);
}
case RendererType::CUDA:
{
- return createCUDARenderer(desc, windowHandle, outRenderer);
+ return createCUDARenderer(desc, outRenderer);
}
#endif
diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp
index fdee8b776..78c0439fd 100644
--- a/tools/gfx/renderer-shared.cpp
+++ b/tools/gfx/renderer-shared.cpp
@@ -16,6 +16,10 @@ const Slang::Guid GfxGUID::IID_IPipelineLayout = SLANG_UUID_IPipelineLayout;
const Slang::Guid GfxGUID::IID_IInputLayout = SLANG_UUID_IInputLayout;
const Slang::Guid GfxGUID::IID_IPipelineState = SLANG_UUID_IPipelineState;
const Slang::Guid GfxGUID::IID_IResourceView = SLANG_UUID_IResourceView;
+const Slang::Guid GfxGUID::IID_IFramebuffer = SLANG_UUID_IFrameBuffer;
+const Slang::Guid GfxGUID::IID_IFramebufferLayout = SLANG_UUID_IFramebufferLayout;
+
+const Slang::Guid GfxGUID::IID_ISwapchain = SLANG_UUID_ISwapchain;
const Slang::Guid GfxGUID::IID_ISamplerState = SLANG_UUID_ISamplerState;
const Slang::Guid GfxGUID::IID_IResource = SLANG_UUID_IResource;
const Slang::Guid GfxGUID::IID_IBufferResource = SLANG_UUID_IBufferResource;
@@ -170,6 +174,7 @@ void PipelineStateBase::initializeBase(const PipelineStateDesc& inDesc)
desc = inDesc;
auto program = desc.getProgram();
+ m_program = program;
isSpecializable = (program->slangProgram && program->slangProgram->getSpecializationParamCount() != 0);
}
@@ -180,10 +185,8 @@ IRenderer* gfx::RendererBase::getInterface(const Guid& guid)
: nullptr;
}
-SLANG_NO_THROW Result SLANG_MCALL RendererBase::initialize(const Desc& desc, void* inWindowHandle)
+SLANG_NO_THROW Result SLANG_MCALL RendererBase::initialize(const Desc& desc)
{
- SLANG_UNUSED(inWindowHandle);
-
shaderCache.init(desc.shaderCacheFileSystem);
return SLANG_OK;
}
diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h
index c9f2b3340..b543e709b 100644
--- a/tools/gfx/renderer-shared.h
+++ b/tools/gfx/renderer-shared.h
@@ -16,6 +16,9 @@ struct GfxGUID
static const Slang::Guid IID_IPipelineLayout;
static const Slang::Guid IID_IPipelineState;
static const Slang::Guid IID_IResourceView;
+ static const Slang::Guid IID_IFramebuffer;
+ static const Slang::Guid IID_IFramebufferLayout;
+ static const Slang::Guid IID_ISwapchain;
static const Slang::Guid IID_ISamplerState;
static const Slang::Guid IID_IResource;
static const Slang::Guid IID_IBufferResource;
@@ -234,7 +237,7 @@ public:
// Indicates whether this is a specializable pipeline. A specializable
// pipeline cannot be used directly and must be specialized first.
bool isSpecializable = false;
-
+ ComPtr<IShaderProgram> m_program;
protected:
void initializeBase(const PipelineStateDesc& inDesc);
};
@@ -388,7 +391,7 @@ protected:
protected:
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle);
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc);
protected:
Slang::List<Slang::String> m_features;
public:
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index 6bfd58dda..e89b6a765 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -14,8 +14,13 @@
// Vulkan has a different coordinate system to ogl
// http://anki3d.org/vulkan-coordinate-system/
-
+#ifndef ENABLE_VALIDATION_LAYER
+#if _DEBUG
#define ENABLE_VALIDATION_LAYER 1
+#else
+#define ENABLE_VALIDATION_LAYER 0
+#endif
+#endif
#ifdef _MSC_VER
# include <stddef.h>
@@ -36,16 +41,23 @@ public:
kMaxRenderTargets = 8,
kMaxAttachments = kMaxRenderTargets + 1,
- kMaxDescriptorSets = 4,
+ kMaxDescriptorSets = 8,
};
-
// Renderer implementation
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override;
virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) override;
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() override;
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() override;
- virtual SLANG_NO_THROW TextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() override;
-
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebufferLayout(const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* frameBuffer) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
IResource::Usage initialUsage,
const ITextureResource::Desc& desc,
@@ -75,7 +87,7 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL
createPipelineLayout(const IPipelineLayout::Desc& desc, IPipelineLayout** outLayout) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
- createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) override;
+ createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override;
@@ -86,8 +98,8 @@ public:
const ComputePipelineStateDesc& desc,
IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -109,8 +121,6 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL
setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override;
virtual SLANG_NO_THROW void SLANG_MCALL
- setDepthStencilTarget(IResourceView* depthStencilView) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
setViewports(UInt count, Viewport const* viewports) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setScissorRects(UInt count, ScissorRect const* rects) override;
@@ -222,7 +232,7 @@ public:
{
m_api->vkFreeMemory(m_api->m_device, m_imageMemory, nullptr);
}
- if (m_image != VK_NULL_HANDLE)
+ if (m_image != VK_NULL_HANDLE && !m_isWeakImageReference)
{
m_api->vkDestroyImage(m_api->m_device, m_image, nullptr);
}
@@ -232,8 +242,9 @@ public:
Usage m_initialUsage;
VkImage m_image = VK_NULL_HANDLE;
+ VkFormat m_vkformat = VK_FORMAT_R8G8B8A8_UNORM;
VkDeviceMemory m_imageMemory = VK_NULL_HANDLE;
-
+ bool m_isWeakImageReference = false;
const VulkanApi* m_api;
};
@@ -328,6 +339,297 @@ public:
VkDeviceSize size;
};
+ class SwapchainImpl
+ : public ISwapchain
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ISwapchain* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
+ return static_cast<ISwapchain*>(this);
+ return nullptr;
+ }
+
+ public:
+ VulkanSwapChain m_swapChain;
+ ISwapchain::Desc m_desc;
+ ShortList<RefPtr<TextureResourceImpl>> m_images;
+ VKRenderer* m_renderer;
+ uint32_t m_currentImageIndex = 0;
+ public:
+ Result init(VKRenderer* renderer, const ISwapchain::Desc& desc, WindowHandle window)
+ {
+ m_desc = desc;
+ m_renderer = renderer;
+
+ VulkanSwapChain::Desc swapchainDesc;
+ VulkanSwapChain::PlatformDesc* platformDesc = nullptr;
+ swapchainDesc.m_imageCount = desc.imageCount;
+ swapchainDesc.init();
+ swapchainDesc.m_format = desc.format;
+ swapchainDesc.m_vsync = desc.enableVSync;
+#if SLANG_WINDOWS_FAMILY
+ VulkanSwapChain::WinPlatformDesc winPlatformDesc;
+ winPlatformDesc.m_hinstance = ::GetModuleHandle(nullptr);
+ winPlatformDesc.m_hwnd = (HWND)window.handleValues[0];
+ platformDesc = &winPlatformDesc;
+#endif
+
+ SLANG_RETURN_ON_FAIL(m_swapChain.init(&renderer->m_deviceQueue, swapchainDesc, platformDesc));
+ m_desc.format = m_swapChain.getDesc().m_format;
+ m_desc.width = m_swapChain.getWidth();
+ m_desc.height = m_swapChain.getHeight();
+ m_desc.imageCount = m_swapChain.getDesc().m_imageCount;
+ auto& images = m_swapChain.getImages();
+ for (uint32_t i = 0; i < desc.imageCount; i++)
+ {
+ ITextureResource::Desc imageDesc = {};
+
+ imageDesc.init2D(
+ IResource::Type::Texture2D,
+ m_swapChain.getDesc().m_format,
+ m_swapChain.getWidth(),
+ m_swapChain.getHeight(),
+ 1);
+ RefPtr<TextureResourceImpl> image = new TextureResourceImpl(imageDesc, gfx::IResource::Usage::RenderTarget, &renderer->m_api);
+ image->m_image = images[i];
+ image->m_imageMemory = 0;
+ image->m_vkformat = m_swapChain.getVkFormat();
+ image->m_isWeakImageReference = true;
+ m_images.add(image);
+ }
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc()
+ {
+ return m_desc;
+ }
+ virtual SLANG_NO_THROW Result getImage(uint32_t index, ITextureResource** outResource)
+ {
+ *outResource = m_images[index];
+ m_images[index]->addRef();
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW Result present()
+ {
+ m_swapChain.present(m_desc.enableVSync);
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW uint32_t acquireNextImage()
+ {
+ m_currentImageIndex = (uint32_t)m_swapChain.nextFrontImageIndex();
+ auto image = m_images[m_currentImageIndex];
+ m_renderer->_transitionImageLayout(
+ image->m_image,
+ image->m_vkformat,
+ *image->getDesc(),
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ return m_currentImageIndex;
+ }
+ };
+
+ class FramebufferLayoutImpl
+ : public IFramebufferLayout
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebufferLayout* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout)
+ return static_cast<IFramebufferLayout*>(this);
+ return nullptr;
+ }
+
+ public:
+ VkRenderPass m_renderPass;
+ VKRenderer* m_renderer;
+
+ public:
+ ~FramebufferLayoutImpl()
+ {
+ m_renderer->m_api.vkDestroyRenderPass(m_renderer->m_api.m_device, m_renderPass, nullptr);
+ }
+ Result init(VKRenderer* renderer, const IFramebufferLayout::Desc& desc)
+ {
+ m_renderer = renderer;
+ // Create render pass.
+ int numAttachments = desc.renderTargetCount;
+ if (desc.depthStencil)
+ {
+ numAttachments++;
+ }
+ bool shouldClear = false;
+ bool shouldClearDepth = false;
+ bool shouldClearStencil = false;
+
+ // We need extra space if we have depth buffer
+ Array<VkAttachmentDescription, kMaxAttachments> attachmentDesc;
+ attachmentDesc.setCount(numAttachments);
+ for (uint32_t i = 0; i < desc.renderTargetCount; ++i)
+ {
+ auto& renderTarget = desc.renderTargets[i];
+ VkAttachmentDescription& dst = attachmentDesc[i];
+
+ dst.flags = 0;
+ dst.format = VulkanUtil::getVkFormat(renderTarget.format);
+ dst.samples = (VkSampleCountFlagBits)renderTarget.sampleCount;
+ dst.loadOp =
+ shouldClear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
+ dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ dst.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ dst.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ dst.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ }
+
+ if (desc.depthStencil)
+ {
+ VkAttachmentDescription& dst = attachmentDesc[desc.renderTargetCount];
+ dst.flags = 0;
+ dst.format = VulkanUtil::getVkFormat(desc.depthStencil->format);
+ dst.samples = (VkSampleCountFlagBits)desc.depthStencil->sampleCount;
+ dst.loadOp =
+ shouldClearDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
+ dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ dst.stencilLoadOp = shouldClearStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR
+ : VK_ATTACHMENT_LOAD_OP_LOAD;
+ dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+ dst.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ dst.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ }
+
+ Array<VkAttachmentReference, kMaxRenderTargets> colorAttachments;
+ colorAttachments.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; ++i)
+ {
+ VkAttachmentReference& dst = colorAttachments[i];
+ dst.attachment = i;
+ dst.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ }
+
+ VkAttachmentReference depthAttachment = {};
+ depthAttachment.attachment = desc.renderTargetCount;
+ depthAttachment.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpassDesc = {};
+ subpassDesc.flags = 0;
+ subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpassDesc.inputAttachmentCount = 0u;
+ subpassDesc.pInputAttachments = nullptr;
+ subpassDesc.colorAttachmentCount = desc.renderTargetCount;
+ subpassDesc.pColorAttachments = colorAttachments.getBuffer();
+ subpassDesc.pResolveAttachments = nullptr;
+ subpassDesc.pDepthStencilAttachment = desc.depthStencil ? &depthAttachment : nullptr;
+ subpassDesc.preserveAttachmentCount = 0u;
+ subpassDesc.pPreserveAttachments = nullptr;
+
+ VkRenderPassCreateInfo renderPassCreateInfo = {};
+ renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ renderPassCreateInfo.attachmentCount = numAttachments;
+ renderPassCreateInfo.pAttachments = attachmentDesc.getBuffer();
+ renderPassCreateInfo.subpassCount = 1;
+ renderPassCreateInfo.pSubpasses = &subpassDesc;
+ SLANG_VK_RETURN_ON_FAIL(m_renderer->m_api.vkCreateRenderPass(
+ m_renderer->m_api.m_device, &renderPassCreateInfo, nullptr, &m_renderPass));
+ return SLANG_OK;
+ }
+ };
+
+ class FramebufferImpl
+ : public IFramebuffer
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebuffer* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebuffer)
+ return static_cast<IFramebuffer*>(this);
+ return nullptr;
+ }
+
+ public:
+ VkFramebuffer m_handle;
+ ShortList<ComPtr<IResourceView>> renderTargetViews;
+ ComPtr<IResourceView> depthStencilView;
+ uint32_t m_width;
+ uint32_t m_height;
+ VKRenderer* m_renderer;
+ RefPtr<FramebufferLayoutImpl> m_layout;
+ public:
+ ~FramebufferImpl()
+ {
+ m_renderer->m_api.vkDestroyFramebuffer(m_renderer->m_api.m_device, m_handle, nullptr);
+ }
+ Result init(VKRenderer* renderer, const IFramebuffer::Desc& desc)
+ {
+ m_renderer = renderer;
+ auto dsv = desc.depthStencilView
+ ? static_cast<TextureResourceViewImpl*>(desc.depthStencilView)
+ : nullptr;
+ // Get frame dimensions from attachments.
+ if (dsv)
+ {
+ // If we have a depth attachment, get frame size from there.
+ auto size = dsv->m_texture->getDesc()->size;
+ m_width = size.width;
+ m_height = size.height;
+ }
+ else
+ {
+ // If we don't have a depth attachment, then we must have at least
+ // one color attachment. Get frame dimension from there.
+ auto size = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[0])
+ ->m_texture->getDesc()
+ ->size;
+ m_width = size.width;
+ m_height = size.height;
+ }
+
+ // Create render pass.
+ int numAttachments = desc.renderTargetCount;
+ if (desc.depthStencilView)
+ numAttachments++;
+ Array<VkImageView, kMaxAttachments> imageViews;
+ imageViews.setCount(numAttachments);
+ renderTargetViews.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; ++i)
+ {
+ auto resourceView =
+ static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[i]);
+ renderTargetViews[i] = resourceView;
+ imageViews[i] = resourceView->m_view;
+ }
+
+ if (dsv)
+ {
+ imageViews[desc.renderTargetCount] = dsv->m_view;
+ depthStencilView = dsv;
+ }
+
+
+ // Create framebuffer.
+ m_layout = static_cast<FramebufferLayoutImpl*>(desc.layout);
+ VkFramebufferCreateInfo framebufferInfo = {};
+ framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ framebufferInfo.renderPass = m_layout->m_renderPass;
+ framebufferInfo.attachmentCount = numAttachments;
+ framebufferInfo.pAttachments = imageViews.getBuffer();
+ framebufferInfo.width = m_width;
+ framebufferInfo.height = m_height;
+ framebufferInfo.layers = 1;
+
+ SLANG_VK_RETURN_ON_FAIL(m_renderer->m_api.vkCreateFramebuffer(
+ m_renderer->m_api.m_device, &framebufferInfo, nullptr, &m_handle));
+ return SLANG_OK;
+ }
+ };
+
class ShaderProgramImpl: public GraphicsCommonShaderProgram
{
public:
@@ -384,15 +686,10 @@ public:
{
m_api->vkDestroyDescriptorSetLayout(m_api->m_device, m_descriptorSetLayout, nullptr);
}
- if (m_descriptorPool != VK_NULL_HANDLE)
- {
- m_api->vkDestroyDescriptorPool(m_api->m_device, m_descriptorPool, nullptr);
- }
}
VulkanApi const* m_api;
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
- VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
// Vulkan descriptor sets are the closest in design to what
// the `Renderer` abstraction exposes as a `DescriptorSet`.
@@ -445,6 +742,10 @@ public:
/// to descriptor sets described by this layout.
///
Index m_totalBoundObjectCount = 0;
+
+ /// Vulkan Descriptor set bindings
+ Slang::List<VkDescriptorSetLayoutBinding> m_vkBindings;
+
};
class PipelineLayoutImpl : public IPipelineLayout, public RefObject
@@ -499,6 +800,7 @@ public:
~DescriptorSetImpl()
{
+ m_renderer->descriptorSetAllocator.free(m_descriptorSet);
}
virtual SLANG_NO_THROW void SLANG_MCALL setConstantBuffer(UInt range, UInt index, IBufferResource* buffer) override;
@@ -520,13 +822,15 @@ public:
VKRenderer* m_renderer = nullptr; ///< Weak pointer, can't be strong, because if set will become circular reference
RefPtr<DescriptorSetLayoutImpl> m_layout;
- VkDescriptorSet m_descriptorSet = VK_NULL_HANDLE;
+ VulkanDescriptorSet m_descriptorSet = {};
/// Records entities that are bound to this descriptor set, and keeps the associated resources/views/state in scope
List<RefPtr<RefObject>> m_boundObjects;
/// Backing storage for root constant ranges belonging to this descriptor set
List<char> m_rootConstantData;
+
+ bool m_isTransient = false;
};
struct BoundVertexBuffer
@@ -570,6 +874,8 @@ public:
RefPtr<PipelineLayoutImpl> m_pipelineLayout;
+ RefPtr<FramebufferLayoutImpl> m_framebufferLayout;
+
RefPtr<ShaderProgramImpl> m_shaderProgram;
VkPipeline m_pipeline = VK_NULL_HANDLE;
@@ -589,11 +895,6 @@ public:
static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData);
- /// Returns true if m_currentPipeline matches the current configuration
-// Pipeline* _getPipeline();
-// bool _isEqual(const Pipeline& pipeline) const;
-// Slang::Result _createPipeline(RefPtr<Pipeline>& pipelineOut);
- void _beginRender();
void _endRender();
Slang::Result _beginPass();
@@ -602,19 +903,15 @@ public:
VkDebugReportCallbackEXT m_debugReportCallback;
-// RefPtr<InputLayoutImpl> m_currentInputLayout;
-
-// RefPtr<BindingStateImpl> m_currentBindingState;
RefPtr<PipelineLayoutImpl> m_currentPipelineLayout;
RefPtr<DescriptorSetImpl> m_currentDescriptorSetImpls [kMaxDescriptorSets];
VkDescriptorSet m_currentDescriptorSets [kMaxDescriptorSets];
-// RefPtr<ShaderProgramImpl> m_currentProgram;
-
-// List<RefPtr<Pipeline> > m_pipelineCache;
RefPtr<PipelineStateImpl> m_currentPipeline;
+ RefPtr<FramebufferImpl> m_currentFramebuffer;
+
List<BoundVertexBuffer> m_boundVertexBuffers;
VkPrimitiveTopology m_primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
@@ -625,15 +922,17 @@ public:
VulkanApi m_api;
VulkanDeviceQueue m_deviceQueue;
- VulkanSwapChain m_swapChain;
-
- VkRenderPass m_renderPass = VK_NULL_HANDLE;
-
- int m_swapChainImageIndex = -1;
float m_clearColor[4] = { 0, 0, 0, 0 };
+ List<VkViewport> m_viewports;
+ List<VkRect2D> m_scissorRects;
Desc m_desc;
+
+ DescriptorSetAllocator descriptorSetAllocator;
+
+ // Temporary list used by flushBindingState to avoid per-frame allocation.
+ List<VkCopyDescriptorSet> m_descSetCopies;
};
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VkRenderer::Buffer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
@@ -672,196 +971,10 @@ Result VKRenderer::Buffer::init(const VulkanApi& api, size_t bufferSize, VkBuffe
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VkRenderer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-#if 0
-bool VKRenderer::_isEqual(const Pipeline& pipeline) const
-{
- return
- pipeline.m_pipelineLayout == m_currentPipelineLayout &&
- pipeline.m_primitiveTopology == m_primitiveTopology &&
- pipeline.m_inputLayout == m_currentInputLayout &&
- pipeline.m_shaderProgram == m_currentProgram;
-}
-
-VKRenderer::Pipeline* VKRenderer::_getPipeline()
-{
- if (m_currentPipeline && _isEqual(*m_currentPipeline))
- {
- return m_currentPipeline;
- }
-
- // Look for a match in the cache
- for (int i = 0; i < int(m_pipelineCache.Count()); ++i)
- {
- Pipeline* pipeline = m_pipelineCache[i];
- if (_isEqual(*pipeline))
- {
- m_currentPipeline = pipeline;
- return pipeline;
- }
- }
-
- RefPtr<Pipeline> pipeline;
- SLANG_RETURN_NULL_ON_FAIL(_createPipeline(pipeline));
- m_pipelineCache.Add(pipeline);
- m_currentPipeline = pipeline;
- return pipeline;
-}
-
-Slang::Result VKRenderer::_createPipeline(RefPtr<Pipeline>& pipelineOut)
-{
- RefPtr<Pipeline> pipeline(new Pipeline(m_api));
-
- // Initialize the state
- pipeline->m_primitiveTopology = m_primitiveTopology;
- pipeline->m_pipelineLayout = m_currentPipelineLayout;
- pipeline->m_shaderProgram = m_currentProgram;
- pipeline->m_inputLayout = m_currentInputLayout;
-
- // Must be equal at this point if all the items are correctly set in pipeline
- assert(_isEqual(*pipeline));
-
- VkPipelineCache pipelineCache = VK_NULL_HANDLE;
-
- if (m_currentProgram->m_pipelineType == PipelineType::Compute)
- {
- // Then create a pipeline to use that layout
-
- VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
- computePipelineInfo.stage = m_currentProgram->m_compute;
- computePipelineInfo.layout = pipeline->m_pipelineLayout->m_pipelineLayout;
-
- SLANG_VK_CHECK(m_api.vkCreateComputePipelines(m_device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline->m_pipeline));
- }
- else if (m_currentProgram->m_pipelineType == PipelineType::Graphics)
- {
- // Create the graphics pipeline
-
- const int width = m_swapChain.getWidth();
- const int height = m_swapChain.getHeight();
-
- VkPipelineShaderStageCreateInfo shaderStages[] = { m_currentProgram->m_vertex, m_currentProgram->m_fragment };
-
- // VertexBuffer/s
- // Currently only handles one
-
- VkPipelineVertexInputStateCreateInfo vertexInputInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
- vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vertexInputInfo.vertexBindingDescriptionCount = 0;
- vertexInputInfo.vertexAttributeDescriptionCount = 0;
-
- VkVertexInputBindingDescription vertexInputBindingDescription;
-
- if (m_currentInputLayout)
- {
- vertexInputBindingDescription.binding = 0;
- vertexInputBindingDescription.stride = m_currentInputLayout->m_vertexSize;
- vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
-
- const auto& srcAttributeDescs = m_currentInputLayout->m_vertexDescs;
-
- vertexInputInfo.vertexBindingDescriptionCount = 1;
- vertexInputInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;
-
- vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(srcAttributeDescs.Count());
- vertexInputInfo.pVertexAttributeDescriptions = srcAttributeDescs.getBuffer();
- }
-
- //
-
- VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
- inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
- inputAssembly.primitiveRestartEnable = VK_FALSE;
-
- VkViewport viewport = {};
- viewport.x = 0.0f;
- viewport.y = 0.0f;
- viewport.width = (float)width;
- viewport.height = (float)height;
- viewport.minDepth = 0.0f;
- viewport.maxDepth = 1.0f;
-
- VkRect2D scissor = {};
- scissor.offset = { 0, 0 };
- scissor.extent = { uint32_t(width), uint32_t(height) };
-
- VkPipelineViewportStateCreateInfo viewportState = {};
- viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- viewportState.viewportCount = 1;
- viewportState.pViewports = &viewport;
- viewportState.scissorCount = 1;
- viewportState.pScissors = &scissor;
-
- VkPipelineRasterizationStateCreateInfo rasterizer = {};
- rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
- rasterizer.depthClampEnable = VK_FALSE;
- rasterizer.rasterizerDiscardEnable = VK_FALSE;
- rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
- rasterizer.lineWidth = 1.0f;
- rasterizer.cullMode = VK_CULL_MODE_NONE;
- rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
- rasterizer.depthBiasEnable = VK_FALSE;
-
- VkPipelineMultisampleStateCreateInfo multisampling = {};
- multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
-
- VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
- colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
- colorBlendAttachment.blendEnable = VK_FALSE;
-
- VkPipelineColorBlendStateCreateInfo colorBlending = {};
- colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- colorBlending.logicOpEnable = VK_FALSE;
- colorBlending.logicOp = VK_LOGIC_OP_COPY;
- colorBlending.attachmentCount = 1;
- colorBlending.pAttachments = &colorBlendAttachment;
- colorBlending.blendConstants[0] = 0.0f;
- colorBlending.blendConstants[1] = 0.0f;
- colorBlending.blendConstants[2] = 0.0f;
- colorBlending.blendConstants[3] = 0.0f;
-
- VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
-
- pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- pipelineInfo.stageCount = 2;
- pipelineInfo.pStages = shaderStages;
- pipelineInfo.pVertexInputState = &vertexInputInfo;
- pipelineInfo.pInputAssemblyState = &inputAssembly;
- pipelineInfo.pViewportState = &viewportState;
- pipelineInfo.pRasterizationState = &rasterizer;
- pipelineInfo.pMultisampleState = &multisampling;
- pipelineInfo.pColorBlendState = &colorBlending;
- pipelineInfo.layout = pipeline->m_pipelineLayout->m_pipelineLayout;
- pipelineInfo.renderPass = m_renderPass;
- pipelineInfo.subpass = 0;
- pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
-
- SLANG_VK_CHECK(m_api.vkCreateGraphicsPipelines(m_device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline->m_pipeline));
- }
- else
- {
- assert(!"Unhandled program type");
- return SLANG_FAIL;
- }
-
- pipelineOut = pipeline;
- return SLANG_OK;
-}
-#endif
-
Result VKRenderer::_beginPass()
{
- if (m_swapChainImageIndex < 0)
- {
- return SLANG_FAIL;
- }
-
const int numRenderTargets = 1;
- const VulkanSwapChain::Image& image = m_swapChain.getImages()[m_swapChainImageIndex];
-
int numAttachments = 0;
// Start render pass
@@ -877,15 +990,15 @@ Result VKRenderer::_beginPass()
clearValue.depthStencil.stencil = 0;
}
- const int width = m_swapChain.getWidth();
- const int height = m_swapChain.getHeight();
+ const int width = m_currentFramebuffer->m_width;
+ const int height = m_currentFramebuffer->m_height;
VkCommandBuffer cmdBuffer = m_deviceQueue.getCommandBuffer();
VkRenderPassBeginInfo renderPassBegin = {};
renderPassBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- renderPassBegin.renderPass = m_renderPass;
- renderPassBegin.framebuffer = image.m_frameBuffer;
+ renderPassBegin.renderPass = m_currentFramebuffer->m_layout->m_renderPass;
+ renderPassBegin.framebuffer = m_currentFramebuffer->m_handle;
renderPassBegin.renderArea.offset.x = 0;
renderPassBegin.renderArea.offset.y = 0;
renderPassBegin.renderArea.extent.width = width;
@@ -896,25 +1009,15 @@ Result VKRenderer::_beginPass()
m_api.vkCmdBeginRenderPass(cmdBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
// Set up scissor and viewport
+ if (m_scissorRects.getCount())
{
- VkRect2D rects[kMaxRenderTargets] = {};
- VkViewport viewports[kMaxRenderTargets] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- rects[i] = VkRect2D{ 0, 0, uint32_t(width), uint32_t(height) };
-
- VkViewport& dstViewport = viewports[i];
-
- dstViewport.x = 0.0f;
- dstViewport.y = 0.0f;
- dstViewport.width = float(width);
- dstViewport.height = float(height);
- dstViewport.minDepth = 0.0f;
- dstViewport.maxDepth = 1.0f;
- }
-
- m_api.vkCmdSetScissor(cmdBuffer, 0, numRenderTargets, rects);
- m_api.vkCmdSetViewport(cmdBuffer, 0, numRenderTargets, viewports);
+ m_api.vkCmdSetScissor(
+ cmdBuffer, 0, (uint32_t)m_scissorRects.getCount(), m_scissorRects.getBuffer());
+ }
+ if (m_viewports.getCount())
+ {
+ m_api.vkCmdSetViewport(
+ cmdBuffer, 0, (uint32_t)m_viewports.getCount(), m_viewports.getBuffer());
}
return SLANG_OK;
@@ -926,25 +1029,23 @@ void VKRenderer::_endPass()
m_api.vkCmdEndRenderPass(cmdBuffer);
}
-void VKRenderer::_beginRender()
+void VKRenderer::_endRender()
{
- m_swapChainImageIndex = m_swapChain.nextFrontImageIndex();
+ m_deviceQueue.flush();
- if (m_swapChainImageIndex < 0)
+ // Make m_currentDescriptorSets consistent with m_currentDescriptorSetImpls
+ // so that we don't mistakenly treat any transient descriptor sets as "copied" in the next frame.
+ for (uint32_t i = 0; i < kMaxDescriptorSets; i++)
{
- return;
+ if (m_currentDescriptorSetImpls[i])
+ m_currentDescriptorSets[i] = m_currentDescriptorSetImpls[i]->m_descriptorSet.handle;
}
}
-void VKRenderer::_endRender()
-{
- m_deviceQueue.flush();
-}
-
-Result SLANG_MCALL createVKRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+Result SLANG_MCALL createVKRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
RefPtr<VKRenderer> result = new VKRenderer();
- SLANG_RETURN_ON_FAIL(result->initialize(*desc, windowHandle));
+ SLANG_RETURN_ON_FAIL(result->initialize(*desc));
*outRenderer = result.detach();
return SLANG_OK;
}
@@ -957,6 +1058,8 @@ VKRenderer::~VKRenderer()
waitForGpu();
}
+ m_currentFramebuffer.setNull();
+
m_currentPipeline.setNull();
// Same as clear but, also dtors all elements, which clear does not
@@ -968,16 +1071,10 @@ VKRenderer::~VKRenderer()
impl.setNull();
}
- if (m_renderPass != VK_NULL_HANDLE)
- {
- m_api.vkDestroyRenderPass(m_device, m_renderPass, nullptr);
- m_renderPass = VK_NULL_HANDLE;
- }
-
- m_swapChain.destroy();
-
m_deviceQueue.destroy();
+ descriptorSetAllocator.close();
+
if (m_device != VK_NULL_HANDLE)
{
m_api.vkDestroyDevice(m_device, nullptr);
@@ -1060,15 +1157,15 @@ VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
+SlangResult VKRenderer::initialize(const Desc& desc)
{
SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_SPIRV, "sm_5_1"));
- SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc, inWindowHandle));
+ SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc));
SLANG_RETURN_ON_FAIL(m_module.init());
SLANG_RETURN_ON_FAIL(m_api.initGlobalProcs(m_module));
-
+ descriptorSetAllocator.m_api = &m_api;
m_desc = desc;
VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
@@ -1150,7 +1247,8 @@ SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
}
#endif
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
+ if (m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance) != VK_SUCCESS)
+ return SLANG_FAIL;
SLANG_RETURN_ON_FAIL(m_api.initInstanceProcs(instance));
#if ENABLE_VALIDATION_LAYER
@@ -1319,110 +1417,6 @@ SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
m_api.vkGetDeviceQueue(m_device, queueFamilyIndex, 0, &queue);
SLANG_RETURN_ON_FAIL(m_deviceQueue.init(m_api, queue, queueFamilyIndex));
}
-
- // set up swap chain
-
- {
- VulkanSwapChain::Desc desc;
- VulkanSwapChain::PlatformDesc* platformDesc = nullptr;
-
- desc.init();
- desc.m_format = Format::RGBA_Unorm_UInt8;
-
-#if SLANG_WINDOWS_FAMILY
- VulkanSwapChain::WinPlatformDesc winPlatformDesc;
- winPlatformDesc.m_hinstance = ::GetModuleHandle(nullptr);
- winPlatformDesc.m_hwnd = (HWND)inWindowHandle;
- platformDesc = &winPlatformDesc;
-#endif
-
- SLANG_RETURN_ON_FAIL(m_swapChain.init(&m_deviceQueue, desc, platformDesc));
- }
-
- // depth/stencil?
-
- // render pass?
-
- {
- const int numRenderTargets = 1;
- bool shouldClear = true;
- bool shouldClearDepth = false;
- bool shouldClearStencil = false;
- bool hasDepthBuffer = false;
-
- Format depthFormat = Format::Unknown;
- VkFormat colorFormat = m_swapChain.getVkFormat();
-
- int numAttachments = 0;
- // We need extra space if we have depth buffer
- VkAttachmentDescription attachmentDesc[kMaxRenderTargets + 1] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- VkAttachmentDescription& dst = attachmentDesc[numAttachments ++];
-
- dst.flags = 0;
- dst.format = colorFormat;
- dst.samples = VK_SAMPLE_COUNT_1_BIT;
- dst.loadOp = shouldClear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
- dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- dst.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- dst.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- dst.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- }
- if (hasDepthBuffer)
- {
- VkAttachmentDescription& dst = attachmentDesc[numAttachments++];
-
- dst.flags = 0;
- dst.format = VulkanUtil::getVkFormat(depthFormat);
- dst.samples = VK_SAMPLE_COUNT_1_BIT;
- dst.loadOp = shouldClearDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
- dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- dst.stencilLoadOp = shouldClearStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
- dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
- dst.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- dst.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- }
-
- VkAttachmentReference colorAttachments[kMaxRenderTargets] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- VkAttachmentReference& dst = colorAttachments[i];
- dst.attachment = i;
- dst.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- }
-
- VkAttachmentReference depthAttachment = {};
- depthAttachment.attachment = numRenderTargets;
- depthAttachment.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-
- VkSubpassDescription subpassDesc = {};
- subpassDesc.flags = 0;
- subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpassDesc.inputAttachmentCount = 0u;
- subpassDesc.pInputAttachments = nullptr;
- subpassDesc.colorAttachmentCount = numRenderTargets;
- subpassDesc.pColorAttachments = colorAttachments;
- subpassDesc.pResolveAttachments = nullptr;
- subpassDesc.pDepthStencilAttachment = hasDepthBuffer ? &depthAttachment : nullptr;
- subpassDesc.preserveAttachmentCount = 0u;
- subpassDesc.pPreserveAttachments = nullptr;
-
- VkRenderPassCreateInfo renderPassCreateInfo = {};
- renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- renderPassCreateInfo.attachmentCount = numAttachments;
- renderPassCreateInfo.pAttachments = attachmentDesc;
- renderPassCreateInfo.subpassCount = 1;
- renderPassCreateInfo.pSubpasses = &subpassDesc;
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateRenderPass(m_device, &renderPassCreateInfo, nullptr, &m_renderPass));
- }
-
- // frame buffer
- SLANG_RETURN_ON_FAIL(m_swapChain.createFrameBuffers(m_renderPass));
-
- _beginRender();
-
return SLANG_OK;
}
@@ -1444,30 +1438,98 @@ void VKRenderer::setClearColor(const float color[4])
void VKRenderer::clearFrame()
{
+ _beginPass();
+ ShortList<VkClearAttachment> clears;
+ for (Index i = 0; i < m_currentFramebuffer->renderTargetViews.getCount(); i++)
+ {
+ VkClearAttachment attachment;
+ attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ memcpy(attachment.clearValue.color.float32, m_clearColor, sizeof(float) * 4);
+ attachment.colorAttachment = (int)i;
+ clears.add(attachment);
+ }
+ if (m_currentFramebuffer->depthStencilView)
+ {
+ VkClearAttachment attachment;
+ attachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ attachment.clearValue.depthStencil.depth = 1.0f;
+ attachment.clearValue.depthStencil.stencil = 0;
+ clears.add(attachment);
+ }
+ VkClearRect rect = {};
+ rect.baseArrayLayer = 0;
+ rect.layerCount = 1;
+ rect.rect.extent.width = m_currentFramebuffer->m_width;
+ rect.rect.extent.height = m_currentFramebuffer->m_height;
+ m_api.vkCmdClearAttachments(
+ m_deviceQueue.getCommandBuffer(),
+ (uint32_t)clears.getCount(),
+ clears.getArrayView().getBuffer(),
+ 1,
+ &rect);
+ _endPass();
+}
+
+void VKRenderer::beginFrame()
+{
+ if (m_deviceQueue.isCurrent(VulkanDeviceQueue::EventType::EndFrame))
+ m_deviceQueue.makeCompleted(VulkanDeviceQueue::EventType::EndFrame);
}
-void VKRenderer::presentFrame()
+void VKRenderer::endFrame()
{
_endRender();
+}
+
+void VKRenderer::makeSwapchainImagePresentable(ISwapchain* swapchain)
+{
+ auto swapchainImpl = static_cast<SwapchainImpl*>(swapchain);
+ auto image = swapchainImpl->m_images[swapchainImpl->m_currentImageIndex];
+ _transitionImageLayout(
+ image->m_image,
+ image->m_vkformat,
+ *image->getDesc(),
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
+ if (!m_deviceQueue.isCurrent(VulkanDeviceQueue::EventType::EndFrame))
+ m_deviceQueue.makeCurrent(VulkanDeviceQueue::EventType::EndFrame);
+}
- const bool vsync = true;
- m_swapChain.present(vsync);
+Result VKRenderer::createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain)
+{
+ RefPtr<SwapchainImpl> sc = new SwapchainImpl();
+ SLANG_RETURN_ON_FAIL(sc->init(this, desc, window));
+ *outSwapchain = sc.detach();
+ return SLANG_OK;
+}
+
+Result VKRenderer::createFramebufferLayout(const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout)
+{
+ RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl();
+ SLANG_RETURN_ON_FAIL(layout->init(this, desc));
+ *outLayout = layout.detach();
+ return SLANG_OK;
+}
- _beginRender();
+Result VKRenderer::createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer)
+{
+ RefPtr<FramebufferImpl> fb = new FramebufferImpl();
+ SLANG_RETURN_ON_FAIL(fb->init(this, desc));
+ *outFramebuffer = fb.detach();
+ return SLANG_OK;
}
-TextureResource::Desc VKRenderer::getSwapChainTextureDesc()
+void VKRenderer::setFramebuffer(IFramebuffer* framebuffer)
{
- TextureResource::Desc desc;
- desc.init2D(IResource::Type::Texture2D, Format::Unknown, m_desc.width, m_desc.height, 1);
- return desc;
+ m_currentFramebuffer = static_cast<FramebufferImpl*>(framebuffer);
}
-SlangResult VKRenderer::captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
+SlangResult VKRenderer::readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize)
{
- SLANG_UNUSED(buffer);
- SLANG_UNUSED(inOutBufferSize);
+ SLANG_UNUSED(texture);
+ SLANG_UNUSED(outBlob);
SLANG_UNUSED(outRowPitch);
SLANG_UNUSED(outPixelSize);
return SLANG_FAIL;
@@ -1578,6 +1640,32 @@ static VkImageUsageFlags _calcImageUsageFlags(int bindFlags, int cpuAccessFlags,
return usage;
}
+bool isDepthFormat(VkFormat format)
+{
+ switch (format)
+ {
+ case VK_FORMAT_D16_UNORM:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ case VK_FORMAT_X8_D24_UNORM_PACK32:
+ case VK_FORMAT_D32_SFLOAT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return true;
+ }
+ return false;
+}
+
+bool isStencilFormat(VkFormat format)
+{
+ switch (format)
+ {
+ case VK_FORMAT_S8_UINT:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return true;
+ }
+ return false;
+}
+
void VKRenderer::_transitionImageLayout(VkImage image, VkFormat format, const TextureResource::Desc& desc, VkImageLayout oldLayout, VkImageLayout newLayout)
{
VkImageMemoryBarrier barrier = {};
@@ -1587,7 +1675,14 @@ void VKRenderer::_transitionImageLayout(VkImage image, VkFormat format, const Te
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
- barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ if (isDepthFormat(format))
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (isStencilFormat(format))
+ barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ if (barrier.subresourceRange.aspectMask == 0)
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = desc.numMipLevels;
barrier.subresourceRange.baseArrayLayer = 0;
@@ -1612,6 +1707,47 @@ void VKRenderer::_transitionImageLayout(VkImage image, VkFormat format, const Te
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
+ else if (
+ oldLayout == VK_IMAGE_LAYOUT_UNDEFINED &&
+ newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
+ {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ }
+ else if (
+ oldLayout == VK_IMAGE_LAYOUT_UNDEFINED &&
+ (newLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL ||
+ newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL))
+ {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+
+ sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ }
+ else if (
+ oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL &&
+ newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
+ {
+ barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ barrier.dstAccessMask = 0;
+
+ sourceStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+ else if (
+ oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR &&
+ newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
+ {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ destinationStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ }
else
{
assert(!"unsupported layout transition!");
@@ -1653,7 +1789,7 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
const int arraySize = desc.calcEffectiveArraySize();
RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(desc, initialUsage, &m_api));
-
+ texture->m_vkformat = format;
// Create the image
{
VkImageCreateInfo imageInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
@@ -1786,7 +1922,7 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
{
const uint8_t* srcData = (const uint8_t*)(initData->subResources[subResourceIndex]);
- for (int l = 0; l < numRows; l++)
+ for (uint32_t l = 0; l < numRows; l++)
{
::memcpy(dstData, srcData, dstRowSizeInBytes);
@@ -1846,7 +1982,30 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
m_deviceQueue.flushAndWait();
}
-
+ else
+ {
+ switch (initialUsage)
+ {
+ case IResource::Usage::RenderTarget:
+ _transitionImageLayout(
+ texture->m_image,
+ format,
+ *texture->getDesc(),
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ break;
+ case IResource::Usage::DepthWrite:
+ _transitionImageLayout(
+ texture->m_image,
+ format,
+ *texture->getDesc(),
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ break;
+ default:
+ break;
+ }
+ }
*outResource = texture.detach();
return SLANG_OK;
}
@@ -1983,6 +2142,44 @@ static VkCompareOp translateComparisonFunc(ComparisonFunc func)
}
}
+static VkStencilOp translateStencilOp(StencilOp op)
+{
+ switch (op)
+ {
+ case StencilOp::DecrementSaturate:
+ return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
+ case StencilOp::DecrementWrap:
+ return VK_STENCIL_OP_DECREMENT_AND_WRAP;
+ case StencilOp::IncrementSaturate:
+ return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
+ case StencilOp::IncrementWrap:
+ return VK_STENCIL_OP_INCREMENT_AND_WRAP;
+ case StencilOp::Invert:
+ return VK_STENCIL_OP_INVERT;
+ case StencilOp::Keep:
+ return VK_STENCIL_OP_KEEP;
+ case StencilOp::Replace:
+ return VK_STENCIL_OP_REPLACE;
+ case StencilOp::Zero:
+ return VK_STENCIL_OP_ZERO;
+ default:
+ return VK_STENCIL_OP_KEEP;
+ }
+}
+
+static VkStencilOpState translateStencilState(DepthStencilOpDesc desc)
+{
+ VkStencilOpState rs;
+ rs.compareMask = desc.stencilCompareMask;
+ rs.compareOp = translateComparisonFunc(desc.stencilFunc);
+ rs.depthFailOp = translateStencilOp(desc.stencilDepthFailOp);
+ rs.failOp = translateStencilOp(desc.stencilFailOp);
+ rs.passOp = translateStencilOp(desc.stencilPassOp);
+ rs.reference = desc.stencilReference;
+ rs.writeMask = desc.stencilWriteMask;
+ return rs;
+}
+
Result VKRenderer::createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler)
{
VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
@@ -2022,7 +2219,7 @@ Result VKRenderer::createTextureView(ITextureResource* texture, IResourceView::D
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.flags = 0;
- createInfo.format = VulkanUtil::getVkFormat(desc.format);
+ createInfo.format = resourceImpl->m_vkformat;
createInfo.image = resourceImpl->m_image;
createInfo.components = VkComponentMapping{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,VK_COMPONENT_SWIZZLE_B,VK_COMPONENT_SWIZZLE_A };
switch (resourceImpl->getType())
@@ -2052,10 +2249,29 @@ Result VKRenderer::createTextureView(ITextureResource* texture, IResourceView::D
{
case IResourceView::Type::DepthStencil:
view->m_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ switch (resourceImpl->m_vkformat)
+ {
+ case VK_FORMAT_D16_UNORM_S8_UINT:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ break;
+ case VK_FORMAT_D16_UNORM:
+ case VK_FORMAT_D32_SFLOAT:
+ case VK_FORMAT_X8_D24_UNORM_PACK32:
+ createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ break;
+ case VK_FORMAT_S8_UINT:
+ createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
+ break;
+ default:
+ break;
+ }
+ createInfo.subresourceRange.levelCount = 1;
break;
case IResourceView::Type::RenderTarget:
view->m_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ createInfo.subresourceRange.levelCount = 1;
break;
case IResourceView::Type::ShaderResource:
view->m_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -2309,20 +2525,16 @@ void VKRenderer::setIndexBuffer(IBufferResource* buffer, Format indexFormat, UIn
{
}
-void VKRenderer::setDepthStencilTarget(IResourceView* depthStencilView)
-{
-}
-
void VKRenderer::setViewports(UInt count, Viewport const* viewports)
{
static const int kMaxViewports = 8; // TODO: base on device caps
assert(count <= kMaxViewports);
- VkViewport vkViewports[kMaxViewports];
+ m_viewports.setCount(count);
for(UInt ii = 0; ii < count; ++ii)
{
auto& inViewport = viewports[ii];
- auto& vkViewport = vkViewports[ii];
+ auto& vkViewport = m_viewports[ii];
vkViewport.x = inViewport.originX;
vkViewport.y = inViewport.originY;
@@ -2333,7 +2545,7 @@ void VKRenderer::setViewports(UInt count, Viewport const* viewports)
}
VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
- m_api.vkCmdSetViewport(commandBuffer, 0, uint32_t(count), vkViewports);
+ m_api.vkCmdSetViewport(commandBuffer, 0, uint32_t(count), m_viewports.getBuffer());
}
void VKRenderer::setScissorRects(UInt count, ScissorRect const* rects)
@@ -2341,20 +2553,21 @@ void VKRenderer::setScissorRects(UInt count, ScissorRect const* rects)
static const int kMaxScissorRects = 8; // TODO: base on device caps
assert(count <= kMaxScissorRects);
- VkRect2D vkRects[kMaxScissorRects];
+ m_scissorRects.setCount(count);
for(UInt ii = 0; ii < count; ++ii)
{
auto& inRect = rects[ii];
- auto& vkRect = vkRects[ii];
+ auto& vkRect = m_scissorRects[ii];
vkRect.offset.x = int32_t(inRect.minX);
vkRect.offset.y = int32_t(inRect.minY);
vkRect.extent.width = uint32_t(inRect.maxX - inRect.minX);
vkRect.extent.height = uint32_t(inRect.maxY - inRect.minY);
+
}
VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
- m_api.vkCmdSetScissor(commandBuffer, 0, uint32_t(count), vkRects);
+ m_api.vkCmdSetScissor(commandBuffer, 0, uint32_t(count), m_scissorRects.getBuffer());
}
void VKRenderer::setPipelineState(IPipelineState* state)
@@ -2365,7 +2578,8 @@ void VKRenderer::setPipelineState(IPipelineState* state)
void VKRenderer::_flushBindingState(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint)
{
auto pipeline = m_currentPipeline;
-
+ auto& descSetCopies = m_descSetCopies;
+ descSetCopies.clear();
// We start by binding the pipeline state.
//
m_api.vkCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline->m_pipeline);
@@ -2375,6 +2589,41 @@ void VKRenderer::_flushBindingState(VkCommandBuffer commandBuffer, VkPipelineBin
auto pipelineLayoutImpl = pipeline->m_pipelineLayout.Ptr();
auto vkPipelineLayout = pipelineLayoutImpl->m_pipelineLayout;
auto descriptorSetCount = pipelineLayoutImpl->m_descriptorSetCount;
+ for (uint32_t i = 0; i < (uint32_t)descriptorSetCount; i++)
+ {
+ if (m_currentDescriptorSetImpls[i]->m_isTransient)
+ {
+ // A transient descriptor set may go out of life cycle after command list recording,
+ // therefore we must make a copy of it in the per-frame descriptor pool.
+
+ // If we have already created a transient copy for this descriptor set, skip the copy.
+ if (m_currentDescriptorSetImpls[i]->m_descriptorSet.handle !=
+ m_currentDescriptorSets[i])
+ continue;
+
+ auto descSet = m_deviceQueue.allocTransientDescriptorSet(
+ m_currentDescriptorSetImpls[i]->m_layout->m_descriptorSetLayout);
+ uint32_t bindingIndex = 0;
+ for (auto binding : m_currentDescriptorSetImpls[i]->m_layout->m_vkBindings)
+ {
+ VkCopyDescriptorSet copy = {};
+ copy.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
+ copy.srcSet = m_currentDescriptorSetImpls[i]->m_descriptorSet.handle;
+ copy.dstSet = descSet.handle;
+ copy.srcBinding = copy.dstBinding = bindingIndex;
+ copy.srcArrayElement = copy.dstArrayElement = 0;
+ copy.descriptorCount = binding.descriptorCount;
+ descSetCopies.add(copy);
+ bindingIndex++;
+ }
+ m_currentDescriptorSets[i] = descSet.handle;
+ }
+ }
+ if (descSetCopies.getCount())
+ {
+ m_api.vkUpdateDescriptorSets(
+ m_api.m_device, 0, nullptr, (uint32_t)descSetCopies.getCount(), descSetCopies.getBuffer());
+ }
m_api.vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, vkPipelineLayout,
0, uint32_t(descriptorSetCount),
&m_currentDescriptorSets[0],
@@ -2509,7 +2758,8 @@ Result VKRenderer::createDescriptorSetLayout(const IDescriptorSetLayout::Desc& d
{
RefPtr<DescriptorSetLayoutImpl> descriptorSetLayoutImpl = new DescriptorSetLayoutImpl(m_api);
- Slang::List<VkDescriptorSetLayoutBinding> dstBindings;
+ auto& dstBindings = descriptorSetLayoutImpl->m_vkBindings;
+
Slang::List<uint32_t> descriptorCountForTypes;
UInt rangeCount = desc.slotRangeCount;
@@ -2610,31 +2860,7 @@ Result VKRenderer::createDescriptorSetLayout(const IDescriptorSetLayout::Desc& d
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
SLANG_VK_CHECK(m_api.vkCreateDescriptorSetLayout(m_device, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout));
- // Create a pool while we are at it, to allocate descriptor sets of this type.
-
- List<VkDescriptorPoolSize> poolSizes;
- for (Index ii = 0; ii < descriptorCountForTypes.getCount(); ++ii)
- {
- auto descriptorCount = descriptorCountForTypes[ii];
- if (descriptorCount > 0)
- {
- VkDescriptorPoolSize poolSize;
- poolSize.type = VkDescriptorType(ii);
- poolSize.descriptorCount = descriptorCount;
- poolSizes.add(poolSize);
- }
- }
-
- VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
- descriptorPoolInfo.maxSets = 128; // TODO: actually pick a size.
- descriptorPoolInfo.poolSizeCount = uint32_t(poolSizes.getCount());
- descriptorPoolInfo.pPoolSizes = poolSizes.getBuffer();
-
- VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
- SLANG_VK_CHECK(m_api.vkCreateDescriptorPool(m_device, &descriptorPoolInfo, nullptr, &descriptorPool));
-
descriptorSetLayoutImpl->m_descriptorSetLayout = descriptorSetLayout;
- descriptorSetLayoutImpl->m_descriptorPool = descriptorPool;
*outLayout = descriptorSetLayoutImpl.detach();
return SLANG_OK;
@@ -2703,22 +2929,18 @@ Result VKRenderer::createPipelineLayout(const IPipelineLayout::Desc& desc, IPipe
return SLANG_OK;
}
-Result VKRenderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet)
+Result VKRenderer::createDescriptorSet(
+ IDescriptorSetLayout* layout,
+ IDescriptorSet::Flag::Enum flag,
+ IDescriptorSet** outDescriptorSet)
{
auto layoutImpl = (DescriptorSetLayoutImpl*)layout;
- VkDescriptorSetAllocateInfo descriptorSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
- descriptorSetAllocInfo.descriptorPool = layoutImpl->m_descriptorPool;
- descriptorSetAllocInfo.descriptorSetCount = 1;
- descriptorSetAllocInfo.pSetLayouts = &layoutImpl->m_descriptorSetLayout;
-
- VkDescriptorSet descriptorSet;
- SLANG_VK_CHECK(m_api.vkAllocateDescriptorSets(m_device, &descriptorSetAllocInfo, &descriptorSet));
-
RefPtr<DescriptorSetImpl> descriptorSetImpl = new DescriptorSetImpl(this);
descriptorSetImpl->m_layout = layoutImpl;
- descriptorSetImpl->m_descriptorSet = descriptorSet;
-
+ descriptorSetImpl->m_descriptorSet =
+ descriptorSetAllocator.allocate(layoutImpl->m_descriptorSetLayout);
+ descriptorSetImpl->m_isTransient = (flag == IDescriptorSet::Flag::Enum::Transient);
descriptorSetImpl->m_rootConstantData.setCount(layoutImpl->m_rootConstantDataSize);
descriptorSetImpl->m_boundObjects.setCount(layoutImpl->m_totalBoundObjectCount);
@@ -2741,7 +2963,7 @@ void VKRenderer::DescriptorSetImpl::setConstantBuffer(UInt range, UInt index, IB
bufferInfo.range = bufferImpl->getDesc()->sizeInBytes;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2771,7 +2993,7 @@ void VKRenderer::DescriptorSetImpl::setResource(UInt range, UInt index, IResourc
imageInfo.imageLayout = textureViewImpl->m_layout;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2787,7 +3009,7 @@ void VKRenderer::DescriptorSetImpl::setResource(UInt range, UInt index, IResourc
auto bufferViewImpl = (TexelBufferResourceViewImpl*)viewImpl;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2808,7 +3030,7 @@ void VKRenderer::DescriptorSetImpl::setResource(UInt range, UInt index, IResourc
bufferInfo.range = bufferViewImpl->size;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2833,7 +3055,7 @@ void VKRenderer::DescriptorSetImpl::setSampler(UInt range, UInt index, ISamplerS
auto descriptorType = rangeInfo.vkDescriptorType;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2915,7 +3137,7 @@ void VKRenderer::setDescriptorSet(PipelineType pipelineType, IPipelineLayout* la
auto descriptorSetImpl = (DescriptorSetImpl*)descriptorSet;
m_currentDescriptorSetImpls[index] = descriptorSetImpl;
- m_currentDescriptorSets[index] = descriptorSetImpl->m_descriptorSet;
+ m_currentDescriptorSets[index] = descriptorSetImpl->m_descriptorSet.handle;
}
Result VKRenderer::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram)
@@ -3062,6 +3284,16 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
VkDynamicState dynamicStates[] = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR};
dynamicStateInfo.pDynamicStates = dynamicStates;
+ VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = {};
+ depthStencilStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ depthStencilStateInfo.depthTestEnable = inDesc.depthStencil.depthTestEnable ? 1 : 0;
+ depthStencilStateInfo.back = translateStencilState(inDesc.depthStencil.backFace);
+ depthStencilStateInfo.front = translateStencilState(inDesc.depthStencil.frontFace);
+ depthStencilStateInfo.depthBoundsTestEnable = 0;
+ depthStencilStateInfo.depthCompareOp = translateComparisonFunc(inDesc.depthStencil.depthFunc);
+ depthStencilStateInfo.depthWriteEnable = inDesc.depthStencil.depthWriteEnable ? 1 : 0;
+ depthStencilStateInfo.stencilTestEnable = inDesc.depthStencil.stencilEnable ? 1 : 0;
+
VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
@@ -3073,8 +3305,9 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
+ pipelineInfo.pDepthStencilState = &depthStencilStateInfo;
pipelineInfo.layout = pipelineLayoutImpl->m_pipelineLayout;
- pipelineInfo.renderPass = m_renderPass;
+ pipelineInfo.renderPass = static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout)->m_renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.pDynamicState = &dynamicStateInfo;
@@ -3085,6 +3318,8 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
RefPtr<PipelineStateImpl> pipelineStateImpl = new PipelineStateImpl(m_api);
pipelineStateImpl->m_pipeline = pipeline;
pipelineStateImpl->m_pipelineLayout = pipelineLayoutImpl;
+ pipelineStateImpl->m_framebufferLayout =
+ static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout);
pipelineStateImpl->m_shaderProgram = programImpl;
pipelineStateImpl->init(desc);
*outState = pipelineStateImpl.detach();
diff --git a/tools/gfx/vulkan/render-vk.h b/tools/gfx/vulkan/render-vk.h
index f259ab44c..b2bceb31c 100644
--- a/tools/gfx/vulkan/render-vk.h
+++ b/tools/gfx/vulkan/render-vk.h
@@ -6,6 +6,6 @@
namespace gfx {
-SlangResult SLANG_MCALL createVKRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer);
+SlangResult SLANG_MCALL createVKRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer);
} // gfx
diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h
index 3fb4b3909..77e6a9a09 100644
--- a/tools/gfx/vulkan/vk-api.h
+++ b/tools/gfx/vulkan/vk-api.h
@@ -14,14 +14,14 @@ namespace gfx {
#define VK_API_INSTANCE_PROCS_OPT(x) \
x(vkGetPhysicalDeviceFeatures2) \
x(vkGetPhysicalDeviceProperties2) \
+ x(vkCreateDebugReportCallbackEXT) \
+ x(vkDestroyDebugReportCallbackEXT) \
+ x(vkDebugReportMessageEXT) \
/* */
#define VK_API_INSTANCE_PROCS(x) \
x(vkCreateDevice) \
x(vkDestroyDevice) \
- x(vkCreateDebugReportCallbackEXT) \
- x(vkDestroyDebugReportCallbackEXT) \
- x(vkDebugReportMessageEXT) \
x(vkEnumeratePhysicalDevices) \
x(vkGetPhysicalDeviceProperties) \
x(vkGetPhysicalDeviceFeatures) \
@@ -34,6 +34,7 @@ namespace gfx {
#define VK_API_DEVICE_PROCS(x) \
x(vkCreateDescriptorPool) \
x(vkDestroyDescriptorPool) \
+ x(vkResetDescriptorPool) \
x(vkGetDeviceQueue) \
x(vkQueueSubmit) \
x(vkQueueWaitIdle) \
@@ -47,6 +48,7 @@ namespace gfx {
x(vkCreateDescriptorSetLayout) \
x(vkDestroyDescriptorSetLayout) \
x(vkAllocateDescriptorSets) \
+ x(vkFreeDescriptorSets) \
x(vkUpdateDescriptorSets) \
x(vkCreatePipelineLayout) \
x(vkDestroyPipelineLayout) \
@@ -74,6 +76,7 @@ namespace gfx {
x(vkGetImageMemoryRequirements) \
\
x(vkCmdBindPipeline) \
+ x(vkCmdClearAttachments) \
x(vkCmdBindDescriptorSets) \
x(vkCmdDispatch) \
x(vkCmdDraw) \
@@ -107,6 +110,7 @@ namespace gfx {
x(vkBeginCommandBuffer) \
x(vkEndCommandBuffer) \
x(vkResetCommandBuffer) \
+ x(vkResetCommandPool) \
\
x(vkBindImageMemory) \
x(vkBindBufferMemory) \
diff --git a/tools/gfx/vulkan/vk-descriptor-allocator.cpp b/tools/gfx/vulkan/vk-descriptor-allocator.cpp
new file mode 100644
index 000000000..c01e37642
--- /dev/null
+++ b/tools/gfx/vulkan/vk-descriptor-allocator.cpp
@@ -0,0 +1,70 @@
+#include "vk-descriptor-allocator.h"
+#include "vk-util.h"
+
+namespace gfx
+{
+VkDescriptorPool DescriptorSetAllocator::newPool()
+{
+ VkDescriptorPoolCreateInfo descriptorPoolInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
+ VkDescriptorPoolSize poolSizes[] = {
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1024},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 256},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 256},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 16},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, 16},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 256}};
+ descriptorPoolInfo.maxSets = 4096;
+ descriptorPoolInfo.poolSizeCount = sizeof(poolSizes) / sizeof(VkDescriptorPoolSize);
+ descriptorPoolInfo.pPoolSizes = poolSizes;
+ descriptorPoolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+
+ VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
+ SLANG_VK_CHECK(m_api->vkCreateDescriptorPool(
+ m_api->m_device, &descriptorPoolInfo, nullptr, &descriptorPool));
+ pools.add(descriptorPool);
+ return descriptorPool;
+}
+
+VulkanDescriptorSet DescriptorSetAllocator::allocate(VkDescriptorSetLayout layout)
+{
+ VulkanDescriptorSet rs = {};
+ VkDescriptorSetAllocateInfo allocInfo = {};
+ allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ allocInfo.descriptorPool = getPool();
+ allocInfo.descriptorSetCount = 1;
+ allocInfo.pSetLayouts = &layout;
+ if (m_api->vkAllocateDescriptorSets(m_api->m_device, &allocInfo, &rs.handle) == VK_SUCCESS)
+ {
+ rs.pool = allocInfo.descriptorPool;
+ return rs;
+ }
+ // If allocation from last pool fails, try all existing pools.
+ for (Slang::Index i = 0; i < pools.getCount() - 1; i++)
+ {
+ allocInfo.descriptorPool = pools[i];
+ if (m_api->vkAllocateDescriptorSets(m_api->m_device, &allocInfo, &rs.handle) == VK_SUCCESS)
+ {
+ rs.pool = allocInfo.descriptorPool;
+ return rs;
+ }
+ }
+ // If we still cannot allocate the descriptor set, add a new pool.
+ auto pool = newPool();
+ allocInfo.descriptorPool = pool;
+ if (m_api->vkAllocateDescriptorSets(m_api->m_device, &allocInfo, &rs.handle) == VK_SUCCESS)
+ {
+ rs.pool = allocInfo.descriptorPool;
+ return rs;
+ }
+ // Failed to allocate from a new pool, we are in trouble.
+ assert(!"descriptor set allocation failed.");
+ return rs;
+}
+}
diff --git a/tools/gfx/vulkan/vk-descriptor-allocator.h b/tools/gfx/vulkan/vk-descriptor-allocator.h
new file mode 100644
index 000000000..3d5c441ad
--- /dev/null
+++ b/tools/gfx/vulkan/vk-descriptor-allocator.h
@@ -0,0 +1,43 @@
+// vk-descriptor-allocator.h
+
+#pragma once
+
+#include "vk-api.h"
+#include "core/slang-list.h"
+
+namespace gfx
+{
+struct VulkanDescriptorSet
+{
+ VkDescriptorSet handle;
+ VkDescriptorPool pool;
+};
+class DescriptorSetAllocator
+{
+public:
+ Slang::List<VkDescriptorPool> pools;
+ const VulkanApi* m_api;
+ VkDescriptorPool newPool();
+ VkDescriptorPool getPool()
+ {
+ if (pools.getCount())
+ return pools.getLast();
+ return newPool();
+ }
+ VulkanDescriptorSet allocate(VkDescriptorSetLayout layout);
+ void free(VulkanDescriptorSet set)
+ {
+ m_api->vkFreeDescriptorSets(m_api->m_device, set.pool, 1, &set.handle);
+ }
+ void reset()
+ {
+ for (auto pool : pools)
+ m_api->vkResetDescriptorPool(m_api->m_device, pool, 0);
+ }
+ void close()
+ {
+ for (auto pool : pools)
+ m_api->vkDestroyDescriptorPool(m_api->m_device, pool, nullptr);
+ }
+};
+} // namespace gfx
diff --git a/tools/gfx/vulkan/vk-device-queue.cpp b/tools/gfx/vulkan/vk-device-queue.cpp
index 0cc9a0a0d..149e5dec2 100644
--- a/tools/gfx/vulkan/vk-device-queue.cpp
+++ b/tools/gfx/vulkan/vk-device-queue.cpp
@@ -24,10 +24,11 @@ void VulkanDeviceQueue::destroy()
for (int i = 0; i < m_numCommandBuffers; i++)
{
- m_api->vkFreeCommandBuffers(m_api->m_device, m_commandPool, 1, &m_commandBuffers[i]);
+ m_api->vkFreeCommandBuffers(m_api->m_device, m_commandPools[i], 1, &m_commandBuffers[i]);
m_api->vkDestroyFence(m_api->m_device, m_fences[i].fence, nullptr);
+ m_api->vkDestroyCommandPool(m_api->m_device, m_commandPools[i], nullptr);
+ m_descSetAllocator[i].close();
}
- m_api->vkDestroyCommandPool(m_api->m_device, m_commandPool, nullptr);
m_api = nullptr;
}
}
@@ -47,26 +48,25 @@ SlangResult VulkanDeviceQueue::init(const VulkanApi& api, VkQueue queue, int que
m_queue = queue;
- VkCommandPoolCreateInfo poolCreateInfo = {};
- poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
-
- poolCreateInfo.queueFamilyIndex = queueIndex;
+ for (int i = 0; i < m_numCommandBuffers; i++)
+ {
+ VkCommandPoolCreateInfo poolCreateInfo = {};
+ poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- api.vkCreateCommandPool(api.m_device, &poolCreateInfo, nullptr, &m_commandPool);
+ poolCreateInfo.queueFamilyIndex = queueIndex;
- VkCommandBufferAllocateInfo commandInfo = {};
- commandInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- commandInfo.commandPool = m_commandPool;
- commandInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- commandInfo.commandBufferCount = 1;
+ api.vkCreateCommandPool(api.m_device, &poolCreateInfo, nullptr, &m_commandPools[i]);
- VkFenceCreateInfo fenceCreateInfo = {};
- fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceCreateInfo.flags = 0; // VK_FENCE_CREATE_SIGNALED_BIT;
+ VkCommandBufferAllocateInfo commandInfo = {};
+ commandInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ commandInfo.commandPool = m_commandPools[i];
+ commandInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ commandInfo.commandBufferCount = 1;
- for (int i = 0; i < m_numCommandBuffers; i++)
- {
+ VkFenceCreateInfo fenceCreateInfo = {};
+ fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceCreateInfo.flags = 0; // VK_FENCE_CREATE_SIGNALED_BIT;
Fence& fence = m_fences[i];
api.vkAllocateCommandBuffers(api.m_device, &commandInfo, &m_commandBuffers[i]);
@@ -74,6 +74,8 @@ SlangResult VulkanDeviceQueue::init(const VulkanApi& api, VkQueue queue, int que
api.vkCreateFence(api.m_device, &fenceCreateInfo, nullptr, &fence.fence);
fence.active = false;
fence.value = 0;
+
+ m_descSetAllocator[i].m_api = &api;
}
VkSemaphoreCreateInfo semaphoreCreateInfo = {};
@@ -133,6 +135,7 @@ void VulkanDeviceQueue::flushStepA()
// No longer waiting on this semaphore
makeCompleted(EventType::BeginFrame);
+ makeCompleted(EventType::EndFrame);
}
void VulkanDeviceQueue::_updateFenceAtIndex( int fenceIndex, bool blocking)
@@ -161,6 +164,7 @@ void VulkanDeviceQueue::flushStepB()
{
m_commandBufferIndex = (m_commandBufferIndex + 1) % m_numCommandBuffers;
m_commandBuffer = m_commandBuffers[m_commandBufferIndex];
+ m_commandPool = m_commandPools[m_commandBufferIndex];
// non-blocking update of fence values
for (int i = 0; i < m_numCommandBuffers; ++i)
@@ -171,9 +175,8 @@ void VulkanDeviceQueue::flushStepB()
// blocking update of fence values
_updateFenceAtIndex(m_commandBufferIndex, true);
- m_api->vkResetCommandBuffer(m_commandBuffer, 0);
-
- //m_api.vkResetCommandPool(m_api->m_device, m_commandPool, 0);
+ m_descSetAllocator[m_commandBufferIndex].reset();
+ m_api->vkResetCommandPool(m_api->m_device, m_commandPool, 0);
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@@ -194,6 +197,11 @@ void VulkanDeviceQueue::flushAndWait()
waitForIdle();
}
+VkSemaphore VulkanDeviceQueue::getSemaphore(EventType eventType)
+{
+ return m_semaphores[int(eventType)];
+}
+
VkSemaphore VulkanDeviceQueue::makeCurrent(EventType eventType)
{
assert(!isCurrent(eventType));
diff --git a/tools/gfx/vulkan/vk-device-queue.h b/tools/gfx/vulkan/vk-device-queue.h
index cd53b6b9d..9869a3caf 100644
--- a/tools/gfx/vulkan/vk-device-queue.h
+++ b/tools/gfx/vulkan/vk-device-queue.h
@@ -2,6 +2,7 @@
#pragma once
#include "vk-api.h"
+#include "vk-descriptor-allocator.h"
namespace gfx {
@@ -35,6 +36,7 @@ struct VulkanDeviceQueue
/// Make the specified event 'current' - meaning it's semaphore must be waited on
VkSemaphore makeCurrent(EventType eventType);
+ VkSemaphore getSemaphore(EventType eventType);
/// Makes the event no longer required to be waited on
void makeCompleted(EventType eventType);
/// Returns true if the event is already current
@@ -43,6 +45,11 @@ struct VulkanDeviceQueue
/// Get the command buffer
VkCommandBuffer getCommandBuffer() const { return m_commandBuffer; }
+ VulkanDescriptorSet allocTransientDescriptorSet(VkDescriptorSetLayout layout)
+ {
+ return m_descSetAllocator[m_commandBufferIndex].allocate(layout);
+ }
+
/// Get the queue
VkQueue getQueue() const { return m_queue; }
@@ -76,19 +83,21 @@ struct VulkanDeviceQueue
VkQueue m_queue = VK_NULL_HANDLE;
- VkCommandPool m_commandPool = VK_NULL_HANDLE;
int m_numCommandBuffers = 0;
int m_commandBufferIndex = 0;
// There are the same amount of command buffers as fences
+ VkCommandPool m_commandPools[kMaxCommandBuffers] = {VK_NULL_HANDLE};
VkCommandBuffer m_commandBuffers[kMaxCommandBuffers] = { VK_NULL_HANDLE };
Fence m_fences[kMaxCommandBuffers] = { {VK_NULL_HANDLE, 0, 0u} };
VkCommandBuffer m_commandBuffer = VK_NULL_HANDLE;
-
+ VkCommandPool m_commandPool = VK_NULL_HANDLE;
VkSemaphore m_semaphores[int(EventType::CountOf)];
VkSemaphore m_currentSemaphores[int(EventType::CountOf)];
+ DescriptorSetAllocator m_descSetAllocator[kMaxCommandBuffers];
+
uint64_t m_lastFenceCompleted = 1;
uint64_t m_nextFenceValue = 2;
diff --git a/tools/gfx/vulkan/vk-swap-chain.cpp b/tools/gfx/vulkan/vk-swap-chain.cpp
index 21460ce61..bc6160a02 100644
--- a/tools/gfx/vulkan/vk-swap-chain.cpp
+++ b/tools/gfx/vulkan/vk-swap-chain.cpp
@@ -83,7 +83,7 @@ SlangResult VulkanSwapChain::init(VulkanDeviceQueue* deviceQueue, const Desc& de
VkFormat format = formats[i];
if (_indexOfFormat(surfaceFormats, format) >= 0)
{
- m_format = format;
+ m_format = format;
}
}
@@ -94,10 +94,12 @@ SlangResult VulkanSwapChain::init(VulkanDeviceQueue* deviceQueue, const Desc& de
// Save the desc
m_desc = desc;
-
SLANG_RETURN_ON_FAIL(_createSwapChain());
- m_desc = desc;
+ if (descIn.m_format == Format::RGBA_Unorm_UInt8 && m_format == VK_FORMAT_B8G8R8A8_UNORM)
+ {
+ m_desc.m_format = Format::BGRA_Unorm_UInt8;
+ }
return SLANG_OK;
}
@@ -121,61 +123,6 @@ void VulkanSwapChain::getWindowSize(int* widthOut, int* heightOut) const
#endif
}
-SlangResult VulkanSwapChain::_createFrameBuffers(VkRenderPass renderPass)
-{
- assert(renderPass != VK_NULL_HANDLE);
-
- for (Index i = 0; i < m_images.getCount(); ++i)
- {
- Image& image = m_images[i];
- VkImageView attachments[] =
- {
- image.m_imageView
- };
-
- VkFramebufferCreateInfo framebufferInfo = {};
- framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebufferInfo.renderPass = renderPass;
- framebufferInfo.attachmentCount = 1;
- framebufferInfo.pAttachments = attachments;
- framebufferInfo.width = m_width;
- framebufferInfo.height = m_height;
- framebufferInfo.layers = 1;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateFramebuffer(m_api->m_device, &framebufferInfo, nullptr, &image.m_frameBuffer));
- }
-
- return SLANG_OK;
-}
-
-void VulkanSwapChain::_destroyFrameBuffers()
-{
- for (Index i = 0; i < m_images.getCount(); ++i)
- {
- Image& image = m_images[i];
- if (image.m_frameBuffer != VK_NULL_HANDLE)
- {
- m_api->vkDestroyFramebuffer(m_api->m_device, image.m_frameBuffer, nullptr);
- image.m_frameBuffer = VK_NULL_HANDLE;
- }
- }
-}
-
-SlangResult VulkanSwapChain::createFrameBuffers(VkRenderPass renderPass)
-{
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _destroyFrameBuffers();
- m_renderPass = VK_NULL_HANDLE;
- }
- if (renderPass != VK_NULL_HANDLE)
- {
- SLANG_RETURN_ON_FAIL(_createFrameBuffers(renderPass));
- }
- m_renderPass = renderPass;
- return SLANG_OK;
-}
-
SlangResult VulkanSwapChain::_createSwapChain()
{
if (hasValidSwapChain())
@@ -215,7 +162,7 @@ SlangResult VulkanSwapChain::_createSwapChain()
{
int numCheckPresentOptions = 3;
VkPresentModeKHR presentOptions[] = { VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR };
- if (m_vsync)
+ if (m_desc.m_vsync)
{
presentOptions[0] = VK_PRESENT_MODE_FIFO_KHR;
presentOptions[1] = VK_PRESENT_MODE_IMMEDIATE_KHR;
@@ -245,7 +192,7 @@ SlangResult VulkanSwapChain::_createSwapChain()
VkSwapchainCreateInfoKHR swapchainDesc = {};
swapchainDesc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainDesc.surface = m_surface;
- swapchainDesc.minImageCount = 3;
+ swapchainDesc.minImageCount = m_desc.m_imageCount;
swapchainDesc.imageFormat = m_format;
swapchainDesc.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
swapchainDesc.imageExtent = imageExtent;
@@ -262,7 +209,7 @@ SlangResult VulkanSwapChain::_createSwapChain()
uint32_t numSwapChainImages = 0;
m_api->vkGetSwapchainImagesKHR(m_api->m_device, m_swapChain, &numSwapChainImages, nullptr);
-
+ m_desc.m_imageCount = numSwapChainImages;
{
List<VkImage> images;
images.setCount(numSwapChainImages);
@@ -272,45 +219,9 @@ SlangResult VulkanSwapChain::_createSwapChain()
m_images.setCount(numSwapChainImages);
for (int i = 0; i < int(numSwapChainImages); ++i)
{
- Image& dstImage = m_images[i];
- dstImage.m_image = images[i];
-
+ m_images[i] = images[i];
}
}
-
- {
- VkImageViewCreateInfo createInfo = {};
- createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
-
- createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- createInfo.format = m_format;
-
- createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
-
- createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- createInfo.subresourceRange.baseMipLevel = 0;
- createInfo.subresourceRange.levelCount = 1;
- createInfo.subresourceRange.baseArrayLayer = 0;
- createInfo.subresourceRange.layerCount = 1;
-
- for (int i = 0; i < int(numSwapChainImages); ++i)
- {
- Image& image = m_images[i];
-
- createInfo.image = image.m_image;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateImageView(m_api->m_device, &createInfo, nullptr, &image.m_imageView));
- }
- }
-
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _createFrameBuffers(m_renderPass);
- }
-
return SLANG_OK;
}
@@ -323,21 +234,6 @@ void VulkanSwapChain::_destroySwapChain()
m_deviceQueue->waitForIdle();
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _destroyFrameBuffers();
- }
-
- for (Index i = 0; i < m_images.getCount(); ++i)
- {
- Image& image = m_images[i];
-
- if (image.m_imageView != VK_NULL_HANDLE)
- {
- m_api->vkDestroyImageView(m_api->m_device, image.m_imageView, nullptr);
- }
- }
-
if (m_swapChain != VK_NULL_HANDLE)
{
m_api->vkDestroySwapchainKHR(m_api->m_device, m_swapChain, nullptr);
@@ -397,7 +293,7 @@ void VulkanSwapChain::present(bool vsync)
return;
}
- VkSemaphore endFrameSemaphore = m_deviceQueue->makeCurrent(VulkanDeviceQueue::EventType::EndFrame);
+ VkSemaphore endFrameSemaphore = m_deviceQueue->getSemaphore(VulkanDeviceQueue::EventType::EndFrame);
m_deviceQueue->flushStepA();
@@ -408,18 +304,19 @@ void VulkanSwapChain::present(bool vsync)
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &m_swapChain;
presentInfo.pImageIndices = swapChainIndices;
- presentInfo.waitSemaphoreCount = 1;
- presentInfo.pWaitSemaphores = &endFrameSemaphore;
-
+ if (endFrameSemaphore != VK_NULL_HANDLE)
+ {
+ presentInfo.waitSemaphoreCount = 1;
+ presentInfo.pWaitSemaphores = &endFrameSemaphore;
+ }
VkResult result = m_api->vkQueuePresentKHR(m_deviceQueue->getQueue(), &presentInfo);
m_deviceQueue->makeCompleted(VulkanDeviceQueue::EventType::EndFrame);
m_deviceQueue->flushStepB();
- if (result != VK_SUCCESS || m_vsync != vsync)
+ if (result != VK_SUCCESS)
{
- m_vsync = vsync;
_destroySwapChain();
}
}
diff --git a/tools/gfx/vulkan/vk-swap-chain.h b/tools/gfx/vulkan/vk-swap-chain.h
index e5162d63b..0a2a40b4f 100644
--- a/tools/gfx/vulkan/vk-swap-chain.h
+++ b/tools/gfx/vulkan/vk-swap-chain.h
@@ -44,29 +44,21 @@ struct VulkanSwapChain
m_depthFormatTypeless = Format::Unknown;
m_depthFormat = Format::Unknown;
m_textureDepthFormat = Format::Unknown;
+ m_imageCount = 2;
+ m_vsync = false;
}
Format m_format;
- //bool m_enableFormat;
Format m_depthFormatTypeless;
Format m_depthFormat;
Format m_textureDepthFormat;
+ uint32_t m_imageCount;
+ bool m_vsync;
};
- struct Image
- {
- VkImage m_image = VK_NULL_HANDLE;
- VkImageView m_imageView = VK_NULL_HANDLE;
- VkFramebuffer m_frameBuffer = VK_NULL_HANDLE;
- };
-
-
/// Must be called before the swap chain can be used
SlangResult init(VulkanDeviceQueue* deviceQueue, const Desc& desc, const PlatformDesc* platformDesc);
- /// Create the frame buffers (they must be compatible with the supplied renderPass)
- SlangResult createFrameBuffers(VkRenderPass renderPass);
-
/// Returned the desc used to construct the swap chain.
/// Is invalid if init hasn't returned with successful result.
const Desc& getDesc() const { return m_desc; }
@@ -89,7 +81,7 @@ struct VulkanSwapChain
int getHeight() const { return m_height; }
/// Get the detail about the images
- const Slang::List<Image>& getImages() const { return m_images; }
+ const Slang::List<VkImage>& getImages() const { return m_images; }
/// Get the next front render image index. Returns -1, if image couldn't be found
int nextFrontImageIndex();
@@ -114,10 +106,7 @@ struct VulkanSwapChain
const T* _getPlatformDesc() const { return static_cast<const T*>((const PlatformDesc*)m_platformDescBuffer.getBuffer()); }
SlangResult _createSwapChain();
void _destroySwapChain();
- SlangResult _createFrameBuffers(VkRenderPass renderPass);
- void _destroyFrameBuffers();
- bool m_vsync = true;
int m_width = 0;
int m_height = 0;
@@ -127,11 +116,9 @@ struct VulkanSwapChain
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSwapchainKHR m_swapChain = VK_NULL_HANDLE;
- VkRenderPass m_renderPass = VK_NULL_HANDLE; //< Not owned
-
int m_currentSwapChainIndex = 0;
- Slang::List<Image> m_images;
+ Slang::List<VkImage> m_images;
VulkanDeviceQueue* m_deviceQueue = nullptr;
const VulkanApi* m_api = nullptr;
diff --git a/tools/gfx/vulkan/vk-util.cpp b/tools/gfx/vulkan/vk-util.cpp
index e8940d1b2..561b97a53 100644
--- a/tools/gfx/vulkan/vk-util.cpp
+++ b/tools/gfx/vulkan/vk-util.cpp
@@ -15,6 +15,7 @@ namespace gfx {
case Format::RG_Float32: return VK_FORMAT_R32G32_SFLOAT;
case Format::R_Float32: return VK_FORMAT_R32_SFLOAT;
case Format::RGBA_Unorm_UInt8: return VK_FORMAT_R8G8B8A8_UNORM;
+ case Format::BGRA_Unorm_UInt8: return VK_FORMAT_B8G8R8A8_UNORM;
case Format::R_UInt32: return VK_FORMAT_R32_UINT;
case Format::D_Float32: return VK_FORMAT_D32_SFLOAT;
diff --git a/tools/graphics-app-framework/gui.cpp b/tools/graphics-app-framework/gui.cpp
index 3bc365701..0d416ec85 100644
--- a/tools/graphics-app-framework/gui.cpp
+++ b/tools/graphics-app-framework/gui.cpp
@@ -36,7 +36,7 @@ void setNativeWindowHook(Window* window, WNDPROC proc);
#endif
-GUI::GUI(Window* window, IRenderer* inRenderer)
+GUI::GUI(Window* window, IRenderer* inRenderer, IFramebufferLayout* framebufferLayout)
: renderer(inRenderer)
{
ImGui::CreateContext();
@@ -188,7 +188,7 @@ GUI::GUI(Window* window, IRenderer* inRenderer)
targetBlendDesc.alpha.dstFactor = BlendFactor::Zero;
GraphicsPipelineStateDesc pipelineDesc;
- pipelineDesc.renderTargetCount = 1;
+ pipelineDesc.framebufferLayout = framebufferLayout;
pipelineDesc.program = program;
pipelineDesc.pipelineLayout = pipelineLayout;
pipelineDesc.inputLayout = inputLayout;
@@ -367,7 +367,7 @@ void GUI::endFrame()
renderer->setScissorRect(rect);
// TODO: This should be a dynamic/transient descriptor set...
- auto descriptorSet = renderer->createDescriptorSet(descriptorSetLayout);
+ auto descriptorSet = renderer->createDescriptorSet(descriptorSetLayout, gfx::IDescriptorSet::Flag::Transient);
descriptorSet->setConstantBuffer(0, 0, constantBuffer);
descriptorSet->setResource(1, 0,
(gfx::IResourceView*) command->TextureId);
diff --git a/tools/graphics-app-framework/gui.h b/tools/graphics-app-framework/gui.h
index 3ef2b0ba5..22b4bf2f5 100644
--- a/tools/graphics-app-framework/gui.h
+++ b/tools/graphics-app-framework/gui.h
@@ -12,7 +12,7 @@ namespace gfx {
struct GUI : Slang::RefObject
{
- GUI(Window* window, IRenderer* renderer);
+ GUI(Window* window, IRenderer* renderer, IFramebufferLayout* framebufferLayout);
~GUI();
void beginFrame();
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index 7bf7dd369..42c14a557 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -80,11 +80,10 @@ struct ShaderOutputPlan
List<Item> items;
};
-class RenderTestApp : public WindowListener
+class RenderTestApp : public RefObject
{
public:
- // WindowListener
- virtual Result update(Window* window) SLANG_OVERRIDE;
+ Result update();
// At initialization time, we are going to load and compile our Slang shader
// code, and then create the API objects we need for rendering.
@@ -110,7 +109,7 @@ protected:
IRenderer* renderer,
Options::ShaderProgramType shaderType,
const ShaderCompilerUtil::Input& input);
-
+ void _initializeFramebuffer();
virtual void finalizeImpl();
uint64_t m_startTicks;
@@ -124,6 +123,9 @@ protected:
ComPtr<IBufferResource> m_vertexBuffer;
ComPtr<IShaderProgram> m_shaderProgram;
ComPtr<IPipelineState> m_pipelineState;
+ ComPtr<IFramebufferLayout> m_framebufferLayout;
+ ComPtr<IFramebuffer> m_framebuffer;
+ ComPtr<ITextureResource> m_colorBuffer;
ShaderCompilerUtil::OutputAndLayout m_compilationOutput;
@@ -472,10 +474,13 @@ SlangResult LegacyRenderTestApp::initialize(
{
m_options = options;
+ m_renderer = renderer;
+
SLANG_RETURN_ON_FAIL(_initializeShaders(session, renderer, options.shaderType, input));
+ _initializeFramebuffer();
+
m_numAddedConstantBuffers = 0;
- m_renderer = renderer;
// TODO(tfoley): use each API's reflection interface to query the constant-buffer size needed
m_constantBufferSize = 16 * sizeof(float);
@@ -557,14 +562,12 @@ SlangResult LegacyRenderTestApp::initialize(
desc.pipelineLayout = m_bindingState->pipelineLayout;
desc.program = m_shaderProgram;
desc.inputLayout = m_inputLayout;
- desc.renderTargetCount = m_bindingState->m_numRenderTargets;
-
+ desc.framebufferLayout = m_framebufferLayout;
m_pipelineState = renderer->createGraphicsPipelineState(desc);
}
break;
}
}
-
// If success must have a pipeline state
return m_pipelineState ? SLANG_OK : SLANG_FAIL;
}
@@ -604,6 +607,8 @@ SlangResult ShaderObjectRenderTestApp::initialize(
m_renderer = renderer;
+ _initializeFramebuffer();
+
{
switch(m_options.shaderType)
{
@@ -649,13 +654,12 @@ SlangResult ShaderObjectRenderTestApp::initialize(
GraphicsPipelineStateDesc desc;
desc.program = m_shaderProgram;
desc.inputLayout = inputLayout;
-
+ desc.framebufferLayout = m_framebufferLayout;
m_pipelineState = renderer->createGraphicsPipelineState(desc);
}
break;
}
}
-
// If success must have a pipeline state
return m_pipelineState ? SLANG_OK : SLANG_FAIL;
}
@@ -678,6 +682,61 @@ Result RenderTestApp::_initializeShaders(
return m_shaderProgram ? SLANG_OK : SLANG_FAIL;
}
+void RenderTestApp::_initializeFramebuffer()
+{
+ gfx::ITextureResource::Desc depthBufferDesc;
+ depthBufferDesc.setDefaults(gfx::IResource::Usage::DepthWrite);
+ depthBufferDesc.init2D(
+ gfx::IResource::Type::Texture2D,
+ gfx::Format::D_Float32,
+ gWindowWidth,
+ gWindowHeight,
+ 0);
+
+ ComPtr<gfx::ITextureResource> depthBufferResource = m_renderer->createTextureResource(
+ gfx::IResource::Usage::DepthWrite, depthBufferDesc, nullptr);
+
+ gfx::ITextureResource::Desc colorBufferDesc;
+ colorBufferDesc.setDefaults(gfx::IResource::Usage::RenderTarget);
+ colorBufferDesc.init2D(
+ gfx::IResource::Type::Texture2D,
+ gfx::Format::RGBA_Unorm_UInt8,
+ gWindowWidth,
+ gWindowHeight,
+ 0);
+ m_colorBuffer = m_renderer->createTextureResource(
+ gfx::IResource::Usage::RenderTarget, colorBufferDesc, nullptr);
+
+ gfx::IResourceView::Desc colorBufferViewDesc;
+ memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc));
+ colorBufferViewDesc.format = gfx::Format::RGBA_Unorm_UInt8;
+ colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D;
+ colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget;
+ ComPtr<gfx::IResourceView> rtv =
+ m_renderer->createTextureView(m_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 =
+ m_renderer->createTextureView(depthBufferResource.get(), depthBufferViewDesc);
+
+ IFramebufferLayout::AttachmentLayout colorAttachment = {gfx::Format::RGBA_Unorm_UInt8, 1};
+ IFramebufferLayout::AttachmentLayout depthAttachment = {gfx::Format::D_Float32, 1};
+ gfx::IFramebufferLayout::Desc framebufferLayoutDesc;
+ framebufferLayoutDesc.renderTargetCount = 1;
+ framebufferLayoutDesc.renderTargets = &colorAttachment;
+ framebufferLayoutDesc.depthStencil = &depthAttachment;
+ m_renderer->createFramebufferLayout(framebufferLayoutDesc, m_framebufferLayout.writeRef());
+ gfx::IFramebuffer::Desc framebufferDesc;
+ framebufferDesc.renderTargetCount = 1;
+ framebufferDesc.depthStencilView = dsv.get();
+ framebufferDesc.renderTargetViews = rtv.readRef();
+ framebufferDesc.layout = m_framebufferLayout;
+ m_renderer->createFramebuffer(framebufferDesc, m_framebuffer.writeRef());
+}
void LegacyRenderTestApp::setProjectionMatrix()
{
@@ -843,14 +902,10 @@ Result ShaderObjectRenderTestApp::writeBindingOutput(BindRoot* bindRoot, const c
Result RenderTestApp::writeScreen(const char* filename)
{
- size_t rowPitch, bufferSize, pixelSize;
- List<uint8_t> buffer;
-
- SLANG_RETURN_ON_FAIL(m_renderer->captureScreenSurface(nullptr, &bufferSize, &rowPitch, &pixelSize));
- buffer.setCount(bufferSize);
- SLANG_RETURN_ON_FAIL(
- m_renderer->captureScreenSurface(buffer.getBuffer(), &bufferSize, &rowPitch, &pixelSize));
-
+ size_t rowPitch, pixelSize;
+ ComPtr<ISlangBlob> blob;
+ SLANG_RETURN_ON_FAIL(m_renderer->readTextureResource(m_colorBuffer, blob.writeRef(), &rowPitch, &pixelSize));
+ auto bufferSize = blob->getBufferSize();
Surface surface;
size_t width = rowPitch / pixelSize;
size_t height = bufferSize / rowPitch;
@@ -859,12 +914,14 @@ Result RenderTestApp::writeScreen(const char* filename)
(int)height,
gfx::Format::RGBA_Unorm_UInt8,
(int)rowPitch,
- buffer.getBuffer());
+ (void*)blob->getBufferPointer());
return PngSerializeUtil::write(filename, surface);
}
-Result RenderTestApp::update(Window* window)
+Result RenderTestApp::update()
{
+ m_renderer->beginFrame();
+
// Whenever we don't have Windows events to process, we render a frame.
if (m_options.shaderType == Options::ShaderProgramType::Compute)
{
@@ -873,9 +930,16 @@ Result RenderTestApp::update(Window* window)
else
{
static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
+ m_renderer->setFramebuffer(m_framebuffer);
+
+ gfx::Viewport viewport = {};
+ viewport.maxZ = 1.0f;
+ viewport.extentX = (float)gWindowWidth;
+ viewport.extentY = (float)gWindowHeight;
+ m_renderer->setViewportAndScissor(viewport);
+
m_renderer->setClearColor(kClearColor);
m_renderer->clearFrame();
-
renderFrame();
}
@@ -947,12 +1011,10 @@ Result RenderTestApp::update(Window* window)
}
}
}
- // We are done
- window->postQuit();
return SLANG_OK;
}
- m_renderer->presentFrame();
+ m_renderer->endFrame();
return SLANG_OK;
}
@@ -999,9 +1061,6 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi
// Parse command-line options
SLANG_RETURN_ON_FAIL(Options::parse(argcIn, argvIn, StdWriters::getError(), options));
- // Declare window pointer before renderer, such that window is released after renderer
- RefPtr<renderer_test::Window> window;
-
ShaderCompilerUtil::Input input;
input.profile = "";
@@ -1281,8 +1340,6 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi
{
IRenderer::Desc desc = {};
desc.rendererType = options.rendererType;
- desc.width = gWindowWidth;
- desc.height = gWindowHeight;
desc.adapter = options.adapter.getBuffer();
List<const char*> requiredFeatureList;
@@ -1294,16 +1351,9 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi
desc.nvapiExtnSlot = int(nvapiExtnSlot);
desc.slang.slangGlobalSession = session;
- window = renderer_test::Window::create();
- void* windowHandle = nullptr;
- if (window)
- {
- SLANG_RETURN_ON_FAIL(window->initialize(gWindowWidth, gWindowHeight));
- windowHandle = window->getHandle();
- }
{
- SlangResult res = gfxCreateRenderer(&desc, windowHandle, renderer.writeRef());
+ SlangResult res = gfxCreateRenderer(&desc, renderer.writeRef());
if (SLANG_FAILED(res))
{
// We need to be careful here about SLANG_E_NOT_AVAILABLE. This return value means that the renderer couldn't
@@ -1351,8 +1401,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi
else
app = new LegacyRenderTestApp();
SLANG_RETURN_ON_FAIL(app->initialize(session, renderer, options, input));
- window->show();
- SLANG_RETURN_ON_FAIL(window->runLoop(app));
+ app->update();
app->finalize();
return SLANG_OK;
}
diff --git a/tools/render-test/shader-renderer-util.cpp b/tools/render-test/shader-renderer-util.cpp
index ad3812ae3..5b3867848 100644
--- a/tools/render-test/shader-renderer-util.cpp
+++ b/tools/render-test/shader-renderer-util.cpp
@@ -283,7 +283,7 @@ ComPtr<ISamplerState> _createSamplerState(IRenderer* renderer,
auto pipelineLayout = renderer->createPipelineLayout(pipelineLayoutDesc);
if(!pipelineLayout) return SLANG_FAIL;
- auto descriptorSet = renderer->createDescriptorSet(descriptorSetLayout);
+ auto descriptorSet = renderer->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient);
if(!descriptorSet) return SLANG_FAIL;
List<BindingStateImpl::OutputBinding> outputBindings;
diff --git a/tools/slang-test/test-reporter.cpp b/tools/slang-test/test-reporter.cpp
index fd9748b28..4a7c76c4c 100644
--- a/tools/slang-test/test-reporter.cpp
+++ b/tools/slang-test/test-reporter.cpp
@@ -314,28 +314,38 @@ void TestReporter::_addResult(const TestInfo& info)
m_testInfos.add(info);
- // printf("OUTPUT_MODE: %d\n", options.outputMode);
- switch (m_outputMode)
+ auto defaultOutputFunc = [](const TestInfo& info)
{
+ char const* resultString = "UNEXPECTED";
+ switch (info.testResult)
+ {
+ case TestResult::Fail:
+ resultString = "FAILED";
+ break;
+ case TestResult::Pass:
+ resultString = "passed";
+ break;
+ case TestResult::Ignored:
+ resultString = "ignored";
+ break;
default:
+ assert(!"unexpected");
+ break;
+ }
+
+ StringBuilder buffer;
+ if (info.executionTime > 0.0f)
{
- char const* resultString = "UNEXPECTED";
- switch (info.testResult)
- {
- case TestResult::Fail: resultString = "FAILED"; break;
- case TestResult::Pass: resultString = "passed"; break;
- case TestResult::Ignored: resultString = "ignored"; break;
- default:
- assert(!"unexpected");
- break;
- }
+ _appendTime(info.executionTime, buffer);
+ }
+ printf("%s test: '%S' %s\n", resultString, info.name.toWString().begin(), buffer.getBuffer());
+ };
- StringBuilder buffer;
- if (info.executionTime > 0.0f)
- {
- _appendTime(info.executionTime, buffer);
- }
- printf("%s test: '%S' %s\n", resultString, info.name.toWString().begin(), buffer.getBuffer());
+ switch (m_outputMode)
+ {
+ default:
+ {
+ defaultOutputFunc(info);
break;
}
case TestOutputMode::TeamCity:
@@ -464,7 +474,7 @@ void TestReporter::_addResult(const TestInfo& info)
exeRes.standardError.begin());
#endif
}
-
+ defaultOutputFunc(info);
break;
}
}