diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml
index 1fd95f890..87f213567 100644
--- a/.github/workflows/build-nightly.yml
+++ b/.github/workflows/build-nightly.yml
@@ -101,47 +101,53 @@ jobs:
WickedEngineEditor
-# linux-steamdeck:
-# runs-on: ubuntu-latest
-# steps:
-# - uses: actions/checkout@v2
-#
-# - name: Build
-# run: |
-# mkdir build
-# echo "---Building Command Strings---"
-# echo -e "#!/bin/bash \
-# \nmkdir -p $(dirname $PWD) \
-# \nln -s /build $PWD \
-# \ncd /build/build \
-# \ncmake .. -DCMAKE_BUILD_TYPE=Release \
-# \nmake \
-# \necho \"---Generating Shader Dump---\" \
-# \ncd WickedEngine \
-# \n./offlineshadercompiler spirv rebuild shaderdump\nmv wiShaderDump.h ../../WickedEngine/ \
-# \necho \"---Rebuilding with ShaderDump---\" \
-# \ncd .. \
-# \nmake -B" > build.sh
-# chmod +x build.sh
-# echo "---Executing Containerized Build---"
-# podman run --name sniper -v $PWD:/build registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest /build/build.sh
-# podman container rm sniper
-#
-# - name: Move files
-# run: |
-# mv build/Editor/WickedEngineEditor ./
-# mv Editor/config.ini ./
-# mv Editor/startup.lua ./
-# mv Editor/terrain ./
-# mv Content/Documentation ./
-#
-# - name: Package Editor
-# uses: actions/upload-artifact@v2
-# with:
-# name: Editor (Linux - Steam Deck)
-# path: |
-# Documentation/
-# terrain/
-# config.ini
-# startup.lua
-# WickedEngineEditor
+ linux-steamdeck:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install dependencies
+ run: |
+ sudo apt update
+ sudo apt install libsdl2-dev
+ sudo apt install libncurses5
+
+ - name: Build
+ run: |
+ mkdir build
+ echo "---Building Command Strings---"
+ echo -e "#!/bin/bash \
+ \nmkdir -p $(dirname $PWD) \
+ \nln -s /build $PWD \
+ \ncd /build/build \
+ \ncmake .. -DCMAKE_BUILD_TYPE=Release \
+ \nmake \
+ \necho \"---Generating Shader Dump---\" \
+ \ncd WickedEngine \
+ \n./offlineshadercompiler spirv rebuild shaderdump\nmv wiShaderDump.h ../../WickedEngine/ \
+ \necho \"---Rebuilding with ShaderDump---\" \
+ \ncd .. \
+ \nmake -B" > build.sh
+ chmod +x build.sh
+ echo "---Executing Containerized Build---"
+ podman run --name sniper -v $PWD:/build registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest /build/build.sh
+ podman container rm sniper
+
+ - name: Move files
+ run: |
+ mv build/Editor/WickedEngineEditor ./
+ mv Editor/config.ini ./
+ mv Editor/startup.lua ./
+ mv Editor/terrain ./
+ mv Content/Documentation ./
+
+ - name: Package Editor
+ uses: actions/upload-artifact@v2
+ with:
+ name: Editor (Linux - Steam Deck)
+ path: |
+ Documentation/
+ terrain/
+ config.ini
+ startup.lua
+ WickedEngineEditor
diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml
index 50af4449f..bd6f83547 100644
--- a/.github/workflows/build-pr.yml
+++ b/.github/workflows/build-pr.yml
@@ -101,47 +101,53 @@ jobs:
WickedEngineEditor
-# linux-steamdeck:
-# runs-on: ubuntu-latest
-# steps:
-# - uses: actions/checkout@v2
-#
-# - name: Build
-# run: |
-# mkdir build
-# echo "---Building Command Strings---"
-# echo -e "#!/bin/bash \
-# \nmkdir -p $(dirname $PWD) \
-# \nln -s /build $PWD \
-# \ncd /build/build \
-# \ncmake .. -DCMAKE_BUILD_TYPE=Release \
-# \nmake \
-# \necho \"---Generating Shader Dump---\" \
-# \ncd WickedEngine \
-# \n./offlineshadercompiler spirv rebuild shaderdump\nmv wiShaderDump.h ../../WickedEngine/ \
-# \necho \"---Rebuilding with ShaderDump---\" \
-# \ncd .. \
-# \nmake -B" > build.sh
-# chmod +x build.sh
-# echo "---Executing Containerized Build---"
-# podman run --name sniper -v $PWD:/build registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest /build/build.sh
-# podman container rm sniper
-#
-# - name: Move files
-# run: |
-# mv build/Editor/WickedEngineEditor ./
-# mv Editor/config.ini ./
-# mv Editor/startup.lua ./
-# mv Editor/terrain ./
-# mv Content/Documentation ./
-#
-# - name: Package Editor
-# uses: actions/upload-artifact@v2
-# with:
-# name: Editor (Linux - Steam Deck)
-# path: |
-# Documentation/
-# terrain/
-# config.ini
-# startup.lua
-# WickedEngineEditor
+ linux-steamdeck:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install dependencies
+ run: |
+ sudo apt update
+ sudo apt install libsdl2-dev
+ sudo apt install libncurses5
+
+ - name: Build
+ run: |
+ mkdir build
+ echo "---Building Command Strings---"
+ echo -e "#!/bin/bash \
+ \nmkdir -p $(dirname $PWD) \
+ \nln -s /build $PWD \
+ \ncd /build/build \
+ \ncmake .. -DCMAKE_BUILD_TYPE=Release \
+ \nmake \
+ \necho \"---Generating Shader Dump---\" \
+ \ncd WickedEngine \
+ \n./offlineshadercompiler spirv rebuild shaderdump\nmv wiShaderDump.h ../../WickedEngine/ \
+ \necho \"---Rebuilding with ShaderDump---\" \
+ \ncd .. \
+ \nmake -B" > build.sh
+ chmod +x build.sh
+ echo "---Executing Containerized Build---"
+ podman run --name sniper -v $PWD:/build registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest /build/build.sh
+ podman container rm sniper
+
+ - name: Move files
+ run: |
+ mv build/Editor/WickedEngineEditor ./
+ mv Editor/config.ini ./
+ mv Editor/startup.lua ./
+ mv Editor/terrain ./
+ mv Content/Documentation ./
+
+ - name: Package Editor
+ uses: actions/upload-artifact@v2
+ with:
+ name: Editor (Linux - Steam Deck)
+ path: |
+ Documentation/
+ terrain/
+ config.ini
+ startup.lua
+ WickedEngineEditor
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4f3e6be2b..7d612cb68 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -102,47 +102,53 @@ jobs:
WickedEngineEditor
-# linux-steamdeck:
-# runs-on: ubuntu-latest
-# steps:
-# - uses: actions/checkout@v2
-#
-# - name: Build
-# run: |
-# mkdir build
-# echo "---Building Command Strings---"
-# echo -e "#!/bin/bash \
-# \nmkdir -p $(dirname $PWD) \
-# \nln -s /build $PWD \
-# \ncd /build/build \
-# \ncmake .. -DCMAKE_BUILD_TYPE=Release \
-# \nmake \
-# \necho \"---Generating Shader Dump---\" \
-# \ncd WickedEngine \
-# \n./offlineshadercompiler spirv rebuild shaderdump\nmv wiShaderDump.h ../../WickedEngine/ \
-# \necho \"---Rebuilding with ShaderDump---\" \
-# \ncd .. \
-# \nmake -B" > build.sh
-# chmod +x build.sh
-# echo "---Executing Containerized Build---"
-# podman run --name sniper -v $PWD:/build registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest /build/build.sh
-# podman container rm sniper
-#
-# - name: Move files
-# run: |
-# mv build/Editor/WickedEngineEditor ./
-# mv Editor/config.ini ./
-# mv Editor/startup.lua ./
-# mv Editor/terrain ./
-# mv Content/Documentation ./
-#
-# - name: Package Editor
-# uses: actions/upload-artifact@v2
-# with:
-# name: Editor (Linux - Steam Deck)
-# path: |
-# Documentation/
-# terrain/
-# config.ini
-# startup.lua
-# WickedEngineEditor
+ linux-steamdeck:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install dependencies
+ run: |
+ sudo apt update
+ sudo apt install libsdl2-dev
+ sudo apt install libncurses5
+
+ - name: Build
+ run: |
+ mkdir build
+ echo "---Building Command Strings---"
+ echo -e "#!/bin/bash \
+ \nmkdir -p $(dirname $PWD) \
+ \nln -s /build $PWD \
+ \ncd /build/build \
+ \ncmake .. -DCMAKE_BUILD_TYPE=Release \
+ \nmake \
+ \necho \"---Generating Shader Dump---\" \
+ \ncd WickedEngine \
+ \n./offlineshadercompiler spirv rebuild shaderdump\nmv wiShaderDump.h ../../WickedEngine/ \
+ \necho \"---Rebuilding with ShaderDump---\" \
+ \ncd .. \
+ \nmake -B" > build.sh
+ chmod +x build.sh
+ echo "---Executing Containerized Build---"
+ podman run --name sniper -v $PWD:/build registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest /build/build.sh
+ podman container rm sniper
+
+ - name: Move files
+ run: |
+ mv build/Editor/WickedEngineEditor ./
+ mv Editor/config.ini ./
+ mv Editor/startup.lua ./
+ mv Editor/terrain ./
+ mv Content/Documentation ./
+
+ - name: Package Editor
+ uses: actions/upload-artifact@v2
+ with:
+ name: Editor (Linux - Steam Deck)
+ path: |
+ Documentation/
+ terrain/
+ config.ini
+ startup.lua
+ WickedEngineEditor
diff --git a/Content/Documentation/WickedEngine-Documentation.md b/Content/Documentation/WickedEngine-Documentation.md
index bf4d96903..4c6e4f95e 100644
--- a/Content/Documentation/WickedEngine-Documentation.md
+++ b/Content/Documentation/WickedEngine-Documentation.md
@@ -607,19 +607,22 @@ Shaders still need to be created with `GraphicsDevice::CreateShader()` in a simi
Depending on the graphics device implementation, the shader code must be different format. For example, DirectX expects DXIL shaders, Vulkan expects SPIR-V shaders. The engine can compile HLSL shader source code to DXIL or SPIRV format with the [Shader Compiler](#shader-compiler).
-##### Render Passes
-Render passes are defining regions in GPU execution where a number of render targets or depth buffers will be used to render into them. Render targets and depth buffers are defined as `RenderPassAttachment`s. The `RenderPassAttachment`s have a pointer to the texture, state the resource type (`RENDERTARGET`, `DEPTH_STENCIL` or `RESOLVE`), state the [subresource](#subresources) index, the load and store operations, and the layout transitions for the textures.
+Note: As an optional paramter, `CreatePipelineState()` function also accepts a `RenderPassInfo` pointer. If this is provided, then all the information will be available for pipeline creation to happen immediately. This means the pipeline will be immediately in final usable state after the function returns, but it can take longer time for this to complete. If the parameter is not provided, the pipeline could be created at a later time, when the render pass information is available on first use. This can have the effect of the longer pipeline compilation happening at an unexpected time. But in this case, the pipeline will also be compatible with more render pass types if it's used at different places.
-- `RENDERTARGET`: The attachment will be used as a (color) render target. The order of these attachments define the shader color output order.
-- `DEPTH_STENCIL`: The attachment will be used as a depth (and/or stencil) buffer.
-- `RESOLVE`: The attachment will be used as MSAA resolve destination. The resolve source is chosen among the `RENDERTARGET` attachments in the same render pass, in the order they were declared in. The declaration order of the `RENDERTARGET` and `RESOLVE` attachment must match to correctly deduce source and destination targets for resolve operations.
+##### Render Passes
+Render passes are defining regions in GPU execution where a number of render targets or depth buffers will be used to render into them. Render targets and depth buffers are defined as `RenderPassImage`s. The `RenderPassImage`s have a pointer to the texture, state the resource type (`RENDERTARGET`, `DEPTH_STENCIL` or `RESOLVE`), state the [subresource](#subresources) index, the load and store operations, and the layout transitions for the textures.
+
+- `RENDERTARGET`: The image will be used as a (color) render target. The order of these images define the shader color output order.
+- `DEPTH_STENCIL`: The image will be used as a depth (and/or stencil) buffer.
+- `RESOLVE`: The image will be used as MSAA resolve destination. The resolve source is chosen among the `RENDERTARGET` images in the same render pass, in the order they were declared in. The declaration order of the `RENDERTARGET` and `RESOLVE` images must match to correctly deduce source and destination targets for resolve operations.
+- `RESOLVE_DEPTH` same as `RESOLVE` but for depth stencil. You can also specify Min or Max resolve operation with the `RenderPassImage::DepthResolveMode` enum. This feature must be supported by GPU and indicated by `GraphicsDeviceCapability::DEPTH_RESOLVE_MIN_MAX` and `GraphicsDeviceCapability::STENCIL_RESOLVE_MIN_MAX` (if image also has stencil)
- Load Operation:
Defines how the texture contents are initialized at the start of the render pass. `LoadOp::LOAD` says that the previous texture content will be retained. `LoadOp::CLEAR` says that the previous contents of the texture will be lost and instead the texture clear color will be used to fill the texture. `LoadOp::DONTCARE` says that the texture contents are undefined, so this should only be used when the developer can ensure that the whole texture will be rendered to and not leaving any region empty (in which case, undefined results will be present in the texture).
- Store operation:
Defines how the texture contents are handled after the render pass ends. `StoreOp::STORE` means that the contents will be preserved. `StoreOp::DONTCARE` means that the contents won't be necessarily preserved, they are only temporarily valid within the duration of the render pass, which can save some memory bandwidth on some platforms (specifically tile based rendering architectures, like mobile GPUs).
- Layout transition:
-Define the `intial_layout`, `subpass_layout` (only for `RENDERTARGET` or `DEPTH_STENCIL`) and `final_layout` members to have an implicit transition performed as part of the render pass, that works like an [IMAGE_BARRIER](#gpu-barriers), but can be more optimal. The `initial_layout` states the starting state of the resource. The resource will be transitioned from `initial_layout` to `subpass_layout` within the render pass. The `subpass_layout` states how the resource is accessed within the render pass. For `RENDERTARGET`, this must be `RENDERTARGET`, for `DEPTH_STENCIL` type, it must be either `DEPTHSTENCIL` or `DEPTHSTENCIL_READONLY`. For `RESOLVE` type, the subpass_layout have no meaning, it is implicitly defined. At the end of the render pass, the resources will be transitioned from `subpass_layout` to `final_layout`.
+Define the `layout_before`, `layout` (only for `DEPTH_STENCIL`) and `layout_after` members to have an implicit transition performed as part of the render pass, that works like an [IMAGE_BARRIER](#gpu-barriers), but can be more optimal. The `layout_before` states the starting state of the resource. The resource will be transitioned from `layout_before` to `layout` within the render pass. The `layout` states how the resource is accessed within the render pass. For `DEPTH_STENCIL` type, it must be either `DEPTHSTENCIL` or `DEPTHSTENCIL_READONLY`. For `RESOLVE` type, the subpass_layout have no meaning, it is implicitly defined. At the end of the render pass, the resources will be transitioned from `layout` to `layout_after`.
Notes:
- When `RenderPassBegin()` is called, `RenderPassEnd()` must be called after on the same command list before the command list gets [submitted](#work-submission).
diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp
index c1cb6350e..ac5f0234f 100644
--- a/Editor/Editor.cpp
+++ b/Editor/Editor.cpp
@@ -123,40 +123,6 @@ void EditorComponent::ResizeBuffers()
assert(success);
success = device->CreateTexture(&desc, nullptr, &rt_selectionOutline[1]);
assert(success);
-
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rt_selectionOutline[0], RenderPassAttachment::LoadOp::CLEAR));
- if (renderPath->getMSAASampleCount() > 1)
- {
- desc.attachments[0].texture = rt_selectionOutline_MSAA;
- desc.attachments.push_back(RenderPassAttachment::Resolve(rt_selectionOutline[0]));
- }
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- *renderPath->GetDepthStencil(),
- RenderPassAttachment::LoadOp::LOAD,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY
- )
- );
-
- success = device->CreateRenderPass(&desc, &renderpass_selectionOutline[0]);
- assert(success);
-
- if (renderPath->getMSAASampleCount() == 1)
- {
- desc.attachments[0].texture = rt_selectionOutline[1]; // rendertarget
- }
- else
- {
- desc.attachments[1].texture = rt_selectionOutline[1]; // resolve
- }
- success = device->CreateRenderPass(&desc, &renderpass_selectionOutline[1]);
- assert(success);
- }
}
{
@@ -169,25 +135,6 @@ void EditorComponent::ResizeBuffers()
desc.misc_flags = ResourceMiscFlag::TRANSIENT_ATTACHMENT;
device->CreateTexture(&desc, nullptr, &editor_depthbuffer);
device->SetName(&editor_depthbuffer, "editor_depthbuffer");
-
- {
- RenderPassDesc desc;
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- editor_depthbuffer,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::DONTCARE
- )
- );
- desc.attachments.push_back(
- RenderPassAttachment::RenderTarget(
- renderPath->GetRenderResult(),
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE
- )
- );
- device->CreateRenderPass(&desc, &renderpass_editor);
- }
}
}
void EditorComponent::ResizeLayout()
@@ -1909,7 +1856,37 @@ void EditorComponent::Render() const
// Materials outline:
{
- device->RenderPassBegin(&renderpass_selectionOutline[0], cmd);
+ if (renderPath->getMSAASampleCount() > 1)
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rt_selectionOutline_MSAA, RenderPassImage::LoadOp::CLEAR, RenderPassImage::StoreOp::DONTCARE),
+ RenderPassImage::Resolve(&rt_selectionOutline[0]),
+ RenderPassImage::DepthStencil(
+ renderPath->GetDepthStencil(),
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
+ else
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rt_selectionOutline[0], RenderPassImage::LoadOp::CLEAR),
+ RenderPassImage::DepthStencil(
+ renderPath->GetDepthStencil(),
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
// Draw solid blocks of selected materials
fx.stencilRef = EDITORSTENCILREF_HIGHLIGHT_MATERIAL;
@@ -1920,7 +1897,37 @@ void EditorComponent::Render() const
// Objects outline:
{
- device->RenderPassBegin(&renderpass_selectionOutline[1], cmd);
+ if (renderPath->getMSAASampleCount() > 1)
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rt_selectionOutline_MSAA, RenderPassImage::LoadOp::CLEAR, RenderPassImage::StoreOp::DONTCARE),
+ RenderPassImage::Resolve(&rt_selectionOutline[1]),
+ RenderPassImage::DepthStencil(
+ renderPath->GetDepthStencil(),
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
+ else
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rt_selectionOutline[1], RenderPassImage::LoadOp::CLEAR),
+ RenderPassImage::DepthStencil(
+ renderPath->GetDepthStencil(),
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
// Draw solid blocks of selected objects
fx.stencilRef = EDITORSTENCILREF_HIGHLIGHT_OBJECT;
@@ -1934,7 +1941,20 @@ void EditorComponent::Render() const
// Full resolution:
{
- device->RenderPassBegin(&renderpass_editor, cmd);
+ const Texture& render_result = renderPath->GetRenderResult();
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(
+ &render_result,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE
+ ),
+ RenderPassImage::DepthStencil(
+ &editor_depthbuffer,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::DONTCARE
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
Viewport vp;
vp.width = (float)editor_depthbuffer.GetDesc().width;
diff --git a/Editor/Editor.h b/Editor/Editor.h
index f39eebc2d..f9273a348 100644
--- a/Editor/Editor.h
+++ b/Editor/Editor.h
@@ -72,14 +72,12 @@ public:
};
wi::graphics::Texture rt_selectionOutline_MSAA;
wi::graphics::Texture rt_selectionOutline[2];
- wi::graphics::RenderPass renderpass_selectionOutline[2];
float selectionOutlineTimer = 0;
const XMFLOAT4 selectionColor = XMFLOAT4(1, 0.6f, 0, 1);
const XMFLOAT4 selectionColor2 = XMFLOAT4(0, 1, 0.6f, 0.35f);
wi::Color inactiveEntityColor = wi::Color::fromFloat4(XMFLOAT4(1, 1, 1, 0.5f));
wi::Color hoveredEntityColor = wi::Color::fromFloat4(XMFLOAT4(1, 1, 1, 1));
- wi::graphics::RenderPass renderpass_editor;
wi::graphics::Texture editor_depthbuffer;
Translator translator;
diff --git a/WickedEngine/wiApplication.cpp b/WickedEngine/wiApplication.cpp
index 6eb7b3790..a5df492df 100644
--- a/WickedEngine/wiApplication.cpp
+++ b/WickedEngine/wiApplication.cpp
@@ -199,7 +199,10 @@ namespace wi
if (colorspace_conversion_required)
{
// In HDR10, we perform the compositing in a custom linear color space render target
- graphicsDevice->RenderPassBegin(&renderpass, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rendertarget, RenderPassImage::LoadOp::CLEAR),
+ };
+ graphicsDevice->RenderPassBegin(rp, arraysize(rp), cmd);
}
else
{
@@ -593,11 +596,6 @@ namespace wi
bool success = graphicsDevice->CreateTexture(&desc, nullptr, &rendertarget);
assert(success);
graphicsDevice->SetName(&rendertarget, "Application::rendertarget");
-
- RenderPassDesc renderpassdesc;
- renderpassdesc.attachments.push_back(RenderPassAttachment::RenderTarget(rendertarget, RenderPassAttachment::LoadOp::CLEAR));
- success = graphicsDevice->CreateRenderPass(&renderpassdesc, &renderpass);
- assert(success);
}
}
diff --git a/WickedEngine/wiApplication.h b/WickedEngine/wiApplication.h
index 656f92b6b..88f8ae030 100644
--- a/WickedEngine/wiApplication.h
+++ b/WickedEngine/wiApplication.h
@@ -42,7 +42,6 @@ namespace wi
// These are used when HDR10 color space is active:
// Because we want to blend in linear color space, but HDR10 is non-linear
wi::graphics::Texture rendertarget;
- wi::graphics::RenderPass renderpass;
std::string infodisplay_str;
diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h
index ccfdd70de..ae789f7aa 100644
--- a/WickedEngine/wiGraphics.h
+++ b/WickedEngine/wiGraphics.h
@@ -382,11 +382,9 @@ namespace wi::graphics
SPARSE_TEXTURE3D = 1 << 15,
SPARSE_NULL_MAPPING = 1 << 16,
GENERIC_SPARSE_TILE_POOL = 1 << 17, // alows using ResourceMiscFlag::SPARSE_TILE_POOL (non resource type specific version)
- DEPTH_RESOLVE_SAMPLE_ZERO = 1 << 18,
- STENCIL_RESOLVE_SAMPLE_ZERO = 1 << 19,
- DEPTH_RESOLVE_MIN_MAX = 1 << 20,
- STENCIL_RESOLVE_MIN_MAX = 1 << 21,
- CACHE_COHERENT_UMA = 1 << 22, // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_feature_data_architecture
+ DEPTH_RESOLVE_MIN_MAX = 1 << 18,
+ STENCIL_RESOLVE_MIN_MAX = 1 << 19,
+ CACHE_COHERENT_UMA = 1 << 20, // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_feature_data_architecture
};
enum class ResourceState
@@ -421,6 +419,14 @@ namespace wi::graphics
HDR_LINEAR, // HDR color space (16 bits per channel)
};
+ enum class RenderPassFlags
+ {
+ NONE = 0,
+ ALLOW_UAV_WRITES = 1 << 0,
+ SUSPENDING = 1 << 1,
+ RESUMING = 1 << 2,
+ };
+
// Descriptor structs:
@@ -787,7 +793,7 @@ namespace wi::graphics
constexpr const TextureDesc& GetDesc() const { return desc; }
};
- struct RenderPassAttachment
+ struct RenderPassImage
{
enum class Type
{
@@ -803,133 +809,182 @@ namespace wi::graphics
CLEAR,
DONTCARE,
} loadop = LoadOp::LOAD;
- Texture texture;
+ const Texture* texture = nullptr;
int subresource = -1;
enum class StoreOp
{
STORE,
DONTCARE,
} storeop = StoreOp::STORE;
- ResourceState initial_layout = ResourceState::UNDEFINED; // layout before the render pass
- ResourceState subpass_layout = ResourceState::UNDEFINED; // layout within the render pass
- ResourceState final_layout = ResourceState::UNDEFINED; // layout after the render pass
+ ResourceState layout_before = ResourceState::UNDEFINED; // layout before the render pass
+ ResourceState layout = ResourceState::UNDEFINED; // layout within the render pass
+ ResourceState layout_after = ResourceState::UNDEFINED; // layout after the render pass
enum class DepthResolveMode
{
Min,
Max,
} depth_resolve_mode = DepthResolveMode::Min;
- static RenderPassAttachment RenderTarget(
- const Texture& resource,
+ static RenderPassImage RenderTarget(
+ const Texture* resource,
LoadOp load_op = LoadOp::LOAD,
StoreOp store_op = StoreOp::STORE,
- ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
- ResourceState subpass_layout = ResourceState::RENDERTARGET,
- ResourceState final_layout = ResourceState::SHADER_RESOURCE,
+ ResourceState layout_before = ResourceState::SHADER_RESOURCE,
+ ResourceState layout_after = ResourceState::SHADER_RESOURCE,
int subresource_RTV = -1
)
{
- RenderPassAttachment attachment;
- attachment.type = Type::RENDERTARGET;
- attachment.texture = resource;
- attachment.loadop = load_op;
- attachment.storeop = store_op;
- attachment.initial_layout = initial_layout;
- attachment.subpass_layout = subpass_layout;
- attachment.final_layout = final_layout;
- attachment.subresource = subresource_RTV;
- return attachment;
+ RenderPassImage image;
+ image.type = Type::RENDERTARGET;
+ image.texture = resource;
+ image.loadop = load_op;
+ image.storeop = store_op;
+ image.layout_before = layout_before;
+ image.layout = ResourceState::RENDERTARGET;
+ image.layout_after = layout_after;
+ image.subresource = subresource_RTV;
+ return image;
}
- static RenderPassAttachment DepthStencil(
- const Texture& resource,
+ static RenderPassImage DepthStencil(
+ const Texture* resource,
LoadOp load_op = LoadOp::LOAD,
StoreOp store_op = StoreOp::STORE,
- ResourceState initial_layout = ResourceState::DEPTHSTENCIL,
- ResourceState subpass_layout = ResourceState::DEPTHSTENCIL,
- ResourceState final_layout = ResourceState::DEPTHSTENCIL,
+ ResourceState layout_before = ResourceState::DEPTHSTENCIL,
+ ResourceState layout = ResourceState::DEPTHSTENCIL,
+ ResourceState layout_after = ResourceState::DEPTHSTENCIL,
int subresource_DSV = -1
)
{
- RenderPassAttachment attachment;
- attachment.type = Type::DEPTH_STENCIL;
- attachment.texture = resource;
- attachment.loadop = load_op;
- attachment.storeop = store_op;
- attachment.initial_layout = initial_layout;
- attachment.subpass_layout = subpass_layout;
- attachment.final_layout = final_layout;
- attachment.subresource = subresource_DSV;
- return attachment;
+ RenderPassImage image;
+ image.type = Type::DEPTH_STENCIL;
+ image.texture = resource;
+ image.loadop = load_op;
+ image.storeop = store_op;
+ image.layout_before = layout_before;
+ image.layout = layout;
+ image.layout_after = layout_after;
+ image.subresource = subresource_DSV;
+ return image;
}
- static RenderPassAttachment Resolve(
- const Texture& resource,
- ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
- ResourceState final_layout = ResourceState::SHADER_RESOURCE,
+ static RenderPassImage Resolve(
+ const Texture* resource,
+ ResourceState layout_before = ResourceState::SHADER_RESOURCE,
+ ResourceState layout_after = ResourceState::SHADER_RESOURCE,
int subresource_SRV = -1
)
{
- RenderPassAttachment attachment;
- attachment.type = Type::RESOLVE;
- attachment.texture = resource;
- attachment.initial_layout = initial_layout;
- attachment.final_layout = final_layout;
- attachment.subresource = subresource_SRV;
- return attachment;
+ RenderPassImage image;
+ image.type = Type::RESOLVE;
+ image.texture = resource;
+ image.layout_before = layout_before;
+ image.layout_after = layout_after;
+ image.subresource = subresource_SRV;
+ return image;
}
- static RenderPassAttachment ResolveDepth(
- const Texture& resource,
+ static RenderPassImage ResolveDepth(
+ const Texture* resource,
DepthResolveMode depth_resolve_mode = DepthResolveMode::Min,
- ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
- ResourceState final_layout = ResourceState::SHADER_RESOURCE,
+ ResourceState layout_before = ResourceState::SHADER_RESOURCE,
+ ResourceState layout_after = ResourceState::SHADER_RESOURCE,
int subresource_SRV = -1
)
{
- RenderPassAttachment attachment;
- attachment.type = Type::RESOLVE_DEPTH;
- attachment.texture = resource;
- attachment.initial_layout = initial_layout;
- attachment.final_layout = final_layout;
- attachment.subresource = subresource_SRV;
- attachment.depth_resolve_mode = depth_resolve_mode;
- return attachment;
+ RenderPassImage image;
+ image.type = Type::RESOLVE_DEPTH;
+ image.texture = resource;
+ image.layout_before = layout_before;
+ image.layout_after = layout_after;
+ image.subresource = subresource_SRV;
+ image.depth_resolve_mode = depth_resolve_mode;
+ return image;
}
- static RenderPassAttachment ShadingRateSource(
- const Texture& resource,
- ResourceState initial_layout = ResourceState::SHADING_RATE_SOURCE,
- ResourceState final_layout = ResourceState::SHADING_RATE_SOURCE
+ static RenderPassImage ShadingRateSource(
+ const Texture* resource,
+ ResourceState layout_before = ResourceState::SHADING_RATE_SOURCE,
+ ResourceState layout_after = ResourceState::SHADING_RATE_SOURCE
)
{
- RenderPassAttachment attachment;
- attachment.type = Type::SHADING_RATE_SOURCE;
- attachment.texture = resource;
- attachment.initial_layout = initial_layout;
- attachment.subpass_layout = ResourceState::SHADING_RATE_SOURCE;
- attachment.final_layout = final_layout;
- return attachment;
+ RenderPassImage image;
+ image.type = Type::SHADING_RATE_SOURCE;
+ image.texture = resource;
+ image.layout_before = layout_before;
+ image.layout = ResourceState::SHADING_RATE_SOURCE;
+ image.layout_after = layout_after;
+ return image;
}
};
- struct RenderPassDesc
+ struct RenderPassInfo
{
- enum class Flags
+ Format rt_formats[8] = {};
+ uint32_t rt_count = 0;
+ Format ds_format = Format::UNKNOWN;
+ uint32_t sample_count = 1;
+
+ constexpr uint64_t get_hash() const
{
- EMPTY = 0,
- ALLOW_UAV_WRITES = 1 << 0,
- };
- Flags flags = Flags::EMPTY;
- wi::vector attachments;
- };
-
- struct RenderPass : public GraphicsDeviceChild
- {
- size_t hash = 0;
- RenderPassDesc desc;
-
- constexpr const RenderPassDesc& GetDesc() const { return desc; }
+ union Hasher
+ {
+ struct
+ {
+ uint64_t rt_format_0 : 6;
+ uint64_t rt_format_1 : 6;
+ uint64_t rt_format_2 : 6;
+ uint64_t rt_format_3 : 6;
+ uint64_t rt_format_4 : 6;
+ uint64_t rt_format_5 : 6;
+ uint64_t rt_format_6 : 6;
+ uint64_t rt_format_7 : 6;
+ uint64_t ds_format : 6;
+ uint64_t sample_count : 3;
+ } bits;
+ uint64_t value;
+ } hasher = {};
+ static_assert(sizeof(Hasher) == sizeof(uint64_t));
+ hasher.bits.rt_format_0 = (uint64_t)rt_formats[0];
+ hasher.bits.rt_format_1 = (uint64_t)rt_formats[1];
+ hasher.bits.rt_format_2 = (uint64_t)rt_formats[2];
+ hasher.bits.rt_format_3 = (uint64_t)rt_formats[3];
+ hasher.bits.rt_format_4 = (uint64_t)rt_formats[4];
+ hasher.bits.rt_format_5 = (uint64_t)rt_formats[5];
+ hasher.bits.rt_format_6 = (uint64_t)rt_formats[6];
+ hasher.bits.rt_format_7 = (uint64_t)rt_formats[7];
+ hasher.bits.ds_format = (uint64_t)ds_format;
+ hasher.bits.sample_count = (uint64_t)sample_count;
+ return hasher.value;
+ }
+ static constexpr RenderPassInfo from(const RenderPassImage* images, uint32_t image_count)
+ {
+ RenderPassInfo info;
+ for (uint32_t i = 0; i < image_count; ++i)
+ {
+ const RenderPassImage& image = images[i];
+ const TextureDesc& desc = image.texture->GetDesc();
+ switch (image.type)
+ {
+ case RenderPassImage::Type::RENDERTARGET:
+ info.rt_formats[info.rt_count++] = desc.format;
+ info.sample_count = desc.sample_count;
+ break;
+ case RenderPassImage::Type::DEPTH_STENCIL:
+ info.ds_format = desc.format;
+ info.sample_count = desc.sample_count;
+ break;
+ }
+ }
+ return info;
+ }
+ static constexpr RenderPassInfo from(const SwapChainDesc& swapchain_desc)
+ {
+ RenderPassInfo info;
+ info.rt_count = 1;
+ info.rt_formats[0] = swapchain_desc.format;
+ return info;
+ }
};
struct GPUQueryHeap : public GraphicsDeviceChild
@@ -941,7 +996,6 @@ namespace wi::graphics
struct PipelineState : public GraphicsDeviceChild
{
- size_t hash = 0;
PipelineStateDesc desc;
constexpr const PipelineStateDesc& GetDesc() const { return desc; }
@@ -1388,6 +1442,218 @@ namespace wi::graphics
return ((value + alignment - 1) / alignment) * alignment;
}
+
+ // Deprecated, kept for back-compat:
+ struct RenderPassAttachment
+ {
+ enum class Type
+ {
+ RENDERTARGET,
+ DEPTH_STENCIL,
+ RESOLVE, // resolve render target (color)
+ RESOLVE_DEPTH,
+ SHADING_RATE_SOURCE
+ } type = Type::RENDERTARGET;
+ enum class LoadOp
+ {
+ LOAD,
+ CLEAR,
+ DONTCARE,
+ } loadop = LoadOp::LOAD;
+ Texture texture;
+ int subresource = -1;
+ enum class StoreOp
+ {
+ STORE,
+ DONTCARE,
+ } storeop = StoreOp::STORE;
+ ResourceState initial_layout = ResourceState::UNDEFINED; // layout before the render pass
+ ResourceState subpass_layout = ResourceState::UNDEFINED; // layout within the render pass
+ ResourceState final_layout = ResourceState::UNDEFINED; // layout after the render pass
+ enum class DepthResolveMode
+ {
+ Min,
+ Max,
+ } depth_resolve_mode = DepthResolveMode::Min;
+
+ static RenderPassAttachment RenderTarget(
+ const Texture& resource,
+ LoadOp load_op = LoadOp::LOAD,
+ StoreOp store_op = StoreOp::STORE,
+ ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
+ ResourceState subpass_layout = ResourceState::RENDERTARGET,
+ ResourceState final_layout = ResourceState::SHADER_RESOURCE,
+ int subresource_RTV = -1
+ )
+ {
+ RenderPassAttachment attachment;
+ attachment.type = Type::RENDERTARGET;
+ attachment.texture = resource;
+ attachment.loadop = load_op;
+ attachment.storeop = store_op;
+ attachment.initial_layout = initial_layout;
+ attachment.subpass_layout = subpass_layout;
+ attachment.final_layout = final_layout;
+ attachment.subresource = subresource_RTV;
+ return attachment;
+ }
+
+ static RenderPassAttachment DepthStencil(
+ const Texture& resource,
+ LoadOp load_op = LoadOp::LOAD,
+ StoreOp store_op = StoreOp::STORE,
+ ResourceState initial_layout = ResourceState::DEPTHSTENCIL,
+ ResourceState subpass_layout = ResourceState::DEPTHSTENCIL,
+ ResourceState final_layout = ResourceState::DEPTHSTENCIL,
+ int subresource_DSV = -1
+ )
+ {
+ RenderPassAttachment attachment;
+ attachment.type = Type::DEPTH_STENCIL;
+ attachment.texture = resource;
+ attachment.loadop = load_op;
+ attachment.storeop = store_op;
+ attachment.initial_layout = initial_layout;
+ attachment.subpass_layout = subpass_layout;
+ attachment.final_layout = final_layout;
+ attachment.subresource = subresource_DSV;
+ return attachment;
+ }
+
+ static RenderPassAttachment Resolve(
+ const Texture& resource,
+ ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
+ ResourceState final_layout = ResourceState::SHADER_RESOURCE,
+ int subresource_SRV = -1
+ )
+ {
+ RenderPassAttachment attachment;
+ attachment.type = Type::RESOLVE;
+ attachment.texture = resource;
+ attachment.initial_layout = initial_layout;
+ attachment.final_layout = final_layout;
+ attachment.subresource = subresource_SRV;
+ return attachment;
+ }
+
+ static RenderPassAttachment ResolveDepth(
+ const Texture& resource,
+ DepthResolveMode depth_resolve_mode = DepthResolveMode::Min,
+ ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
+ ResourceState final_layout = ResourceState::SHADER_RESOURCE,
+ int subresource_SRV = -1
+ )
+ {
+ RenderPassAttachment attachment;
+ attachment.type = Type::RESOLVE_DEPTH;
+ attachment.texture = resource;
+ attachment.initial_layout = initial_layout;
+ attachment.final_layout = final_layout;
+ attachment.subresource = subresource_SRV;
+ attachment.depth_resolve_mode = depth_resolve_mode;
+ return attachment;
+ }
+
+ static RenderPassAttachment ShadingRateSource(
+ const Texture& resource,
+ ResourceState initial_layout = ResourceState::SHADING_RATE_SOURCE,
+ ResourceState final_layout = ResourceState::SHADING_RATE_SOURCE
+ )
+ {
+ RenderPassAttachment attachment;
+ attachment.type = Type::SHADING_RATE_SOURCE;
+ attachment.texture = resource;
+ attachment.initial_layout = initial_layout;
+ attachment.subpass_layout = ResourceState::SHADING_RATE_SOURCE;
+ attachment.final_layout = final_layout;
+ return attachment;
+ }
+
+ constexpr operator RenderPassImage() const
+ {
+ RenderPassImage image;
+ switch (type)
+ {
+ default:
+ case Type::RENDERTARGET:
+ image.type = RenderPassImage::Type::RENDERTARGET;
+ break;
+ case Type::DEPTH_STENCIL:
+ image.type = RenderPassImage::Type::DEPTH_STENCIL;
+ break;
+ case Type::RESOLVE:
+ image.type = RenderPassImage::Type::RESOLVE;
+ break;
+ case Type::RESOLVE_DEPTH:
+ image.type = RenderPassImage::Type::RESOLVE_DEPTH;
+ break;
+ case Type::SHADING_RATE_SOURCE:
+ image.type = RenderPassImage::Type::SHADING_RATE_SOURCE;
+ break;
+ }
+ switch (depth_resolve_mode)
+ {
+ default:
+ case DepthResolveMode::Min:
+ image.depth_resolve_mode = RenderPassImage::DepthResolveMode::Min;
+ break;
+ case DepthResolveMode::Max:
+ image.depth_resolve_mode = RenderPassImage::DepthResolveMode::Max;
+ break;
+ }
+ switch (loadop)
+ {
+ case RenderPassAttachment::LoadOp::LOAD:
+ image.loadop = RenderPassImage::LoadOp::LOAD;
+ break;
+ case RenderPassAttachment::LoadOp::CLEAR:
+ image.loadop = RenderPassImage::LoadOp::CLEAR;
+ break;
+ case RenderPassAttachment::LoadOp::DONTCARE:
+ image.loadop = RenderPassImage::LoadOp::DONTCARE;
+ break;
+ default:
+ break;
+ }
+ switch (storeop)
+ {
+ case RenderPassAttachment::StoreOp::STORE:
+ image.storeop = RenderPassImage::StoreOp::STORE;
+ break;
+ case RenderPassAttachment::StoreOp::DONTCARE:
+ image.storeop = RenderPassImage::StoreOp::DONTCARE;
+ break;
+ default:
+ break;
+ }
+ image.layout_before = initial_layout;
+ image.layout = subpass_layout;
+ image.layout_after = final_layout;
+ image.texture = &texture;
+ image.subresource = subresource;
+ return image;
+ }
+ };
+ // Deprecated, kept for back-compat:
+ struct RenderPassDesc
+ {
+ enum class Flags
+ {
+ EMPTY = 0,
+ ALLOW_UAV_WRITES = 1 << 0,
+ };
+ Flags flags = Flags::EMPTY;
+ wi::vector attachments;
+ };
+ // Deprecated, kept for back-compat:
+ struct RenderPass
+ {
+ bool valid = false;
+ RenderPassDesc desc;
+
+ constexpr const RenderPassDesc& GetDesc() const { return desc; }
+ constexpr bool IsValid() const { return valid; }
+ };
}
template<>
@@ -1414,3 +1680,7 @@ template<>
struct enable_bitmask_operators {
static const bool enable = true;
};
+template<>
+struct enable_bitmask_operators {
+ static const bool enable = true;
+};
diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h
index 26c812141..146188bc2 100644
--- a/WickedEngine/wiGraphicsDevice.h
+++ b/WickedEngine/wiGraphicsDevice.h
@@ -73,8 +73,8 @@ namespace wi::graphics
virtual bool CreateShader(ShaderStage stage, const void* shadercode, size_t shadercode_size, Shader* shader) const = 0;
virtual bool CreateSampler(const SamplerDesc* desc, Sampler* sampler) const = 0;
virtual bool CreateQueryHeap(const GPUQueryHeapDesc* desc, GPUQueryHeap* queryheap) const = 0;
- virtual bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso) const = 0;
- virtual bool CreateRenderPass(const RenderPassDesc* desc, RenderPass* renderpass) const = 0;
+ // Creates a graphics pipeline state. If renderpass_info is specified, then it will be only compatible with that renderpass info, but it will be created immediately (it can also take longer to be created)
+ virtual bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info = nullptr) const = 0;
virtual bool CreateRaytracingAccelerationStructure(const RaytracingAccelerationStructureDesc* desc, RaytracingAccelerationStructure* bvh) const { return false; }
virtual bool CreateRaytracingPipelineState(const RaytracingPipelineStateDesc* desc, RaytracingPipelineState* rtpso) const { return false; }
@@ -172,7 +172,7 @@ namespace wi::graphics
virtual void WaitCommandList(CommandList cmd, CommandList wait_for) = 0;
virtual void RenderPassBegin(const SwapChain* swapchain, CommandList cmd) = 0;
- virtual void RenderPassBegin(const RenderPass* renderpass, CommandList cmd) = 0;
+ virtual void RenderPassBegin(const RenderPassImage* images, uint32_t image_count, CommandList cmd, RenderPassFlags flags = RenderPassFlags::NONE) = 0;
virtual void RenderPassEnd(CommandList cmd) = 0;
virtual void BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) = 0;
virtual void BindViewports(uint32_t NumViewports, const Viewport* pViewports, CommandList cmd) = 0;
@@ -223,6 +223,7 @@ namespace wi::graphics
virtual void EventEnd(CommandList cmd) = 0;
virtual void SetMarker(const char* name, CommandList cmd) = 0;
+ virtual RenderPassInfo GetRenderPassInfo(CommandList cmd) = 0;
// Some useful helpers:
@@ -307,6 +308,29 @@ namespace wi::graphics
std::memcpy(allocation.data, &data, sizeof(T));
BindConstantBuffer(&allocation.buffer, slot, cmd, allocation.offset);
}
+
+ // Deprecated, kept for back-compat:
+ bool CreateRenderPass(const RenderPassDesc* desc, RenderPass* renderpass) const
+ {
+ renderpass->valid = true;
+ renderpass->desc = *desc;
+ return true;
+ }
+ // Deprecated, kept for back-compat:
+ void RenderPassBegin(const RenderPass* renderpass, CommandList cmd)
+ {
+ RenderPassFlags flags = {};
+ if (has_flag(renderpass->desc.flags, RenderPassDesc::Flags::ALLOW_UAV_WRITES))
+ {
+ flags |= RenderPassFlags::ALLOW_UAV_WRITES;
+ }
+ RenderPassImage rp[32] = {};
+ for (size_t i = 0; i < renderpass->desc.attachments.size(); ++i)
+ {
+ rp[i] = renderpass->desc.attachments[i];
+ }
+ RenderPassBegin(rp, (uint32_t)renderpass->desc.attachments.size(), cmd, flags);
+ }
};
diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp
index 9e3de9850..badc696c4 100644
--- a/WickedEngine/wiGraphicsDevice_DX12.cpp
+++ b/WickedEngine/wiGraphicsDevice_DX12.cpp
@@ -26,6 +26,9 @@ using namespace Microsoft::WRL;
namespace wi::graphics
{
+// Note: pipeline library is disabled, because it is slower to use than not using it
+// There is driver-side caching that is much faster
+//#define PIPELINE_LIBRARY_ENABLED
namespace dx12_internal
{
@@ -1385,6 +1388,7 @@ namespace dx12_internal
std::shared_ptr allocationhandler;
ComPtr resource;
ComPtr rootSignature;
+ size_t hash = 0;
wi::vector shadercode;
wi::vector input_elements;
@@ -1459,21 +1463,6 @@ namespace dx12_internal
allocationhandler->destroylocker.unlock();
}
};
- struct RenderPass_DX12
- {
- wi::vector barrierdescs_begin;
- wi::vector barrierdescs_end;
-
- D3D12_RENDER_PASS_FLAGS flags = D3D12_RENDER_PASS_FLAG_NONE;
- uint32_t rt_count = 0;
- D3D12_RENDER_PASS_RENDER_TARGET_DESC RTVs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {};
- D3D12_RENDER_PASS_DEPTH_STENCIL_DESC DSV = {};
- Texture shading_rate_image;
-
- // Due to a API bug, this resolve_subresources array must be kept alive between BeginRenderpass() and EndRenderpass()!
- wi::vector resolve_subresources[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {};
- wi::vector resolve_subresources_dsv = {};
- };
struct SwapChain_DX12
{
std::shared_ptr allocationhandler;
@@ -1482,8 +1471,6 @@ namespace dx12_internal
wi::vector backbufferRTV;
Texture dummyTexture;
- RenderPass renderpass;
-
ColorSpace colorSpace = ColorSpace::SRGB;
~SwapChain_DX12()
@@ -1538,10 +1525,6 @@ namespace dx12_internal
{
return static_cast(param->internal_state.get());
}
- RenderPass_DX12* to_internal(const RenderPass* param)
- {
- return static_cast(param->internal_state.get());
- }
SwapChain_DX12* to_internal(const SwapChain* param)
{
return static_cast(param->internal_state.get());
@@ -1549,7 +1532,7 @@ namespace dx12_internal
inline const std::string GetCachePath()
{
- return wi::helper::GetTempDirectoryPath() + "WickedD3D12PipelineCache.data";
+ return wi::helper::GetTempDirectoryPath() + "wiPipelineCache_DX12";
}
inline void HashToName(uint64_t hash, std::wstring& name)
@@ -1981,7 +1964,6 @@ using namespace dx12_internal;
assert(dirty == 0ull); // check that all dirty root parameters were handled
}
-
void GraphicsDevice_DX12::pso_validate(CommandList cmd)
{
CommandList_DX12& commandlist = GetCommandList(cmd);
@@ -2011,38 +1993,17 @@ using namespace dx12_internal;
// make copy, mustn't overwrite internal_state from here!
PipelineState_DX12::PSO_STREAM stream = internal_state->stream;
- DXGI_FORMAT DSFormat = DXGI_FORMAT_UNKNOWN;
+ DXGI_FORMAT DSFormat = _ConvertFormat(commandlist.renderpass_info.ds_format);
D3D12_RT_FORMAT_ARRAY formats = {};
- formats.NumRenderTargets = 0;
- DXGI_SAMPLE_DESC sampleDesc = {};
- sampleDesc.Count = 1;
- sampleDesc.Quality = 0;
- for (auto& attachment : commandlist.active_renderpass->desc.attachments)
+ formats.NumRenderTargets = commandlist.renderpass_info.rt_count;
+ for (uint32_t i = 0; i < commandlist.renderpass_info.rt_count; ++i)
{
- if (attachment.type == RenderPassAttachment::Type::RESOLVE ||
- attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH ||
- attachment.type == RenderPassAttachment::Type::SHADING_RATE_SOURCE)
- continue;
-
-
- assert(attachment.texture.desc.format != Format::UNKNOWN);
- switch (attachment.type)
- {
- case RenderPassAttachment::Type::RENDERTARGET:
- formats.RTFormats[formats.NumRenderTargets] = _ConvertFormat(attachment.texture.desc.format);
- formats.NumRenderTargets++;
- break;
- case RenderPassAttachment::Type::DEPTH_STENCIL:
- DSFormat = _ConvertFormat(attachment.texture.desc.format);
- break;
- default:
- assert(0);
- break;
- }
-
- sampleDesc.Count = attachment.texture.desc.sample_count;
- sampleDesc.Quality = 0;
+ formats.RTFormats[i] = _ConvertFormat(commandlist.renderpass_info.rt_formats[i]);
}
+ DXGI_SAMPLE_DESC sampleDesc = {};
+ sampleDesc.Count = commandlist.renderpass_info.sample_count;
+ sampleDesc.Quality = 0;
+
stream.stream1.DSFormat = DSFormat;
stream.stream1.Formats = formats;
stream.stream1.SampleDesc = sampleDesc;
@@ -2056,25 +2017,33 @@ using namespace dx12_internal;
}
ComPtr newpso;
-#if defined(WICKED_DX12_USE_PIPELINE_LIBRARY)
- std::wstring name;
- HashToName(pipeline_hash, name);
- HRESULT hr = pipelineLibrary->LoadPipeline(name.c_str(), &streamDesc, IID_PPV_ARGS(&newpso));
+ HRESULT hr = E_INVALIDARG;
+ std::wstring name;
+
+ if (pipelineLibrary != nullptr)
+ {
+ HashToName(pipeline_hash, name);
+ pipelineLibraryLocker.lock(); // LoadPipeline must be synchronized: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device1-createpipelinelibrary#thread-safety
+ hr = pipelineLibrary->LoadPipeline(name.c_str(), &streamDesc, IID_PPV_ARGS(&newpso));
+ }
+
if (hr == E_INVALIDARG)
{
hr = device->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&newpso));
- if (SUCCEEDED(hr))
+ if (pipelineLibrary != nullptr && SUCCEEDED(hr))
{
hr = pipelineLibrary->StorePipeline(name.c_str(), newpso.Get());
}
}
-#else
- HRESULT hr = device->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&newpso));
-#endif
assert(SUCCEEDED(hr));
+ if (pipelineLibrary != nullptr)
+ {
+ pipelineLibraryLocker.unlock();
+ }
+
commandlist.pipelines_worker.push_back(std::make_pair(pipeline_hash, newpso));
pipeline = newpso.Get();
}
@@ -2351,14 +2320,13 @@ using namespace dx12_internal;
enabledSeverities.push_back(D3D12_MESSAGE_SEVERITY_INFO);
}
+ disabledMessages.push_back(D3D12_MESSAGE_ID_DRAW_EMPTY_SCISSOR_RECTANGLE);
disabledMessages.push_back(D3D12_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS);
disabledMessages.push_back(D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE);
-#if defined(WICKED_DX12_USE_PIPELINE_LIBRARY)
disabledMessages.push_back(D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_DRIVERVERSIONMISMATCH);
disabledMessages.push_back(D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_ADAPTERVERSIONMISMATCH);
disabledMessages.push_back(D3D12_MESSAGE_ID_LOADPIPELINE_NAMENOTFOUND);
-#endif
D3D12_INFO_QUEUE_FILTER filter = {};
filter.AllowList.NumSeverities = static_cast(enabledSeverities.size());
@@ -2565,8 +2533,6 @@ using namespace dx12_internal;
capabilities |= GraphicsDeviceCapability::TESSELLATION;
capabilities |= GraphicsDeviceCapability::PREDICATION;
- capabilities |= GraphicsDeviceCapability::DEPTH_RESOLVE_SAMPLE_ZERO;
- capabilities |= GraphicsDeviceCapability::STENCIL_RESOLVE_SAMPLE_ZERO;
capabilities |= GraphicsDeviceCapability::DEPTH_RESOLVE_MIN_MAX;
capabilities |= GraphicsDeviceCapability::STENCIL_RESOLVE_MIN_MAX;
@@ -2709,17 +2675,15 @@ using namespace dx12_internal;
}
// Create pipeline library:
-#if defined(WICKED_DX12_USE_PIPELINE_LIBRARY)
+#ifdef PIPELINE_LIBRARY_ENABLED
// Try to read pipeline cache file if exists.
- wi::vector pipelineData;
-
std::string cachePath = GetCachePath();
- if (!wi::helper::FileRead(cachePath, pipelineData))
+ if (!wi::helper::FileRead(cachePath, pipelineLibraryData))
{
- pipelineData.clear();
+ pipelineLibraryData.clear();
}
- hr = device->CreatePipelineLibrary(pipelineData.data(), pipelineData.size(), IID_PPV_ARGS(&pipelineLibrary));
+ hr = device->CreatePipelineLibrary(pipelineLibraryData.data(), pipelineLibraryData.size(), IID_PPV_ARGS(&pipelineLibrary));
switch (hr)
{
case DXGI_ERROR_UNSUPPORTED: // The driver doesn't support Pipeline libraries. WDDM2.1 drivers must support it.
@@ -2736,7 +2700,7 @@ using namespace dx12_internal;
assert(SUCCEEDED(hr));
break;
}
-#endif
+#endif // PIPELINE_LIBRARY_ENABLED
#ifndef PLATFORM_UWP
// Create fence to detect device removal
@@ -2921,16 +2885,18 @@ using namespace dx12_internal;
{
WaitForGPU();
-#if defined(WICKED_DX12_USE_PIPELINE_LIBRARY)
- std::vector serializedData(pipelineLibrary->GetSerializedSize());
- HRESULT hr = pipelineLibrary->Serialize(serializedData.data(), serializedData.size());
- if (SUCCEEDED(hr))
+ if (pipelineLibrary != nullptr)
{
- // Write pipeline cache data to a file in binary format
- std::string cachePath = GetCachePath();
- wi::helper::FileWrite(cachePath, serializedData.data(), serializedData.size());
+ std::vector serializedData(pipelineLibrary->GetSerializedSize());
+ HRESULT hr = pipelineLibrary->Serialize(serializedData.data(), serializedData.size());
+ assert(SUCCEEDED(hr));
+ if (SUCCEEDED(hr))
+ {
+ // Write pipeline cache data to a file in binary format
+ std::string cachePath = GetCachePath();
+ wi::helper::FileWrite(cachePath, serializedData.data(), serializedData.size());
+ }
}
-#endif
#ifndef PLATFORM_UWP
std::ignore = UnregisterWait(deviceRemovedWaitHandle);
@@ -3106,10 +3072,6 @@ using namespace dx12_internal;
internal_state->dummyTexture.desc.format = desc->format;
internal_state->dummyTexture.desc.width = desc->width;
internal_state->dummyTexture.desc.height = desc->height;
- internal_state->renderpass = {};
- wi::helper::hash_combine(internal_state->renderpass.hash, desc->format);
- internal_state->renderpass.desc.attachments.push_back(RenderPassAttachment::RenderTarget(internal_state->dummyTexture));
-
return true;
}
bool GraphicsDevice_DX12::CreateBuffer(const GPUBufferDesc* desc, const void* initial_data, GPUBuffer* buffer) const
@@ -3567,7 +3529,18 @@ using namespace dx12_internal;
shader->internal_state = internal_state;
internal_state->shadercode.resize(shadercode_size);
+ internal_state->hash = 0;
+#ifndef PIPELINE_LIBRARY_ENABLED
std::memcpy(internal_state->shadercode.data(), shadercode, shadercode_size);
+#else
+ // while copying over shader data, also compute hash for pipeline library serialization:
+ for (size_t i = 0; i < shadercode_size; ++i)
+ {
+ uint8_t byte = ((uint8_t*)shadercode)[i];
+ wi::helper::hash_combine(internal_state->hash, byte);
+ internal_state->shadercode[i] = byte;
+ }
+#endif // PIPELINE_LIBRARY_ENABLED
shader->stage = stage;
HRESULT hr = (internal_state->shadercode.empty() ? E_FAIL : S_OK);
@@ -3615,8 +3588,31 @@ using namespace dx12_internal;
streamDesc.pPipelineStateSubobjectStream = &stream;
streamDesc.SizeInBytes = sizeof(stream);
- hr = device->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&internal_state->resource));
+ HRESULT hr = E_INVALIDARG;
+
+ std::wstring name;
+ if (pipelineLibrary != nullptr)
+ {
+ HashToName(internal_state->hash, name);
+ pipelineLibraryLocker.lock(); // LoadPipeline must be synchronized: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device1-createpipelinelibrary#thread-safety
+ hr = pipelineLibrary->LoadPipeline(name.c_str(), &streamDesc, IID_PPV_ARGS(&internal_state->resource));
+ }
+
+ if (hr == E_INVALIDARG)
+ {
+ hr = device->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&internal_state->resource));
+
+ if (pipelineLibrary != nullptr && SUCCEEDED(hr))
+ {
+ hr = pipelineLibrary->StorePipeline(name.c_str(), internal_state->resource.Get());
+ }
+ }
assert(SUCCEEDED(hr));
+
+ if (pipelineLibrary != nullptr)
+ {
+ pipelineLibraryLocker.unlock();
+ }
}
return SUCCEEDED(hr);
@@ -3694,7 +3690,7 @@ using namespace dx12_internal;
return SUCCEEDED(hr);
}
- bool GraphicsDevice_DX12::CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso) const
+ bool GraphicsDevice_DX12::CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info) const
{
auto internal_state = std::make_shared();
internal_state->allocationhandler = allocationhandler;
@@ -3702,20 +3698,115 @@ using namespace dx12_internal;
pso->desc = *desc;
- pso->hash = 0;
- wi::helper::hash_combine(pso->hash, desc->ms);
- wi::helper::hash_combine(pso->hash, desc->as);
- wi::helper::hash_combine(pso->hash, desc->vs);
- wi::helper::hash_combine(pso->hash, desc->ps);
- wi::helper::hash_combine(pso->hash, desc->hs);
- wi::helper::hash_combine(pso->hash, desc->ds);
- wi::helper::hash_combine(pso->hash, desc->gs);
- wi::helper::hash_combine(pso->hash, desc->il);
- wi::helper::hash_combine(pso->hash, desc->rs);
- wi::helper::hash_combine(pso->hash, desc->bs);
- wi::helper::hash_combine(pso->hash, desc->dss);
- wi::helper::hash_combine(pso->hash, desc->pt);
- wi::helper::hash_combine(pso->hash, desc->sample_mask);
+#ifndef PIPELINE_LIBRARY_ENABLED
+ internal_state->hash = 0;
+ wi::helper::hash_combine(internal_state->hash, desc->ms);
+ wi::helper::hash_combine(internal_state->hash, desc->as);
+ wi::helper::hash_combine(internal_state->hash, desc->vs);
+ wi::helper::hash_combine(internal_state->hash, desc->ps);
+ wi::helper::hash_combine(internal_state->hash, desc->hs);
+ wi::helper::hash_combine(internal_state->hash, desc->ds);
+ wi::helper::hash_combine(internal_state->hash, desc->gs);
+ wi::helper::hash_combine(internal_state->hash, desc->il);
+ wi::helper::hash_combine(internal_state->hash, desc->rs);
+ wi::helper::hash_combine(internal_state->hash, desc->bs);
+ wi::helper::hash_combine(internal_state->hash, desc->dss);
+ wi::helper::hash_combine(internal_state->hash, desc->pt);
+ wi::helper::hash_combine(internal_state->hash, desc->sample_mask);
+#else
+ // Shouldn't hash pointers here, because hash can be serialized with pipeline library:
+ internal_state->hash = 0;
+ if (desc->ms != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, to_internal(desc->ms)->hash);
+ }
+ if (desc->as != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, to_internal(desc->as)->hash);
+ }
+ if (desc->vs != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, to_internal(desc->vs)->hash);
+ }
+ if (desc->ps != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, to_internal(desc->ps)->hash);
+ }
+ if (desc->hs != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, to_internal(desc->hs)->hash);
+ }
+ if (desc->ds != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, to_internal(desc->ds)->hash);
+ }
+ if (desc->gs != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, to_internal(desc->gs)->hash);
+ }
+ if (desc->il != nullptr)
+ {
+ for (auto& x : desc->il->elements)
+ {
+ wi::helper::hash_combine(internal_state->hash, x.format);
+ wi::helper::hash_combine(internal_state->hash, x.aligned_byte_offset);
+ wi::helper::hash_combine(internal_state->hash, x.input_slot);
+ wi::helper::hash_combine(internal_state->hash, x.input_slot_class);
+ wi::helper::hash_combine(internal_state->hash, x.semantic_index);
+ wi::helper::hash_combine(internal_state->hash, wi::helper::string_hash(x.semantic_name.c_str()));
+ }
+ }
+ if (desc->rs != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, desc->rs->antialiased_line_enable);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->conservative_rasterization_enable);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->cull_mode);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->depth_bias);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->depth_bias_clamp);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->depth_clip_enable);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->fill_mode);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->forced_sample_count);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->front_counter_clockwise);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->multisample_enable);
+ wi::helper::hash_combine(internal_state->hash, desc->rs->slope_scaled_depth_bias);
+ }
+ if (desc->bs != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, desc->bs->alpha_to_coverage_enable);
+ wi::helper::hash_combine(internal_state->hash, desc->bs->independent_blend_enable);
+ for (auto& x : desc->bs->render_target)
+ {
+ wi::helper::hash_combine(internal_state->hash, x.blend_enable);
+ wi::helper::hash_combine(internal_state->hash, x.blend_op);
+ wi::helper::hash_combine(internal_state->hash, x.blend_op_alpha);
+ wi::helper::hash_combine(internal_state->hash, x.dest_blend);
+ wi::helper::hash_combine(internal_state->hash, x.dest_blend_alpha);
+ wi::helper::hash_combine(internal_state->hash, x.render_target_write_mask);
+ wi::helper::hash_combine(internal_state->hash, x.src_blend);
+ wi::helper::hash_combine(internal_state->hash, x.src_blend_alpha);
+ }
+ }
+ if (desc->dss != nullptr)
+ {
+ wi::helper::hash_combine(internal_state->hash, desc->dss->depth_bounds_test_enable);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->depth_enable);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->depth_func);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->depth_write_mask);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->stencil_enable);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->stencil_read_mask);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->stencil_write_mask);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->front_face.stencil_depth_fail_op);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->front_face.stencil_fail_op);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->front_face.stencil_func);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->front_face.stencil_pass_op);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->back_face.stencil_depth_fail_op);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->back_face.stencil_fail_op);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->back_face.stencil_func);
+ wi::helper::hash_combine(internal_state->hash, desc->dss->back_face.stencil_pass_op);
+ }
+ wi::helper::hash_combine(internal_state->hash, desc->pt);
+ wi::helper::hash_combine(internal_state->hash, desc->sample_mask);
+#endif // PIPELINE_LIBRARY_ENABLED
auto& stream = internal_state->stream;
if (pso->desc.vs != nullptr)
@@ -3904,371 +3995,55 @@ using namespace dx12_internal;
stream.stream1.STRIP = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
- return true;
- }
- bool GraphicsDevice_DX12::CreateRenderPass(const RenderPassDesc* desc, RenderPass* renderpass) const
- {
- auto internal_state = std::make_shared();
- renderpass->internal_state = internal_state;
-
- renderpass->desc = *desc;
-
- if (has_flag(renderpass->desc.flags, RenderPassDesc::Flags::ALLOW_UAV_WRITES))
+ if (renderpass_info != nullptr)
{
- internal_state->flags |= D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES;
- }
-
- renderpass->hash = 0;
- wi::helper::hash_combine(renderpass->hash, desc->attachments.size());
- int resolve_dst_counter = 0;
- for (auto& attachment : desc->attachments)
- {
- if (attachment.type == RenderPassAttachment::Type::RENDERTARGET || attachment.type == RenderPassAttachment::Type::DEPTH_STENCIL)
+ wi::helper::hash_combine(internal_state->hash, renderpass_info->get_hash());
+ DXGI_FORMAT DSFormat = _ConvertFormat(renderpass_info->ds_format);
+ D3D12_RT_FORMAT_ARRAY formats = {};
+ formats.NumRenderTargets = renderpass_info->rt_count;
+ for (uint32_t i = 0; i < renderpass_info->rt_count; ++i)
{
- wi::helper::hash_combine(renderpass->hash, attachment.texture.desc.format);
- wi::helper::hash_combine(renderpass->hash, attachment.texture.desc.sample_count);
+ formats.RTFormats[i] = _ConvertFormat(renderpass_info->rt_formats[i]);
+ }
+ DXGI_SAMPLE_DESC sampleDesc = {};
+ sampleDesc.Count = renderpass_info->sample_count;
+ sampleDesc.Quality = 0;
+
+ stream.stream1.DSFormat = DSFormat;
+ stream.stream1.Formats = formats;
+ stream.stream1.SampleDesc = sampleDesc;
+
+ D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = {};
+ streamDesc.pPipelineStateSubobjectStream = &stream;
+ streamDesc.SizeInBytes = sizeof(stream.stream1);
+ if (CheckCapability(GraphicsDeviceCapability::MESH_SHADER))
+ {
+ streamDesc.SizeInBytes += sizeof(stream.stream2);
}
- const Texture* texture = &attachment.texture;
- int subresource = attachment.subresource;
- auto texture_internal = to_internal(texture);
-
- D3D12_CLEAR_VALUE clear_value;
- clear_value.Format = _ConvertFormat(texture->desc.format);
-
- if (attachment.type == RenderPassAttachment::Type::RENDERTARGET)
+ HRESULT hr = E_INVALIDARG;
+ std::wstring name;
+ if (pipelineLibrary != nullptr)
{
-
- if (subresource < 0 || texture_internal->subresources_rtv.empty())
- {
- internal_state->RTVs[internal_state->rt_count].cpuDescriptor = texture_internal->rtv.handle;
- }
- else
- {
- assert(texture_internal->subresources_rtv.size() > size_t(subresource) && "Invalid RTV subresource!");
- internal_state->RTVs[internal_state->rt_count].cpuDescriptor = texture_internal->subresources_rtv[subresource].handle;
- }
-
- switch (attachment.loadop)
- {
- default:
- case RenderPassAttachment::LoadOp::LOAD:
- internal_state->RTVs[internal_state->rt_count].BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
- break;
- case RenderPassAttachment::LoadOp::CLEAR:
- internal_state->RTVs[internal_state->rt_count].BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
- clear_value.Color[0] = texture->desc.clear.color[0];
- clear_value.Color[1] = texture->desc.clear.color[1];
- clear_value.Color[2] = texture->desc.clear.color[2];
- clear_value.Color[3] = texture->desc.clear.color[3];
- internal_state->RTVs[internal_state->rt_count].BeginningAccess.Clear.ClearValue = clear_value;
- break;
- case RenderPassAttachment::LoadOp::DONTCARE:
- internal_state->RTVs[internal_state->rt_count].BeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD;
- break;
- }
-
- switch (attachment.storeop)
- {
- default:
- case RenderPassAttachment::StoreOp::STORE:
- internal_state->RTVs[internal_state->rt_count].EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
- break;
- case RenderPassAttachment::StoreOp::DONTCARE:
- internal_state->RTVs[internal_state->rt_count].EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD;
- break;
- }
-
- internal_state->rt_count++;
+ HashToName(internal_state->hash, name);
+ pipelineLibraryLocker.lock(); // LoadPipeline must be synchronized: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device1-createpipelinelibrary#thread-safety
+ hr = pipelineLibrary->LoadPipeline(name.c_str(), &streamDesc, IID_PPV_ARGS(&internal_state->resource));
}
- else if (attachment.type == RenderPassAttachment::Type::DEPTH_STENCIL)
+
+ if (hr == E_INVALIDARG)
{
- if (subresource < 0 || texture_internal->subresources_dsv.empty())
- {
- internal_state->DSV.cpuDescriptor = texture_internal->dsv.handle;
- }
- else
- {
- assert(texture_internal->subresources_dsv.size() > size_t(subresource) && "Invalid DSV subresource!");
- internal_state->DSV.cpuDescriptor = texture_internal->subresources_dsv[subresource].handle;
- }
+ hr = device->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&internal_state->resource));
- switch (attachment.loadop)
+ if (pipelineLibrary != nullptr && SUCCEEDED(hr))
{
- default:
- case RenderPassAttachment::LoadOp::LOAD:
- internal_state->DSV.DepthBeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
- internal_state->DSV.StencilBeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
- break;
- case RenderPassAttachment::LoadOp::CLEAR:
- internal_state->DSV.DepthBeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
- internal_state->DSV.StencilBeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
- clear_value.DepthStencil.Depth = texture->desc.clear.depth_stencil.depth;
- clear_value.DepthStencil.Stencil = texture->desc.clear.depth_stencil.stencil;
- internal_state->DSV.DepthBeginningAccess.Clear.ClearValue = clear_value;
- internal_state->DSV.StencilBeginningAccess.Clear.ClearValue = clear_value;
- break;
- case RenderPassAttachment::LoadOp::DONTCARE:
- internal_state->DSV.DepthBeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD;
- internal_state->DSV.StencilBeginningAccess.Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD;
- break;
- }
-
- switch (attachment.storeop)
- {
- default:
- case RenderPassAttachment::StoreOp::STORE:
- internal_state->DSV.DepthEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
- internal_state->DSV.StencilEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
- break;
- case RenderPassAttachment::StoreOp::DONTCARE:
- internal_state->DSV.DepthEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD;
- internal_state->DSV.StencilEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD;
- break;
+ hr = pipelineLibrary->StorePipeline(name.c_str(), internal_state->resource.Get());
}
}
- else if (attachment.type == RenderPassAttachment::Type::RESOLVE)
+ assert(SUCCEEDED(hr));
+
+ if (pipelineLibrary != nullptr)
{
- if (texture != nullptr)
- {
- int resolve_src_counter = 0;
- for (auto& src : renderpass->desc.attachments)
- {
- if (src.type == RenderPassAttachment::Type::RENDERTARGET && src.texture.IsValid())
- {
- if (resolve_src_counter == resolve_dst_counter)
- {
- auto src_internal = to_internal(&src.texture);
- int src_subresource = src.subresource;
- const SingleDescriptor& src_descriptor = src_subresource < 0 ? src_internal->rtv : src_internal->subresources_rtv[src_subresource];
-
- D3D12_RENDER_PASS_RENDER_TARGET_DESC& src_RTV = internal_state->RTVs[resolve_src_counter];
- src_RTV.EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE;
- src_RTV.EndingAccess.Resolve.PreserveResolveSource = src.storeop == RenderPassAttachment::StoreOp::STORE ? TRUE : FALSE;
- src_RTV.EndingAccess.Resolve.Format = src_descriptor.rtv.Format;
- src_RTV.EndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_AVERAGE;
- src_RTV.EndingAccess.Resolve.pDstResource = texture_internal->resource.Get();
- src_RTV.EndingAccess.Resolve.pSrcResource = src_internal->resource.Get();
-
- const SingleDescriptor& dst_descriptor = subresource < 0 ? texture_internal->srv : texture_internal->subresources_srv[subresource];
- for (uint32_t mip = 0; mip < std::min(attachment.texture.desc.mip_levels, dst_descriptor.mipCount); ++mip)
- {
- for (uint32_t slice = 0; slice < std::min(attachment.texture.desc.array_size, dst_descriptor.sliceCount); ++slice)
- {
- D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS& params = internal_state->resolve_subresources[resolve_src_counter].emplace_back();
- params.SrcSubresource = D3D12CalcSubresource(src_descriptor.firstMip + mip, src_descriptor.firstSlice + slice, 0, src.texture.desc.mip_levels, src.texture.desc.array_size);
- params.DstSubresource = D3D12CalcSubresource(dst_descriptor.firstMip + mip, dst_descriptor.firstSlice + slice, 0, texture->desc.mip_levels, texture->desc.array_size);
- params.SrcRect.left = 0;
- params.SrcRect.top = 0;
- params.SrcRect.right = (LONG)texture->desc.width;
- params.SrcRect.bottom = (LONG)texture->desc.height;
- }
- }
- src_RTV.EndingAccess.Resolve.SubresourceCount = (UINT)internal_state->resolve_subresources[resolve_src_counter].size();
- src_RTV.EndingAccess.Resolve.pSubresourceParameters = internal_state->resolve_subresources[resolve_src_counter].data();
- break;
- }
- resolve_src_counter++;
- }
- }
- }
- resolve_dst_counter++;
- }
- else if (attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
- {
- if (texture != nullptr)
- {
- for (auto& src : renderpass->desc.attachments)
- {
- if (src.type == RenderPassAttachment::Type::DEPTH_STENCIL && src.texture.IsValid())
- {
- auto src_internal = to_internal(&src.texture);
- int src_subresource = src.subresource;
- const SingleDescriptor& src_descriptor = src_subresource < 0 ? src_internal->dsv : src_internal->subresources_dsv[src_subresource];
-
- D3D12_RENDER_PASS_DEPTH_STENCIL_DESC& src_DSV = internal_state->DSV;
- src_DSV.DepthEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE;
- src_DSV.DepthEndingAccess.Resolve.PreserveResolveSource = src.storeop == RenderPassAttachment::StoreOp::STORE ? TRUE : FALSE;
- src_DSV.DepthEndingAccess.Resolve.Format = src_descriptor.dsv.Format;
-
- switch (attachment.depth_resolve_mode)
- {
- default:
- case RenderPassAttachment::DepthResolveMode::Min:
- src_DSV.DepthEndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_MIN;
- break;
- case RenderPassAttachment::DepthResolveMode::Max:
- src_DSV.DepthEndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_MAX;
- break;
- }
-
- src_DSV.DepthEndingAccess.Resolve.pDstResource = texture_internal->resource.Get();
- src_DSV.DepthEndingAccess.Resolve.pSrcResource = src_internal->resource.Get();
-
- const SingleDescriptor& dst_descriptor = subresource < 0 ? texture_internal->srv : texture_internal->subresources_srv[subresource];
- for (uint32_t mip = 0; mip < std::min(attachment.texture.desc.mip_levels, dst_descriptor.mipCount); ++mip)
- {
- for (uint32_t slice = 0; slice < std::min(attachment.texture.desc.array_size, dst_descriptor.sliceCount); ++slice)
- {
- D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS& params = internal_state->resolve_subresources_dsv.emplace_back();
- params.SrcSubresource = D3D12CalcSubresource(src_descriptor.firstMip + mip, src_descriptor.firstSlice + slice, 0, src.texture.desc.mip_levels, src.texture.desc.array_size);
- params.DstSubresource = D3D12CalcSubresource(dst_descriptor.firstMip + mip, dst_descriptor.firstSlice + slice, 0, texture->desc.mip_levels, texture->desc.array_size);
- params.SrcRect.left = 0;
- params.SrcRect.top = 0;
- params.SrcRect.right = (LONG)texture->desc.width;
- params.SrcRect.bottom = (LONG)texture->desc.height;
- }
- }
- src_DSV.DepthEndingAccess.Resolve.SubresourceCount = (UINT)internal_state->resolve_subresources_dsv.size();
- src_DSV.DepthEndingAccess.Resolve.pSubresourceParameters = internal_state->resolve_subresources_dsv.data();
- if (IsFormatStencilSupport(attachment.texture.desc.format))
- {
- src_DSV.StencilBeginningAccess = src_DSV.DepthBeginningAccess;
- src_DSV.StencilEndingAccess = src_DSV.DepthEndingAccess;
- }
- break;
- }
- }
- }
- }
- else if (attachment.type == RenderPassAttachment::Type::SHADING_RATE_SOURCE)
- {
- internal_state->shading_rate_image = *texture;
- }
- }
-
-
- // Beginning barriers:
- for (auto& attachment : renderpass->desc.attachments)
- {
- if (!attachment.texture.IsValid())
- continue;
-
- D3D12_RESOURCE_STATES before = _ParseResourceState(attachment.initial_layout);
- D3D12_RESOURCE_STATES after = _ParseResourceState(attachment.subpass_layout);
- if (attachment.type == RenderPassAttachment::Type::RESOLVE || attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
- {
- after = D3D12_RESOURCE_STATE_RESOLVE_DEST;
- }
- if (before == after)
- continue;
-
- auto texture_internal = to_internal(&attachment.texture);
-
- D3D12_RESOURCE_BARRIER barrierdesc = {};
- barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrierdesc.Transition.pResource = texture_internal->resource.Get();
- barrierdesc.Transition.StateBefore = before;
- barrierdesc.Transition.StateAfter = after;
-
- if (attachment.subresource >= 0)
- {
- // Need to unroll descriptor into multiple subresource barriers:
- const SingleDescriptor* descriptor = nullptr;
- if (attachment.type == RenderPassAttachment::Type::RENDERTARGET)
- {
- descriptor = &texture_internal->subresources_rtv[attachment.subresource];
- }
- else if (attachment.type == RenderPassAttachment::Type::DEPTH_STENCIL)
- {
- descriptor = &texture_internal->subresources_dsv[attachment.subresource];
- }
- else if (attachment.type == RenderPassAttachment::Type::RESOLVE || attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
- {
- // Single barrier for whole resource:
- // From debug layer it looks like the resolve operation requires entire resource to be in RESOLVE_DEST
- barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
- internal_state->barrierdescs_begin.push_back(barrierdesc);
- continue;
- }
- else
- {
- assert(0); // not handled attachment type, this shouldn't happen
- continue;
- }
-
- for (uint32_t mip = descriptor->firstMip; mip < std::min(attachment.texture.desc.mip_levels, descriptor->firstMip + descriptor->mipCount); ++mip)
- {
- for (uint32_t slice = descriptor->firstSlice; slice < std::min(attachment.texture.desc.array_size, descriptor->firstSlice + descriptor->sliceCount); ++slice)
- {
- barrierdesc.Transition.Subresource = D3D12CalcSubresource(mip, slice, 0, attachment.texture.desc.mip_levels, attachment.texture.desc.array_size);
- internal_state->barrierdescs_begin.push_back(barrierdesc);
- }
- }
- }
- else
- {
- // Single barrier for whole resource:
- barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
- internal_state->barrierdescs_begin.push_back(barrierdesc);
- }
- }
-
- // Ending barriers:
- for (auto& attachment : renderpass->desc.attachments)
- {
- if (!attachment.texture.IsValid())
- continue;
-
- D3D12_RESOURCE_STATES before = _ParseResourceState(attachment.subpass_layout);
- D3D12_RESOURCE_STATES after = _ParseResourceState(attachment.final_layout);
- if (attachment.type == RenderPassAttachment::Type::RESOLVE || attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
- {
- before = D3D12_RESOURCE_STATE_RESOLVE_DEST;
- }
- if (before == after)
- continue;
-
- auto texture_internal = to_internal(&attachment.texture);
-
- D3D12_RESOURCE_BARRIER barrierdesc = {};
- barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrierdesc.Transition.pResource = texture_internal->resource.Get();
- barrierdesc.Transition.StateBefore = before;
- barrierdesc.Transition.StateAfter = after;
-
- if (attachment.subresource >= 0)
- {
- // Need to unroll descriptor into multiple subresource barriers:
- const SingleDescriptor* descriptor = nullptr;
- if (attachment.type == RenderPassAttachment::Type::RENDERTARGET)
- {
- descriptor = &texture_internal->subresources_rtv[attachment.subresource];
- }
- else if (attachment.type == RenderPassAttachment::Type::DEPTH_STENCIL)
- {
- descriptor = &texture_internal->subresources_dsv[attachment.subresource];
- }
- else if (attachment.type == RenderPassAttachment::Type::RESOLVE || attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
- {
- // Single barrier for whole resource:
- // From debug layer it looks like the resolve operation requires entire resource to be in RESOLVE_DEST
- barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
- internal_state->barrierdescs_end.push_back(barrierdesc);
- continue;
- }
- else
- {
- assert(0); // not handled attachment type, this shouldn't happen
- continue;
- }
-
- for (uint32_t mip = descriptor->firstMip; mip < std::min(attachment.texture.desc.mip_levels, descriptor->firstMip + descriptor->mipCount); ++mip)
- {
- for (uint32_t slice = descriptor->firstSlice; slice < std::min(attachment.texture.desc.array_size, descriptor->firstSlice + descriptor->sliceCount); ++slice)
- {
- barrierdesc.Transition.Subresource = D3D12CalcSubresource(mip, slice, 0, attachment.texture.desc.mip_levels, attachment.texture.desc.array_size);
- internal_state->barrierdescs_end.push_back(barrierdesc);
- }
- }
- }
- else
- {
- // Single barrier for whole resource:
- barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
- internal_state->barrierdescs_end.push_back(barrierdesc);
+ pipelineLibraryLocker.unlock();
}
}
@@ -5532,10 +5307,10 @@ using namespace dx12_internal;
void GraphicsDevice_DX12::RenderPassBegin(const SwapChain* swapchain, CommandList cmd)
{
CommandList_DX12& commandlist = GetCommandList(cmd);
+ commandlist.renderpass_barriers_begin.clear();
+ commandlist.renderpass_barriers_end.clear();
commandlist.swapchains.push_back(swapchain);
auto internal_state = to_internal(swapchain);
- commandlist.active_renderpass = &internal_state->renderpass;
- commandlist.active_backbuffer = internal_state->backBuffers[internal_state->swapChain->GetCurrentBackBufferIndex()];
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
@@ -5545,6 +5320,10 @@ using namespace dx12_internal;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
commandlist.GetGraphicsCommandList()->ResourceBarrier(1, &barrier);
+
+ barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
+ barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
+ commandlist.renderpass_barriers_end.push_back(barrier);
D3D12_RENDER_PASS_RENDER_TARGET_DESC RTV = {};
RTV.cpuDescriptor = internal_state->backbufferRTV[internal_state->swapChain->GetCurrentBackBufferIndex()];
@@ -5556,67 +5335,336 @@ using namespace dx12_internal;
RTV.EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
commandlist.GetGraphicsCommandList()->BeginRenderPass(1, &RTV, nullptr, D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES);
+ commandlist.renderpass_info = RenderPassInfo::from(swapchain->desc);
}
- void GraphicsDevice_DX12::RenderPassBegin(const RenderPass* renderpass, CommandList cmd)
+ void GraphicsDevice_DX12::RenderPassBegin(const RenderPassImage* images, uint32_t image_count, CommandList cmd, RenderPassFlags flags)
{
CommandList_DX12& commandlist = GetCommandList(cmd);
- commandlist.active_renderpass = renderpass;
+ commandlist.renderpass_barriers_begin.clear();
+ commandlist.renderpass_barriers_end.clear();
- auto internal_state = to_internal(commandlist.active_renderpass);
+ uint32_t rt_count = 0;
+ D3D12_RENDER_PASS_RENDER_TARGET_DESC RTVs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {};
+ D3D12_RENDER_PASS_DEPTH_STENCIL_DESC DSV = {};
- if (!internal_state->barrierdescs_begin.empty())
+ // Some bookkeeping for resolves:
+ uint32_t rt_resolve_count = 0;
+ struct ResolveSourceInfo
{
- commandlist.GetGraphicsCommandList()->ResourceBarrier((UINT)internal_state->barrierdescs_begin.size(), internal_state->barrierdescs_begin.data());
+ ID3D12Resource* resource = nullptr;
+ BOOL preserve = FALSE;
+ uint32_t firstMip = 0;
+ uint32_t mipCount = 0;
+ uint32_t firstSlice = 0;
+ uint32_t sliceCount = 0;
+ uint32_t total_mipCount = 0;
+ uint32_t total_sliceCount = 0;
+ };
+ ResolveSourceInfo RT_resolve_src_infos[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
+ ResolveSourceInfo DS_resolve_src_info;
+
+ for (uint32_t i = 0; i < image_count; ++i)
+ {
+ const RenderPassImage& image = images[i];
+ const Texture* texture = image.texture;
+ const TextureDesc& desc = texture->GetDesc();
+ int subresource = image.subresource;
+ auto internal_state = to_internal(texture);
+
+ D3D12_CLEAR_VALUE clear_value;
+ clear_value.Format = _ConvertFormat(desc.format);
+
+ D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE beginning_access_type;
+ switch (image.loadop)
+ {
+ default:
+ case RenderPassImage::LoadOp::LOAD:
+ beginning_access_type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
+ break;
+ case RenderPassImage::LoadOp::CLEAR:
+ beginning_access_type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
+ break;
+ case RenderPassImage::LoadOp::DONTCARE:
+ beginning_access_type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD;
+ break;
+ }
+
+ D3D12_RENDER_PASS_ENDING_ACCESS_TYPE ending_access_type;
+ switch (image.storeop)
+ {
+ default:
+ case RenderPassImage::StoreOp::STORE:
+ ending_access_type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
+ break;
+ case RenderPassImage::StoreOp::DONTCARE:
+ ending_access_type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD;
+ break;
+ }
+
+ SingleDescriptor descriptor;
+
+ switch (image.type)
+ {
+ case RenderPassImage::Type::RENDERTARGET:
+ {
+ descriptor = subresource < 0 ? internal_state->rtv : internal_state->subresources_rtv[subresource];
+ ResolveSourceInfo& resolve_src_info = RT_resolve_src_infos[rt_count];
+ D3D12_RENDER_PASS_RENDER_TARGET_DESC& RTV = RTVs[rt_count++];
+ RTV.cpuDescriptor = descriptor.handle;
+ RTV.BeginningAccess.Type = beginning_access_type;
+ RTV.EndingAccess.Type = ending_access_type;
+ clear_value.Color[0] = desc.clear.color[0];
+ clear_value.Color[1] = desc.clear.color[1];
+ clear_value.Color[2] = desc.clear.color[2];
+ clear_value.Color[3] = desc.clear.color[3];
+ RTV.BeginningAccess.Clear.ClearValue = clear_value;
+ resolve_src_info.resource = internal_state->resource.Get();
+ resolve_src_info.preserve = ending_access_type == D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
+ resolve_src_info.firstMip = descriptor.firstMip;
+ resolve_src_info.mipCount = descriptor.mipCount;
+ resolve_src_info.firstSlice = descriptor.firstSlice;
+ resolve_src_info.sliceCount = descriptor.sliceCount;
+ resolve_src_info.total_mipCount = desc.mip_levels;
+ resolve_src_info.total_sliceCount = desc.array_size;
+ }
+ break;
+
+ case RenderPassImage::Type::RESOLVE:
+ {
+ descriptor = subresource < 0 ? internal_state->srv : internal_state->subresources_srv[subresource];
+ ResolveSourceInfo& resolve_src_info = RT_resolve_src_infos[rt_resolve_count];
+ D3D12_RENDER_PASS_RENDER_TARGET_DESC& RTV = RTVs[rt_resolve_count];
+ RTV.EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE;
+ RTV.EndingAccess.Resolve.Format = clear_value.Format;
+ RTV.EndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_AVERAGE;
+ RTV.EndingAccess.Resolve.pDstResource = internal_state->resource.Get();
+ RTV.EndingAccess.Resolve.pSrcResource = resolve_src_info.resource;
+ RTV.EndingAccess.Resolve.PreserveResolveSource = resolve_src_info.preserve;
+ for (uint32_t mip = 0; mip < std::min(desc.mip_levels, descriptor.mipCount); ++mip)
+ {
+ for (uint32_t slice = 0; slice < std::min(desc.array_size, descriptor.sliceCount); ++slice)
+ {
+ D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS& params = commandlist.resolve_subresources[rt_resolve_count].emplace_back();
+ params.SrcSubresource = D3D12CalcSubresource(resolve_src_info.firstMip + mip, resolve_src_info.firstSlice + slice, 0, resolve_src_info.total_mipCount, resolve_src_info.total_sliceCount);
+ params.DstSubresource = D3D12CalcSubresource(descriptor.firstMip + mip, descriptor.firstSlice + slice, 0, desc.mip_levels, desc.array_size);
+ params.SrcRect.left = 0;
+ params.SrcRect.top = 0;
+ params.SrcRect.right = (LONG)desc.width;
+ params.SrcRect.bottom = (LONG)desc.height;
+ }
+ }
+ RTV.EndingAccess.Resolve.pSubresourceParameters = commandlist.resolve_subresources[rt_resolve_count].data();
+ RTV.EndingAccess.Resolve.SubresourceCount = (UINT)commandlist.resolve_subresources[rt_resolve_count].size();
+ rt_resolve_count++;
+ }
+ break;
+
+ case RenderPassImage::Type::DEPTH_STENCIL:
+ {
+ descriptor = subresource < 0 ? internal_state->dsv : internal_state->subresources_dsv[subresource];
+ DSV.cpuDescriptor = descriptor.handle;
+ DSV.DepthBeginningAccess.Type = beginning_access_type;
+ DSV.DepthEndingAccess.Type = ending_access_type;
+ clear_value.DepthStencil.Depth = desc.clear.depth_stencil.depth;
+ clear_value.DepthStencil.Stencil = desc.clear.depth_stencil.stencil;
+ DSV.DepthBeginningAccess.Clear.ClearValue = clear_value;
+ DSV.DepthEndingAccess.Resolve.pSrcResource = internal_state->resource.Get();
+ DSV.DepthEndingAccess.Resolve.PreserveResolveSource = ending_access_type == D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
+ DS_resolve_src_info.resource = internal_state->resource.Get();
+ DS_resolve_src_info.preserve = ending_access_type == D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
+ DS_resolve_src_info.firstMip = descriptor.firstMip;
+ DS_resolve_src_info.mipCount = descriptor.mipCount;
+ DS_resolve_src_info.firstSlice = descriptor.firstSlice;
+ DS_resolve_src_info.sliceCount = descriptor.sliceCount;
+ DS_resolve_src_info.total_mipCount = desc.mip_levels;
+ DS_resolve_src_info.total_sliceCount = desc.array_size;
+ if (IsFormatStencilSupport(desc.format))
+ {
+ DSV.StencilBeginningAccess = DSV.DepthBeginningAccess;
+ DSV.StencilEndingAccess = DSV.DepthEndingAccess;
+ }
+ }
+ break;
+
+ case RenderPassImage::Type::RESOLVE_DEPTH:
+ {
+ descriptor = subresource < 0 ? internal_state->dsv : internal_state->subresources_dsv[subresource];
+ DSV.DepthEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE;
+ DSV.DepthEndingAccess.Resolve.Format = clear_value.Format;
+ switch (image.depth_resolve_mode)
+ {
+ default:
+ case RenderPassImage::DepthResolveMode::Min:
+ DSV.DepthEndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_MIN;
+ break;
+ case RenderPassImage::DepthResolveMode::Max:
+ DSV.DepthEndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_MAX;
+ break;
+ }
+ DSV.DepthEndingAccess.Resolve.pDstResource = internal_state->resource.Get();
+ DSV.DepthEndingAccess.Resolve.pSrcResource = DS_resolve_src_info.resource;
+ DSV.DepthEndingAccess.Resolve.PreserveResolveSource = DS_resolve_src_info.preserve;
+ for (uint32_t mip = 0; mip < std::min(desc.mip_levels, descriptor.mipCount); ++mip)
+ {
+ for (uint32_t slice = 0; slice < std::min(desc.array_size, descriptor.sliceCount); ++slice)
+ {
+ D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS& params = commandlist.resolve_subresources_dsv.emplace_back();
+ params.SrcSubresource = D3D12CalcSubresource(DS_resolve_src_info.firstMip + mip, DS_resolve_src_info.firstSlice + slice, 0, DS_resolve_src_info.total_mipCount, DS_resolve_src_info.total_sliceCount);
+ params.DstSubresource = D3D12CalcSubresource(descriptor.firstMip + mip, descriptor.firstSlice + slice, 0, desc.mip_levels, desc.array_size);
+ params.SrcRect.left = 0;
+ params.SrcRect.top = 0;
+ params.SrcRect.right = (LONG)desc.width;
+ params.SrcRect.bottom = (LONG)desc.height;
+ }
+ }
+ DSV.DepthEndingAccess.Resolve.pSubresourceParameters = commandlist.resolve_subresources_dsv.data();
+ DSV.DepthEndingAccess.Resolve.SubresourceCount = (UINT)commandlist.resolve_subresources_dsv.size();
+ if (IsFormatStencilSupport(desc.format))
+ {
+ DSV.StencilEndingAccess = DSV.DepthEndingAccess;
+ }
+ }
+ break;
+
+ case RenderPassImage::Type::SHADING_RATE_SOURCE:
+ commandlist.shading_rate_image = internal_state->resource.Get(); // will be set after barriers
+ break;
+
+ default:
+ break;
+ }
+
+
+ // Beginning barriers:
+ {
+ D3D12_RESOURCE_STATES before = _ParseResourceState(image.layout_before);
+ D3D12_RESOURCE_STATES after = _ParseResourceState(image.layout);
+ if (image.type == RenderPassImage::Type::RESOLVE || image.type == RenderPassImage::Type::RESOLVE_DEPTH)
+ {
+ after = D3D12_RESOURCE_STATE_RESOLVE_DEST;
+ }
+ if (before != after)
+ {
+ D3D12_RESOURCE_BARRIER barrierdesc = {};
+ barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrierdesc.Transition.pResource = internal_state->resource.Get();
+ barrierdesc.Transition.StateBefore = before;
+ barrierdesc.Transition.StateAfter = after;
+
+ if (subresource >= 0)
+ {
+ // Need to unroll descriptor into multiple subresource barriers:
+ for (uint32_t mip = descriptor.firstMip; mip < std::min(desc.mip_levels, descriptor.firstMip + descriptor.mipCount); ++mip)
+ {
+ for (uint32_t slice = descriptor.firstSlice; slice < std::min(desc.array_size, descriptor.firstSlice + descriptor.sliceCount); ++slice)
+ {
+ barrierdesc.Transition.Subresource = D3D12CalcSubresource(mip, slice, 0, desc.mip_levels, desc.array_size);
+ commandlist.renderpass_barriers_begin.push_back(barrierdesc);
+ }
+ }
+ }
+ else
+ {
+ // Single barrier for whole resource:
+ barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ commandlist.renderpass_barriers_begin.push_back(barrierdesc);
+ }
+ }
+ }
+
+ // Ending barriers:
+ {
+ D3D12_RESOURCE_STATES before = _ParseResourceState(image.layout);
+ D3D12_RESOURCE_STATES after = _ParseResourceState(image.layout_after);
+ if (image.type == RenderPassImage::Type::RESOLVE || image.type == RenderPassImage::Type::RESOLVE_DEPTH)
+ {
+ before = D3D12_RESOURCE_STATE_RESOLVE_DEST;
+ }
+ if (before != after)
+ {
+ D3D12_RESOURCE_BARRIER barrierdesc = {};
+ barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrierdesc.Transition.pResource = internal_state->resource.Get();
+ barrierdesc.Transition.StateBefore = before;
+ barrierdesc.Transition.StateAfter = after;
+
+ if (subresource >= 0)
+ {
+ // Need to unroll descriptor into multiple subresource barriers:
+ for (uint32_t mip = descriptor.firstMip; mip < std::min(desc.mip_levels, descriptor.firstMip + descriptor.mipCount); ++mip)
+ {
+ for (uint32_t slice = descriptor.firstSlice; slice < std::min(desc.array_size, descriptor.firstSlice + descriptor.sliceCount); ++slice)
+ {
+ barrierdesc.Transition.Subresource = D3D12CalcSubresource(mip, slice, 0, desc.mip_levels, desc.array_size);
+ commandlist.renderpass_barriers_end.push_back(barrierdesc);
+ }
+ }
+ }
+ else
+ {
+ // Single barrier for whole resource:
+ barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ commandlist.renderpass_barriers_end.push_back(barrierdesc);
+ }
+ }
+ }
}
- if (internal_state->shading_rate_image.IsValid())
+ if (!commandlist.renderpass_barriers_begin.empty())
{
- commandlist.GetGraphicsCommandList()->RSSetShadingRateImage(to_internal(&internal_state->shading_rate_image)->resource.Get());
+ commandlist.GetGraphicsCommandList()->ResourceBarrier((UINT)commandlist.renderpass_barriers_begin.size(), commandlist.renderpass_barriers_begin.data());
+ }
+
+ if (commandlist.shading_rate_image != nullptr)
+ {
+ commandlist.GetGraphicsCommandList()->RSSetShadingRateImage(commandlist.shading_rate_image);
+ }
+
+ D3D12_RENDER_PASS_FLAGS FLAGS = D3D12_RENDER_PASS_FLAG_NONE;
+ if (has_flag(flags, RenderPassFlags::ALLOW_UAV_WRITES))
+ {
+ FLAGS |= D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES;
+ }
+ if (has_flag(flags, RenderPassFlags::SUSPENDING))
+ {
+ FLAGS |= D3D12_RENDER_PASS_FLAG_SUSPENDING_PASS;
+ }
+ if (has_flag(flags, RenderPassFlags::RESUMING))
+ {
+ FLAGS |= D3D12_RENDER_PASS_FLAG_RESUMING_PASS;
}
commandlist.GetGraphicsCommandList()->BeginRenderPass(
- internal_state->rt_count,
- internal_state->RTVs,
- internal_state->DSV.cpuDescriptor.ptr == 0 ? nullptr : &internal_state->DSV,
- internal_state->flags
+ rt_count,
+ RTVs,
+ DSV.cpuDescriptor.ptr == 0 ? nullptr : &DSV,
+ FLAGS
);
+ commandlist.renderpass_info = RenderPassInfo::from(images, image_count);
}
void GraphicsDevice_DX12::RenderPassEnd(CommandList cmd)
{
CommandList_DX12& commandlist = GetCommandList(cmd);
commandlist.GetGraphicsCommandList()->EndRenderPass();
- auto internal_state = to_internal(commandlist.active_renderpass);
-
- if (internal_state != nullptr)
+ if (commandlist.shading_rate_image != nullptr)
{
- if (internal_state->shading_rate_image.IsValid())
- {
- commandlist.GetGraphicsCommandList()->RSSetShadingRateImage(nullptr);
- }
-
- if (!internal_state->barrierdescs_end.empty())
- {
- commandlist.GetGraphicsCommandList()->ResourceBarrier((UINT)internal_state->barrierdescs_end.size(), internal_state->barrierdescs_end.data());
- }
+ commandlist.GetGraphicsCommandList()->RSSetShadingRateImage(nullptr);
+ commandlist.shading_rate_image = nullptr;
}
- commandlist.active_renderpass = nullptr;
-
- if (commandlist.active_backbuffer)
+ if (!commandlist.renderpass_barriers_end.empty())
{
- D3D12_RESOURCE_BARRIER barrier = {};
- barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrier.Transition.pResource = commandlist.active_backbuffer.Get();
- barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
- barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
- barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
- barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- commandlist.GetGraphicsCommandList()->ResourceBarrier(1, &barrier);
-
- commandlist.active_backbuffer = nullptr;
+ commandlist.GetGraphicsCommandList()->ResourceBarrier(
+ (UINT)commandlist.renderpass_barriers_end.size(),
+ commandlist.renderpass_barriers_end.data()
+ );
}
+
+ commandlist.renderpass_info = {};
}
void GraphicsDevice_DX12::BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd)
{
@@ -5851,19 +5899,33 @@ using namespace dx12_internal;
commandlist.active_cs = nullptr;
commandlist.active_rt = nullptr;
- size_t pipeline_hash = 0;
- wi::helper::hash_combine(pipeline_hash, pso->hash);
- if (commandlist.active_renderpass != nullptr)
- {
- wi::helper::hash_combine(pipeline_hash, commandlist.active_renderpass->hash);
- }
- if (commandlist.prev_pipeline_hash == pipeline_hash)
- {
- return;
- }
- commandlist.prev_pipeline_hash = pipeline_hash;
-
auto internal_state = to_internal(pso);
+ if (internal_state->resource != nullptr)
+ {
+ commandlist.GetGraphicsCommandList()->SetPipelineState(internal_state->resource.Get());
+
+ if (commandlist.prev_pt != internal_state->primitiveTopology)
+ {
+ commandlist.prev_pt = internal_state->primitiveTopology;
+
+ commandlist.GetGraphicsCommandList()->IASetPrimitiveTopology(internal_state->primitiveTopology);
+ }
+
+ commandlist.prev_pipeline_hash = 0;
+ commandlist.dirty_pso = false;
+ }
+ else
+ {
+ size_t pipeline_hash = 0;
+ wi::helper::hash_combine(pipeline_hash, internal_state->hash);
+ wi::helper::hash_combine(pipeline_hash, commandlist.renderpass_info.get_hash());
+ if (commandlist.prev_pipeline_hash == pipeline_hash)
+ {
+ return;
+ }
+ commandlist.prev_pipeline_hash = pipeline_hash;
+ commandlist.dirty_pso = true;
+ }
if (commandlist.active_rootsig_graphics != internal_state->rootSignature.Get())
{
@@ -5876,7 +5938,6 @@ using namespace dx12_internal;
}
commandlist.active_pso = pso;
- commandlist.dirty_pso = true;
}
void GraphicsDevice_DX12::BindComputeShader(const Shader* cs, CommandList cmd)
{
@@ -6156,7 +6217,6 @@ using namespace dx12_internal;
void GraphicsDevice_DX12::QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd)
{
CommandList_DX12& commandlist = GetCommandList(cmd);
- assert(commandlist.active_renderpass == nullptr); // Can't resolve inside renderpass!
auto internal_state = to_internal(heap);
auto dst_internal = to_internal(dest);
@@ -6198,7 +6258,6 @@ using namespace dx12_internal;
void GraphicsDevice_DX12::Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd)
{
CommandList_DX12& commandlist = GetCommandList(cmd);
- assert(commandlist.active_renderpass == nullptr);
auto& barrierdescs = commandlist.frame_barriers;
diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h
index e924d1f6d..a012bc452 100644
--- a/WickedEngine/wiGraphicsDevice_DX12.h
+++ b/WickedEngine/wiGraphicsDevice_DX12.h
@@ -31,10 +31,9 @@ namespace wi::graphics
Microsoft::WRL::ComPtr dxgiFactory;
Microsoft::WRL::ComPtr dxgiAdapter;
Microsoft::WRL::ComPtr device;
-
-#if defined(WICKED_DX12_USE_PIPELINE_LIBRARY)
Microsoft::WRL::ComPtr pipelineLibrary;
-#endif
+ wi::vector pipelineLibraryData; // must be alive while pipelineLibrary object is alive!
+ mutable std::mutex pipelineLibraryLocker;
#ifndef PLATFORM_UWP
Microsoft::WRL::ComPtr deviceRemovedFence;
@@ -141,12 +140,18 @@ namespace wi::graphics
const RaytracingPipelineState* active_rt = {};
const ID3D12RootSignature* active_rootsig_graphics = {};
const ID3D12RootSignature* active_rootsig_compute = {};
- const RenderPass* active_renderpass = {};
ShadingRate prev_shadingrate = {};
wi::vector swapchains;
- Microsoft::WRL::ComPtr active_backbuffer;
bool dirty_pso = {};
wi::vector accelerationstructure_build_geometries;
+ RenderPassInfo renderpass_info;
+ wi::vector renderpass_barriers_begin;
+ wi::vector renderpass_barriers_end;
+ ID3D12Resource* shading_rate_image = nullptr;
+
+ // Due to a API bug, this resolve_subresources array must be kept alive between BeginRenderpass() and EndRenderpass()!
+ wi::vector resolve_subresources[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {};
+ wi::vector resolve_subresources_dsv = {};
void reset(uint32_t bufferindex)
{
@@ -161,11 +166,18 @@ namespace wi::graphics
active_rt = nullptr;
active_rootsig_graphics = nullptr;
active_rootsig_compute = nullptr;
- active_renderpass = nullptr;
prev_shadingrate = ShadingRate::RATE_INVALID;
dirty_pso = false;
swapchains.clear();
- active_backbuffer = nullptr;
+ renderpass_info = {};
+ renderpass_barriers_begin.clear();
+ renderpass_barriers_end.clear();
+ for (size_t i = 0; i < arraysize(resolve_subresources); ++i)
+ {
+ resolve_subresources[i].clear();
+ }
+ resolve_subresources_dsv.clear();
+ shading_rate_image = nullptr;
}
inline ID3D12CommandAllocator* GetCommandAllocator()
@@ -208,8 +220,7 @@ namespace wi::graphics
bool CreateShader(ShaderStage stage, const void* shadercode, size_t shadercode_size, Shader* shader) const override;
bool CreateSampler(const SamplerDesc* desc, Sampler* sampler) const override;
bool CreateQueryHeap(const GPUQueryHeapDesc* desc, GPUQueryHeap* queryheap) const override;
- bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso) const override;
- bool CreateRenderPass(const RenderPassDesc* desc, RenderPass* renderpass) const override;
+ bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info = nullptr) const override;
bool CreateRaytracingAccelerationStructure(const RaytracingAccelerationStructureDesc* desc, RaytracingAccelerationStructure* bvh) const override;
bool CreateRaytracingPipelineState(const RaytracingPipelineStateDesc* desc, RaytracingPipelineState* rtpso) const override;
@@ -276,7 +287,7 @@ namespace wi::graphics
void WaitCommandList(CommandList cmd, CommandList wait_for) override;
void RenderPassBegin(const SwapChain* swapchain, CommandList cmd) override;
- void RenderPassBegin(const RenderPass* renderpass, CommandList cmd) override;
+ void RenderPassBegin(const RenderPassImage* images, uint32_t image_count, CommandList cmd, RenderPassFlags flags = RenderPassFlags::NONE) override;
void RenderPassEnd(CommandList cmd) override;
void BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) override;
void BindViewports(uint32_t NumViewports, const Viewport* pViewports, CommandList cmd) override;
@@ -327,6 +338,11 @@ namespace wi::graphics
void EventEnd(CommandList cmd) override;
void SetMarker(const char* name, CommandList cmd) override;
+ RenderPassInfo GetRenderPassInfo(CommandList cmd) override
+ {
+ return GetCommandList(cmd).renderpass_info;
+ }
+
GPULinearAllocator& GetFrameAllocator(CommandList cmd) override
{
return GetCommandList(cmd).frame_allocators[GetBufferIndex()];
diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp
index 819dd9c58..e17578999 100644
--- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp
+++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp
@@ -493,10 +493,15 @@ namespace vulkan_internal
{
ss += "[Vulkan Error]: ";
ss += callback_data->pMessage;
+#if 1
wi::backlog::post(ss, wi::backlog::LogLevel::Error);
-#ifdef _DEBUG
- assert(0);
-#endif // _DEBUG
+#else
+ OutputDebugStringA(callback_data->pMessage);
+ OutputDebugStringA("\n");
+#endif
+//#ifdef _DEBUG
+// assert(0);
+//#endif // _DEBUG
}
return VK_FALSE;
@@ -601,22 +606,25 @@ namespace vulkan_internal
{
VkImageView image_view = VK_NULL_HANDLE;
int index = -1; // bindless
+ uint32_t firstMip = 0;
+ uint32_t mipCount = 0;
+ uint32_t firstSlice = 0;
+ uint32_t sliceCount = 0;
constexpr bool IsValid() const
{
- return index >= 0;
+ return image_view != VK_NULL_HANDLE;
}
};
TextureSubresource srv;
TextureSubresource uav;
- VkImageView rtv = VK_NULL_HANDLE;
- VkImageView dsv = VK_NULL_HANDLE;
+ TextureSubresource rtv;
+ TextureSubresource dsv;
uint32_t framebuffer_layercount = 0;
wi::vector subresources_srv;
wi::vector subresources_uav;
- wi::vector subresources_rtv;
- wi::vector subresources_dsv;
- wi::vector subresources_framebuffer_layercount;
+ wi::vector subresources_rtv;
+ wi::vector subresources_dsv;
wi::vector mapped_subresources;
SparseTextureProperties sparse_texture_properties;
@@ -649,13 +657,13 @@ namespace vulkan_internal
allocationhandler->destroyer_imageviews.push_back(std::make_pair(uav.image_view, framecount));
allocationhandler->destroyer_bindlessStorageImages.push_back(std::make_pair(uav.index, framecount));
}
- if (rtv != VK_NULL_HANDLE)
+ if (rtv.IsValid())
{
- allocationhandler->destroyer_imageviews.push_back(std::make_pair(rtv, framecount));
+ allocationhandler->destroyer_imageviews.push_back(std::make_pair(rtv.image_view, framecount));
}
- if (dsv != VK_NULL_HANDLE)
+ if (dsv.IsValid())
{
- allocationhandler->destroyer_imageviews.push_back(std::make_pair(dsv, framecount));
+ allocationhandler->destroyer_imageviews.push_back(std::make_pair(dsv.image_view, framecount));
}
for (auto x : subresources_srv)
{
@@ -669,11 +677,11 @@ namespace vulkan_internal
}
for (auto x : subresources_rtv)
{
- allocationhandler->destroyer_imageviews.push_back(std::make_pair(x, framecount));
+ allocationhandler->destroyer_imageviews.push_back(std::make_pair(x.image_view, framecount));
}
for (auto x : subresources_dsv)
{
- allocationhandler->destroyer_imageviews.push_back(std::make_pair(x, framecount));
+ allocationhandler->destroyer_imageviews.push_back(std::make_pair(x.image_view, framecount));
}
allocationhandler->destroylocker.unlock();
}
@@ -746,10 +754,12 @@ namespace vulkan_internal
struct PipelineState_Vulkan
{
std::shared_ptr allocationhandler;
+ VkPipeline pipeline = VK_NULL_HANDLE;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; // no lifetime management here
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; // no lifetime management here
wi::vector layoutBindings;
wi::vector imageViewTypes;
+ size_t hash = 0;
wi::vector bindlessBindings;
wi::vector bindlessSets;
@@ -773,23 +783,14 @@ namespace vulkan_internal
VkPipelineDepthStencilStateCreateInfo depthstencil = {};
VkSampleMask samplemask = {};
VkPipelineTessellationStateCreateInfo tessellationInfo = {};
- };
- struct RenderPass_Vulkan
- {
- std::shared_ptr allocationhandler;
- VkRenderPass renderpass = VK_NULL_HANDLE;
- VkFramebuffer framebuffer = VK_NULL_HANDLE;
- VkRenderPassBeginInfo beginInfo = {};
- VkClearValue clearColors[9] = {};
- ~RenderPass_Vulkan()
+ ~PipelineState_Vulkan()
{
if (allocationhandler == nullptr)
return;
allocationhandler->destroylocker.lock();
uint64_t framecount = allocationhandler->framecount;
- if (renderpass) allocationhandler->destroyer_renderpasses.push_back(std::make_pair(renderpass, framecount));
- if (framebuffer) allocationhandler->destroyer_framebuffers.push_back(std::make_pair(framebuffer, framecount));
+ if (pipeline) allocationhandler->destroyer_pipelines.push_back(std::make_pair(pipeline, framecount));
allocationhandler->destroylocker.unlock();
}
};
@@ -844,10 +845,8 @@ namespace vulkan_internal
VkExtent2D swapChainExtent;
wi::vector swapChainImages;
wi::vector swapChainImageViews;
- wi::vector swapChainFramebuffers;
Texture dummyTexture;
- RenderPass renderpass;
VkSurfaceKHR surface = VK_NULL_HANDLE;
@@ -868,7 +867,6 @@ namespace vulkan_internal
for (size_t i = 0; i < swapChainImages.size(); ++i)
{
- allocationhandler->destroyer_framebuffers.push_back(std::make_pair(swapChainFramebuffers[i], framecount));
allocationhandler->destroyer_imageviews.push_back(std::make_pair(swapChainImageViews[i], framecount));
}
@@ -913,10 +911,6 @@ namespace vulkan_internal
{
return static_cast(param->internal_state.get());
}
- RenderPass_Vulkan* to_internal(const RenderPass* param)
- {
- return static_cast(param->internal_state.get());
- }
BVH_Vulkan* to_internal(const RaytracingAccelerationStructure* param)
{
return static_cast(param->internal_state.get());
@@ -932,7 +926,7 @@ namespace vulkan_internal
inline const std::string GetCachePath()
{
- return wi::helper::GetTempDirectoryPath() + "WickedVkPipelineCache.data";
+ return wi::helper::GetTempDirectoryPath() + "wiPipelineCache_Vulkan";
}
bool CreateSwapChainInternal(
@@ -1085,62 +1079,8 @@ namespace vulkan_internal
assert(res == VK_SUCCESS);
internal_state->swapChainImageFormat = surfaceFormat.format;
- // Create default render pass:
- {
- VkAttachmentDescription colorAttachment = {};
- colorAttachment.format = internal_state->swapChainImageFormat;
- colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
- colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-
- VkAttachmentReference colorAttachmentRef = {};
- colorAttachmentRef.attachment = 0;
- colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-
- VkSubpassDescription subpass = {};
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass.colorAttachmentCount = 1;
- subpass.pColorAttachments = &colorAttachmentRef;
-
- VkRenderPassCreateInfo renderPassInfo = {};
- renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- renderPassInfo.attachmentCount = 1;
- renderPassInfo.pAttachments = &colorAttachment;
- renderPassInfo.subpassCount = 1;
- renderPassInfo.pSubpasses = &subpass;
-
- VkSubpassDependency dependency = {};
- dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
- dependency.dstSubpass = 0;
- dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- dependency.srcAccessMask = 0;
- dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-
- renderPassInfo.dependencyCount = 1;
- renderPassInfo.pDependencies = &dependency;
-
- internal_state->dummyTexture.desc.format = internal_state->desc.format;
- internal_state->dummyTexture.desc.width = internal_state->desc.width;
- internal_state->dummyTexture.desc.height = internal_state->desc.height;
- internal_state->renderpass = {};
- wi::helper::hash_combine(internal_state->renderpass.hash, internal_state->swapChainImageFormat);
- auto renderpass_internal = std::make_shared();
- renderpass_internal->allocationhandler = allocationhandler;
- internal_state->renderpass.internal_state = renderpass_internal;
- internal_state->renderpass.desc.attachments.push_back(RenderPassAttachment::RenderTarget(internal_state->dummyTexture));
- res = vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderpass_internal->renderpass);
- assert(res == VK_SUCCESS);
-
- }
-
// Create swap chain render targets:
internal_state->swapChainImageViews.resize(internal_state->swapChainImages.size());
- internal_state->swapChainFramebuffers.resize(internal_state->swapChainImages.size());
for (size_t i = 0; i < internal_state->swapChainImages.size(); ++i)
{
VkImageViewCreateInfo createInfo = {};
@@ -1166,28 +1106,6 @@ namespace vulkan_internal
}
res = vkCreateImageView(device, &createInfo, nullptr, &internal_state->swapChainImageViews[i]);
assert(res == VK_SUCCESS);
-
- VkImageView attachments[] = {
- internal_state->swapChainImageViews[i]
- };
-
- VkFramebufferCreateInfo framebufferInfo = {};
- framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebufferInfo.renderPass = to_internal(&internal_state->renderpass)->renderpass;
- framebufferInfo.attachmentCount = 1;
- framebufferInfo.pAttachments = attachments;
- framebufferInfo.width = internal_state->swapChainExtent.width;
- framebufferInfo.height = internal_state->swapChainExtent.height;
- framebufferInfo.layers = 1;
-
- if (internal_state->swapChainFramebuffers[i] != VK_NULL_HANDLE)
- {
- allocationhandler->destroylocker.lock();
- allocationhandler->destroyer_framebuffers.push_back(std::make_pair(internal_state->swapChainFramebuffers[i], allocationhandler->framecount));
- allocationhandler->destroylocker.unlock();
- }
- res = vkCreateFramebuffer(device, &framebufferInfo, nullptr, &internal_state->swapChainFramebuffers[i]);
- assert(res == VK_SUCCESS);
}
@@ -1999,7 +1917,6 @@ using namespace vulkan_internal;
const PipelineState* pso = commandlist.active_pso;
size_t pipeline_hash = commandlist.prev_pipeline_hash;
- wi::helper::hash_combine(pipeline_hash, commandlist.vb_hash);
auto internal_state = to_internal(pso);
VkPipeline pipeline = VK_NULL_HANDLE;
@@ -2018,18 +1935,12 @@ using namespace vulkan_internal;
if (pipeline == VK_NULL_HANDLE)
{
VkGraphicsPipelineCreateInfo pipelineInfo = internal_state->pipelineInfo; // make a copy here
- pipelineInfo.renderPass = to_internal(commandlist.active_renderpass)->renderpass;
- pipelineInfo.subpass = 0;
// MSAA:
VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
- if (commandlist.active_renderpass->desc.attachments.size() > 0 && commandlist.active_renderpass->desc.attachments[0].texture.IsValid())
- {
- multisampling.rasterizationSamples = (VkSampleCountFlagBits)commandlist.active_renderpass->desc.attachments[0].texture.desc.sample_count;
- }
+ multisampling.rasterizationSamples = (VkSampleCountFlagBits)commandlist.renderpass_info.sample_count;
if (pso->desc.rs != nullptr)
{
const RasterizerState& desc = *pso->desc.rs;
@@ -2058,14 +1969,8 @@ using namespace vulkan_internal;
// Blending:
uint32_t numBlendAttachments = 0;
VkPipelineColorBlendAttachmentState colorBlendAttachments[8] = {};
- const size_t blend_loopCount = commandlist.active_renderpass->desc.attachments.size();
- for (size_t i = 0; i < blend_loopCount; ++i)
+ for (size_t i = 0; i < commandlist.renderpass_info.rt_count; ++i)
{
- if (commandlist.active_renderpass->desc.attachments[i].type != RenderPassAttachment::Type::RENDERTARGET)
- {
- continue;
- }
-
size_t attachmentIndex = 0;
if (pso->desc.bs->independent_blend_enable)
attachmentIndex = i;
@@ -2131,7 +2036,7 @@ using namespace vulkan_internal;
VkVertexInputBindingDescription& bind = bindings.emplace_back();
bind.binding = x.input_slot;
bind.inputRate = x.input_slot_class == InputClassification::PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
- bind.stride = commandlist.vb_strides[x.input_slot];
+ bind.stride = GetFormatStride(x.format);
}
uint32_t offset = 0;
@@ -2168,6 +2073,25 @@ using namespace vulkan_internal;
}
pipelineInfo.pVertexInputState = &vertexInputInfo;
+ pipelineInfo.renderPass = VK_NULL_HANDLE; // instead we use VkPipelineRenderingCreateInfo
+
+ VkPipelineRenderingCreateInfo renderingInfo = {};
+ renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
+ renderingInfo.viewMask = 0;
+ renderingInfo.colorAttachmentCount = commandlist.renderpass_info.rt_count;
+ VkFormat formats[8] = {};
+ for (uint32_t i = 0; i < commandlist.renderpass_info.rt_count; ++i)
+ {
+ formats[i] = _ConvertFormat(commandlist.renderpass_info.rt_formats[i]);
+ }
+ renderingInfo.pColorAttachmentFormats = formats;
+ renderingInfo.depthAttachmentFormat = _ConvertFormat(commandlist.renderpass_info.ds_format);
+ if (IsFormatStencilSupport(commandlist.renderpass_info.ds_format))
+ {
+ renderingInfo.stencilAttachmentFormat = renderingInfo.depthAttachmentFormat;
+ }
+ pipelineInfo.pNext = &renderingInfo;
+
VkResult res = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline);
assert(res == VK_SUCCESS);
@@ -2223,7 +2147,7 @@ using namespace vulkan_internal;
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "Wicked Engine";
appInfo.engineVersion = VK_MAKE_VERSION(wi::version::GetMajor(), wi::version::GetMinor(), wi::version::GetRevision());
- appInfo.apiVersion = VK_API_VERSION_1_2;
+ appInfo.apiVersion = VK_API_VERSION_1_3;
// Enumerate available layers and extensions:
uint32_t instanceLayerCount;
@@ -2404,9 +2328,11 @@ using namespace vulkan_internal;
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
features_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
+ features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
features2.pNext = &features_1_1;
features_1_1.pNext = &features_1_2;
- void** features_chain = &features_1_2.pNext;
+ features_1_2.pNext = &features_1_3;
+ void** features_chain = &features_1_3.pNext;
acceleration_structure_features = {};
raytracing_features = {};
raytracing_query_features = {};
@@ -2418,9 +2344,11 @@ using namespace vulkan_internal;
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
properties_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES;
+ properties_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES;
properties2.pNext = &properties_1_1;
properties_1_1.pNext = &properties_1_2;
- void** properties_chain = &properties_1_2.pNext;
+ properties_1_2.pNext = &properties_1_3;
+ void** properties_chain = &properties_1_3.pNext;
sampler_minmax_properties = {};
acceleration_structure_properties = {};
raytracing_properties = {};
@@ -2539,6 +2467,7 @@ using namespace vulkan_internal;
assert(features2.features.textureCompressionBC == VK_TRUE);
assert(features2.features.occlusionQueryPrecise == VK_TRUE);
assert(features_1_2.descriptorIndexing == VK_TRUE);
+ assert(features_1_3.dynamicRendering == VK_TRUE);
// Init adapter properties
vendorId = properties2.properties.vendorID;
@@ -2649,14 +2578,6 @@ using namespace vulkan_internal;
capabilities |= GraphicsDeviceCapability::GENERIC_SPARSE_TILE_POOL;
}
- if (depth_stencil_resolve_properties.supportedDepthResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
- {
- capabilities |= GraphicsDeviceCapability::DEPTH_RESOLVE_SAMPLE_ZERO;
- }
- if (depth_stencil_resolve_properties.supportedStencilResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
- {
- capabilities |= GraphicsDeviceCapability::STENCIL_RESOLVE_SAMPLE_ZERO;
- }
if (
(depth_stencil_resolve_properties.supportedDepthResolveModes & VK_RESOLVE_MODE_MIN_BIT) &&
(depth_stencil_resolve_properties.supportedDepthResolveModes & VK_RESOLVE_MODE_MAX_BIT)
@@ -3126,6 +3047,7 @@ using namespace vulkan_internal;
{
pso_dynamicStates.push_back(VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
}
+ pso_dynamicStates.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
dynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicStateInfo.dynamicStateCount = (uint32_t)pso_dynamicStates.size();
@@ -4513,7 +4435,6 @@ using namespace vulkan_internal;
// Create compute pipeline state in place:
pipelineInfo.stage = internal_state->stageInfo;
-
res = vkCreateComputePipelines(device, pipelineCache, 1, &pipelineInfo, nullptr, &internal_state->pipeline_cs);
assert(res == VK_SUCCESS);
}
@@ -4785,27 +4706,27 @@ using namespace vulkan_internal;
return res == VK_SUCCESS;
}
- bool GraphicsDevice_Vulkan::CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso) const
+ bool GraphicsDevice_Vulkan::CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info) const
{
auto internal_state = std::make_shared();
internal_state->allocationhandler = allocationhandler;
pso->internal_state = internal_state;
pso->desc = *desc;
- pso->hash = 0;
- wi::helper::hash_combine(pso->hash, desc->ms);
- wi::helper::hash_combine(pso->hash, desc->as);
- wi::helper::hash_combine(pso->hash, desc->vs);
- wi::helper::hash_combine(pso->hash, desc->ps);
- wi::helper::hash_combine(pso->hash, desc->hs);
- wi::helper::hash_combine(pso->hash, desc->ds);
- wi::helper::hash_combine(pso->hash, desc->gs);
- wi::helper::hash_combine(pso->hash, desc->il);
- wi::helper::hash_combine(pso->hash, desc->rs);
- wi::helper::hash_combine(pso->hash, desc->bs);
- wi::helper::hash_combine(pso->hash, desc->dss);
- wi::helper::hash_combine(pso->hash, desc->pt);
- wi::helper::hash_combine(pso->hash, desc->sample_mask);
+ internal_state->hash = 0;
+ wi::helper::hash_combine(internal_state->hash, desc->ms);
+ wi::helper::hash_combine(internal_state->hash, desc->as);
+ wi::helper::hash_combine(internal_state->hash, desc->vs);
+ wi::helper::hash_combine(internal_state->hash, desc->ps);
+ wi::helper::hash_combine(internal_state->hash, desc->hs);
+ wi::helper::hash_combine(internal_state->hash, desc->ds);
+ wi::helper::hash_combine(internal_state->hash, desc->gs);
+ wi::helper::hash_combine(internal_state->hash, desc->il);
+ wi::helper::hash_combine(internal_state->hash, desc->rs);
+ wi::helper::hash_combine(internal_state->hash, desc->bs);
+ wi::helper::hash_combine(internal_state->hash, desc->dss);
+ wi::helper::hash_combine(internal_state->hash, desc->pt);
+ wi::helper::hash_combine(internal_state->hash, desc->sample_mask);
VkResult res = VK_SUCCESS;
@@ -5256,372 +5177,172 @@ using namespace vulkan_internal;
pipelineInfo.pTessellationState = &tessellationInfo;
-
pipelineInfo.pDynamicState = &dynamicStateInfo;
- return res == VK_SUCCESS;
- }
- bool GraphicsDevice_Vulkan::CreateRenderPass(const RenderPassDesc* desc, RenderPass* renderpass) const
- {
- auto internal_state = std::make_shared();
- internal_state->allocationhandler = allocationhandler;
- renderpass->internal_state = internal_state;
- renderpass->desc = *desc;
-
- renderpass->hash = 0;
- wi::helper::hash_combine(renderpass->hash, desc->attachments.size());
- for (auto& attachment : desc->attachments)
+ if (desc->il == nullptr)
{
- if (attachment.type == RenderPassAttachment::Type::RENDERTARGET || attachment.type == RenderPassAttachment::Type::DEPTH_STENCIL)
- {
- wi::helper::hash_combine(renderpass->hash, attachment.texture.desc.format);
- wi::helper::hash_combine(renderpass->hash, attachment.texture.desc.sample_count);
- }
}
- VkResult res;
-
- VkImageView attachments[18] = {};
- VkAttachmentDescription2 attachmentDescriptions[18] = {};
- VkAttachmentReference2 colorAttachmentRefs[8] = {};
- VkAttachmentReference2 resolveAttachmentRefs[8] = {};
- VkAttachmentReference2 shadingRateAttachmentRef = {};
- VkAttachmentReference2 depthAttachmentRef = {};
- VkSubpassDescriptionDepthStencilResolve depthResolve = {};
- VkAttachmentReference2 depthResolveAttachmentRef = {};
-
- VkFragmentShadingRateAttachmentInfoKHR shading_rate_attachment = {};
- shading_rate_attachment.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
- shading_rate_attachment.pFragmentShadingRateAttachment = &shadingRateAttachmentRef;
- shading_rate_attachment.shadingRateAttachmentTexelSize.width = VARIABLE_RATE_SHADING_TILE_SIZE;
- shading_rate_attachment.shadingRateAttachmentTexelSize.height = VARIABLE_RATE_SHADING_TILE_SIZE;
-
- int resolvecount = 0;
-
- VkSubpassDescription2 subpass = {};
- subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2;
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- const void** subpass_chain = &subpass.pNext;
-
- uint32_t validAttachmentCount = 0;
- for (auto& attachment : renderpass->desc.attachments)
+ if (renderpass_info != nullptr)
{
- const Texture* texture = &attachment.texture;
- const TextureDesc& texdesc = texture->desc;
- int subresource = attachment.subresource;
- auto texture_internal_state = to_internal(texture);
-
- attachmentDescriptions[validAttachmentCount].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
- attachmentDescriptions[validAttachmentCount].format = _ConvertFormat(texdesc.format);
- attachmentDescriptions[validAttachmentCount].samples = (VkSampleCountFlagBits)texdesc.sample_count;
-
- switch (attachment.loadop)
+ // MSAA:
+ VkPipelineMultisampleStateCreateInfo multisampling = {};
+ multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ multisampling.sampleShadingEnable = VK_FALSE;
+ multisampling.rasterizationSamples = (VkSampleCountFlagBits)renderpass_info->sample_count;
+ if (pso->desc.rs != nullptr)
{
- default:
- case RenderPassAttachment::LoadOp::LOAD:
- attachmentDescriptions[validAttachmentCount].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- break;
- case RenderPassAttachment::LoadOp::CLEAR:
- attachmentDescriptions[validAttachmentCount].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- break;
- case RenderPassAttachment::LoadOp::DONTCARE:
- attachmentDescriptions[validAttachmentCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- break;
- }
-
- switch (attachment.storeop)
- {
- default:
- case RenderPassAttachment::StoreOp::STORE:
- attachmentDescriptions[validAttachmentCount].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- break;
- case RenderPassAttachment::StoreOp::DONTCARE:
- attachmentDescriptions[validAttachmentCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- break;
- }
-
- attachmentDescriptions[validAttachmentCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachmentDescriptions[validAttachmentCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-
- attachmentDescriptions[validAttachmentCount].initialLayout = _ConvertImageLayout(attachment.initial_layout);
- attachmentDescriptions[validAttachmentCount].finalLayout = _ConvertImageLayout(attachment.final_layout);
-
- if (attachment.type == RenderPassAttachment::Type::RENDERTARGET)
- {
- if (subresource < 0 || texture_internal_state->subresources_rtv.empty())
+ const RasterizerState& desc = *pso->desc.rs;
+ if (desc.forced_sample_count > 1)
{
- attachments[validAttachmentCount] = texture_internal_state->rtv;
- }
- else
- {
- assert(texture_internal_state->subresources_rtv.size() > size_t(subresource) && "Invalid RTV subresource!");
- attachments[validAttachmentCount] = texture_internal_state->subresources_rtv[subresource];
- }
- if (attachments[validAttachmentCount] == VK_NULL_HANDLE)
- {
- continue;
- }
-
- colorAttachmentRefs[subpass.colorAttachmentCount].sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
- colorAttachmentRefs[subpass.colorAttachmentCount].attachment = validAttachmentCount;
- colorAttachmentRefs[subpass.colorAttachmentCount].layout = _ConvertImageLayout(attachment.subpass_layout);
- colorAttachmentRefs[subpass.colorAttachmentCount].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- subpass.colorAttachmentCount++;
- subpass.pColorAttachments = colorAttachmentRefs;
- }
- else if (attachment.type == RenderPassAttachment::Type::DEPTH_STENCIL)
- {
- if (subresource < 0 || texture_internal_state->subresources_dsv.empty())
- {
- attachments[validAttachmentCount] = texture_internal_state->dsv;
- }
- else
- {
- assert(texture_internal_state->subresources_dsv.size() > size_t(subresource) && "Invalid DSV subresource!");
- attachments[validAttachmentCount] = texture_internal_state->subresources_dsv[subresource];
- }
- if (attachments[validAttachmentCount] == VK_NULL_HANDLE)
- {
- continue;
- }
-
- depthAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
- depthAttachmentRef.attachment = validAttachmentCount;
- depthAttachmentRef.layout = _ConvertImageLayout(attachment.subpass_layout);
- depthAttachmentRef.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- subpass.pDepthStencilAttachment = &depthAttachmentRef;
-
- if (IsFormatStencilSupport(texdesc.format))
- {
- depthAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
- switch (attachment.loadop)
- {
- default:
- case RenderPassAttachment::LoadOp::LOAD:
- attachmentDescriptions[validAttachmentCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- break;
- case RenderPassAttachment::LoadOp::CLEAR:
- attachmentDescriptions[validAttachmentCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- break;
- case RenderPassAttachment::LoadOp::DONTCARE:
- attachmentDescriptions[validAttachmentCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- break;
- }
-
- switch (attachment.storeop)
- {
- default:
- case RenderPassAttachment::StoreOp::STORE:
- attachmentDescriptions[validAttachmentCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
- break;
- case RenderPassAttachment::StoreOp::DONTCARE:
- attachmentDescriptions[validAttachmentCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- break;
- }
+ multisampling.rasterizationSamples = (VkSampleCountFlagBits)desc.forced_sample_count;
}
}
- else if (attachment.type == RenderPassAttachment::Type::RESOLVE)
+ multisampling.minSampleShading = 1.0f;
+ VkSampleMask samplemask = internal_state->samplemask;
+ samplemask = pso->desc.sample_mask;
+ multisampling.pSampleMask = &samplemask;
+ if (pso->desc.bs != nullptr)
{
- resolveAttachmentRefs[resolvecount].sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
-
- if (!attachment.texture.IsValid())
- {
- resolveAttachmentRefs[resolvecount].attachment = VK_ATTACHMENT_UNUSED;
- }
- else
- {
- if (subresource < 0 || texture_internal_state->subresources_srv.empty())
- {
- attachments[validAttachmentCount] = texture_internal_state->srv.image_view;
- }
- else
- {
- assert(texture_internal_state->subresources_srv.size() > size_t(subresource) && "Invalid SRV subresource!");
- attachments[validAttachmentCount] = texture_internal_state->subresources_srv[subresource].image_view;
- }
- if (attachments[validAttachmentCount] == VK_NULL_HANDLE)
- {
- continue;
- }
- resolveAttachmentRefs[resolvecount].attachment = validAttachmentCount;
- resolveAttachmentRefs[resolvecount].layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- resolveAttachmentRefs[resolvecount].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- }
-
- resolvecount++;
- subpass.pResolveAttachments = resolveAttachmentRefs;
- }
- else if (attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
- {
-
- if (!attachment.texture.IsValid())
- {
- resolveAttachmentRefs[resolvecount].attachment = VK_ATTACHMENT_UNUSED;
- }
- else
- {
- if (subresource < 0 || texture_internal_state->subresources_srv.empty())
- {
- attachments[validAttachmentCount] = texture_internal_state->srv.image_view;
- }
- else
- {
- assert(texture_internal_state->subresources_srv.size() > size_t(subresource) && "Invalid SRV subresource!");
- attachments[validAttachmentCount] = texture_internal_state->subresources_srv[subresource].image_view;
- }
- if (attachments[validAttachmentCount] == VK_NULL_HANDLE)
- {
- continue;
- }
- }
-
- depthResolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
-
- switch (attachment.depth_resolve_mode)
- {
- default:
- case RenderPassAttachment::DepthResolveMode::Min:
- depthResolve.depthResolveMode = VK_RESOLVE_MODE_MIN_BIT;
- depthResolve.stencilResolveMode = VK_RESOLVE_MODE_MIN_BIT;
- break;
- case RenderPassAttachment::DepthResolveMode::Max:
- depthResolve.depthResolveMode = VK_RESOLVE_MODE_MAX_BIT;
- depthResolve.stencilResolveMode = VK_RESOLVE_MODE_MAX_BIT;
- break;
- }
-
- depthResolveAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
- depthResolveAttachmentRef.attachment = validAttachmentCount;
- depthResolveAttachmentRef.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- if (IsFormatStencilSupport(attachment.texture.desc.format))
- {
- depthResolveAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
- }
- depthResolveAttachmentRef.layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- depthResolve.pDepthStencilResolveAttachment = &depthResolveAttachmentRef;
-
- *subpass_chain = &depthResolve;
- subpass_chain = &depthResolve.pNext;
- }
- else if (attachment.type == RenderPassAttachment::Type::SHADING_RATE_SOURCE && CheckCapability(GraphicsDeviceCapability::VARIABLE_RATE_SHADING_TIER2))
- {
- shadingRateAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
-
- if (!attachment.texture.IsValid())
- {
- shadingRateAttachmentRef.attachment = VK_ATTACHMENT_UNUSED;
- }
- else
- {
- if (subresource < 0 || texture_internal_state->subresources_uav.empty())
- {
- attachments[validAttachmentCount] = texture_internal_state->uav.image_view;
- }
- else
- {
- assert(texture_internal_state->subresources_uav.size() > size_t(subresource) && "Invalid UAV subresource!");
- attachments[validAttachmentCount] = texture_internal_state->subresources_uav[subresource].image_view;
- }
- if (attachments[validAttachmentCount] == VK_NULL_HANDLE)
- {
- continue;
- }
- shadingRateAttachmentRef.attachment = validAttachmentCount;
- shadingRateAttachmentRef.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
- shadingRateAttachmentRef.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- }
-
- *subpass_chain = &shading_rate_attachment;
- subpass_chain = &shading_rate_attachment.pNext;
- }
-
- validAttachmentCount++;
- }
- assert(renderpass->desc.attachments.size() == validAttachmentCount);
-
- VkRenderPassCreateInfo2 renderPassInfo = {};
- renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2;
- renderPassInfo.attachmentCount = validAttachmentCount;
- renderPassInfo.pAttachments = attachmentDescriptions;
- renderPassInfo.subpassCount = 1;
- renderPassInfo.pSubpasses = &subpass;
-
- res = vkCreateRenderPass2(device, &renderPassInfo, nullptr, &internal_state->renderpass);
- assert(res == VK_SUCCESS);
-
- VkFramebufferCreateInfo framebufferInfo = {};
- framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebufferInfo.renderPass = internal_state->renderpass;
- framebufferInfo.attachmentCount = validAttachmentCount;
-
- if (validAttachmentCount > 0)
- {
- const TextureDesc& texdesc = renderpass->desc.attachments[0].texture.desc;
- auto texture_internal = to_internal(&renderpass->desc.attachments[0].texture);
- framebufferInfo.pAttachments = attachments;
- framebufferInfo.width = texdesc.width;
- framebufferInfo.height = texdesc.height;
- if (renderpass->desc.attachments[0].subresource >= 0)
- {
- framebufferInfo.layers = texture_internal->subresources_framebuffer_layercount[0];
+ multisampling.alphaToCoverageEnable = pso->desc.bs->alpha_to_coverage_enable ? VK_TRUE : VK_FALSE;
}
else
{
- framebufferInfo.layers = texture_internal->framebuffer_layercount;
+ multisampling.alphaToCoverageEnable = VK_FALSE;
}
- framebufferInfo.layers = std::min(framebufferInfo.layers, texdesc.array_size);
- }
- else
- {
- framebufferInfo.pAttachments = nullptr;
- framebufferInfo.width = properties2.properties.limits.maxFramebufferWidth;
- framebufferInfo.height = properties2.properties.limits.maxFramebufferHeight;
- framebufferInfo.layers = properties2.properties.limits.maxFramebufferLayers;
- }
+ multisampling.alphaToOneEnable = VK_FALSE;
- res = vkCreateFramebuffer(device, &framebufferInfo, nullptr, &internal_state->framebuffer);
- assert(res == VK_SUCCESS);
+ pipelineInfo.pMultisampleState = &multisampling;
- internal_state->beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- internal_state->beginInfo.renderPass = internal_state->renderpass;
- internal_state->beginInfo.framebuffer = internal_state->framebuffer;
- internal_state->beginInfo.renderArea.offset = { 0, 0 };
- internal_state->beginInfo.renderArea.extent.width = framebufferInfo.width;
- internal_state->beginInfo.renderArea.extent.height = framebufferInfo.height;
-
- if (validAttachmentCount > 0)
- {
- internal_state->beginInfo.clearValueCount = validAttachmentCount;
- internal_state->beginInfo.pClearValues = internal_state->clearColors;
-
- int i = 0;
- for (auto& attachment : renderpass->desc.attachments)
+ // Blending:
+ uint32_t numBlendAttachments = 0;
+ VkPipelineColorBlendAttachmentState colorBlendAttachments[8] = {};
+ for (size_t i = 0; i < renderpass_info->rt_count; ++i)
{
- if (renderpass->desc.attachments[i].type == RenderPassAttachment::Type::RESOLVE ||
- renderpass->desc.attachments[i].type == RenderPassAttachment::Type::SHADING_RATE_SOURCE ||
- !attachment.texture.IsValid())
- continue;
+ size_t attachmentIndex = 0;
+ if (pso->desc.bs->independent_blend_enable)
+ attachmentIndex = i;
- const ClearValue& clear = renderpass->desc.attachments[i].texture.desc.clear;
- if (renderpass->desc.attachments[i].type == RenderPassAttachment::Type::RENDERTARGET)
+ const auto& desc = pso->desc.bs->render_target[attachmentIndex];
+ VkPipelineColorBlendAttachmentState& attachment = colorBlendAttachments[numBlendAttachments];
+ numBlendAttachments++;
+
+ attachment.blendEnable = desc.blend_enable ? VK_TRUE : VK_FALSE;
+
+ attachment.colorWriteMask = 0;
+ if (has_flag(desc.render_target_write_mask, ColorWrite::ENABLE_RED))
{
- internal_state->clearColors[i].color.float32[0] = clear.color[0];
- internal_state->clearColors[i].color.float32[1] = clear.color[1];
- internal_state->clearColors[i].color.float32[2] = clear.color[2];
- internal_state->clearColors[i].color.float32[3] = clear.color[3];
+ attachment.colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;
}
- else if (renderpass->desc.attachments[i].type == RenderPassAttachment::Type::DEPTH_STENCIL)
+ if (has_flag(desc.render_target_write_mask, ColorWrite::ENABLE_GREEN))
{
- internal_state->clearColors[i].depthStencil.depth = clear.depth_stencil.depth;
- internal_state->clearColors[i].depthStencil.stencil = clear.depth_stencil.stencil;
+ attachment.colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;
}
- else
+ if (has_flag(desc.render_target_write_mask, ColorWrite::ENABLE_BLUE))
{
- assert(0);
+ attachment.colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;
}
- i++;
+ if (has_flag(desc.render_target_write_mask, ColorWrite::ENABLE_ALPHA))
+ {
+ attachment.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
+ }
+
+ attachment.srcColorBlendFactor = _ConvertBlend(desc.src_blend);
+ attachment.dstColorBlendFactor = _ConvertBlend(desc.dest_blend);
+ attachment.colorBlendOp = _ConvertBlendOp(desc.blend_op);
+ attachment.srcAlphaBlendFactor = _ConvertBlend(desc.src_blend_alpha);
+ attachment.dstAlphaBlendFactor = _ConvertBlend(desc.dest_blend_alpha);
+ attachment.alphaBlendOp = _ConvertBlendOp(desc.blend_op_alpha);
}
+
+ 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 = numBlendAttachments;
+ colorBlending.pAttachments = colorBlendAttachments;
+ colorBlending.blendConstants[0] = 1.0f;
+ colorBlending.blendConstants[1] = 1.0f;
+ colorBlending.blendConstants[2] = 1.0f;
+ colorBlending.blendConstants[3] = 1.0f;
+
+ pipelineInfo.pColorBlendState = &colorBlending;
+
+ // Input layout:
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ wi::vector bindings;
+ wi::vector attributes;
+ if (pso->desc.il != nullptr)
+ {
+ uint32_t lastBinding = 0xFFFFFFFF;
+ for (auto& x : pso->desc.il->elements)
+ {
+ if (x.input_slot == lastBinding)
+ continue;
+ lastBinding = x.input_slot;
+ VkVertexInputBindingDescription& bind = bindings.emplace_back();
+ bind.binding = x.input_slot;
+ bind.inputRate = x.input_slot_class == InputClassification::PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
+ bind.stride = GetFormatStride(x.format);
+ }
+
+ uint32_t offset = 0;
+ uint32_t i = 0;
+ lastBinding = 0xFFFFFFFF;
+ for (auto& x : pso->desc.il->elements)
+ {
+ VkVertexInputAttributeDescription attr = {};
+ attr.binding = x.input_slot;
+ if (attr.binding != lastBinding)
+ {
+ lastBinding = attr.binding;
+ offset = 0;
+ }
+ attr.format = _ConvertFormat(x.format);
+ attr.location = i;
+ attr.offset = x.aligned_byte_offset;
+ if (attr.offset == InputLayout::APPEND_ALIGNED_ELEMENT)
+ {
+ // need to manually resolve this from the format spec.
+ attr.offset = offset;
+ offset += GetFormatStride(x.format);
+ }
+
+ attributes.push_back(attr);
+
+ i++;
+ }
+
+ vertexInputInfo.vertexBindingDescriptionCount = static_cast(bindings.size());
+ vertexInputInfo.pVertexBindingDescriptions = bindings.data();
+ vertexInputInfo.vertexAttributeDescriptionCount = static_cast(attributes.size());
+ vertexInputInfo.pVertexAttributeDescriptions = attributes.data();
+ }
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ pipelineInfo.renderPass = VK_NULL_HANDLE; // instead we use VkPipelineRenderingCreateInfo
+
+ VkPipelineRenderingCreateInfo renderingInfo = {};
+ renderingInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
+ renderingInfo.viewMask = 0;
+ renderingInfo.colorAttachmentCount = renderpass_info->rt_count;
+ VkFormat formats[8] = {};
+ for (uint32_t i = 0; i < renderpass_info->rt_count; ++i)
+ {
+ formats[i] = _ConvertFormat(renderpass_info->rt_formats[i]);
+ }
+ renderingInfo.pColorAttachmentFormats = formats;
+ renderingInfo.depthAttachmentFormat = _ConvertFormat(renderpass_info->ds_format);
+ if (IsFormatStencilSupport(renderpass_info->ds_format))
+ {
+ renderingInfo.stencilAttachmentFormat = renderingInfo.depthAttachmentFormat;
+ }
+ pipelineInfo.pNext = &renderingInfo;
+
+ VkResult res = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineInfo, nullptr, &internal_state->pipeline);
+ assert(res == VK_SUCCESS);
}
return res == VK_SUCCESS;
@@ -5904,7 +5625,7 @@ using namespace vulkan_internal;
VkResult res = vkCreateRayTracingPipelinesKHR(
device,
VK_NULL_HANDLE,
- VK_NULL_HANDLE,
+ pipelineCache,
1,
&info,
nullptr,
@@ -5925,6 +5646,12 @@ using namespace vulkan_internal;
format = *format_change;
}
+ Texture_Vulkan::TextureSubresource subresource;
+ subresource.firstMip = firstMip;
+ subresource.mipCount = mipCount;
+ subresource.firstSlice = firstSlice;
+ subresource.sliceCount = sliceCount;
+
VkImageViewCreateInfo view_desc = {};
view_desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view_desc.flags = 0;
@@ -5993,7 +5720,6 @@ using namespace vulkan_internal;
viewUsageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
view_desc.pNext = &viewUsageInfo;
- Texture_Vulkan::TextureSubresource subresource;
VkResult res = vkCreateImageView(device, &view_desc, nullptr, &subresource.image_view);
subresource.index = allocationhandler->bindlessSampledImages.allocate();
@@ -6036,7 +5762,6 @@ using namespace vulkan_internal;
view_desc.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
}
- Texture_Vulkan::TextureSubresource subresource;
VkResult res = vkCreateImageView(device, &view_desc, nullptr, &subresource.image_view);
subresource.index = allocationhandler->bindlessStorageImages.allocate();
@@ -6074,20 +5799,18 @@ using namespace vulkan_internal;
break;
case SubresourceType::RTV:
{
- VkImageView rtv;
view_desc.subresourceRange.levelCount = 1;
- VkResult res = vkCreateImageView(device, &view_desc, nullptr, &rtv);
+ VkResult res = vkCreateImageView(device, &view_desc, nullptr, &subresource.image_view);
if (res == VK_SUCCESS)
{
- if (internal_state->rtv == VK_NULL_HANDLE)
+ if (!internal_state->rtv.IsValid())
{
- internal_state->rtv = rtv;
+ internal_state->rtv = subresource;
internal_state->framebuffer_layercount = view_desc.subresourceRange.layerCount;
return -1;
}
- internal_state->subresources_rtv.push_back(rtv);
- internal_state->subresources_framebuffer_layercount.push_back(view_desc.subresourceRange.layerCount);
+ internal_state->subresources_rtv.push_back(subresource);
return int(internal_state->subresources_rtv.size() - 1);
}
else
@@ -6101,19 +5824,17 @@ using namespace vulkan_internal;
view_desc.subresourceRange.levelCount = 1;
view_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- VkImageView dsv;
- VkResult res = vkCreateImageView(device, &view_desc, nullptr, &dsv);
+ VkResult res = vkCreateImageView(device, &view_desc, nullptr, &subresource.image_view);
if (res == VK_SUCCESS)
{
- if (internal_state->dsv == VK_NULL_HANDLE)
+ if (!internal_state->dsv.IsValid())
{
- internal_state->dsv = dsv;
+ internal_state->dsv = subresource;
internal_state->framebuffer_layercount = view_desc.subresourceRange.layerCount;
return -1;
}
- internal_state->subresources_dsv.push_back(dsv);
- internal_state->subresources_framebuffer_layercount.push_back(view_desc.subresourceRange.layerCount);
+ internal_state->subresources_dsv.push_back(subresource);
return int(internal_state->subresources_dsv.size() - 1);
}
else
@@ -6547,6 +6268,10 @@ using namespace vulkan_internal;
{
vkCmdSetDepthBounds(commandlist.GetCommandBuffer(), 0.0f, 1.0f);
}
+
+ // Silence validation about uninitialized stride:
+ const VkDeviceSize zero = {};
+ vkCmdBindVertexBuffers2(commandlist.GetCommandBuffer(), 0, 1, &nullBuffer, &zero, &zero, &zero);
}
return cmd;
@@ -6999,9 +6724,9 @@ using namespace vulkan_internal;
void GraphicsDevice_Vulkan::RenderPassBegin(const SwapChain* swapchain, CommandList cmd)
{
CommandList_Vulkan& commandlist = GetCommandList(cmd);
-
+ commandlist.renderpass_barriers_begin.clear();
+ commandlist.renderpass_barriers_end.clear();
auto internal_state = to_internal(swapchain);
- commandlist.active_renderpass = &internal_state->renderpass;
commandlist.prev_swapchains.push_back(*swapchain);
internal_state->locker.lock();
@@ -7029,37 +6754,336 @@ using namespace vulkan_internal;
assert(0);
}
- VkClearValue clearColor = {
- swapchain->desc.clear_color[0],
- swapchain->desc.clear_color[1],
- swapchain->desc.clear_color[2],
- swapchain->desc.clear_color[3],
- };
- VkRenderPassBeginInfo renderPassInfo = {};
- renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- renderPassInfo.renderPass = to_internal(&internal_state->renderpass)->renderpass;
- renderPassInfo.framebuffer = internal_state->swapChainFramebuffers[internal_state->swapChainImageIndex];
- renderPassInfo.renderArea.offset = { 0, 0 };
- renderPassInfo.renderArea.extent = internal_state->swapChainExtent;
- renderPassInfo.clearValueCount = 1;
- renderPassInfo.pClearValues = &clearColor;
- vkCmdBeginRenderPass(commandlist.GetCommandBuffer(), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
-
+ VkRenderingInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
+ info.renderArea.offset.x = 0;
+ info.renderArea.offset.y = 0;
+ info.renderArea.extent.width = swapchain->desc.width;
+ info.renderArea.extent.height = swapchain->desc.height;
+ info.layerCount = 1;
+
+ VkRenderingAttachmentInfo color_attachment = {};
+ color_attachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
+ color_attachment.imageView = internal_state->swapChainImageViews[internal_state->swapChainImageIndex];
+ color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ color_attachment.clearValue.color.float32[0] = swapchain->desc.clear_color[0];
+ color_attachment.clearValue.color.float32[1] = swapchain->desc.clear_color[1];
+ color_attachment.clearValue.color.float32[2] = swapchain->desc.clear_color[2];
+ color_attachment.clearValue.color.float32[3] = swapchain->desc.clear_color[3];
+
+ info.colorAttachmentCount = 1;
+ info.pColorAttachments = &color_attachment;
+
+ VkImageMemoryBarrier barrier = {};
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.image = internal_state->swapChainImages[internal_state->swapChainImageIndex];
+ barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_NONE;
+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vkCmdPipelineBarrier(
+ commandlist.GetCommandBuffer(),
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ 0,
+ 0, nullptr,
+ 0, nullptr,
+ 1, &barrier
+ );
+ barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_NONE;
+ commandlist.renderpass_barriers_end.push_back(barrier);
+
+ vkCmdBeginRendering(commandlist.GetCommandBuffer(), &info);
+
+ commandlist.renderpass_info = RenderPassInfo::from(swapchain->desc);
}
- void GraphicsDevice_Vulkan::RenderPassBegin(const RenderPass* renderpass, CommandList cmd)
+ void GraphicsDevice_Vulkan::RenderPassBegin(const RenderPassImage* images, uint32_t image_count, CommandList cmd, RenderPassFlags flags)
{
CommandList_Vulkan& commandlist = GetCommandList(cmd);
- commandlist.active_renderpass = renderpass;
+ commandlist.renderpass_barriers_begin.clear();
+ commandlist.renderpass_barriers_end.clear();
- auto internal_state = to_internal(renderpass);
- vkCmdBeginRenderPass(commandlist.GetCommandBuffer(), &internal_state->beginInfo, VK_SUBPASS_CONTENTS_INLINE);
+ VkRenderingInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
+ if (has_flag(flags, RenderPassFlags::SUSPENDING))
+ {
+ info.flags |= VK_RENDERING_SUSPENDING_BIT;
+ }
+ if (has_flag(flags, RenderPassFlags::RESUMING))
+ {
+ info.flags |= VK_RENDERING_RESUMING_BIT;
+ }
+ info.layerCount = 1;
+ info.renderArea.offset.x = 0;
+ info.renderArea.offset.y = 0;
+ if (image_count == 0)
+ {
+ // no attachments can still render (UAV only rendering)
+ info.renderArea.extent.width = properties2.properties.limits.maxFramebufferWidth;
+ info.renderArea.extent.height = properties2.properties.limits.maxFramebufferHeight;
+ }
+ VkRenderingAttachmentInfo color_attachments[8] = {};
+ VkRenderingAttachmentInfo depth_attachment = {};
+ VkRenderingAttachmentInfo stencil_attachment = {};
+ VkRenderingFragmentShadingRateAttachmentInfoKHR shading_rate_attachment = {};
+ bool color = false;
+ bool depth = false;
+ bool stencil = false;
+ uint32_t color_resolve_count = 0;
+ for (uint32_t i = 0; i < image_count; ++i)
+ {
+ const RenderPassImage& image = images[i];
+ const Texture* texture = image.texture;
+ const TextureDesc& desc = texture->GetDesc();
+ int subresource = image.subresource;
+ auto internal_state = to_internal(texture);
+
+ info.renderArea.extent.width = std::max(info.renderArea.extent.width, desc.width);
+ info.renderArea.extent.height = std::max(info.renderArea.extent.height, desc.height);
+
+ VkAttachmentLoadOp loadOp;
+ switch (image.loadop)
+ {
+ default:
+ case RenderPassImage::LoadOp::LOAD:
+ loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ break;
+ case RenderPassImage::LoadOp::CLEAR:
+ loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ break;
+ case RenderPassImage::LoadOp::DONTCARE:
+ loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ break;
+ }
+
+ VkAttachmentStoreOp storeOp;
+ switch (image.storeop)
+ {
+ default:
+ case RenderPassImage::StoreOp::STORE:
+ storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ break;
+ case RenderPassImage::StoreOp::DONTCARE:
+ storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ break;
+ }
+
+ Texture_Vulkan::TextureSubresource descriptor;
+
+ switch (image.type)
+ {
+ case RenderPassImage::Type::RENDERTARGET:
+ {
+ descriptor = subresource < 0 ? internal_state->rtv : internal_state->subresources_rtv[subresource];
+ VkRenderingAttachmentInfo& color_attachment = color_attachments[info.colorAttachmentCount++];
+ color_attachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
+ color_attachment.imageView = descriptor.image_view;
+ color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ color_attachment.loadOp = loadOp;
+ color_attachment.storeOp = storeOp;
+ color_attachment.clearValue.color.float32[0] = desc.clear.color[0];
+ color_attachment.clearValue.color.float32[1] = desc.clear.color[1];
+ color_attachment.clearValue.color.float32[2] = desc.clear.color[2];
+ color_attachment.clearValue.color.float32[3] = desc.clear.color[3];
+ color = true;
+ }
+ break;
+
+ case RenderPassImage::Type::RESOLVE:
+ {
+ descriptor = subresource < 0 ? internal_state->srv : internal_state->subresources_srv[subresource];
+ VkRenderingAttachmentInfo& color_attachment = color_attachments[color_resolve_count++];
+ color_attachment.resolveImageView = descriptor.image_view;
+ color_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ color_attachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
+ }
+ break;
+
+ case RenderPassImage::Type::DEPTH_STENCIL:
+ {
+ descriptor = subresource < 0 ? internal_state->dsv : internal_state->subresources_dsv[subresource];
+ depth_attachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
+ depth_attachment.imageView = descriptor.image_view;
+ if (image.layout == ResourceState::DEPTHSTENCIL_READONLY)
+ {
+ depth_attachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
+ }
+ else
+ {
+ depth_attachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
+ }
+ depth_attachment.loadOp = loadOp;
+ depth_attachment.storeOp = storeOp;
+ depth_attachment.clearValue.depthStencil.depth = desc.clear.depth_stencil.depth;
+ depth = true;
+ if (IsFormatStencilSupport(desc.format))
+ {
+ stencil_attachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
+ stencil_attachment.imageView = subresource < 0 ? internal_state->dsv.image_view : internal_state->subresources_dsv[subresource].image_view;
+ if (image.layout == ResourceState::DEPTHSTENCIL_READONLY)
+ {
+ stencil_attachment.imageLayout = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL;
+ }
+ else
+ {
+ stencil_attachment.imageLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
+ }
+ stencil_attachment.loadOp = loadOp;
+ stencil_attachment.storeOp = storeOp;
+ stencil_attachment.clearValue.depthStencil.stencil = desc.clear.depth_stencil.stencil;
+ stencil = true;
+ }
+ }
+ break;
+
+ case RenderPassImage::Type::RESOLVE_DEPTH:
+ {
+ descriptor = subresource < 0 ? internal_state->dsv : internal_state->subresources_dsv[subresource];
+ depth_attachment.resolveImageView = descriptor.image_view;
+ stencil_attachment.resolveImageView = descriptor.image_view;
+ depth_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
+ stencil_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
+ switch (image.depth_resolve_mode)
+ {
+ default:
+ case RenderPassImage::DepthResolveMode::Min:
+ depth_attachment.resolveMode = VK_RESOLVE_MODE_MIN_BIT;
+ stencil_attachment.resolveMode = VK_RESOLVE_MODE_MIN_BIT;
+ break;
+ case RenderPassImage::DepthResolveMode::Max:
+ depth_attachment.resolveMode = VK_RESOLVE_MODE_MAX_BIT;
+ stencil_attachment.resolveMode = VK_RESOLVE_MODE_MAX_BIT;
+ break;
+ }
+ }
+ break;
+
+ case RenderPassImage::Type::SHADING_RATE_SOURCE:
+ descriptor = subresource < 0 ? internal_state->uav : internal_state->subresources_uav[subresource];
+ shading_rate_attachment.sType = VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
+ shading_rate_attachment.imageView = descriptor.image_view;
+ shading_rate_attachment.imageLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+ shading_rate_attachment.shadingRateAttachmentTexelSize.width = VARIABLE_RATE_SHADING_TILE_SIZE;
+ shading_rate_attachment.shadingRateAttachmentTexelSize.height = VARIABLE_RATE_SHADING_TILE_SIZE;
+ info.pNext = &shading_rate_attachment;
+ break;
+ default:
+ break;
+ }
+
+ if (image.layout_before != image.layout)
+ {
+ VkImageMemoryBarrier& barrier = commandlist.renderpass_barriers_begin.emplace_back();
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.image = internal_state->resource;
+ barrier.oldLayout = _ConvertImageLayout(image.layout_before);
+ barrier.newLayout = _ConvertImageLayout(image.layout);
+ barrier.srcAccessMask = _ParseResourceState(image.layout_before);
+ barrier.dstAccessMask = _ParseResourceState(image.layout);
+ if (IsFormatDepthSupport(desc.format))
+ {
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (IsFormatStencilSupport(desc.format))
+ {
+ barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ }
+ }
+ else
+ {
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+ barrier.subresourceRange.baseMipLevel = descriptor.firstMip;
+ barrier.subresourceRange.levelCount = descriptor.mipCount;
+ barrier.subresourceRange.baseArrayLayer = descriptor.firstSlice;
+ barrier.subresourceRange.layerCount = descriptor.sliceCount;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ }
+
+ if (image.layout != image.layout_after)
+ {
+ VkImageMemoryBarrier& barrier = commandlist.renderpass_barriers_end.emplace_back();
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.image = internal_state->resource;
+ barrier.oldLayout = _ConvertImageLayout(image.layout);
+ barrier.newLayout = _ConvertImageLayout(image.layout_after);
+ barrier.srcAccessMask = _ParseResourceState(image.layout);
+ barrier.dstAccessMask = _ParseResourceState(image.layout_after);
+ if (IsFormatDepthSupport(desc.format))
+ {
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (IsFormatStencilSupport(desc.format))
+ {
+ barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ }
+ }
+ else
+ {
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+ barrier.subresourceRange.baseMipLevel = descriptor.firstMip;
+ barrier.subresourceRange.levelCount = descriptor.mipCount;
+ barrier.subresourceRange.baseArrayLayer = descriptor.firstSlice;
+ barrier.subresourceRange.layerCount = descriptor.sliceCount;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ }
+
+ info.layerCount = std::min(desc.array_size, std::max(info.layerCount, descriptor.sliceCount));
+ }
+ info.pColorAttachments = color ? color_attachments : nullptr;
+ info.pDepthAttachment = depth ? &depth_attachment : nullptr;
+ info.pStencilAttachment = stencil ? &stencil_attachment : nullptr;
+
+ if (!commandlist.renderpass_barriers_begin.empty())
+ {
+ vkCmdPipelineBarrier(
+ commandlist.GetCommandBuffer(),
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ 0,
+ 0, nullptr,
+ 0, nullptr,
+ (uint32_t)commandlist.renderpass_barriers_begin.size(), commandlist.renderpass_barriers_begin.data()
+ );
+ }
+
+ vkCmdBeginRendering(commandlist.GetCommandBuffer(), &info);
+
+ commandlist.renderpass_info = RenderPassInfo::from(images, image_count);
}
void GraphicsDevice_Vulkan::RenderPassEnd(CommandList cmd)
{
CommandList_Vulkan& commandlist = GetCommandList(cmd);
- vkCmdEndRenderPass(commandlist.GetCommandBuffer());
+ vkCmdEndRendering(commandlist.GetCommandBuffer());
- commandlist.active_renderpass = nullptr;
+ if (!commandlist.renderpass_barriers_end.empty())
+ {
+ vkCmdPipelineBarrier(
+ commandlist.GetCommandBuffer(),
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ 0,
+ 0, nullptr,
+ 0, nullptr,
+ (uint32_t)commandlist.renderpass_barriers_end.size(), commandlist.renderpass_barriers_end.data()
+ );
+ commandlist.renderpass_barriers_end.clear();
+ }
+
+ commandlist.renderpass_info = {};
}
void GraphicsDevice_Vulkan::BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd)
{
@@ -7174,12 +7198,12 @@ using namespace vulkan_internal;
size_t hash = 0;
VkDeviceSize voffsets[8] = {};
+ VkDeviceSize vstrides[8] = {};
VkBuffer vbuffers[8] = {};
assert(count <= 8);
for (uint32_t i = 0; i < count; ++i)
{
wi::helper::hash_combine(hash, strides[i]);
- commandlist.vb_strides[i] = strides[i];
if (vertexBuffers[i] == nullptr || !vertexBuffers[i]->IsValid())
{
@@ -7193,20 +7217,14 @@ using namespace vulkan_internal;
{
voffsets[i] = offsets[i];
}
+ if (strides != nullptr)
+ {
+ vstrides[i] = strides[i];
+ }
}
}
- for (int i = count; i < arraysize(commandlist.vb_strides); ++i)
- {
- commandlist.vb_strides[i] = 0;
- }
- vkCmdBindVertexBuffers(commandlist.GetCommandBuffer(), static_cast(slot), static_cast(count), vbuffers, voffsets);
-
- if (hash != commandlist.vb_hash)
- {
- commandlist.vb_hash = hash;
- commandlist.dirty_pso = true;
- }
+ vkCmdBindVertexBuffers2(commandlist.GetCommandBuffer(), slot, count, vbuffers, voffsets, nullptr, vstrides);
}
void GraphicsDevice_Vulkan::BindIndexBuffer(const GPUBuffer* indexBuffer, const IndexBufferFormat format, uint64_t offset, CommandList cmd)
{
@@ -7315,20 +7333,28 @@ using namespace vulkan_internal;
commandlist.active_cs = nullptr;
commandlist.active_rt = nullptr;
- size_t pipeline_hash = 0;
- wi::helper::hash_combine(pipeline_hash, pso->hash);
- if (commandlist.active_renderpass != nullptr)
- {
- wi::helper::hash_combine(pipeline_hash, commandlist.active_renderpass->hash);
- }
- if (commandlist.prev_pipeline_hash == pipeline_hash)
- {
- return;
- }
- commandlist.prev_pipeline_hash = pipeline_hash;
-
auto internal_state = to_internal(pso);
+ if (internal_state->pipeline != VK_NULL_HANDLE)
+ {
+ vkCmdBindPipeline(commandlist.GetCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, internal_state->pipeline);
+
+ commandlist.prev_pipeline_hash = 0;
+ commandlist.dirty_pso = false;
+ }
+ else
+ {
+ size_t pipeline_hash = 0;
+ wi::helper::hash_combine(pipeline_hash, internal_state->hash);
+ wi::helper::hash_combine(pipeline_hash, commandlist.renderpass_info.get_hash());
+ if (commandlist.prev_pipeline_hash == pipeline_hash)
+ {
+ return;
+ }
+ commandlist.prev_pipeline_hash = pipeline_hash;
+ commandlist.dirty_pso = true;
+ }
+
if (commandlist.active_pso == nullptr)
{
commandlist.binder.dirty |= DescriptorBinder::DIRTY_ALL;
@@ -7357,7 +7383,6 @@ using namespace vulkan_internal;
}
commandlist.active_pso = pso;
- commandlist.dirty_pso = true;
}
void GraphicsDevice_Vulkan::BindComputeShader(const Shader* cs, CommandList cmd)
{
@@ -7769,7 +7794,6 @@ using namespace vulkan_internal;
void GraphicsDevice_Vulkan::QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd)
{
CommandList_Vulkan& commandlist = GetCommandList(cmd);
- assert(commandlist.active_renderpass == nullptr); // Can't resolve inside renderpass!
auto internal_state = to_internal(heap);
auto dst_internal = to_internal(dest);
@@ -7801,7 +7825,6 @@ using namespace vulkan_internal;
void GraphicsDevice_Vulkan::QueryReset(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd)
{
CommandList_Vulkan& commandlist = GetCommandList(cmd);
- assert(commandlist.active_renderpass == nullptr); // Can't resolve inside renderpass!
auto internal_state = to_internal(heap);
@@ -7816,7 +7839,6 @@ using namespace vulkan_internal;
void GraphicsDevice_Vulkan::Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd)
{
CommandList_Vulkan& commandlist = GetCommandList(cmd);
- assert(commandlist.active_renderpass == nullptr);
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h
index 437ad52c2..357da2035 100644
--- a/WickedEngine/wiGraphicsDevice_Vulkan.h
+++ b/WickedEngine/wiGraphicsDevice_Vulkan.h
@@ -49,6 +49,7 @@ namespace wi::graphics
VkPhysicalDeviceProperties2 properties2 = {};
VkPhysicalDeviceVulkan11Properties properties_1_1 = {};
VkPhysicalDeviceVulkan12Properties properties_1_2 = {};
+ VkPhysicalDeviceVulkan13Properties properties_1_3 = {};
VkPhysicalDeviceSamplerFilterMinmaxProperties sampler_minmax_properties = {};
VkPhysicalDeviceAccelerationStructurePropertiesKHR acceleration_structure_properties = {};
VkPhysicalDeviceRayTracingPipelinePropertiesKHR raytracing_properties = {};
@@ -60,6 +61,7 @@ namespace wi::graphics
VkPhysicalDeviceFeatures2 features2 = {};
VkPhysicalDeviceVulkan11Features features_1_1 = {};
VkPhysicalDeviceVulkan12Features features_1_2 = {};
+ VkPhysicalDeviceVulkan13Features features_1_3 = {};
VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features = {};
VkPhysicalDeviceRayTracingPipelineFeaturesKHR raytracing_features = {};
VkPhysicalDeviceRayQueryFeaturesKHR raytracing_query_features = {};
@@ -213,17 +215,17 @@ namespace wi::graphics
const PipelineState* active_pso = {};
const Shader* active_cs = {};
const RaytracingPipelineState* active_rt = {};
- const RenderPass* active_renderpass = {};
ShadingRate prev_shadingrate = {};
wi::vector prev_swapchains;
- uint32_t vb_strides[8] = {};
- size_t vb_hash = {};
bool dirty_pso = {};
wi::vector frame_memoryBarriers;
wi::vector frame_imageBarriers;
wi::vector frame_bufferBarriers;
wi::vector accelerationstructure_build_geometries;
wi::vector accelerationstructure_build_ranges;
+ RenderPassInfo renderpass_info;
+ wi::vector renderpass_barriers_begin;
+ wi::vector renderpass_barriers_end;
void reset(uint32_t bufferindex)
{
@@ -236,15 +238,12 @@ namespace wi::graphics
active_pso = nullptr;
active_cs = nullptr;
active_rt = nullptr;
- active_renderpass = nullptr;
dirty_pso = false;
prev_shadingrate = ShadingRate::RATE_INVALID;
- vb_hash = 0;
- for (int i = 0; i < arraysize(vb_strides); ++i)
- {
- vb_strides[i] = 0;
- }
prev_swapchains.clear();
+ renderpass_info = {};
+ renderpass_barriers_begin.clear();
+ renderpass_barriers_end.clear();
}
inline VkCommandPool GetCommandPool() const
@@ -297,8 +296,7 @@ namespace wi::graphics
bool CreateShader(ShaderStage stage, const void* shadercode, size_t shadercode_size, Shader* shader) const override;
bool CreateSampler(const SamplerDesc* desc, Sampler* sampler) const override;
bool CreateQueryHeap(const GPUQueryHeapDesc* desc, GPUQueryHeap* queryheap) const override;
- bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso) const override;
- bool CreateRenderPass(const RenderPassDesc* desc, RenderPass* renderpass) const override;
+ bool CreatePipelineState(const PipelineStateDesc* desc, PipelineState* pso, const RenderPassInfo* renderpass_info = nullptr) const override;
bool CreateRaytracingAccelerationStructure(const RaytracingAccelerationStructureDesc* desc, RaytracingAccelerationStructure* bvh) const override;
bool CreateRaytracingPipelineState(const RaytracingPipelineStateDesc* desc, RaytracingPipelineState* rtpso) const override;
@@ -371,7 +369,7 @@ namespace wi::graphics
void WaitCommandList(CommandList cmd, CommandList wait_for) override;
void RenderPassBegin(const SwapChain* swapchain, CommandList cmd) override;
- void RenderPassBegin(const RenderPass* renderpass, CommandList cmd) override;
+ void RenderPassBegin(const RenderPassImage* images, uint32_t image_count, CommandList cmd, RenderPassFlags flags = RenderPassFlags::NONE) override;
void RenderPassEnd(CommandList cmd) override;
void BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) override;
void BindViewports(uint32_t NumViewports, const Viewport *pViewports, CommandList cmd) override;
@@ -422,6 +420,11 @@ namespace wi::graphics
void EventEnd(CommandList cmd) override;
void SetMarker(const char* name, CommandList cmd) override;
+ RenderPassInfo GetRenderPassInfo(CommandList cmd) override
+ {
+ return GetCommandList(cmd).renderpass_info;
+ }
+
GPULinearAllocator& GetFrameAllocator(CommandList cmd) override
{
return GetCommandList(cmd).frame_allocators[GetBufferIndex()];
@@ -560,8 +563,6 @@ namespace wi::graphics
std::deque> destroyer_shadermodules;
std::deque> destroyer_pipelineLayouts;
std::deque> destroyer_pipelines;
- std::deque> destroyer_renderpasses;
- std::deque> destroyer_framebuffers;
std::deque> destroyer_querypools;
std::deque> destroyer_swapchains;
std::deque> destroyer_surfaces;
@@ -763,32 +764,6 @@ namespace wi::graphics
break;
}
}
- while (!destroyer_renderpasses.empty())
- {
- if (destroyer_renderpasses.front().second + BUFFERCOUNT < FRAMECOUNT)
- {
- auto item = destroyer_renderpasses.front();
- destroyer_renderpasses.pop_front();
- vkDestroyRenderPass(device, item.first, nullptr);
- }
- else
- {
- break;
- }
- }
- while (!destroyer_framebuffers.empty())
- {
- if (destroyer_framebuffers.front().second + BUFFERCOUNT < FRAMECOUNT)
- {
- auto item = destroyer_framebuffers.front();
- destroyer_framebuffers.pop_front();
- vkDestroyFramebuffer(device, item.first, nullptr);
- }
- else
- {
- break;
- }
- }
while (!destroyer_querypools.empty())
{
if (destroyer_querypools.front().second + BUFFERCOUNT < FRAMECOUNT)
diff --git a/WickedEngine/wiJobSystem.cpp b/WickedEngine/wiJobSystem.cpp
index 8c26ecc81..a25797ebb 100644
--- a/WickedEngine/wiJobSystem.cpp
+++ b/WickedEngine/wiJobSystem.cpp
@@ -67,11 +67,19 @@ namespace wi::jobsystem
~InternalState()
{
alive.store(false); // indicate that new jobs cannot be started from this point
- wakeCondition.notify_all(); // wakes up sleeping worker threads
+ bool wake_loop = true;
+ std::thread waker([&] {
+ while (wake_loop)
+ {
+ wakeCondition.notify_all(); // wakes up sleeping worker threads
+ }
+ });
for (auto& thread : threads)
{
thread.join();
}
+ wake_loop = false;
+ waker.join();
}
} static internal_state;
diff --git a/WickedEngine/wiRenderPath2D.cpp b/WickedEngine/wiRenderPath2D.cpp
index 4316fa6c8..de7c8626f 100644
--- a/WickedEngine/wiRenderPath2D.cpp
+++ b/WickedEngine/wiRenderPath2D.cpp
@@ -47,51 +47,6 @@ namespace wi
device->CreateTexture(&desc, nullptr, &rtFinal);
device->SetName(&rtFinal, "rtFinal");
}
-
- if (rtStenciled.IsValid())
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtStenciled, RenderPassAttachment::LoadOp::CLEAR));
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- *dsv,
- RenderPassAttachment::LoadOp::LOAD,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY
- )
- );
-
- if (rtStenciled.GetDesc().sample_count > 1)
- {
- desc.attachments.push_back(RenderPassAttachment::Resolve(rtStenciled_resolved));
- }
-
- device->CreateRenderPass(&desc, &renderpass_stenciled);
-
- dsv = nullptr;
- }
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtFinal, RenderPassAttachment::LoadOp::CLEAR));
-
- if (dsv != nullptr && !rtStenciled.IsValid())
- {
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- *dsv,
- RenderPassAttachment::LoadOp::LOAD,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY
- )
- );
- }
-
- device->CreateRenderPass(&desc, &renderpass_final);
- }
}
void RenderPath2D::ResizeLayout()
{
@@ -179,11 +134,44 @@ namespace wi
wi::image::SetBackground(*GetGUIBlurredBackground());
}
+ const Texture* dsv = GetDepthStencil();
+
// Special care for internal resolution, because stencil buffer is of internal resolution,
// so we might need to render stencil sprites to separate render target that matches internal resolution!
if (rtStenciled.IsValid())
{
- device->RenderPassBegin(&renderpass_stenciled, cmd);
+ if (rtStenciled.GetDesc().sample_count > 1)
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtStenciled, RenderPassImage::LoadOp::CLEAR),
+ RenderPassImage::DepthStencil(
+ dsv,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ RenderPassImage::Resolve(&rtStenciled_resolved)
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
+ else
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtStenciled, RenderPassImage::LoadOp::CLEAR),
+ RenderPassImage::DepthStencil(
+ dsv,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
+ dsv = nullptr;
Viewport vp;
vp.width = (float)rtStenciled.GetDesc().width;
@@ -208,7 +196,28 @@ namespace wi
device->RenderPassEnd(cmd);
}
- device->RenderPassBegin(&renderpass_final, cmd);
+ if (dsv != nullptr && !rtStenciled.IsValid())
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtFinal, RenderPassImage::LoadOp::CLEAR),
+ RenderPassImage::DepthStencil(
+ dsv,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
+ else
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtFinal, RenderPassImage::LoadOp::CLEAR),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
Viewport vp;
vp.width = (float)rtFinal.GetDesc().width;
diff --git a/WickedEngine/wiRenderPath2D.h b/WickedEngine/wiRenderPath2D.h
index f2be31ec5..3abe34508 100644
--- a/WickedEngine/wiRenderPath2D.h
+++ b/WickedEngine/wiRenderPath2D.h
@@ -18,9 +18,6 @@ namespace wi
wi::graphics::Texture rtStenciled_resolved;
wi::graphics::Texture rtFinal;
- wi::graphics::RenderPass renderpass_stenciled;
- wi::graphics::RenderPass renderpass_final;
-
wi::gui::GUI GUI;
XMUINT2 current_buffersize{};
diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp
index 9baf48c28..078d93342 100644
--- a/WickedEngine/wiRenderPath3D.cpp
+++ b/WickedEngine/wiRenderPath3D.cpp
@@ -51,17 +51,6 @@ namespace wi
depthBuffer_Reflection = {};
rtLinearDepth = {};
- renderpass_depthprepass = {};
- renderpass_main = {};
- renderpass_transparent = {};
- renderpass_reflection_depthprepass = {};
- renderpass_reflection = {};
- renderpass_lightshafts = {};
- renderpass_volumetriclight = {};
- renderpass_particledistortion = {};
- renderpass_waterripples = {};
- renderpass_outline_source = {};
-
debugUAV = {};
tiledLightResources = {};
tiledLightResources_planarReflection = {};
@@ -285,103 +274,6 @@ namespace wi
}
}
- // Render passes:
- {
- RenderPassDesc desc;
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- depthBuffer_Main,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL,
- ResourceState::DEPTHSTENCIL_READONLY
- )
- );
- desc.attachments.push_back(
- RenderPassAttachment::RenderTarget(
- rtPrimitiveID_render,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::SHADER_RESOURCE_COMPUTE,
- ResourceState::RENDERTARGET,
- ResourceState::SHADER_RESOURCE_COMPUTE
- )
- );
- device->CreateRenderPass(&desc, &renderpass_depthprepass);
-
- desc.attachments.clear();
- desc.attachments.push_back(
- RenderPassAttachment::RenderTarget(
- rtMain_render,
- RenderPassAttachment::LoadOp::LOAD
- )
- );
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- depthBuffer_Main,
- RenderPassAttachment::LoadOp::LOAD,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY
- )
- );
- if (getMSAASampleCount() > 1)
- {
- desc.attachments.push_back(RenderPassAttachment::Resolve(rtMain));
- }
-
- if (device->CheckCapability(GraphicsDeviceCapability::VARIABLE_RATE_SHADING_TIER2) && rtShadingRate.IsValid())
- {
- desc.attachments.push_back(RenderPassAttachment::ShadingRateSource(rtShadingRate, ResourceState::UNORDERED_ACCESS, ResourceState::UNORDERED_ACCESS));
- }
-
- desc.flags |= RenderPassDesc::Flags::ALLOW_UAV_WRITES;
- device->CreateRenderPass(&desc, &renderpass_main);
- }
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtMain_render, RenderPassAttachment::LoadOp::LOAD));
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- depthBuffer_Main,
- RenderPassAttachment::LoadOp::LOAD,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL,
- ResourceState::DEPTHSTENCIL_READONLY
- )
- );
- if (getMSAASampleCount() > 1)
- {
- desc.attachments.push_back(RenderPassAttachment::Resolve(rtMain));
- }
- desc.flags |= RenderPassDesc::Flags::ALLOW_UAV_WRITES;
- device->CreateRenderPass(&desc, &renderpass_transparent);
- }
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtParticleDistortion, RenderPassAttachment::LoadOp::CLEAR));
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- depthBuffer_Main,
- RenderPassAttachment::LoadOp::LOAD,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY
- )
- );
-
- if (getMSAASampleCount() > 1)
- {
- desc.attachments.push_back(RenderPassAttachment::Resolve(rtParticleDistortion_Resolved));
- }
-
- device->CreateRenderPass(&desc, &renderpass_particledistortion);
- }
-
// Other resources:
{
@@ -576,18 +468,11 @@ namespace wi
desc.height = internalResolution.y / 8;
device->CreateTexture(&desc, nullptr, &rtWaterRipple);
device->SetName(&rtWaterRipple, "rtWaterRipple");
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtWaterRipple, RenderPassAttachment::LoadOp::CLEAR));
-
- device->CreateRenderPass(&desc, &renderpass_waterripples);
- }
}
}
else
{
rtWaterRipple = {};
- renderpass_waterripples = {};
}
if (wi::renderer::GetSurfelGIEnabled())
@@ -829,7 +714,24 @@ namespace wi
wi::renderer::OcclusionCulling_Reset(visibility_main, cmd); // must be outside renderpass!
- device->RenderPassBegin(&renderpass_depthprepass, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Main,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ RenderPassImage::RenderTarget(
+ &rtPrimitiveID_render,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::SHADER_RESOURCE_COMPUTE,
+ ResourceState::SHADER_RESOURCE_COMPUTE
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
device->EventBegin("Opaque Z-prepass", cmd);
auto range = wi::profiler::BeginRangeGPU("Z-Prepass", cmd);
@@ -1030,7 +932,17 @@ namespace wi
vp.height = (float)depthBuffer_Reflection.GetDesc().height;
device->BindViewports(1, &vp, cmd);
- device->RenderPassBegin(&renderpass_reflection_depthprepass, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Reflection,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL,
+ ResourceState::DEPTHSTENCIL,
+ ResourceState::SHADER_RESOURCE
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
wi::renderer::DrawScene(visibility_reflection, RENDERPASS_PREPASS, cmd, wi::renderer::DRAWSCENE_OPAQUE | wi::renderer::DRAWSCENE_IMPOSTOR);
@@ -1077,8 +989,22 @@ namespace wi
vp.height = (float)depthBuffer_Reflection.GetDesc().height;
device->BindViewports(1, &vp, cmd);
-
- device->RenderPassBegin(&renderpass_reflection, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(
+ &rtReflection,
+ RenderPassImage::LoadOp::DONTCARE,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::SHADER_RESOURCE,
+ ResourceState::SHADER_RESOURCE
+ ),
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Reflection,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::DONTCARE,
+ ResourceState::SHADER_RESOURCE
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
wi::renderer::DrawScene(visibility_reflection, RENDERPASS_MAIN, cmd, wi::renderer::DRAWSCENE_OPAQUE | wi::renderer::DRAWSCENE_IMPOSTOR);
wi::renderer::DrawScene(visibility_reflection, RENDERPASS_MAIN, cmd, wi::renderer::DRAWSCENE_TRANSPARENT); // separate renderscene, to be drawn after opaque and transparent sort order
@@ -1177,7 +1103,12 @@ namespace wi
{
// Cut off outline source from linear depth:
device->EventBegin("Outline Source", cmd);
- device->RenderPassBegin(&renderpass_outline_source, cmd);
+
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtOutlineSource, RenderPassImage::LoadOp::CLEAR),
+ RenderPassImage::DepthStencil(&depthBuffer_Main, RenderPassImage::LoadOp::LOAD)
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
wi::image::Params params;
params.enableFullScreen();
params.stencilRefMode = wi::image::STENCILREFMODE_ENGINE;
@@ -1190,8 +1121,32 @@ namespace wi
device->EventEnd(cmd);
}
-
- device->RenderPassBegin(&renderpass_main, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(
+ &rtMain_render,
+ RenderPassImage::LoadOp::LOAD
+ ),
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Main,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ RenderPassImage::Resolve(&rtMain),
+ RenderPassImage::ShadingRateSource(&rtShadingRate, ResourceState::UNORDERED_ACCESS, ResourceState::UNORDERED_ACCESS),
+ };
+ uint32_t rp_count = 2;
+ if (getMSAASampleCount() > 1)
+ {
+ rp_count++;
+ }
+ if (device->CheckCapability(GraphicsDeviceCapability::VARIABLE_RATE_SHADING_TIER2) && rtShadingRate.IsValid())
+ {
+ rp_count++;
+ }
+ device->RenderPassBegin(rp, rp_count, cmd, RenderPassFlags::ALLOW_UAV_WRITES);
if (visibility_shading_in_compute)
{
@@ -1423,7 +1378,37 @@ namespace wi
// Render sun stencil cutout:
{
- device->RenderPassBegin(&renderpass_lightshafts, cmd);
+ if (getMSAASampleCount() > 1)
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Main,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ RenderPassImage::RenderTarget(&rtSun[0], RenderPassImage::LoadOp::CLEAR, RenderPassImage::StoreOp::DONTCARE),
+ RenderPassImage::Resolve(&rtSun_resolved),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
+ else
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Main,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ RenderPassImage::RenderTarget(&rtSun[0], RenderPassImage::LoadOp::CLEAR),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
Viewport vp;
vp.width = (float)depthBuffer_Main.GetDesc().width;
@@ -1454,7 +1439,7 @@ namespace wi
XMFLOAT2 sun;
XMStoreFloat2(&sun, sunPos);
wi::renderer::Postprocess_LightShafts(
- renderpass_lightshafts.desc.attachments.back().texture,
+ getMSAASampleCount() > 1 ? rtSun_resolved : rtSun[0],
rtSun[1],
cmd,
sun,
@@ -1473,7 +1458,10 @@ namespace wi
GraphicsDevice* device = wi::graphics::GetDevice();
- device->RenderPassBegin(&renderpass_volumetriclight, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtVolumetricLights[0], RenderPassImage::LoadOp::CLEAR),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
Viewport vp;
vp.width = (float)rtVolumetricLights[0].GetDesc().width;
@@ -1518,7 +1506,11 @@ namespace wi
// Water ripple rendering:
if (!scene->waterRipples.empty())
{
- device->RenderPassBegin(&renderpass_waterripples, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtWaterRipple, RenderPassImage::LoadOp::CLEAR),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+
Viewport vp;
vp.width = (float)rtWaterRipple.GetDesc().width;
vp.height = (float)rtWaterRipple.GetDesc().height;
@@ -1549,7 +1541,19 @@ namespace wi
device->Barrier(barriers, arraysize(barriers), cmd);
}
- device->RenderPassBegin(&renderpass_transparent, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtMain_render, RenderPassImage::LoadOp::LOAD),
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Main,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ RenderPassImage::Resolve(&rtMain),
+ };
+ device->RenderPassBegin(rp, getMSAASampleCount() > 1 ? 3 : 2, cmd);
Viewport vp;
vp.width = (float)depthBuffer_Main.GetDesc().width;
@@ -1579,8 +1583,14 @@ namespace wi
if (getVolumeLightsEnabled() && visibility_main.IsRequestedVolumetricLights())
{
device->EventBegin("Contribute Volumetric Lights", cmd);
- wi::renderer::Postprocess_Upsample_Bilateral(rtVolumetricLights[0], rtLinearDepth,
- renderpass_transparent.desc.attachments[0].texture, cmd, true, 1.5f);
+ wi::renderer::Postprocess_Upsample_Bilateral(
+ rtVolumetricLights[0],
+ rtLinearDepth,
+ rtMain,
+ cmd,
+ true,
+ 1.5f
+ );
device->EventEnd(cmd);
}
@@ -1610,7 +1620,37 @@ namespace wi
// Distortion particles:
{
- device->RenderPassBegin(&renderpass_particledistortion, cmd);
+ if (getMSAASampleCount() > 1)
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtParticleDistortion, RenderPassImage::LoadOp::CLEAR),
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Main,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ RenderPassImage::Resolve(&rtParticleDistortion_Resolved)
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
+ else
+ {
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&rtParticleDistortion, RenderPassImage::LoadOp::CLEAR),
+ RenderPassImage::DepthStencil(
+ &depthBuffer_Main,
+ RenderPassImage::LoadOp::LOAD,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY,
+ ResourceState::DEPTHSTENCIL_READONLY
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
+ }
Viewport vp;
vp.width = (float)rtParticleDistortion.GetDesc().width;
@@ -2090,60 +2130,19 @@ namespace wi
device->SetName(&rtReflection, "rtReflection");
desc.bind_flags = BindFlag::DEPTH_STENCIL | BindFlag::SHADER_RESOURCE;
- desc.format = Format::D32_FLOAT;
+ desc.format = Format::D32_FLOAT_S8X24_UINT;
desc.width = internalResolution.x / 2;
desc.height = internalResolution.y / 2;
desc.layout = ResourceState::DEPTHSTENCIL;
device->CreateTexture(&desc, nullptr, &depthBuffer_Reflection);
device->SetName(&depthBuffer_Reflection, "depthBuffer_Reflection");
- {
- RenderPassDesc desc;
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- depthBuffer_Reflection,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL,
- ResourceState::DEPTHSTENCIL,
- ResourceState::SHADER_RESOURCE
- )
- );
-
- device->CreateRenderPass(&desc, &renderpass_reflection_depthprepass);
- }
- {
- RenderPassDesc desc;
- desc.attachments.push_back(
- RenderPassAttachment::RenderTarget(
- rtReflection,
- RenderPassAttachment::LoadOp::DONTCARE,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::SHADER_RESOURCE,
- ResourceState::RENDERTARGET,
- ResourceState::SHADER_RESOURCE
- )
- );
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- depthBuffer_Reflection,
- RenderPassAttachment::LoadOp::LOAD,
- RenderPassAttachment::StoreOp::DONTCARE,
- ResourceState::SHADER_RESOURCE
- )
- );
-
- device->CreateRenderPass(&desc, &renderpass_reflection);
- }
-
wi::renderer::CreateTiledLightResources(tiledLightResources_planarReflection, XMUINT2(depthBuffer_Reflection.desc.width, depthBuffer_Reflection.desc.height));
}
else
{
rtReflection = {};
depthBuffer_Reflection = {};
- renderpass_reflection_depthprepass = {};
- renderpass_reflection = {};
tiledLightResources_planarReflection = {};
}
}
@@ -2180,18 +2179,11 @@ namespace wi
device->SetName(&rtVolumetricLights[0], "rtVolumetricLights[0]");
device->CreateTexture(&desc, nullptr, &rtVolumetricLights[1]);
device->SetName(&rtVolumetricLights[1], "rtVolumetricLights[1]");
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtVolumetricLights[0], RenderPassAttachment::LoadOp::CLEAR));
-
- device->CreateRenderPass(&desc, &renderpass_volumetriclight);
- }
}
else
{
rtVolumetricLights[0] = {};
rtVolumetricLights[1] = {};
- renderpass_volumetriclight = {};
}
}
void RenderPath3D::setLightShaftsEnabled(bool value)
@@ -2229,35 +2221,12 @@ namespace wi
device->CreateTexture(&desc, nullptr, &rtSun_resolved);
device->SetName(&rtSun_resolved, "rtSun_resolved");
}
-
- {
- RenderPassDesc desc;
- desc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- depthBuffer_Main,
- RenderPassAttachment::LoadOp::LOAD,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY,
- ResourceState::DEPTHSTENCIL_READONLY
- )
- );
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtSun[0], RenderPassAttachment::LoadOp::CLEAR));
- if (getMSAASampleCount() > 1)
- {
- desc.attachments.back().storeop = RenderPassAttachment::StoreOp::DONTCARE;
- desc.attachments.push_back(RenderPassAttachment::Resolve(rtSun_resolved));
- }
-
- device->CreateRenderPass(&desc, &renderpass_lightshafts);
- }
}
else
{
rtSun[0] = {};
rtSun[1] = {};
rtSun_resolved = {};
- renderpass_lightshafts = {};
}
}
void RenderPath3D::setOutlineEnabled(bool value)
@@ -2278,19 +2247,10 @@ namespace wi
desc.height = internalResolution.y;
device->CreateTexture(&desc, nullptr, &rtOutlineSource);
device->SetName(&rtOutlineSource, "rtOutlineSource");
-
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(rtOutlineSource, RenderPassAttachment::LoadOp::CLEAR));
- desc.attachments.push_back(RenderPassAttachment::DepthStencil(depthBuffer_Main, RenderPassAttachment::LoadOp::LOAD));
-
- device->CreateRenderPass(&desc, &renderpass_outline_source);
- }
}
else
{
rtOutlineSource = {};
- renderpass_outline_source = {};
}
}
diff --git a/WickedEngine/wiRenderPath3D.h b/WickedEngine/wiRenderPath3D.h
index b6fe44617..5e624ca08 100644
--- a/WickedEngine/wiRenderPath3D.h
+++ b/WickedEngine/wiRenderPath3D.h
@@ -116,17 +116,6 @@ namespace wi
wi::graphics::Texture depthBuffer_Reflection; // used for reflection, single sample
wi::graphics::Texture rtLinearDepth; // linear depth result + mipchain (max filter)
- wi::graphics::RenderPass renderpass_depthprepass;
- wi::graphics::RenderPass renderpass_main;
- wi::graphics::RenderPass renderpass_transparent;
- wi::graphics::RenderPass renderpass_reflection_depthprepass;
- wi::graphics::RenderPass renderpass_reflection;
- wi::graphics::RenderPass renderpass_lightshafts;
- wi::graphics::RenderPass renderpass_volumetriclight;
- wi::graphics::RenderPass renderpass_particledistortion;
- wi::graphics::RenderPass renderpass_waterripples;
- wi::graphics::RenderPass renderpass_outline_source;
-
wi::graphics::Texture debugUAV; // debug UAV can be used by some shaders...
wi::renderer::TiledLightResources tiledLightResources;
wi::renderer::TiledLightResources tiledLightResources_planarReflection;
diff --git a/WickedEngine/wiRenderPath3D_PathTracing.cpp b/WickedEngine/wiRenderPath3D_PathTracing.cpp
index 5006f419d..386d1c971 100644
--- a/WickedEngine/wiRenderPath3D_PathTracing.cpp
+++ b/WickedEngine/wiRenderPath3D_PathTracing.cpp
@@ -88,13 +88,6 @@ namespace wi
device->SetName(&rtGUIBlurredBackground[2], "rtGUIBlurredBackground[2]");
}
- {
- RenderPassDesc desc;
- desc.attachments.push_back(RenderPassAttachment::RenderTarget(traceResult, RenderPassAttachment::LoadOp::CLEAR));
-
- device->CreateRenderPass(&desc, &renderpass_debugbvh);
- }
-
wi::renderer::CreateLuminanceResources(luminanceResources, internalResolution);
wi::renderer::CreateBloomResources(bloomResources, internalResolution);
@@ -306,7 +299,10 @@ namespace wi
if (wi::renderer::GetRaytraceDebugBVHVisualizerEnabled())
{
- device->RenderPassBegin(&renderpass_debugbvh, cmd);
+ RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(&traceResult, RenderPassImage::LoadOp::CLEAR)
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
Viewport vp;
vp.width = (float)traceResult.GetDesc().width;
diff --git a/WickedEngine/wiRenderPath3D_PathTracing.h b/WickedEngine/wiRenderPath3D_PathTracing.h
index 9359bc1f4..7948516a4 100644
--- a/WickedEngine/wiRenderPath3D_PathTracing.h
+++ b/WickedEngine/wiRenderPath3D_PathTracing.h
@@ -22,8 +22,6 @@ namespace wi
wi::graphics::Texture denoiserResult;
wi::jobsystem::context denoiserContext;
- wi::graphics::RenderPass renderpass_debugbvh;
-
void ResizeBuffers() override;
public:
diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp
index f7fd734bd..4f2a32fef 100644
--- a/WickedEngine/wiRenderer.cpp
+++ b/WickedEngine/wiRenderer.cpp
@@ -124,7 +124,6 @@ struct VoxelizedSceneData
Texture shadowMapAtlas;
Texture shadowMapAtlas_Transparent;
-RenderPass renderpass_shadowMapAtlas;
int max_shadow_resolution_2D = 1024;
int max_shadow_resolution_cube = 256;
@@ -311,21 +310,24 @@ union ObjectRenderingVariant
{
struct
{
+ uint32_t renderpass : 4; // wi::enums::RENDERPASS
uint32_t shadertype : 8; // MaterialComponent::SHADERTYPE
uint32_t blendmode : 4; // wi::enums::BLENDMODE
uint32_t cullmode : 2; // wi::graphics::CullMode
uint32_t tessellation : 1; // bool
uint32_t alphatest : 1; // bool
uint32_t wind : 1; // bool
+ uint32_t sample_count : 4; // 1, 2, 4, 8
} bits;
uint32_t value;
};
static_assert(sizeof(ObjectRenderingVariant) == sizeof(uint32_t));
-wi::unordered_map PSO_object[RENDERPASS_COUNT];
-inline PipelineState* GetObjectPSO(RENDERPASS renderPass, ObjectRenderingVariant variant)
+wi::unordered_map PSO_object[RENDERPASS_COUNT][MaterialComponent::SHADERTYPE_COUNT];
+inline PipelineState* GetObjectPSO(ObjectRenderingVariant variant)
{
- return &PSO_object[renderPass][variant.value];
+ return &PSO_object[variant.bits.renderpass][variant.bits.shadertype][variant.value];
}
+wi::jobsystem::context object_pso_job_ctx;
PipelineState PSO_object_wire;
PipelineState PSO_object_wire_tessellation;
@@ -1062,6 +1064,15 @@ void LoadShaders()
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_SURFEL_RAYTRACE], "surfel_raytraceCS.cso"); });
}
+ if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING))
+ {
+ LoadShader(ShaderStage::CS, shaders[CSTYPE_RAYTRACE], "raytraceCS_rtapi.cso", ShaderModel::SM_6_5);
+ }
+ else
+ {
+ LoadShader(ShaderStage::CS, shaders[CSTYPE_RAYTRACE], "raytraceCS.cso");
+ }
+
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_VISIBILITY_RESOLVE], "visibility_resolveCS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_VISIBILITY_RESOLVE_MSAA], "visibility_resolveCS_MSAA.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_VISIBILITY_INDIRECT_PREPARE], "visibility_indirect_prepareCS.cso"); });
@@ -1163,158 +1174,6 @@ void LoadShaders()
wi::jobsystem::Wait(ctx);
- // default objectshaders:
- wi::jobsystem::Dispatch(ctx, RENDERPASS_COUNT, 1, [](wi::jobsystem::JobArgs args) {
- RENDERPASS renderPass = (RENDERPASS)args.jobIndex;
-
- for (uint32_t shaderType = 0; shaderType < MaterialComponent::SHADERTYPE_COUNT; ++shaderType)
- {
- for (uint32_t blendMode = 0; blendMode < BLENDMODE_COUNT; ++blendMode)
- {
- for (uint32_t cullMode = 0; cullMode <= 3; ++cullMode)
- {
- for (uint32_t tessellation = 0; tessellation <= 1; ++tessellation)
- {
- for (uint32_t alphatest = 0; alphatest <= 1; ++alphatest)
- {
- for (uint32_t wind = 0; wind <= 1; ++wind)
- {
- const bool transparency = blendMode != BLENDMODE_OPAQUE;
- SHADERTYPE realVS = GetVSTYPE(renderPass, tessellation, alphatest, transparency, wind);
- SHADERTYPE realHS = GetHSTYPE(renderPass, tessellation, alphatest);
- SHADERTYPE realDS = GetDSTYPE(renderPass, tessellation, alphatest);
- SHADERTYPE realGS = GetGSTYPE(renderPass, alphatest, transparency);
- SHADERTYPE realPS = GetPSTYPE(renderPass, alphatest, transparency, (MaterialComponent::SHADERTYPE)shaderType);
-
- if (tessellation && (realHS == SHADERTYPE_COUNT || realDS == SHADERTYPE_COUNT))
- {
- continue;
- }
-
- PipelineStateDesc desc;
- desc.vs = realVS < SHADERTYPE_COUNT ? &shaders[realVS] : nullptr;
- desc.hs = realHS < SHADERTYPE_COUNT ? &shaders[realHS] : nullptr;
- desc.ds = realDS < SHADERTYPE_COUNT ? &shaders[realDS] : nullptr;
- desc.gs = realGS < SHADERTYPE_COUNT ? &shaders[realGS] : nullptr;
- desc.ps = realPS < SHADERTYPE_COUNT ? &shaders[realPS] : nullptr;
-
- switch (blendMode)
- {
- case BLENDMODE_OPAQUE:
- desc.bs = &blendStates[BSTYPE_OPAQUE];
- break;
- case BLENDMODE_ALPHA:
- desc.bs = &blendStates[BSTYPE_TRANSPARENT];
- break;
- case BLENDMODE_ADDITIVE:
- desc.bs = &blendStates[BSTYPE_ADDITIVE];
- break;
- case BLENDMODE_PREMULTIPLIED:
- desc.bs = &blendStates[BSTYPE_PREMULTIPLIED];
- break;
- case BLENDMODE_MULTIPLY:
- desc.bs = &blendStates[BSTYPE_MULTIPLY];
- break;
- default:
- assert(0);
- break;
- }
-
- switch (renderPass)
- {
- case RENDERPASS_SHADOW:
- case RENDERPASS_SHADOWCUBE:
- desc.bs = &blendStates[transparency ? BSTYPE_TRANSPARENTSHADOW : BSTYPE_COLORWRITEDISABLE];
- break;
- default:
- break;
- }
-
- switch (renderPass)
- {
- case RENDERPASS_SHADOW:
- case RENDERPASS_SHADOWCUBE:
- desc.dss = &depthStencils[transparency ? DSSTYPE_DEPTHREAD : DSSTYPE_SHADOW];
- break;
- case RENDERPASS_MAIN:
- if (blendMode == BLENDMODE_ADDITIVE)
- {
- desc.dss = &depthStencils[DSSTYPE_DEPTHREAD];
- }
- else
- {
- desc.dss = &depthStencils[transparency ? DSSTYPE_DEFAULT : DSSTYPE_DEPTHREADEQUAL];
- }
- break;
- case RENDERPASS_ENVMAPCAPTURE:
- desc.dss = &depthStencils[DSSTYPE_ENVMAP];
- break;
- case RENDERPASS_VOXELIZE:
- desc.dss = &depthStencils[DSSTYPE_DEPTHDISABLED];
- break;
- default:
- if (blendMode == BLENDMODE_ADDITIVE)
- {
- desc.dss = &depthStencils[DSSTYPE_DEPTHREAD];
- }
- else
- {
- desc.dss = &depthStencils[DSSTYPE_DEFAULT];
- }
- break;
- }
-
- switch (renderPass)
- {
- case RENDERPASS_SHADOW:
- case RENDERPASS_SHADOWCUBE:
- desc.rs = &rasterizers[cullMode == (int)CullMode::NONE ? RSTYPE_SHADOW_DOUBLESIDED : RSTYPE_SHADOW];
- break;
- case RENDERPASS_VOXELIZE:
- desc.rs = &rasterizers[RSTYPE_VOXELIZE];
- break;
- default:
- switch ((CullMode)cullMode)
- {
- default:
- case CullMode::BACK:
- desc.rs = &rasterizers[RSTYPE_FRONT];
- break;
- case CullMode::NONE:
- desc.rs = &rasterizers[RSTYPE_DOUBLESIDED];
- break;
- case CullMode::FRONT:
- desc.rs = &rasterizers[RSTYPE_BACK];
- break;
- }
- break;
- }
-
- if (tessellation)
- {
- desc.pt = PrimitiveTopology::PATCHLIST;
- }
- else
- {
- desc.pt = PrimitiveTopology::TRIANGLELIST;
- }
-
- ObjectRenderingVariant variant = {};
- variant.bits.shadertype = shaderType;
- variant.bits.blendmode = blendMode;
- variant.bits.cullmode = cullMode;
- variant.bits.tessellation = tessellation;
- variant.bits.alphatest = alphatest;
- variant.bits.wind = wind;
- device->CreatePipelineState(&desc, GetObjectPSO(renderPass, variant));
- }
- }
- }
- }
- }
- }
- });
-
// Clear custom shaders (Custom shaders coming from user will need to be handled by the user in case of shader reload):
customShaders.clear();
@@ -1496,7 +1355,11 @@ void LoadShaders()
desc.bs = &blendStates[BSTYPE_TRANSPARENT];
desc.dss = &depthStencils[DSSTYPE_DEPTHDISABLED];
- device->CreatePipelineState(&desc, &PSO_renderlightmap);
+ RenderPassInfo renderpass_info;
+ renderpass_info.rt_count = 1;
+ renderpass_info.rt_formats[0] = Format::R32G32B32A32_FLOAT;
+
+ device->CreatePipelineState(&desc, &PSO_renderlightmap, &renderpass_info);
});
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) {
PipelineStateDesc desc;
@@ -1761,6 +1624,218 @@ void LoadShaders()
wi::jobsystem::Wait(ctx);
+
+
+ // default objectshaders:
+ // We don't wait for these here, because then it can slow down the init time a lot
+ // We will wait for these to complete in RenderMeshes() just before they will be first used
+ wi::jobsystem::Wait(object_pso_job_ctx);
+ for (uint32_t renderPass = 0; renderPass < RENDERPASS_COUNT; ++renderPass)
+ {
+ for (uint32_t shaderType = 0; shaderType < MaterialComponent::SHADERTYPE_COUNT; ++shaderType)
+ {
+ wi::jobsystem::Execute(object_pso_job_ctx, [=](wi::jobsystem::JobArgs args) {
+ for (uint32_t blendMode = 0; blendMode < BLENDMODE_COUNT; ++blendMode)
+ {
+ for (uint32_t cullMode = 0; cullMode <= 3; ++cullMode)
+ {
+ for (uint32_t tessellation = 0; tessellation <= 1; ++tessellation)
+ {
+ for (uint32_t alphatest = 0; alphatest <= 1; ++alphatest)
+ {
+ for (uint32_t wind = 0; wind <= 1; ++wind)
+ {
+ const bool transparency = blendMode != BLENDMODE_OPAQUE;
+ if (renderPass == RENDERPASS_PREPASS && transparency)
+ continue;
+
+ SHADERTYPE realVS = GetVSTYPE((RENDERPASS)renderPass, tessellation, alphatest, transparency, wind);
+ SHADERTYPE realHS = GetHSTYPE((RENDERPASS)renderPass, tessellation, alphatest);
+ SHADERTYPE realDS = GetDSTYPE((RENDERPASS)renderPass, tessellation, alphatest);
+ SHADERTYPE realGS = GetGSTYPE((RENDERPASS)renderPass, alphatest, transparency);
+ SHADERTYPE realPS = GetPSTYPE((RENDERPASS)renderPass, alphatest, transparency, (MaterialComponent::SHADERTYPE)shaderType);
+
+ if (tessellation && (realHS == SHADERTYPE_COUNT || realDS == SHADERTYPE_COUNT))
+ continue;
+
+ PipelineStateDesc desc;
+ desc.vs = realVS < SHADERTYPE_COUNT ? &shaders[realVS] : nullptr;
+ desc.hs = realHS < SHADERTYPE_COUNT ? &shaders[realHS] : nullptr;
+ desc.ds = realDS < SHADERTYPE_COUNT ? &shaders[realDS] : nullptr;
+ desc.gs = realGS < SHADERTYPE_COUNT ? &shaders[realGS] : nullptr;
+ desc.ps = realPS < SHADERTYPE_COUNT ? &shaders[realPS] : nullptr;
+
+ switch (blendMode)
+ {
+ case BLENDMODE_OPAQUE:
+ desc.bs = &blendStates[BSTYPE_OPAQUE];
+ break;
+ case BLENDMODE_ALPHA:
+ desc.bs = &blendStates[BSTYPE_TRANSPARENT];
+ break;
+ case BLENDMODE_ADDITIVE:
+ desc.bs = &blendStates[BSTYPE_ADDITIVE];
+ break;
+ case BLENDMODE_PREMULTIPLIED:
+ desc.bs = &blendStates[BSTYPE_PREMULTIPLIED];
+ break;
+ case BLENDMODE_MULTIPLY:
+ desc.bs = &blendStates[BSTYPE_MULTIPLY];
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ switch (renderPass)
+ {
+ case RENDERPASS_SHADOW:
+ case RENDERPASS_SHADOWCUBE:
+ desc.bs = &blendStates[transparency ? BSTYPE_TRANSPARENTSHADOW : BSTYPE_COLORWRITEDISABLE];
+ break;
+ default:
+ break;
+ }
+
+ switch (renderPass)
+ {
+ case RENDERPASS_SHADOW:
+ case RENDERPASS_SHADOWCUBE:
+ desc.dss = &depthStencils[transparency ? DSSTYPE_DEPTHREAD : DSSTYPE_SHADOW];
+ break;
+ case RENDERPASS_MAIN:
+ if (blendMode == BLENDMODE_ADDITIVE)
+ {
+ desc.dss = &depthStencils[DSSTYPE_DEPTHREAD];
+ }
+ else
+ {
+ desc.dss = &depthStencils[transparency ? DSSTYPE_DEFAULT : DSSTYPE_DEPTHREADEQUAL];
+ }
+ break;
+ case RENDERPASS_ENVMAPCAPTURE:
+ desc.dss = &depthStencils[DSSTYPE_ENVMAP];
+ break;
+ case RENDERPASS_VOXELIZE:
+ desc.dss = &depthStencils[DSSTYPE_DEPTHDISABLED];
+ break;
+ default:
+ if (blendMode == BLENDMODE_ADDITIVE)
+ {
+ desc.dss = &depthStencils[DSSTYPE_DEPTHREAD];
+ }
+ else
+ {
+ desc.dss = &depthStencils[DSSTYPE_DEFAULT];
+ }
+ break;
+ }
+
+ switch (renderPass)
+ {
+ case RENDERPASS_SHADOW:
+ case RENDERPASS_SHADOWCUBE:
+ desc.rs = &rasterizers[cullMode == (int)CullMode::NONE ? RSTYPE_SHADOW_DOUBLESIDED : RSTYPE_SHADOW];
+ break;
+ case RENDERPASS_VOXELIZE:
+ desc.rs = &rasterizers[RSTYPE_VOXELIZE];
+ break;
+ default:
+ switch ((CullMode)cullMode)
+ {
+ default:
+ case CullMode::BACK:
+ desc.rs = &rasterizers[RSTYPE_FRONT];
+ break;
+ case CullMode::NONE:
+ desc.rs = &rasterizers[RSTYPE_DOUBLESIDED];
+ break;
+ case CullMode::FRONT:
+ desc.rs = &rasterizers[RSTYPE_BACK];
+ break;
+ }
+ break;
+ }
+
+ if (tessellation)
+ {
+ desc.pt = PrimitiveTopology::PATCHLIST;
+ }
+ else
+ {
+ desc.pt = PrimitiveTopology::TRIANGLELIST;
+ }
+
+ ObjectRenderingVariant variant = {};
+ variant.bits.renderpass = renderPass;
+ variant.bits.shadertype = shaderType;
+ variant.bits.blendmode = blendMode;
+ variant.bits.cullmode = cullMode;
+ variant.bits.tessellation = tessellation;
+ variant.bits.alphatest = alphatest;
+ variant.bits.wind = wind;
+ variant.bits.sample_count = 1;
+
+ switch (renderPass)
+ {
+ case RENDERPASS_MAIN:
+ case RENDERPASS_PREPASS:
+ {
+ RenderPassInfo renderpass_info;
+ renderpass_info.rt_count = 1;
+ renderpass_info.rt_formats[0] = renderPass == RENDERPASS_MAIN ? Format::R11G11B10_FLOAT : Format::R32_UINT;
+ renderpass_info.ds_format = Format::D32_FLOAT_S8X24_UINT;
+ const uint32_t msaa_support[] = { 1,2,4,8 };
+ for (uint32_t msaa : msaa_support)
+ {
+ variant.bits.sample_count = msaa;
+ renderpass_info.sample_count = msaa;
+ device->CreatePipelineState(&desc, GetObjectPSO(variant), &renderpass_info);
+ }
+ }
+ break;
+
+ case RENDERPASS_ENVMAPCAPTURE:
+ {
+ RenderPassInfo renderpass_info;
+ renderpass_info.rt_count = 1;
+ renderpass_info.rt_formats[0] = Format::R11G11B10_FLOAT;
+ renderpass_info.ds_format = Format::D16_UNORM;
+ const uint32_t msaa_support[] = { 1,8 };
+ for (uint32_t msaa : msaa_support)
+ {
+ variant.bits.sample_count = msaa;
+ renderpass_info.sample_count = msaa;
+ device->CreatePipelineState(&desc, GetObjectPSO(variant), &renderpass_info);
+ }
+ }
+ break;
+
+ case RENDERPASS_SHADOW:
+ case RENDERPASS_SHADOWCUBE:
+ {
+ RenderPassInfo renderpass_info;
+ renderpass_info.rt_count = 1;
+ renderpass_info.rt_formats[0] = Format::R16G16B16A16_FLOAT;
+ renderpass_info.ds_format = Format::D16_UNORM;
+ device->CreatePipelineState(&desc, GetObjectPSO(variant), &renderpass_info);
+ }
+ break;
+
+ default:
+ device->CreatePipelineState(&desc, GetObjectPSO(variant));
+ break;
+ }
+
+ }
+ }
+ }
+ }
+ }
+ });
+ }
+ }
+
}
void LoadBuffers()
{
@@ -2424,19 +2499,15 @@ void Workaround(const int bug , CommandList cmd)
//PE: https://github.com/turanszkij/WickedEngine/issues/450#issuecomment-1143647323
//PE: We MUST use RENDERPASS_VOXELIZE (DSSTYPE_DEPTHDISABLED) or it will not work ?
+ wi::jobsystem::Wait(object_pso_job_ctx);
ObjectRenderingVariant variant = {};
+ variant.bits.renderpass = RENDERPASS_VOXELIZE;
variant.bits.blendmode = BLENDMODE_OPAQUE;
- const PipelineState* pso = &PSO_object[RENDERPASS_VOXELIZE][variant.value];
+ variant.bits.sample_count = 1;
+ const PipelineState* pso = GetObjectPSO(variant);
device->EventBegin("Workaround 1", cmd);
- static RenderPass renderpass_clear;
- if (!renderpass_clear.IsValid())
- {
- RenderPassDesc renderpassdesc;
- renderpassdesc.flags = RenderPassDesc::Flags::EMPTY;
- device->CreateRenderPass(&renderpassdesc, &renderpass_clear);
- }
- device->RenderPassBegin(&renderpass_clear, cmd);
+ device->RenderPassBegin(nullptr, 0, cmd);
device->BindPipelineState(pso, cmd);
device->DrawIndexedInstanced(0, 0, 0, 0, 0, cmd); //PE: Just need predraw(cmd);
device->RenderPassEnd(cmd);
@@ -2461,6 +2532,9 @@ void RenderMeshes(
device->EventBegin("RenderMeshes", cmd);
+ wi::jobsystem::Wait(object_pso_job_ctx);
+ RenderPassInfo renderpass_info = device->GetRenderPassInfo(cmd);
+
tessellation = tessellation && device->CheckCapability(GraphicsDeviceCapability::TESSELLATION);
// Do we need to compute a light mask for this pass on the CPU?
@@ -2562,20 +2636,22 @@ void RenderMeshes(
else
{
ObjectRenderingVariant variant = {};
+ variant.bits.renderpass = renderPass;
variant.bits.shadertype = material.shaderType;
variant.bits.blendmode = material.GetBlendMode();
variant.bits.cullmode = (mesh.IsDoubleSided() || material.IsDoubleSided() || (shadowRendering && mesh.IsDoubleSidedShadow())) ? (uint32_t)CullMode::NONE : (uint32_t)CullMode::BACK;
variant.bits.tessellation = tessellatorRequested;
variant.bits.alphatest = material.IsAlphaTestEnabled() || forceAlphaTestForDithering;
variant.bits.wind = material.IsUsingWind();
+ variant.bits.sample_count = renderpass_info.sample_count;
- pso = GetObjectPSO(renderPass, variant);
+ pso = GetObjectPSO(variant);
assert(pso->IsValid());
if ((filterMask & FILTER_TRANSPARENT) && variant.bits.cullmode == (uint32_t)CullMode::NONE)
{
variant.bits.cullmode = (uint32_t)CullMode::FRONT;
- pso_backside = GetObjectPSO(renderPass, variant);
+ pso_backside = GetObjectPSO(variant);
}
}
}
@@ -3163,29 +3239,6 @@ void UpdatePerFrameData(
device->CreateTexture(&desc, nullptr, &shadowMapAtlas_Transparent);
device->SetName(&shadowMapAtlas_Transparent, "shadowMapAtlas_Transparent");
-
- RenderPassDesc renderpassdesc;
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- shadowMapAtlas,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::SHADER_RESOURCE,
- ResourceState::DEPTHSTENCIL,
- ResourceState::SHADER_RESOURCE
- )
- );
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::RenderTarget(
- shadowMapAtlas_Transparent,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::SHADER_RESOURCE,
- ResourceState::RENDERTARGET,
- ResourceState::SHADER_RESOURCE
- )
- );
- device->CreateRenderPass(&renderpassdesc, &renderpass_shadowMapAtlas);
}
break;
@@ -4888,7 +4941,7 @@ void DrawShadowmaps(
if (IsWireRender())
return;
- if (!vis.visibleLights.empty() && renderpass_shadowMapAtlas.IsValid())
+ if (!vis.visibleLights.empty() && shadowMapAtlas.IsValid())
{
device->EventBegin("DrawShadowmaps", cmd);
auto range_cpu = wi::profiler::BeginRangeCPU("Shadowmap Rendering");
@@ -4908,7 +4961,24 @@ void DrawShadowmaps(
static thread_local RenderQueue renderQueue;
- device->RenderPassBegin(&renderpass_shadowMapAtlas, cmd);
+ const RenderPassImage rp[] = {
+ RenderPassImage::DepthStencil(
+ &shadowMapAtlas,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::SHADER_RESOURCE,
+ ResourceState::DEPTHSTENCIL,
+ ResourceState::SHADER_RESOURCE
+ ),
+ RenderPassImage::RenderTarget(
+ &shadowMapAtlas_Transparent,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::SHADER_RESOURCE,
+ ResourceState::SHADER_RESOURCE
+ ),
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
for (uint32_t lightIndex : vis.visibleLights)
{
@@ -6805,11 +6875,52 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd)
if (probe.IsMSAA())
{
- device->RenderPassBegin(&vis.scene->renderpasses_envmap_MSAA[probe.textureIndex], cmd);
+ const RenderPassImage rp[] = {
+ RenderPassImage::DepthStencil(
+ &vis.scene->envrenderingDepthBuffer_MSAA,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::SHADER_RESOURCE,
+ ResourceState::DEPTHSTENCIL,
+ ResourceState::SHADER_RESOURCE
+ ),
+ RenderPassImage::RenderTarget(
+ &vis.scene->envrenderingColorBuffer_MSAA,
+ RenderPassImage::LoadOp::DONTCARE,
+ RenderPassImage::StoreOp::DONTCARE,
+ ResourceState::RENDERTARGET,
+ ResourceState::RENDERTARGET
+ ),
+ RenderPassImage::Resolve(
+ &vis.scene->envmapArray,
+ ResourceState::SHADER_RESOURCE,
+ ResourceState::SHADER_RESOURCE,
+ vis.scene->envmapArray.desc.mip_levels + vis.scene->envmapCount + probe.textureIndex // subresource: individual cubes only mip0
+ )
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
}
else
{
- device->RenderPassBegin(&vis.scene->renderpasses_envmap[probe.textureIndex], cmd);
+ const RenderPassImage rp[] = {
+ RenderPassImage::DepthStencil(
+ &vis.scene->envrenderingDepthBuffer,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::SHADER_RESOURCE,
+ ResourceState::DEPTHSTENCIL,
+ ResourceState::SHADER_RESOURCE
+ ),
+ RenderPassImage::RenderTarget(
+ &vis.scene->envmapArray,
+ RenderPassImage::LoadOp::DONTCARE,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::SHADER_RESOURCE,
+ ResourceState::SHADER_RESOURCE,
+ probe.textureIndex
+ )
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
}
// Scene will only be rendered if this is a real probe entity:
@@ -7101,8 +7212,40 @@ void RefreshImpostors(const Scene& scene, CommandList cmd)
BindCameraCB(impostorcamera, impostorcamera, impostorcamera, cmd);
- int slice = (int)(impostor.textureIndex * impostorCaptureAngles + i);
- device->RenderPassBegin(&scene.renderpasses_impostor[slice], cmd);
+ int slice = (int)(impostor.textureIndex * impostorCaptureAngles * 3 + i * 3);
+
+ const RenderPassImage rp[] = {
+ RenderPassImage::RenderTarget(
+ &scene.impostorArray,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::RENDERTARGET,
+ ResourceState::RENDERTARGET,
+ slice
+ ),
+ RenderPassImage::RenderTarget(
+ &scene.impostorArray,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::RENDERTARGET,
+ ResourceState::RENDERTARGET,
+ slice + 1
+ ),
+ RenderPassImage::RenderTarget(
+ &scene.impostorArray,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::STORE,
+ ResourceState::RENDERTARGET,
+ ResourceState::RENDERTARGET,
+ slice + 2
+ ),
+ RenderPassImage::DepthStencil(
+ &scene.impostorDepthStencil,
+ RenderPassImage::LoadOp::CLEAR,
+ RenderPassImage::StoreOp::DONTCARE
+ )
+ };
+ device->RenderPassBegin(rp, arraysize(rp), cmd);
uint32_t first_subset = 0;
uint32_t last_subset = 0;
@@ -7146,15 +7289,6 @@ void VoxelRadiance(const Visibility& vis, CommandList cmd)
device->EventBegin("Voxel Radiance", cmd);
auto range = wi::profiler::BeginRangeGPU("Voxel Radiance", cmd);
- static RenderPass renderpass_voxelize;
-
- if (!renderpass_voxelize.IsValid())
- {
- RenderPassDesc renderpassdesc;
- renderpassdesc.flags = RenderPassDesc::Flags::ALLOW_UAV_WRITES;
- device->CreateRenderPass(&renderpassdesc, &renderpass_voxelize);
- }
-
Texture* result = &textures[TEXTYPE_3D_VOXELRADIANCE];
AABB bbox;
@@ -7191,7 +7325,7 @@ void VoxelRadiance(const Visibility& vis, CommandList cmd)
BindCommonResources(cmd);
- device->RenderPassBegin(&renderpass_voxelize, cmd);
+ device->RenderPassBegin(nullptr, 0, cmd, RenderPassFlags::ALLOW_UAV_WRITES);
RenderMeshes(vis, renderQueue, RENDERPASS_VOXELIZE, FILTER_OPAQUE, cmd, false, nullptr, 1);
device->RenderPassEnd(cmd);
@@ -7828,23 +7962,6 @@ void RayTraceScene(
cb.xTraceSampleIndex = (uint32_t)accumulation_sample;
device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(RaytracingCB), cmd);
- if (!shaders[CSTYPE_RAYTRACE].IsValid())
- {
- static auto init_shader = [] {
- if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING))
- {
- LoadShader(ShaderStage::CS, shaders[CSTYPE_RAYTRACE], "raytraceCS_rtapi.cso", ShaderModel::SM_6_5);
- }
- else
- {
- LoadShader(ShaderStage::CS, shaders[CSTYPE_RAYTRACE], "raytraceCS.cso");
- }
- };
-
- static wi::eventhandler::Handle handle = wi::eventhandler::Subscribe(wi::eventhandler::EVENT_RELOAD_SHADERS, [](uint64_t userdata) { init_shader(); });
- init_shader();
- }
-
device->BindComputeShader(&shaders[CSTYPE_RAYTRACE], cmd);
const GPUResource* uavs[] = {
@@ -7926,11 +8043,13 @@ void RefreshLightmaps(const Scene& scene, CommandList cmd, uint8_t instanceInclu
if (object.lightmapIterationCount == 0)
{
- device->RenderPassBegin(&object.renderpass_lightmap_clear, cmd);
+ RenderPassImage rp = RenderPassImage::RenderTarget(&object.lightmap, RenderPassImage::LoadOp::CLEAR);
+ device->RenderPassBegin(&rp, 1, cmd);
}
else
{
- device->RenderPassBegin(&object.renderpass_lightmap_accumulate, cmd);
+ RenderPassImage rp = RenderPassImage::RenderTarget(&object.lightmap, RenderPassImage::LoadOp::LOAD);
+ device->RenderPassBegin(&rp, 1, cmd);
}
Viewport vp;
diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp
index cd83be820..6ff4671be 100644
--- a/WickedEngine/wiScene.cpp
+++ b/WickedEngine/wiScene.cpp
@@ -3234,57 +3234,6 @@ namespace wi::scene
subresource_index = device->CreateSubresource(&impostorArray, SubresourceType::RTV, i, 1, 0, 1);
assert(subresource_index == i);
}
-
- renderpasses_impostor.resize(desc.array_size / 3);
- for (uint32_t i = 0; i < desc.array_size / 3; ++i)
- {
- RenderPassDesc renderpassdesc;
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::RenderTarget(
- impostorArray,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::RENDERTARGET,
- ResourceState::RENDERTARGET,
- ResourceState::RENDERTARGET
- )
- );
- renderpassdesc.attachments.back().subresource = i * 3;
-
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::RenderTarget(
- impostorArray,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::RENDERTARGET,
- ResourceState::RENDERTARGET,
- ResourceState::RENDERTARGET
- )
- );
- renderpassdesc.attachments.back().subresource = i * 3 + 1;
-
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::RenderTarget(
- impostorArray,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::RENDERTARGET,
- ResourceState::RENDERTARGET,
- ResourceState::RENDERTARGET
- )
- );
- renderpassdesc.attachments.back().subresource = i * 3 + 2;
-
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- impostorDepthStencil,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::DONTCARE
- )
- );
-
- device->CreateRenderPass(&renderpassdesc, &renderpasses_impostor[i]);
- }
}
// reconstruct impostor array status:
@@ -3620,15 +3569,6 @@ namespace wi::scene
device->CreateTexture(&desc, nullptr, &object.lightmap);
device->SetName(&object.lightmap, "lightmap_renderable");
- RenderPassDesc renderpassdesc;
-
- renderpassdesc.attachments.push_back(RenderPassAttachment::RenderTarget(object.lightmap, RenderPassAttachment::LoadOp::CLEAR));
-
- device->CreateRenderPass(&renderpassdesc, &object.renderpass_lightmap_clear);
-
- renderpassdesc.attachments.back().loadop = RenderPassAttachment::LoadOp::LOAD;
- device->CreateRenderPass(&renderpassdesc, &object.renderpass_lightmap_accumulate);
-
object.lightmapIterationCount = 0; // reset accumulation
}
}
@@ -3797,72 +3737,11 @@ namespace wi::scene
assert(subresource_index == envmapArray.desc.mip_levels + envmapCount + i);
}
- renderpasses_envmap.resize(envmapCount);
- renderpasses_envmap_MSAA.resize(envmapCount);
for (uint32_t i = 0; i < envmapCount; ++i)
{
- // Non MSAA:
- {
- int subresource_index;
- subresource_index = device->CreateSubresource(&envmapArray, SubresourceType::RTV, i * 6, 6, 0, 1);
- assert(subresource_index == i);
-
- RenderPassDesc renderpassdesc;
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- envrenderingDepthBuffer,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::SHADER_RESOURCE,
- ResourceState::DEPTHSTENCIL,
- ResourceState::SHADER_RESOURCE
- )
- );
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::RenderTarget(envmapArray,
- RenderPassAttachment::LoadOp::DONTCARE,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::SHADER_RESOURCE,
- ResourceState::RENDERTARGET,
- ResourceState::SHADER_RESOURCE,
- subresource_index
- )
- );
- device->CreateRenderPass(&renderpassdesc, &renderpasses_envmap[i]);
- }
-
- // MSAA:
- {
- RenderPassDesc renderpassdesc;
- renderpassdesc.attachments.clear();
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::DepthStencil(
- envrenderingDepthBuffer_MSAA,
- RenderPassAttachment::LoadOp::CLEAR,
- RenderPassAttachment::StoreOp::STORE,
- ResourceState::SHADER_RESOURCE,
- ResourceState::DEPTHSTENCIL,
- ResourceState::SHADER_RESOURCE
- )
- );
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::RenderTarget(envrenderingColorBuffer_MSAA,
- RenderPassAttachment::LoadOp::DONTCARE,
- RenderPassAttachment::StoreOp::DONTCARE,
- ResourceState::RENDERTARGET,
- ResourceState::RENDERTARGET,
- ResourceState::RENDERTARGET
- )
- );
- renderpassdesc.attachments.push_back(
- RenderPassAttachment::Resolve(envmapArray,
- ResourceState::SHADER_RESOURCE,
- ResourceState::SHADER_RESOURCE,
- envmapArray.desc.mip_levels + envmapCount + i // subresource: individual cubes only mip0
- )
- );
- device->CreateRenderPass(&renderpassdesc, &renderpasses_envmap_MSAA[i]);
- }
+ int subresource_index;
+ subresource_index = device->CreateSubresource(&envmapArray, SubresourceType::RTV, i * 6, 6, 0, 1);
+ assert(subresource_index == i);
}
}
diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h
index a8b7ddeb1..1273ee8c6 100644
--- a/WickedEngine/wiScene.h
+++ b/WickedEngine/wiScene.h
@@ -184,15 +184,12 @@ namespace wi::scene
wi::graphics::Texture envrenderingDepthBuffer_MSAA;
wi::graphics::Texture envrenderingColorBuffer_MSAA;
wi::graphics::Texture envmapArray;
- wi::vector renderpasses_envmap;
- wi::vector renderpasses_envmap_MSAA;
// Impostor state:
static constexpr uint32_t maxImpostorCount = 8;
static constexpr uint32_t impostorTextureDim = 128;
wi::graphics::Texture impostorDepthStencil;
wi::graphics::Texture impostorArray;
- wi::vector renderpasses_impostor;
wi::graphics::GPUBuffer impostorBuffer;
MeshComponent::BufferView impostor_ib;
MeshComponent::BufferView impostor_vb;
diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h
index ec94e25f1..762d8981f 100644
--- a/WickedEngine/wiScene_Components.h
+++ b/WickedEngine/wiScene_Components.h
@@ -662,8 +662,6 @@ namespace wi::scene
uint32_t filterMaskDynamic = 0;
wi::graphics::Texture lightmap;
- wi::graphics::RenderPass renderpass_lightmap_clear;
- wi::graphics::RenderPass renderpass_lightmap_accumulate;
mutable uint32_t lightmapIterationCount = 0;
XMFLOAT3 center = XMFLOAT3(0, 0, 0);
diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp
index fbf6f4fcc..01a7c4447 100644
--- a/WickedEngine/wiVersion.cpp
+++ b/WickedEngine/wiVersion.cpp
@@ -9,7 +9,7 @@ namespace wi::version
// minor features, major updates, breaking compatibility changes
const int minor = 71;
// minor bug fixes, alterations, refactors, updates
- const int revision = 122;
+ const int revision = 123;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);