From 26af9078c96d05dfd0a36874bb7bb6c19621c8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Wed, 8 Jul 2020 22:07:45 +0100 Subject: [PATCH] Vulkan and DX12 fixes (#134) * renderpass updates, vulkan and dx12 warning removal #78 * lots of fixes --- Editor/Editor.cpp | 19 +- Tests/Tests.h | 2 +- WickedEngine/RenderPath2D.cpp | 29 +- WickedEngine/RenderPath3D.cpp | 91 +- WickedEngine/RenderPath3D_Deferred.cpp | 105 +- WickedEngine/RenderPath3D_Forward.cpp | 58 +- WickedEngine/RenderPath3D_PathTracing.cpp | 5 +- WickedEngine/RenderPath3D_TiledDeferred.cpp | 7 +- WickedEngine/RenderPath3D_TiledForward.cpp | 11 +- WickedEngine/wiEmittedParticle.cpp | 13 +- WickedEngine/wiGraphics.h | 48 +- WickedEngine/wiGraphicsDevice_DX11.cpp | 229 ++-- WickedEngine/wiGraphicsDevice_DX11.h | 4 + WickedEngine/wiGraphicsDevice_DX12.cpp | 598 +++++----- WickedEngine/wiGraphicsDevice_DX12.h | 3 + WickedEngine/wiGraphicsDevice_Vulkan.cpp | 1141 ++++++++++++------- WickedEngine/wiGraphicsDevice_Vulkan.h | 19 +- WickedEngine/wiRenderer.cpp | 81 +- WickedEngine/wiVersion.cpp | 4 +- WickedEngine/wiWidget.cpp | 101 +- 20 files changed, 1559 insertions(+), 1009 deletions(-) diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 9fe811b84..0ef23ae1b 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -195,20 +195,27 @@ void EditorComponent::ResizeBuffers() { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET, RenderPassAttachment::LOADOP_CLEAR, &rt_selectionOutline[0], -1 }; + 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[1] = { RenderPassAttachment::DEPTH_STENCIL, RenderPassAttachment::LOADOP_LOAD, renderPath->GetDepthStencil(), -1 }; + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + renderPath->GetDepthStencil(), + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); hr = device->CreateRenderPass(&desc, &renderpass_selectionOutline[0]); assert(SUCCEEDED(hr)); - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET, RenderPassAttachment::LOADOP_CLEAR, &rt_selectionOutline[1], -1 }; - if (renderPath->getMSAASampleCount() > 1) + if (renderPath->getMSAASampleCount() == 1) { - desc.attachments[0].texture = &rt_selectionOutline_MSAA; + desc.attachments[0].texture = &rt_selectionOutline[1]; } hr = device->CreateRenderPass(&desc, &renderpass_selectionOutline[1]); assert(SUCCEEDED(hr)); diff --git a/Tests/Tests.h b/Tests/Tests.h index 21b7bca30..e5bb5ed32 100644 --- a/Tests/Tests.h +++ b/Tests/Tests.h @@ -2,7 +2,7 @@ #include "WickedEngine.h" -class TestsRenderer : public RenderPath3D_Deferred +class TestsRenderer : public RenderPath3D_TiledForward { wiLabel* label = nullptr; wiComboBox* testSelector = nullptr; diff --git a/WickedEngine/RenderPath2D.cpp b/WickedEngine/RenderPath2D.cpp index f6b5e766f..454396c0d 100644 --- a/WickedEngine/RenderPath2D.cpp +++ b/WickedEngine/RenderPath2D.cpp @@ -42,9 +42,17 @@ void RenderPath2D::ResizeBuffers() if (rtStenciled.IsValid()) { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&rtStenciled,-1 }; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,dsv,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtStenciled, RenderPassAttachment::LOADOP_CLEAR)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + dsv, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_stenciled); @@ -52,13 +60,20 @@ void RenderPath2D::ResizeBuffers() } { RenderPassDesc desc; - desc.numAttachments = 1; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&rtFinal,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtFinal, RenderPassAttachment::LOADOP_CLEAR)); if(dsv != nullptr && !rtStenciled.IsValid()) { - desc.numAttachments = 2; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,dsv,-1 }; + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + dsv, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); } device->CreateRenderPass(&desc, &renderpass_final); diff --git a/WickedEngine/RenderPath3D.cpp b/WickedEngine/RenderPath3D.cpp index f9805fa68..d9ae00c69 100644 --- a/WickedEngine/RenderPath3D.cpp +++ b/WickedEngine/RenderPath3D.cpp @@ -210,6 +210,7 @@ void RenderPath3D::ResizeBuffers() desc.Format = FORMAT_R32G8X24_TYPELESS; desc.BindFlags = BIND_DEPTH_STENCIL | BIND_SHADER_RESOURCE; desc.SampleCount = getMSAASampleCount(); + desc.layout = IMAGE_LAYOUT_DEPTHSTENCIL_READONLY; device->CreateTexture(&desc, nullptr, &depthBuffer); device->SetName(&depthBuffer, "depthBuffer"); @@ -223,6 +224,7 @@ void RenderPath3D::ResizeBuffers() desc.Format = FORMAT_R32G8X24_TYPELESS; } desc.SampleCount = 1; + desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; device->CreateTexture(&desc, nullptr, &depthBuffer_Copy); device->SetName(&depthBuffer_Copy, "depthBuffer_Copy"); } @@ -269,60 +271,106 @@ void RenderPath3D::ResizeBuffers() // Render passes: { RenderPassDesc desc; - desc.numAttachments = 1; - desc.attachments[0] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&smallDepth,-1,RenderPassAttachment::STOREOP_DONTCARE,IMAGE_LAYOUT_DEPTHSTENCIL_READONLY,IMAGE_LAYOUT_DEPTHSTENCIL }; + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &smallDepth, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_DONTCARE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_occlusionculling); } { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_DONTCARE,&rtReflection,-1,RenderPassAttachment::STOREOP_STORE,IMAGE_LAYOUT_RENDERTARGET,IMAGE_LAYOUT_SHADER_RESOURCE }; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_CLEAR,&depthBuffer_Reflection,-1,RenderPassAttachment::STOREOP_DONTCARE,IMAGE_LAYOUT_DEPTHSTENCIL,IMAGE_LAYOUT_DEPTHSTENCIL }; + desc.attachments.push_back( + RenderPassAttachment::RenderTarget( + &rtReflection, + RenderPassAttachment::LOADOP_DONTCARE, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_SHADER_RESOURCE, + IMAGE_LAYOUT_RENDERTARGET, + IMAGE_LAYOUT_SHADER_RESOURCE + ) + ); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer_Reflection, + RenderPassAttachment::LOADOP_CLEAR, + RenderPassAttachment::STOREOP_DONTCARE, + IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT_DEPTHSTENCIL + ) + ); device->CreateRenderPass(&desc, &renderpass_reflection); } { RenderPassDesc desc; - desc.numAttachments = 1; - desc.attachments[0] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_DONTCARE,&smallDepth,-1,RenderPassAttachment::STOREOP_STORE,IMAGE_LAYOUT_DEPTHSTENCIL,IMAGE_LAYOUT_DEPTHSTENCIL_READONLY }; + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &smallDepth, + RenderPassAttachment::LOADOP_DONTCARE, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_downsampledepthbuffer); } { RenderPassDesc desc; - desc.numAttachments = 1; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_DONTCARE,&rtSceneCopy}; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtSceneCopy, RenderPassAttachment::LOADOP_DONTCARE)); device->CreateRenderPass(&desc, &renderpass_downsamplescene); } { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&rtSun[0],-1 }; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&depthBuffer,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtSun[0], RenderPassAttachment::LOADOP_CLEAR)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_lightshafts); } { RenderPassDesc desc; - desc.numAttachments = 1; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&rtVolumetricLights,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtVolumetricLights, RenderPassAttachment::LOADOP_CLEAR)); device->CreateRenderPass(&desc, &renderpass_volumetriclight); } { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&rtParticleDistortion,-1 }; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&depthBuffer,-1,RenderPassAttachment::STOREOP_DONTCARE }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtParticleDistortion, RenderPassAttachment::LOADOP_CLEAR)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_particledistortion); } { RenderPassDesc desc; - desc.numAttachments = 1; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&rtWaterRipple,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtWaterRipple, RenderPassAttachment::LOADOP_CLEAR)); device->CreateRenderPass(&desc, &renderpass_waterripples); } @@ -408,11 +456,6 @@ void RenderPath3D::RenderReflections(CommandList cmd) const wiRenderer::SetClipPlane(water, cmd); - GPUBarrier barriers[] = { - GPUBarrier::Image(&rtReflection, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_RENDERTARGET), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - device->RenderPassBegin(&renderpass_reflection, cmd); wiRenderer::DrawScene(wiRenderer::GetRefCamera(), RENDERPASS_TEXTURE, cmd); diff --git a/WickedEngine/RenderPath3D_Deferred.cpp b/WickedEngine/RenderPath3D_Deferred.cpp index d617d359f..acd5f29c5 100644 --- a/WickedEngine/RenderPath3D_Deferred.cpp +++ b/WickedEngine/RenderPath3D_Deferred.cpp @@ -70,60 +70,108 @@ void RenderPath3D_Deferred::ResizeBuffers() { RenderPassDesc desc; - desc.numAttachments = 6; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_DONTCARE,&rtGBuffer[0],-1 }; - desc.attachments[1] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&rtGBuffer[1],-1 }; - desc.attachments[2] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_DONTCARE,&rtGBuffer[2],-1 }; - desc.attachments[3] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_DONTCARE,&lightbuffer_diffuse,-1 }; - desc.attachments[4] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_DONTCARE,&lightbuffer_specular,-1 }; - desc.attachments[5] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_CLEAR,&depthBuffer,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGBuffer[0], RenderPassAttachment::LOADOP_DONTCARE)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGBuffer[1], RenderPassAttachment::LOADOP_CLEAR)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGBuffer[2], RenderPassAttachment::LOADOP_DONTCARE)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&lightbuffer_diffuse, RenderPassAttachment::LOADOP_DONTCARE)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&lightbuffer_specular, RenderPassAttachment::LOADOP_DONTCARE)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_CLEAR, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_gbuffer); } { RenderPassDesc desc; - desc.numAttachments = 3; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&lightbuffer_diffuse,-1 }; - desc.attachments[1] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&lightbuffer_specular,-1 }; - desc.attachments[2] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&depthBuffer,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&lightbuffer_diffuse, RenderPassAttachment::LOADOP_LOAD)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&lightbuffer_specular, RenderPassAttachment::LOADOP_LOAD)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_lights); } { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&rtGBuffer[0],-1 }; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&depthBuffer,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGBuffer[0], RenderPassAttachment::LOADOP_LOAD)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_decals); } { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&rtDeferred,-1 }; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&depthBuffer,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtDeferred, RenderPassAttachment::LOADOP_LOAD)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_deferredcomposition); } { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&depthBuffer,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&lightbuffer_diffuse, RenderPassAttachment::LOADOP_LOAD)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&lightbuffer_diffuse,-1 }; device->CreateRenderPass(&desc, &renderpass_SSS[0]); - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&rtSSS[0],-1 }; + desc.attachments[0].texture = &rtSSS[0]; device->CreateRenderPass(&desc, &renderpass_SSS[1]); - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&rtSSS[1],-1 }; + desc.attachments[0].texture = &rtSSS[1]; device->CreateRenderPass(&desc, &renderpass_SSS[2]); } { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&rtDeferred,-1 }; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&depthBuffer,-1,RenderPassAttachment::STOREOP_DONTCARE }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtDeferred, RenderPassAttachment::LOADOP_LOAD)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_transparent); } @@ -160,11 +208,6 @@ void RenderPath3D_Deferred::Render() const { auto range = wiProfiler::BeginRangeGPU("Opaque Scene", cmd); - GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_DEPTHSTENCIL), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - device->RenderPassBegin(&renderpass_gbuffer, cmd); Viewport vp; @@ -182,7 +225,7 @@ void RenderPath3D_Deferred::Render() const { GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL, IMAGE_LAYOUT_COPY_SRC), + GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_COPY_SRC), GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_COPY_DST) }; device->Barrier(barriers, arraysize(barriers), cmd); diff --git a/WickedEngine/RenderPath3D_Forward.cpp b/WickedEngine/RenderPath3D_Forward.cpp index 3f36e3fd1..fb6dbe407 100644 --- a/WickedEngine/RenderPath3D_Forward.cpp +++ b/WickedEngine/RenderPath3D_Forward.cpp @@ -60,24 +60,47 @@ void RenderPath3D_Forward::ResizeBuffers() { RenderPassDesc desc; - - desc.numAttachments = 1; - desc.attachments[0] = { RenderPassAttachment::DEPTH_STENCIL, RenderPassAttachment::LOADOP_CLEAR, &depthBuffer, -1 }; + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_CLEAR, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_depthprepass); - desc.numAttachments = 4; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET, RenderPassAttachment::LOADOP_DONTCARE, &rtMain[0], -1 }; - desc.attachments[1] = { RenderPassAttachment::RENDERTARGET, RenderPassAttachment::LOADOP_CLEAR, &rtMain[1], -1 }; - desc.attachments[2] = { RenderPassAttachment::RENDERTARGET, RenderPassAttachment::LOADOP_CLEAR, &rtMain[2], -1 }; - desc.attachments[3] = { RenderPassAttachment::DEPTH_STENCIL, RenderPassAttachment::LOADOP_LOAD, &depthBuffer, -1 }; + desc.attachments.clear(); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtMain[0], RenderPassAttachment::LOADOP_DONTCARE)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtMain[1], RenderPassAttachment::LOADOP_CLEAR)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtMain[2], RenderPassAttachment::LOADOP_CLEAR)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_main); } { RenderPassDesc desc; - desc.numAttachments = 2; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&rtMain[0],-1 }; - desc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_LOAD,&depthBuffer,-1,RenderPassAttachment::STOREOP_DONTCARE }; - + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtMain[0], RenderPassAttachment::LOADOP_LOAD)); + desc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &depthBuffer, + RenderPassAttachment::LOADOP_LOAD, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, + IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + ) + ); device->CreateRenderPass(&desc, &renderpass_transparent); } } @@ -113,11 +136,6 @@ void RenderPath3D_Forward::Render() const { auto range = wiProfiler::BeginRangeGPU("Z-Prepass", cmd); - GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_DEPTHSTENCIL), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - device->RenderPassBegin(&renderpass_depthprepass, cmd); Viewport vp; @@ -136,7 +154,8 @@ void RenderPath3D_Forward::Render() const { { GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL, IMAGE_LAYOUT_SHADER_RESOURCE), + GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_SHADER_RESOURCE), + GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_GENERAL) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -146,6 +165,7 @@ void RenderPath3D_Forward::Render() const { GPUBarrier barriers[] = { GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY), + GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_GENERAL, IMAGE_LAYOUT_SHADER_RESOURCE) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -154,7 +174,7 @@ void RenderPath3D_Forward::Render() const { { GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL, IMAGE_LAYOUT_COPY_SRC), + GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_COPY_SRC), GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_COPY_DST) }; device->Barrier(barriers, arraysize(barriers), cmd); diff --git a/WickedEngine/RenderPath3D_PathTracing.cpp b/WickedEngine/RenderPath3D_PathTracing.cpp index d4ff28341..311bdebd3 100644 --- a/WickedEngine/RenderPath3D_PathTracing.cpp +++ b/WickedEngine/RenderPath3D_PathTracing.cpp @@ -55,8 +55,9 @@ void RenderPath3D_PathTracing::ResizeBuffers() { RenderPassDesc desc; - desc.numAttachments = 1; - desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&traceResult,-1 }; + //desc.numAttachments = 1; + //desc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&traceResult,-1 }; + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&traceResult, RenderPassAttachment::LOADOP_CLEAR)); device->CreateRenderPass(&desc, &renderpass_debugbvh); } diff --git a/WickedEngine/RenderPath3D_TiledDeferred.cpp b/WickedEngine/RenderPath3D_TiledDeferred.cpp index 1dca4c34f..b3bc09e60 100644 --- a/WickedEngine/RenderPath3D_TiledDeferred.cpp +++ b/WickedEngine/RenderPath3D_TiledDeferred.cpp @@ -64,11 +64,6 @@ void RenderPath3D_TiledDeferred::Render() const { auto range = wiProfiler::BeginRangeGPU("Opaque Scene", cmd); - GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_DEPTHSTENCIL), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - device->RenderPassBegin(&renderpass_gbuffer, cmd); Viewport vp; @@ -86,7 +81,7 @@ void RenderPath3D_TiledDeferred::Render() const { GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL, IMAGE_LAYOUT_COPY_SRC), + GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_COPY_SRC), GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_COPY_DST) }; device->Barrier(barriers, arraysize(barriers), cmd); diff --git a/WickedEngine/RenderPath3D_TiledForward.cpp b/WickedEngine/RenderPath3D_TiledForward.cpp index 10765a51e..d52d7b3e4 100644 --- a/WickedEngine/RenderPath3D_TiledForward.cpp +++ b/WickedEngine/RenderPath3D_TiledForward.cpp @@ -41,11 +41,6 @@ void RenderPath3D_TiledForward::Render() const { auto range = wiProfiler::BeginRangeGPU("Z-Prepass", cmd); - GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_DEPTHSTENCIL), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - device->RenderPassBegin(&renderpass_depthprepass, cmd); Viewport vp; @@ -64,7 +59,8 @@ void RenderPath3D_TiledForward::Render() const { { GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL, IMAGE_LAYOUT_SHADER_RESOURCE), + GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_SHADER_RESOURCE), + GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_GENERAL) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -74,6 +70,7 @@ void RenderPath3D_TiledForward::Render() const { GPUBarrier barriers[] = { GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY), + GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_GENERAL, IMAGE_LAYOUT_SHADER_RESOURCE) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -82,7 +79,7 @@ void RenderPath3D_TiledForward::Render() const { { GPUBarrier barriers[] = { - GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL, IMAGE_LAYOUT_COPY_SRC), + GPUBarrier::Image(&depthBuffer, IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, IMAGE_LAYOUT_COPY_SRC), GPUBarrier::Image(&depthBuffer_Copy, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_COPY_DST) }; device->Barrier(barriers, arraysize(barriers), cmd); diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index e59a95dfd..893f8244a 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -575,6 +575,13 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat device->UnbindUAVs(0, arraysize(uavs), cmd); device->UnbindResources(TEXSLOT_ONDEMAND0, arraysize(res), cmd); device->EventEnd(cmd); + + + const GPUBarrier barriers[] = { + GPUBarrier::Buffer(&particleBuffer, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&aliveList[1], BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); } } @@ -598,12 +605,6 @@ void wiEmittedParticle::Draw(const CameraComponent& camera, const MaterialCompon device->BindConstantBuffer(VS, &constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); device->BindConstantBuffer(PS, &constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); - const GPUBarrier barriers[] = { - GPUBarrier::Buffer(&particleBuffer, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&aliveList[1], BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - const GPUResource* res[] = { &particleBuffer, &aliveList[1] // NEW aliveList diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h index 2423e2612..211cba66b 100644 --- a/WickedEngine/wiGraphics.h +++ b/WickedEngine/wiGraphics.h @@ -551,13 +551,53 @@ namespace wiGraphics STOREOP_STORE, STOREOP_DONTCARE, } storeop = STOREOP_STORE; - IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_GENERAL; - IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_GENERAL; + IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_GENERAL; // layout before the render pass + IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_GENERAL; // layout after the render pass + IMAGE_LAYOUT subpass_layout = IMAGE_LAYOUT_RENDERTARGET;// layout within the render pass + + static RenderPassAttachment RenderTarget( + const Texture* resource = nullptr, + LOAD_OPERATION load_op = LOADOP_LOAD, + STORE_OPERATION store_op = STOREOP_STORE, + IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_GENERAL, + IMAGE_LAYOUT subpass_layout = IMAGE_LAYOUT_RENDERTARGET, + IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_GENERAL + ) + { + RenderPassAttachment attachment; + attachment.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; + return attachment; + } + + static RenderPassAttachment DepthStencil( + const Texture* resource = nullptr, + LOAD_OPERATION load_op = LOADOP_LOAD, + STORE_OPERATION store_op = STOREOP_STORE, + IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT subpass_layout = IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_DEPTHSTENCIL + ) + { + RenderPassAttachment attachment; + attachment.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; + return attachment; + } }; struct RenderPassDesc { - uint32_t numAttachments = 0; - RenderPassAttachment attachments[9] = {}; + std::vector attachments; }; struct IndirectDrawArgsInstanced { diff --git a/WickedEngine/wiGraphicsDevice_DX11.cpp b/WickedEngine/wiGraphicsDevice_DX11.cpp index 7cd75a2ae..4b0bb21d6 100644 --- a/WickedEngine/wiGraphicsDevice_DX11.cpp +++ b/WickedEngine/wiGraphicsDevice_DX11.cpp @@ -1182,6 +1182,114 @@ namespace DX11_Internal } using namespace DX11_Internal; +void GraphicsDevice_DX11::pso_validate(CommandList cmd) +{ + if (!dirty_pso[cmd]) + return; + + const PipelineState* pso = active_pso[cmd]; + const PipelineStateDesc& desc = pso != nullptr ? pso->GetDesc() : PipelineStateDesc(); + + ID3D11VertexShader* vs = desc.vs == nullptr ? nullptr : static_cast(desc.vs->internal_state.get())->resource.Get(); + if (vs != prev_vs[cmd]) + { + deviceContexts[cmd]->VSSetShader(vs, nullptr, 0); + prev_vs[cmd] = vs; + } + ID3D11PixelShader* ps = desc.ps == nullptr ? nullptr : static_cast(desc.ps->internal_state.get())->resource.Get(); + if (ps != prev_ps[cmd]) + { + deviceContexts[cmd]->PSSetShader(ps, nullptr, 0); + prev_ps[cmd] = ps; + } + ID3D11HullShader* hs = desc.hs == nullptr ? nullptr : static_cast(desc.hs->internal_state.get())->resource.Get(); + if (hs != prev_hs[cmd]) + { + deviceContexts[cmd]->HSSetShader(hs, nullptr, 0); + prev_hs[cmd] = hs; + } + ID3D11DomainShader* ds = desc.ds == nullptr ? nullptr : static_cast(desc.ds->internal_state.get())->resource.Get(); + if (ds != prev_ds[cmd]) + { + deviceContexts[cmd]->DSSetShader(ds, nullptr, 0); + prev_ds[cmd] = ds; + } + ID3D11GeometryShader* gs = desc.gs == nullptr ? nullptr : static_cast(desc.gs->internal_state.get())->resource.Get(); + if (gs != prev_gs[cmd]) + { + deviceContexts[cmd]->GSSetShader(gs, nullptr, 0); + prev_gs[cmd] = gs; + } + + ID3D11BlendState* bs = desc.bs == nullptr ? nullptr : to_internal(desc.bs)->resource.Get(); + if (bs != prev_bs[cmd] || desc.sampleMask != prev_samplemask[cmd] || + blendFactor[cmd].x != prev_blendfactor[cmd].x || + blendFactor[cmd].y != prev_blendfactor[cmd].y || + blendFactor[cmd].z != prev_blendfactor[cmd].z || + blendFactor[cmd].w != prev_blendfactor[cmd].w + ) + { + const float fact[4] = { blendFactor[cmd].x, blendFactor[cmd].y, blendFactor[cmd].z, blendFactor[cmd].w }; + deviceContexts[cmd]->OMSetBlendState(bs, fact, desc.sampleMask); + prev_bs[cmd] = bs; + prev_blendfactor[cmd] = blendFactor[cmd]; + prev_samplemask[cmd] = desc.sampleMask; + } + + ID3D11RasterizerState* rs = desc.rs == nullptr ? nullptr : to_internal(desc.rs)->resource.Get(); + if (rs != prev_rs[cmd]) + { + deviceContexts[cmd]->RSSetState(rs); + prev_rs[cmd] = rs; + } + + ID3D11DepthStencilState* dss = desc.dss == nullptr ? nullptr : to_internal(desc.dss)->resource.Get(); + if (dss != prev_dss[cmd] || stencilRef[cmd] != prev_stencilRef[cmd]) + { + deviceContexts[cmd]->OMSetDepthStencilState(dss, stencilRef[cmd]); + prev_dss[cmd] = dss; + prev_stencilRef[cmd] = stencilRef[cmd]; + } + + ID3D11InputLayout* il = desc.il == nullptr ? nullptr : to_internal(desc.il)->resource.Get(); + if (il != prev_il[cmd]) + { + deviceContexts[cmd]->IASetInputLayout(il); + prev_il[cmd] = il; + } + + if (prev_pt[cmd] != desc.pt) + { + D3D11_PRIMITIVE_TOPOLOGY d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + switch (desc.pt) + { + case TRIANGLELIST: + d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + break; + case TRIANGLESTRIP: + d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + break; + case POINTLIST: + d3dType = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; + break; + case LINELIST: + d3dType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST; + break; + case LINESTRIP: + d3dType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP; + break; + case PATCHLIST: + d3dType = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; + break; + default: + d3dType = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + break; + }; + deviceContexts[cmd]->IASetPrimitiveTopology(d3dType); + + prev_pt[cmd] = desc.pt; + } +} // Engine functions GraphicsDevice_DX11::GraphicsDevice_DX11(wiPlatform::window_type window, bool fullscreen, bool debuglayer) @@ -2423,6 +2531,7 @@ CommandList GraphicsDevice_DX11::BeginCommandList() bool success = CreateBuffer(&frameAllocatorDesc, nullptr, &frame_allocators[cmd].buffer); assert(success); SetName(&frame_allocators[cmd].buffer, "frame_allocator"); + } BindPipelineState(nullptr, cmd); @@ -2447,6 +2556,9 @@ CommandList GraphicsDevice_DX11::BeginCommandList() } deviceContexts[cmd]->RSSetScissorRects(8, pRects); + active_pso[cmd] = nullptr; + dirty_pso[cmd] = false; + return cmd; } @@ -2473,12 +2585,11 @@ void GraphicsDevice_DX11::RenderPassBegin(const RenderPass* renderpass, CommandL const RenderPassDesc& desc = renderpass->GetDesc(); uint32_t rt_count = 0; - ID3D11RenderTargetView* RTVs[8] = {}; + ID3D11RenderTargetView* RTVs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {}; ID3D11DepthStencilView* DSV = nullptr; - assert(desc.numAttachments < arraysize(RTVs) + 1); - for (uint32_t i = 0; i < desc.numAttachments; ++i) + assert(desc.attachments.size() < arraysize(RTVs) + 1); + for (auto& attachment : desc.attachments) { - const RenderPassAttachment& attachment = desc.attachments[i]; const Texture* texture = attachment.texture; int subresource = attachment.subresource; auto internal_state = to_internal(texture); @@ -2808,107 +2919,11 @@ void GraphicsDevice_DX11::BindBlendFactor(float r, float g, float b, float a, Co } void GraphicsDevice_DX11::BindPipelineState(const PipelineState* pso, CommandList cmd) { - const PipelineStateDesc& desc = pso != nullptr ? pso->GetDesc() : PipelineStateDesc(); + if (active_pso[cmd] == pso) + return; - ID3D11VertexShader* vs = desc.vs == nullptr ? nullptr : static_cast(desc.vs->internal_state.get())->resource.Get(); - if (vs != prev_vs[cmd]) - { - deviceContexts[cmd]->VSSetShader(vs, nullptr, 0); - prev_vs[cmd] = vs; - } - ID3D11PixelShader* ps = desc.ps == nullptr ? nullptr : static_cast(desc.ps->internal_state.get())->resource.Get(); - if (ps != prev_ps[cmd]) - { - deviceContexts[cmd]->PSSetShader(ps, nullptr, 0); - prev_ps[cmd] = ps; - } - ID3D11HullShader* hs = desc.hs == nullptr ? nullptr : static_cast(desc.hs->internal_state.get())->resource.Get(); - if (hs != prev_hs[cmd]) - { - deviceContexts[cmd]->HSSetShader(hs, nullptr, 0); - prev_hs[cmd] = hs; - } - ID3D11DomainShader* ds = desc.ds == nullptr ? nullptr : static_cast(desc.ds->internal_state.get())->resource.Get(); - if (ds != prev_ds[cmd]) - { - deviceContexts[cmd]->DSSetShader(ds, nullptr, 0); - prev_ds[cmd] = ds; - } - ID3D11GeometryShader* gs = desc.gs == nullptr ? nullptr : static_cast(desc.gs->internal_state.get())->resource.Get(); - if (gs != prev_gs[cmd]) - { - deviceContexts[cmd]->GSSetShader(gs, nullptr, 0); - prev_gs[cmd] = gs; - } - - ID3D11BlendState* bs = desc.bs == nullptr ? nullptr : to_internal(desc.bs)->resource.Get(); - if (bs != prev_bs[cmd] || desc.sampleMask != prev_samplemask[cmd] || - blendFactor[cmd].x != prev_blendfactor[cmd].x || - blendFactor[cmd].y != prev_blendfactor[cmd].y || - blendFactor[cmd].z != prev_blendfactor[cmd].z || - blendFactor[cmd].w != prev_blendfactor[cmd].w - ) - { - const float fact[4] = { blendFactor[cmd].x, blendFactor[cmd].y, blendFactor[cmd].z, blendFactor[cmd].w }; - deviceContexts[cmd]->OMSetBlendState(bs, fact, desc.sampleMask); - prev_bs[cmd] = bs; - prev_blendfactor[cmd] = blendFactor[cmd]; - prev_samplemask[cmd] = desc.sampleMask; - } - - ID3D11RasterizerState* rs = desc.rs == nullptr ? nullptr : to_internal(desc.rs)->resource.Get(); - if (rs != prev_rs[cmd]) - { - deviceContexts[cmd]->RSSetState(rs); - prev_rs[cmd] = rs; - } - - ID3D11DepthStencilState* dss = desc.dss == nullptr ? nullptr : to_internal(desc.dss)->resource.Get(); - if (dss != prev_dss[cmd] || stencilRef[cmd] != prev_stencilRef[cmd]) - { - deviceContexts[cmd]->OMSetDepthStencilState(dss, stencilRef[cmd]); - prev_dss[cmd] = dss; - prev_stencilRef[cmd] = stencilRef[cmd]; - } - - ID3D11InputLayout* il = desc.il == nullptr ? nullptr : to_internal(desc.il)->resource.Get(); - if (il != prev_il[cmd]) - { - deviceContexts[cmd]->IASetInputLayout(il); - prev_il[cmd] = il; - } - - if (prev_pt[cmd] != desc.pt) - { - D3D11_PRIMITIVE_TOPOLOGY d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - switch (desc.pt) - { - case TRIANGLELIST: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - break; - case TRIANGLESTRIP: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; - break; - case POINTLIST: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; - break; - case LINELIST: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST; - break; - case LINESTRIP: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP; - break; - case PATCHLIST: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; - break; - default: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; - break; - }; - deviceContexts[cmd]->IASetPrimitiveTopology(d3dType); - - prev_pt[cmd] = desc.pt; - } + active_pso[cmd] = pso; + dirty_pso[cmd] = true; } void GraphicsDevice_DX11::BindComputeShader(const Shader* cs, CommandList cmd) { @@ -2921,36 +2936,42 @@ void GraphicsDevice_DX11::BindComputeShader(const Shader* cs, CommandList cmd) } void GraphicsDevice_DX11::Draw(uint32_t vertexCount, uint32_t startVertexLocation, CommandList cmd) { + pso_validate(cmd); commit_allocations(cmd); deviceContexts[cmd]->Draw(vertexCount, startVertexLocation); } void GraphicsDevice_DX11::DrawIndexed(uint32_t indexCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, CommandList cmd) { + pso_validate(cmd); commit_allocations(cmd); deviceContexts[cmd]->DrawIndexed(indexCount, startIndexLocation, baseVertexLocation); } void GraphicsDevice_DX11::DrawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation, CommandList cmd) { + pso_validate(cmd); commit_allocations(cmd); deviceContexts[cmd]->DrawInstanced(vertexCount, instanceCount, startVertexLocation, startInstanceLocation); } void GraphicsDevice_DX11::DrawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, uint32_t startInstanceLocation, CommandList cmd) { + pso_validate(cmd); commit_allocations(cmd); deviceContexts[cmd]->DrawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); } void GraphicsDevice_DX11::DrawInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) { + pso_validate(cmd); commit_allocations(cmd); deviceContexts[cmd]->DrawInstancedIndirect((ID3D11Buffer*)to_internal(args)->resource.Get(), args_offset); } void GraphicsDevice_DX11::DrawIndexedInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) { + pso_validate(cmd); commit_allocations(cmd); deviceContexts[cmd]->DrawIndexedInstancedIndirect((ID3D11Buffer*)to_internal(args)->resource.Get(), args_offset); diff --git a/WickedEngine/wiGraphicsDevice_DX11.h b/WickedEngine/wiGraphicsDevice_DX11.h index b0cd44e7c..82bf20e03 100644 --- a/WickedEngine/wiGraphicsDevice_DX11.h +++ b/WickedEngine/wiGraphicsDevice_DX11.h @@ -50,6 +50,10 @@ namespace wiGraphics ID3D11InputLayout* prev_il[COMMANDLIST_COUNT] = {}; PRIMITIVETOPOLOGY prev_pt[COMMANDLIST_COUNT] = {}; + const PipelineState* active_pso[COMMANDLIST_COUNT] = {}; + bool dirty_pso[COMMANDLIST_COUNT] = {}; + void pso_validate(CommandList cmd); + ID3D11UnorderedAccessView* raster_uavs[COMMANDLIST_COUNT][8] = {}; uint8_t raster_uavs_slot[COMMANDLIST_COUNT] = {}; uint8_t raster_uavs_count[COMMANDLIST_COUNT] = {}; diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index 8f553b3e5..3bb85d1c2 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -33,7 +33,7 @@ #include // Uncomment this to enable DX12 renderpass feature: -//#define DX12_REAL_RENDERPASS +#define DX12_REAL_RENDERPASS using namespace Microsoft::WRL; @@ -1284,14 +1284,14 @@ using namespace DX12_Internal; // Resources: if (!PSO_table.resources.empty()) { - DescriptorHeap& heap = heaps_resource[currentheap_resource]; - if ((heap.ringOffset + (uint32_t)PSO_table.resources.size()) >= heap.heapDesc.NumDescriptors) + if ((heaps_resource[currentheap_resource].ringOffset + (uint32_t)PSO_table.resources.size()) >= heaps_resource[currentheap_resource].heapDesc.NumDescriptors) { // start new heap if the current one is full currentheap_resource++; heaps_bound = false; create_or_bind_heaps_on_demand(cmd); } + DescriptorHeap& heap = heaps_resource[currentheap_resource]; D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {}; D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; @@ -1431,14 +1431,14 @@ using namespace DX12_Internal; // Samplers: if (!PSO_table.samplers.empty()) { - DescriptorHeap& heap = heaps_sampler[currentheap_sampler]; - if ((heap.ringOffset + (uint32_t)PSO_table.samplers.size()) >= heap.heapDesc.NumDescriptors) + if ((heaps_sampler[currentheap_sampler].ringOffset + (uint32_t)PSO_table.samplers.size()) >= heaps_sampler[currentheap_sampler].heapDesc.NumDescriptors) { // start new heap if the current one is full currentheap_sampler++; heaps_bound = false; create_or_bind_heaps_on_demand(cmd); } + DescriptorHeap& heap = heaps_sampler[currentheap_sampler]; D3D12_SAMPLER_DESC sampler_desc = {}; sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; @@ -1491,6 +1491,267 @@ using namespace DX12_Internal; dirty_graphics_compute[1] = false; } + void GraphicsDevice_DX12::pso_validate(CommandList cmd) + { + if (!dirty_pso[cmd]) + return; + + const PipelineState* pso = active_pso[cmd]; + size_t pipeline_hash = prev_pipeline_hash[cmd]; + + auto internal_state = to_internal(pso); + + ID3D12PipelineState* pipeline = nullptr; + auto it = pipelines_global.find(pipeline_hash); + if (it == pipelines_global.end()) + { + for (auto& x : pipelines_worker[cmd]) + { + if (pipeline_hash == x.first) + { + pipeline = x.second.Get(); + break; + } + } + + if (pipeline == nullptr) + { + D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; + + if (pso->desc.vs != nullptr) + { + desc.VS.pShaderBytecode = pso->desc.vs->code.data(); + desc.VS.BytecodeLength = pso->desc.vs->code.size(); + } + if (pso->desc.hs != nullptr) + { + desc.HS.pShaderBytecode = pso->desc.hs->code.data(); + desc.HS.BytecodeLength = pso->desc.hs->code.size(); + } + if (pso->desc.ds != nullptr) + { + desc.DS.pShaderBytecode = pso->desc.ds->code.data(); + desc.DS.BytecodeLength = pso->desc.ds->code.size(); + } + if (pso->desc.gs != nullptr) + { + desc.GS.pShaderBytecode = pso->desc.gs->code.data(); + desc.GS.BytecodeLength = pso->desc.gs->code.size(); + } + if (pso->desc.ps != nullptr) + { + desc.PS.BytecodeLength = pso->desc.ps->code.size(); + desc.PS.pShaderBytecode = pso->desc.ps->code.data(); + } + + RasterizerStateDesc pRasterizerStateDesc = pso->desc.rs != nullptr ? pso->desc.rs->GetDesc() : RasterizerStateDesc(); + desc.RasterizerState.FillMode = _ConvertFillMode(pRasterizerStateDesc.FillMode); + desc.RasterizerState.CullMode = _ConvertCullMode(pRasterizerStateDesc.CullMode); + desc.RasterizerState.FrontCounterClockwise = pRasterizerStateDesc.FrontCounterClockwise; + desc.RasterizerState.DepthBias = pRasterizerStateDesc.DepthBias; + desc.RasterizerState.DepthBiasClamp = pRasterizerStateDesc.DepthBiasClamp; + desc.RasterizerState.SlopeScaledDepthBias = pRasterizerStateDesc.SlopeScaledDepthBias; + desc.RasterizerState.DepthClipEnable = pRasterizerStateDesc.DepthClipEnable; + desc.RasterizerState.MultisampleEnable = pRasterizerStateDesc.MultisampleEnable; + desc.RasterizerState.AntialiasedLineEnable = pRasterizerStateDesc.AntialiasedLineEnable; + desc.RasterizerState.ConservativeRaster = ((CONSERVATIVE_RASTERIZATION && pRasterizerStateDesc.ConservativeRasterizationEnable) ? D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON : D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF); + desc.RasterizerState.ForcedSampleCount = pRasterizerStateDesc.ForcedSampleCount; + + + DepthStencilStateDesc pDepthStencilStateDesc = pso->desc.dss != nullptr ? pso->desc.dss->GetDesc() : DepthStencilStateDesc(); + desc.DepthStencilState.DepthEnable = pDepthStencilStateDesc.DepthEnable; + desc.DepthStencilState.DepthWriteMask = _ConvertDepthWriteMask(pDepthStencilStateDesc.DepthWriteMask); + desc.DepthStencilState.DepthFunc = _ConvertComparisonFunc(pDepthStencilStateDesc.DepthFunc); + desc.DepthStencilState.StencilEnable = pDepthStencilStateDesc.StencilEnable; + desc.DepthStencilState.StencilReadMask = pDepthStencilStateDesc.StencilReadMask; + desc.DepthStencilState.StencilWriteMask = pDepthStencilStateDesc.StencilWriteMask; + desc.DepthStencilState.FrontFace.StencilDepthFailOp = _ConvertStencilOp(pDepthStencilStateDesc.FrontFace.StencilDepthFailOp); + desc.DepthStencilState.FrontFace.StencilFailOp = _ConvertStencilOp(pDepthStencilStateDesc.FrontFace.StencilFailOp); + desc.DepthStencilState.FrontFace.StencilFunc = _ConvertComparisonFunc(pDepthStencilStateDesc.FrontFace.StencilFunc); + desc.DepthStencilState.FrontFace.StencilPassOp = _ConvertStencilOp(pDepthStencilStateDesc.FrontFace.StencilPassOp); + desc.DepthStencilState.BackFace.StencilDepthFailOp = _ConvertStencilOp(pDepthStencilStateDesc.BackFace.StencilDepthFailOp); + desc.DepthStencilState.BackFace.StencilFailOp = _ConvertStencilOp(pDepthStencilStateDesc.BackFace.StencilFailOp); + desc.DepthStencilState.BackFace.StencilFunc = _ConvertComparisonFunc(pDepthStencilStateDesc.BackFace.StencilFunc); + desc.DepthStencilState.BackFace.StencilPassOp = _ConvertStencilOp(pDepthStencilStateDesc.BackFace.StencilPassOp); + + + BlendStateDesc pBlendStateDesc = pso->desc.bs != nullptr ? pso->desc.bs->GetDesc() : BlendStateDesc(); + desc.BlendState.AlphaToCoverageEnable = pBlendStateDesc.AlphaToCoverageEnable; + desc.BlendState.IndependentBlendEnable = pBlendStateDesc.IndependentBlendEnable; + for (int i = 0; i < 8; ++i) + { + desc.BlendState.RenderTarget[i].BlendEnable = pBlendStateDesc.RenderTarget[i].BlendEnable; + desc.BlendState.RenderTarget[i].SrcBlend = _ConvertBlend(pBlendStateDesc.RenderTarget[i].SrcBlend); + desc.BlendState.RenderTarget[i].DestBlend = _ConvertBlend(pBlendStateDesc.RenderTarget[i].DestBlend); + desc.BlendState.RenderTarget[i].BlendOp = _ConvertBlendOp(pBlendStateDesc.RenderTarget[i].BlendOp); + desc.BlendState.RenderTarget[i].SrcBlendAlpha = _ConvertBlend(pBlendStateDesc.RenderTarget[i].SrcBlendAlpha); + desc.BlendState.RenderTarget[i].DestBlendAlpha = _ConvertBlend(pBlendStateDesc.RenderTarget[i].DestBlendAlpha); + desc.BlendState.RenderTarget[i].BlendOpAlpha = _ConvertBlendOp(pBlendStateDesc.RenderTarget[i].BlendOpAlpha); + desc.BlendState.RenderTarget[i].RenderTargetWriteMask = _ParseColorWriteMask(pBlendStateDesc.RenderTarget[i].RenderTargetWriteMask); + } + + std::vector elements; + if (pso->desc.il != nullptr) + { + desc.InputLayout.NumElements = (uint32_t)pso->desc.il->desc.size(); + elements.resize(desc.InputLayout.NumElements); + for (uint32_t i = 0; i < desc.InputLayout.NumElements; ++i) + { + elements[i].SemanticName = pso->desc.il->desc[i].SemanticName.c_str(); + elements[i].SemanticIndex = pso->desc.il->desc[i].SemanticIndex; + elements[i].Format = _ConvertFormat(pso->desc.il->desc[i].Format); + elements[i].InputSlot = pso->desc.il->desc[i].InputSlot; + elements[i].AlignedByteOffset = pso->desc.il->desc[i].AlignedByteOffset; + if (elements[i].AlignedByteOffset == InputLayoutDesc::APPEND_ALIGNED_ELEMENT) + elements[i].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT; + elements[i].InputSlotClass = _ConvertInputClassification(pso->desc.il->desc[i].InputSlotClass); + elements[i].InstanceDataStepRate = pso->desc.il->desc[i].InstanceDataStepRate; + } + } + desc.InputLayout.pInputElementDescs = elements.data(); + + desc.NumRenderTargets = 0; + desc.DSVFormat = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + if (active_renderpass[cmd] == nullptr) + { + desc.NumRenderTargets = 1; + desc.RTVFormats[0] = _ConvertFormat(BACKBUFFER_FORMAT); + } + else + { + for (auto& attachment : active_renderpass[cmd]->desc.attachments) + { + + switch (attachment.type) + { + case RenderPassAttachment::RENDERTARGET: + switch (attachment.texture->desc.Format) + { + case FORMAT_R16_TYPELESS: + desc.RTVFormats[desc.NumRenderTargets] = DXGI_FORMAT_R16_UNORM; + break; + case FORMAT_R32_TYPELESS: + desc.RTVFormats[desc.NumRenderTargets] = DXGI_FORMAT_R32_FLOAT; + break; + case FORMAT_R24G8_TYPELESS: + desc.RTVFormats[desc.NumRenderTargets] = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + break; + case FORMAT_R32G8X24_TYPELESS: + desc.RTVFormats[desc.NumRenderTargets] = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + break; + default: + desc.RTVFormats[desc.NumRenderTargets] = _ConvertFormat(attachment.texture->desc.Format); + break; + } + desc.NumRenderTargets++; + break; + case RenderPassAttachment::DEPTH_STENCIL: + switch (attachment.texture->desc.Format) + { + case FORMAT_R16_TYPELESS: + desc.DSVFormat = DXGI_FORMAT_D16_UNORM; + break; + case FORMAT_R32_TYPELESS: + desc.DSVFormat = DXGI_FORMAT_D32_FLOAT; + break; + case FORMAT_R24G8_TYPELESS: + desc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; + break; + case FORMAT_R32G8X24_TYPELESS: + desc.DSVFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + break; + default: + desc.DSVFormat = _ConvertFormat(attachment.texture->desc.Format); + break; + } + break; + default: + assert(0); + break; + } + + desc.SampleDesc.Count = attachment.texture->desc.SampleCount; + desc.SampleDesc.Quality = 0; + } + } + desc.SampleMask = pso->desc.sampleMask; + + switch (pso->desc.pt) + { + case POINTLIST: + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; + break; + case LINELIST: + case LINESTRIP: + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; + break; + case TRIANGLELIST: + case TRIANGLESTRIP: + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + break; + case PATCHLIST: + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; + break; + default: + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED; + break; + } + + desc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; + + desc.pRootSignature = internal_state->rootSignature.Get(); + + ComPtr newpso; + HRESULT hr = device->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&newpso)); + assert(SUCCEEDED(hr)); + + pipelines_worker[cmd].push_back(std::make_pair(pipeline_hash, newpso)); + pipeline = newpso.Get(); + } + } + else + { + pipeline = it->second.Get(); + } + assert(pipeline != nullptr); + + GetDirectCommandList(cmd)->SetPipelineState(pipeline); + + GetDirectCommandList(cmd)->SetGraphicsRootSignature(internal_state->rootSignature.Get()); + + if (prev_pt[cmd] != pso->desc.pt) + { + prev_pt[cmd] = pso->desc.pt; + + D3D12_PRIMITIVE_TOPOLOGY d3dType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + switch (pso->desc.pt) + { + case TRIANGLELIST: + d3dType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + break; + case TRIANGLESTRIP: + d3dType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + break; + case POINTLIST: + d3dType = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; + break; + case LINELIST: + d3dType = D3D_PRIMITIVE_TOPOLOGY_LINELIST; + break; + case LINESTRIP: + d3dType = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; + break; + case PATCHLIST: + d3dType = D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; + break; + default: + break; + }; + GetDirectCommandList(cmd)->IASetPrimitiveTopology(d3dType); + } + } // Engine functions @@ -2605,11 +2866,11 @@ using namespace DX12_Internal; renderpass->desc = *pDesc; renderpass->hash = 0; - wiHelper::hash_combine(renderpass->hash, pDesc->numAttachments); - for (uint32_t i = 0; i < pDesc->numAttachments; ++i) + wiHelper::hash_combine(renderpass->hash, pDesc->attachments.size()); + for (auto& attachment : pDesc->attachments) { - wiHelper::hash_combine(renderpass->hash, pDesc->attachments[i].texture->desc.Format); - wiHelper::hash_combine(renderpass->hash, pDesc->attachments[i].texture->desc.SampleCount); + wiHelper::hash_combine(renderpass->hash, attachment.texture->desc.Format); + wiHelper::hash_combine(renderpass->hash, attachment.texture->desc.SampleCount); } return true; @@ -3458,6 +3719,10 @@ using namespace DX12_Internal; frames[fr].descriptors[cmd].init(this); frames[fr].resourceBuffer[cmd].init(this, 1024 * 1024); // 1 MB starting size + + std::wstringstream wss; + wss << "cmd" << cmd; + frames[fr].commandLists[cmd].Get()->SetName(wss.str().c_str()); } } @@ -3495,6 +3760,7 @@ using namespace DX12_Internal; active_pso[cmd] = nullptr; active_cs[cmd] = nullptr; active_renderpass[cmd] = nullptr; + dirty_pso[cmd] = false; return cmd; } @@ -3530,6 +3796,34 @@ using namespace DX12_Internal; void GraphicsDevice_DX12::RenderPassBegin(const RenderPass* renderpass, CommandList cmd) { active_renderpass[cmd] = renderpass; + const RenderPassDesc& desc = renderpass->GetDesc(); + + // Perform render pass transitions: + D3D12_RESOURCE_BARRIER barrierdescs[9]; + uint32_t numBarriers = 0; + for (auto& attachment : desc.attachments) + { + auto internal_state = to_internal(attachment.texture); + + D3D12_RESOURCE_BARRIER& barrierdesc = barrierdescs[numBarriers++]; + + barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrierdesc.Transition.pResource = internal_state->resource.Get(); + barrierdesc.Transition.StateBefore = _ConvertImageLayout(attachment.initial_layout); + barrierdesc.Transition.StateAfter = _ConvertImageLayout(attachment.subpass_layout); + barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + + if (barrierdesc.Transition.StateBefore == barrierdesc.Transition.StateAfter) + { + numBarriers--; + continue; + } + } + if (numBarriers > 0) + { + GetDirectCommandList(cmd)->ResourceBarrier(numBarriers, barrierdescs); + } D3D12_CPU_DESCRIPTOR_HANDLE descriptors_RTV = rtv_descriptor_heap_start; descriptors_RTV.ptr += rtv_descriptor_size * D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT * cmd; @@ -3537,17 +3831,14 @@ using namespace DX12_Internal; D3D12_CPU_DESCRIPTOR_HANDLE descriptors_DSV = dsv_descriptor_heap_start; descriptors_DSV.ptr += dsv_descriptor_size * cmd; - const RenderPassDesc& desc = renderpass->GetDesc(); - #ifdef DX12_REAL_RENDERPASS uint32_t rt_count = 0; - D3D12_RENDER_PASS_RENDER_TARGET_DESC RTVs[8] = {}; + D3D12_RENDER_PASS_RENDER_TARGET_DESC RTVs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {}; bool dsv = false; D3D12_RENDER_PASS_DEPTH_STENCIL_DESC DSV = {}; - for (uint32_t i = 0; i < desc.numAttachments; ++i) + for (auto& attachment : desc.attachments) { - const RenderPassAttachment& attachment = desc.attachments[i]; const Texture* texture = attachment.texture; int subresource = attachment.subresource; auto internal_state = to_internal(texture); @@ -3661,9 +3952,8 @@ using namespace DX12_Internal; uint32_t rt_count = 0; D3D12_RENDER_TARGET_VIEW_DESC RTVs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {}; D3D12_DEPTH_STENCIL_VIEW_DESC* DSV = nullptr; - for (uint32_t i = 0; i < desc.numAttachments; ++i) + for (auto& attachment : desc.attachments) { - const RenderPassAttachment& attachment = desc.attachments[i]; const Texture* texture = attachment.texture; int subresource = attachment.subresource; auto internal_state = to_internal(texture); @@ -3732,13 +4022,8 @@ using namespace DX12_Internal; // Perform render pass transitions: D3D12_RESOURCE_BARRIER barrierdescs[9]; uint32_t numBarriers = 0; - for (uint32_t i = 0; i < active_renderpass[cmd]->desc.numAttachments; ++i) + for (auto& attachment : active_renderpass[cmd]->desc.attachments) { - const RenderPassAttachment& attachment = active_renderpass[cmd]->desc.attachments[i]; - if (attachment.initial_layout == attachment.final_layout) - { - continue; - } auto internal_state = to_internal(attachment.texture); D3D12_RESOURCE_BARRIER& barrierdesc = barrierdescs[numBarriers++]; @@ -3746,9 +4031,15 @@ using namespace DX12_Internal; barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrierdesc.Transition.pResource = internal_state->resource.Get(); - barrierdesc.Transition.StateBefore = _ConvertImageLayout(attachment.initial_layout); + barrierdesc.Transition.StateBefore = _ConvertImageLayout(attachment.subpass_layout); barrierdesc.Transition.StateAfter = _ConvertImageLayout(attachment.final_layout); barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + + if (barrierdesc.Transition.StateBefore == barrierdesc.Transition.StateAfter) + { + numBarriers--; + continue; + } } if (numBarriers > 0) { @@ -3914,260 +4205,7 @@ using namespace DX12_Internal; GetFrameResources().descriptors[cmd].dirty_graphics_compute[0] = true; active_pso[cmd] = pso; - - auto internal_state = to_internal(pso); - - ID3D12PipelineState* pipeline = nullptr; - auto it = pipelines_global.find(pipeline_hash); - if (it == pipelines_global.end()) - { - for (auto& x : pipelines_worker[cmd]) - { - if (pipeline_hash == x.first) - { - pipeline = x.second.Get(); - break; - } - } - - if (pipeline == nullptr) - { - D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; - - if (pso->desc.vs != nullptr) - { - desc.VS.pShaderBytecode = pso->desc.vs->code.data(); - desc.VS.BytecodeLength = pso->desc.vs->code.size(); - } - if (pso->desc.hs != nullptr) - { - desc.HS.pShaderBytecode = pso->desc.hs->code.data(); - desc.HS.BytecodeLength = pso->desc.hs->code.size(); - } - if (pso->desc.ds != nullptr) - { - desc.DS.pShaderBytecode = pso->desc.ds->code.data(); - desc.DS.BytecodeLength = pso->desc.ds->code.size(); - } - if (pso->desc.gs != nullptr) - { - desc.GS.pShaderBytecode = pso->desc.gs->code.data(); - desc.GS.BytecodeLength = pso->desc.gs->code.size(); - } - if (pso->desc.ps != nullptr) - { - desc.PS.BytecodeLength = pso->desc.ps->code.size(); - desc.PS.pShaderBytecode = pso->desc.ps->code.data(); - } - - RasterizerStateDesc pRasterizerStateDesc = pso->desc.rs != nullptr ? pso->desc.rs->GetDesc() : RasterizerStateDesc(); - desc.RasterizerState.FillMode = _ConvertFillMode(pRasterizerStateDesc.FillMode); - desc.RasterizerState.CullMode = _ConvertCullMode(pRasterizerStateDesc.CullMode); - desc.RasterizerState.FrontCounterClockwise = pRasterizerStateDesc.FrontCounterClockwise; - desc.RasterizerState.DepthBias = pRasterizerStateDesc.DepthBias; - desc.RasterizerState.DepthBiasClamp = pRasterizerStateDesc.DepthBiasClamp; - desc.RasterizerState.SlopeScaledDepthBias = pRasterizerStateDesc.SlopeScaledDepthBias; - desc.RasterizerState.DepthClipEnable = pRasterizerStateDesc.DepthClipEnable; - desc.RasterizerState.MultisampleEnable = pRasterizerStateDesc.MultisampleEnable; - desc.RasterizerState.AntialiasedLineEnable = pRasterizerStateDesc.AntialiasedLineEnable; - desc.RasterizerState.ConservativeRaster = ((CONSERVATIVE_RASTERIZATION && pRasterizerStateDesc.ConservativeRasterizationEnable) ? D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON : D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF); - desc.RasterizerState.ForcedSampleCount = pRasterizerStateDesc.ForcedSampleCount; - - - DepthStencilStateDesc pDepthStencilStateDesc = pso->desc.dss != nullptr ? pso->desc.dss->GetDesc() : DepthStencilStateDesc(); - desc.DepthStencilState.DepthEnable = pDepthStencilStateDesc.DepthEnable; - desc.DepthStencilState.DepthWriteMask = _ConvertDepthWriteMask(pDepthStencilStateDesc.DepthWriteMask); - desc.DepthStencilState.DepthFunc = _ConvertComparisonFunc(pDepthStencilStateDesc.DepthFunc); - desc.DepthStencilState.StencilEnable = pDepthStencilStateDesc.StencilEnable; - desc.DepthStencilState.StencilReadMask = pDepthStencilStateDesc.StencilReadMask; - desc.DepthStencilState.StencilWriteMask = pDepthStencilStateDesc.StencilWriteMask; - desc.DepthStencilState.FrontFace.StencilDepthFailOp = _ConvertStencilOp(pDepthStencilStateDesc.FrontFace.StencilDepthFailOp); - desc.DepthStencilState.FrontFace.StencilFailOp = _ConvertStencilOp(pDepthStencilStateDesc.FrontFace.StencilFailOp); - desc.DepthStencilState.FrontFace.StencilFunc = _ConvertComparisonFunc(pDepthStencilStateDesc.FrontFace.StencilFunc); - desc.DepthStencilState.FrontFace.StencilPassOp = _ConvertStencilOp(pDepthStencilStateDesc.FrontFace.StencilPassOp); - desc.DepthStencilState.BackFace.StencilDepthFailOp = _ConvertStencilOp(pDepthStencilStateDesc.BackFace.StencilDepthFailOp); - desc.DepthStencilState.BackFace.StencilFailOp = _ConvertStencilOp(pDepthStencilStateDesc.BackFace.StencilFailOp); - desc.DepthStencilState.BackFace.StencilFunc = _ConvertComparisonFunc(pDepthStencilStateDesc.BackFace.StencilFunc); - desc.DepthStencilState.BackFace.StencilPassOp = _ConvertStencilOp(pDepthStencilStateDesc.BackFace.StencilPassOp); - - - BlendStateDesc pBlendStateDesc = pso->desc.bs != nullptr ? pso->desc.bs->GetDesc() : BlendStateDesc(); - desc.BlendState.AlphaToCoverageEnable = pBlendStateDesc.AlphaToCoverageEnable; - desc.BlendState.IndependentBlendEnable = pBlendStateDesc.IndependentBlendEnable; - for (int i = 0; i < 8; ++i) - { - desc.BlendState.RenderTarget[i].BlendEnable = pBlendStateDesc.RenderTarget[i].BlendEnable; - desc.BlendState.RenderTarget[i].SrcBlend = _ConvertBlend(pBlendStateDesc.RenderTarget[i].SrcBlend); - desc.BlendState.RenderTarget[i].DestBlend = _ConvertBlend(pBlendStateDesc.RenderTarget[i].DestBlend); - desc.BlendState.RenderTarget[i].BlendOp = _ConvertBlendOp(pBlendStateDesc.RenderTarget[i].BlendOp); - desc.BlendState.RenderTarget[i].SrcBlendAlpha = _ConvertBlend(pBlendStateDesc.RenderTarget[i].SrcBlendAlpha); - desc.BlendState.RenderTarget[i].DestBlendAlpha = _ConvertBlend(pBlendStateDesc.RenderTarget[i].DestBlendAlpha); - desc.BlendState.RenderTarget[i].BlendOpAlpha = _ConvertBlendOp(pBlendStateDesc.RenderTarget[i].BlendOpAlpha); - desc.BlendState.RenderTarget[i].RenderTargetWriteMask = _ParseColorWriteMask(pBlendStateDesc.RenderTarget[i].RenderTargetWriteMask); - } - - std::vector elements; - if (pso->desc.il != nullptr) - { - desc.InputLayout.NumElements = (uint32_t)pso->desc.il->desc.size(); - elements.resize(desc.InputLayout.NumElements); - for (uint32_t i = 0; i < desc.InputLayout.NumElements; ++i) - { - elements[i].SemanticName = pso->desc.il->desc[i].SemanticName.c_str(); - elements[i].SemanticIndex = pso->desc.il->desc[i].SemanticIndex; - elements[i].Format = _ConvertFormat(pso->desc.il->desc[i].Format); - elements[i].InputSlot = pso->desc.il->desc[i].InputSlot; - elements[i].AlignedByteOffset = pso->desc.il->desc[i].AlignedByteOffset; - if (elements[i].AlignedByteOffset == InputLayoutDesc::APPEND_ALIGNED_ELEMENT) - elements[i].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT; - elements[i].InputSlotClass = _ConvertInputClassification(pso->desc.il->desc[i].InputSlotClass); - elements[i].InstanceDataStepRate = pso->desc.il->desc[i].InstanceDataStepRate; - } - } - desc.InputLayout.pInputElementDescs = elements.data(); - - desc.NumRenderTargets = 0; - desc.DSVFormat = DXGI_FORMAT_UNKNOWN; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - if (active_renderpass[cmd] == nullptr) - { - desc.NumRenderTargets = 1; - desc.RTVFormats[0] = _ConvertFormat(BACKBUFFER_FORMAT); - } - else - { - for (uint32_t i = 0; i < active_renderpass[cmd]->desc.numAttachments; ++i) - { - const RenderPassAttachment& attachment = active_renderpass[cmd]->desc.attachments[i]; - - switch (attachment.type) - { - case RenderPassAttachment::RENDERTARGET: - switch (attachment.texture->desc.Format) - { - case FORMAT_R16_TYPELESS: - desc.RTVFormats[desc.NumRenderTargets] = DXGI_FORMAT_R16_UNORM; - break; - case FORMAT_R32_TYPELESS: - desc.RTVFormats[desc.NumRenderTargets] = DXGI_FORMAT_R32_FLOAT; - break; - case FORMAT_R24G8_TYPELESS: - desc.RTVFormats[desc.NumRenderTargets] = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; - break; - case FORMAT_R32G8X24_TYPELESS: - desc.RTVFormats[desc.NumRenderTargets] = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; - break; - default: - desc.RTVFormats[desc.NumRenderTargets] = _ConvertFormat(attachment.texture->desc.Format); - break; - } - desc.NumRenderTargets++; - break; - case RenderPassAttachment::DEPTH_STENCIL: - switch (attachment.texture->desc.Format) - { - case FORMAT_R16_TYPELESS: - desc.DSVFormat = DXGI_FORMAT_D16_UNORM; - break; - case FORMAT_R32_TYPELESS: - desc.DSVFormat = DXGI_FORMAT_D32_FLOAT; - break; - case FORMAT_R24G8_TYPELESS: - desc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; - break; - case FORMAT_R32G8X24_TYPELESS: - desc.DSVFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; - break; - default: - desc.DSVFormat = _ConvertFormat(attachment.texture->desc.Format); - break; - } - break; - default: - assert(0); - break; - } - - desc.SampleDesc.Count = attachment.texture->desc.SampleCount; - desc.SampleDesc.Quality = 0; - } - } - desc.SampleMask = pso->desc.sampleMask; - - switch (pso->desc.pt) - { - case POINTLIST: - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; - break; - case LINELIST: - case LINESTRIP: - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; - break; - case TRIANGLELIST: - case TRIANGLESTRIP: - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - break; - case PATCHLIST: - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; - break; - default: - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED; - break; - } - - desc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; - - desc.pRootSignature = internal_state->rootSignature.Get(); - - ComPtr newpso; - HRESULT hr = device->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&newpso)); - assert(SUCCEEDED(hr)); - - pipelines_worker[cmd].push_back(std::make_pair(pipeline_hash, newpso)); - pipeline = newpso.Get(); - } - } - else - { - pipeline = it->second.Get(); - } - assert(pipeline != nullptr); - - GetDirectCommandList(cmd)->SetPipelineState(pipeline); - - GetDirectCommandList(cmd)->SetGraphicsRootSignature(internal_state->rootSignature.Get()); - - if (prev_pt[cmd] != pso->desc.pt) - { - prev_pt[cmd] = pso->desc.pt; - - D3D12_PRIMITIVE_TOPOLOGY d3dType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - switch (pso->desc.pt) - { - case TRIANGLELIST: - d3dType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - break; - case TRIANGLESTRIP: - d3dType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; - break; - case POINTLIST: - d3dType = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; - break; - case LINELIST: - d3dType = D3D_PRIMITIVE_TOPOLOGY_LINELIST; - break; - case LINESTRIP: - d3dType = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; - break; - case PATCHLIST: - d3dType = D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; - break; - default: - break; - }; - GetDirectCommandList(cmd)->IASetPrimitiveTopology(d3dType); - } + dirty_pso[cmd] = true; } void GraphicsDevice_DX12::BindComputeShader(const Shader* cs, CommandList cmd) { @@ -4185,33 +4223,39 @@ using namespace DX12_Internal; } void GraphicsDevice_DX12::Draw(uint32_t vertexCount, uint32_t startVertexLocation, CommandList cmd) { + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); GetDirectCommandList(cmd)->DrawInstanced(vertexCount, 1, startVertexLocation, 0); } void GraphicsDevice_DX12::DrawIndexed(uint32_t indexCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, CommandList cmd) { + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); GetDirectCommandList(cmd)->DrawIndexedInstanced(indexCount, 1, startIndexLocation, baseVertexLocation, 0); } void GraphicsDevice_DX12::DrawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation, CommandList cmd) { + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); GetDirectCommandList(cmd)->DrawInstanced(vertexCount, instanceCount, startVertexLocation, startInstanceLocation); } void GraphicsDevice_DX12::DrawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, uint32_t startInstanceLocation, CommandList cmd) { + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); GetDirectCommandList(cmd)->DrawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); } void GraphicsDevice_DX12::DrawInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) { auto internal_state = to_internal(args); + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); GetDirectCommandList(cmd)->ExecuteIndirect(drawInstancedIndirectCommandSignature.Get(), 1, internal_state->resource.Get(), args_offset, nullptr, 0); } void GraphicsDevice_DX12::DrawIndexedInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) { auto internal_state = to_internal(args); + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); GetDirectCommandList(cmd)->ExecuteIndirect(drawIndexedInstancedIndirectCommandSignature.Get(), 1, internal_state->resource.Get(), args_offset, nullptr, 0); } diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index 72b4bc3bf..aef5d7f57 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -158,6 +158,9 @@ namespace wiGraphics const Shader* active_cs[COMMANDLIST_COUNT] = {}; const RenderPass* active_renderpass[COMMANDLIST_COUNT] = {}; + bool dirty_pso[COMMANDLIST_COUNT] = {}; + void pso_validate(CommandList cmd); + struct Query_Resolve { GPU_QUERY_TYPE type; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index bc3b51cd9..7a805daef 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -882,6 +882,7 @@ namespace Vulkan_Internal VkPipelineShaderStageCreateInfo stageInfo = {}; VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; std::vector layoutBindings; + std::vector imageViewTypes; std::vector entrypoints; @@ -1231,6 +1232,7 @@ using namespace Vulkan_Internal; } auto shader_internal = to_internal(shader); + int i = 0; for (auto& x : shader_internal->layoutBindings) { descriptorWrites.emplace_back(); @@ -1243,6 +1245,8 @@ using namespace Vulkan_Internal; write.dstBinding = x.binding; write.descriptorCount = 1; + VkImageViewType viewtype = shader_internal->imageViewTypes[i++]; + switch (x.descriptorType) { case VK_DESCRIPTOR_TYPE_SAMPLER: @@ -1275,7 +1279,34 @@ using namespace Vulkan_Internal; const GPUResource* SRV = table.SRV[original_binding]; if (SRV == nullptr || !SRV->IsValid() || !SRV->IsTexture()) { - imageInfos.back().imageView = device->nullImageView; + switch (viewtype) + { + case VK_IMAGE_VIEW_TYPE_1D: + imageInfos.back().imageView = device->nullImageView1D; + break; + case VK_IMAGE_VIEW_TYPE_2D: + imageInfos.back().imageView = device->nullImageView2D; + break; + case VK_IMAGE_VIEW_TYPE_3D: + imageInfos.back().imageView = device->nullImageView3D; + break; + case VK_IMAGE_VIEW_TYPE_CUBE: + imageInfos.back().imageView = device->nullImageViewCube; + break; + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: + imageInfos.back().imageView = device->nullImageView1DArray; + break; + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: + imageInfos.back().imageView = device->nullImageView2DArray; + break; + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: + imageInfos.back().imageView = device->nullImageViewCubeArray; + break; + case VK_IMAGE_VIEW_TYPE_MAX_ENUM: + break; + default: + break; + } } else { @@ -1289,6 +1320,7 @@ using namespace Vulkan_Internal; { imageInfos.back().imageView = to_internal(texture)->srv; } + imageInfos.back().imageLayout = _ConvertImageLayout(texture->desc.layout); } } break; @@ -1298,12 +1330,40 @@ using namespace Vulkan_Internal; imageInfos.emplace_back(); write.pImageInfo = &imageInfos.back(); imageInfos.back() = {}; + imageInfos.back().imageLayout = VK_IMAGE_LAYOUT_GENERAL; const uint32_t original_binding = x.binding - VULKAN_BINDING_SHIFT_U - VULKAN_BINDING_SHIFT_STAGE(stage); const GPUResource* UAV = table.UAV[original_binding]; if (UAV == nullptr || !UAV->IsValid() || !UAV->IsTexture()) { - imageInfos.back().imageView = device->nullImageView; + switch (viewtype) + { + case VK_IMAGE_VIEW_TYPE_1D: + imageInfos.back().imageView = device->nullImageView1D; + break; + case VK_IMAGE_VIEW_TYPE_2D: + imageInfos.back().imageView = device->nullImageView2D; + break; + case VK_IMAGE_VIEW_TYPE_3D: + imageInfos.back().imageView = device->nullImageView3D; + break; + case VK_IMAGE_VIEW_TYPE_CUBE: + imageInfos.back().imageView = device->nullImageViewCube; + break; + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: + imageInfos.back().imageView = device->nullImageView1DArray; + break; + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: + imageInfos.back().imageView = device->nullImageView2DArray; + break; + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: + imageInfos.back().imageView = device->nullImageViewCubeArray; + break; + case VK_IMAGE_VIEW_TYPE_MAX_ENUM: + break; + default: + break; + } } else { @@ -1317,7 +1377,7 @@ using namespace Vulkan_Internal; { imageInfos.back().imageView = to_internal(texture)->uav; } - imageInfos.back().imageLayout = VK_IMAGE_LAYOUT_GENERAL; + imageInfos.back().imageLayout = _ConvertImageLayout(texture->desc.layout); } } break; @@ -1333,6 +1393,7 @@ using namespace Vulkan_Internal; if (CBV == nullptr || !CBV->IsValid()) { bufferInfos.back().buffer = device->nullBuffer; + bufferInfos.back().range = VK_WHOLE_SIZE; } else { @@ -1428,6 +1489,7 @@ using namespace Vulkan_Internal; if (UAV == nullptr || !UAV->IsValid() || !UAV->IsBuffer()) { bufferInfos.back().buffer = device->nullBuffer; + bufferInfos.back().range = VK_WHOLE_SIZE; } else { @@ -1444,6 +1506,7 @@ using namespace Vulkan_Internal; if (SRV == nullptr || !SRV->IsValid() || !SRV->IsBuffer()) { bufferInfos.back().buffer = device->nullBuffer; + bufferInfos.back().range = VK_WHOLE_SIZE; } else { @@ -1494,6 +1557,394 @@ using namespace Vulkan_Internal; dirty_graphics_compute[1] = false; } + void GraphicsDevice_Vulkan::pso_validate(CommandList cmd) + { + if (!dirty_pso[cmd]) + return; + + const PipelineState* pso = active_pso[cmd]; + size_t pipeline_hash = prev_pipeline_hash[cmd]; + + VkPipeline pipeline = VK_NULL_HANDLE; + auto it = pipelines_global.find(pipeline_hash); + if (it == pipelines_global.end()) + { + for (auto& x : pipelines_worker[cmd]) + { + if (pipeline_hash == x.first) + { + pipeline = x.second; + break; + } + } + + if (pipeline == VK_NULL_HANDLE) + { + VkResult res; + + VkGraphicsPipelineCreateInfo pipelineInfo = {}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.layout = to_internal(pso)->pipelineLayout; + pipelineInfo.renderPass = active_renderpass[cmd] == nullptr ? defaultRenderPass : to_internal(active_renderpass[cmd])->renderpass; + pipelineInfo.subpass = 0; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + + // Shaders: + + uint32_t shaderStageCount = 0; + VkPipelineShaderStageCreateInfo shaderStages[SHADERSTAGE_COUNT - 1]; + if (pso->desc.vs != nullptr && pso->desc.vs->IsValid()) + { + shaderStages[shaderStageCount++] = to_internal(pso->desc.vs)->stageInfo; + } + if (pso->desc.hs != nullptr && pso->desc.hs->IsValid()) + { + shaderStages[shaderStageCount++] = to_internal(pso->desc.hs)->stageInfo; + } + if (pso->desc.ds != nullptr && pso->desc.ds->IsValid()) + { + shaderStages[shaderStageCount++] = to_internal(pso->desc.ds)->stageInfo; + } + if (pso->desc.gs != nullptr && pso->desc.gs->IsValid()) + { + shaderStages[shaderStageCount++] = to_internal(pso->desc.gs)->stageInfo; + } + if (pso->desc.ps != nullptr && pso->desc.ps->IsValid()) + { + shaderStages[shaderStageCount++] = to_internal(pso->desc.ps)->stageInfo; + } + pipelineInfo.stageCount = shaderStageCount; + pipelineInfo.pStages = shaderStages; + + + // Fixed function states: + + // Input layout: + VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + std::vector bindings; + std::vector attributes; + if (pso->desc.il != nullptr) + { + uint32_t lastBinding = 0xFFFFFFFF; + for (auto& x : pso->desc.il->desc) + { + VkVertexInputBindingDescription bind = {}; + bind.binding = x.InputSlot; + bind.inputRate = x.InputSlotClass == INPUT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; + bind.stride = x.AlignedByteOffset; + if (bind.stride == InputLayoutDesc::APPEND_ALIGNED_ELEMENT) + { + // need to manually resolve this from the format spec. + bind.stride = GetFormatStride(x.Format); + } + + if (lastBinding != bind.binding) + { + bindings.push_back(bind); + lastBinding = bind.binding; + } + else + { + bindings.back().stride += bind.stride; + } + } + + uint32_t offset = 0; + uint32_t i = 0; + lastBinding = 0xFFFFFFFF; + for (auto& x : pso->desc.il->desc) + { + VkVertexInputAttributeDescription attr = {}; + attr.binding = x.InputSlot; + if (attr.binding != lastBinding) + { + lastBinding = attr.binding; + offset = 0; + } + attr.format = _ConvertFormat(x.Format); + attr.location = i; + attr.offset = x.AlignedByteOffset; + if (attr.offset == InputLayoutDesc::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; + + // Primitive type: + VkPipelineInputAssemblyStateCreateInfo inputAssembly = {}; + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + switch (pso->desc.pt) + { + case POINTLIST: + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; + break; + case LINELIST: + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; + break; + case LINESTRIP: + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; + break; + case TRIANGLESTRIP: + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + break; + case TRIANGLELIST: + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + break; + case PATCHLIST: + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; + break; + default: + break; + } + inputAssembly.primitiveRestartEnable = VK_FALSE; + + pipelineInfo.pInputAssemblyState = &inputAssembly; + + + // Rasterizer: + VkPipelineRasterizationStateCreateInfo rasterizer = {}; + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_TRUE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_NONE; + rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + rasterizer.depthBiasConstantFactor = 0.0f; + rasterizer.depthBiasClamp = 0.0f; + rasterizer.depthBiasSlopeFactor = 0.0f; + + // depth clip will be enabled via Vulkan 1.1 extension VK_EXT_depth_clip_enable: + VkPipelineRasterizationDepthClipStateCreateInfoEXT depthclip = {}; + depthclip.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT; + depthclip.depthClipEnable = VK_TRUE; + rasterizer.pNext = &depthclip; + + if (pso->desc.rs != nullptr) + { + const RasterizerStateDesc& desc = pso->desc.rs->desc; + + switch (desc.FillMode) + { + case FILL_WIREFRAME: + rasterizer.polygonMode = VK_POLYGON_MODE_LINE; + break; + case FILL_SOLID: + default: + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + break; + } + + switch (desc.CullMode) + { + case CULL_BACK: + rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; + break; + case CULL_FRONT: + rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT; + break; + case CULL_NONE: + default: + rasterizer.cullMode = VK_CULL_MODE_NONE; + break; + } + + rasterizer.frontFace = desc.FrontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE; + rasterizer.depthBiasEnable = desc.DepthBias != 0 || desc.SlopeScaledDepthBias != 0; + rasterizer.depthBiasConstantFactor = static_cast(desc.DepthBias); + rasterizer.depthBiasClamp = desc.DepthBiasClamp; + rasterizer.depthBiasSlopeFactor = desc.SlopeScaledDepthBias; + + // depth clip is extension in Vulkan 1.1: + depthclip.depthClipEnable = desc.DepthClipEnable ? VK_TRUE : VK_FALSE; + } + + pipelineInfo.pRasterizationState = &rasterizer; + + + // Viewport, Scissor: + VkViewport viewport = {}; + viewport.x = 0; + viewport.y = 0; + viewport.width = 65535; + viewport.height = 65535; + viewport.minDepth = 0; + viewport.maxDepth = 1; + + VkRect2D scissor = {}; + scissor.extent.width = 65535; + scissor.extent.height = 65535; + + VkPipelineViewportStateCreateInfo viewportState = {}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + pipelineInfo.pViewportState = &viewportState; + + + // Depth-Stencil: + VkPipelineDepthStencilStateCreateInfo depthstencil = {}; + depthstencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + if (pso->desc.dss != nullptr) + { + depthstencil.depthTestEnable = pso->desc.dss->desc.DepthEnable ? VK_TRUE : VK_FALSE; + depthstencil.depthWriteEnable = pso->desc.dss->desc.DepthWriteMask == DEPTH_WRITE_MASK_ZERO ? VK_FALSE : VK_TRUE; + depthstencil.depthCompareOp = _ConvertComparisonFunc(pso->desc.dss->desc.DepthFunc); + + depthstencil.stencilTestEnable = pso->desc.dss->desc.StencilEnable ? VK_TRUE : VK_FALSE; + + depthstencil.front.compareMask = pso->desc.dss->desc.StencilReadMask; + depthstencil.front.writeMask = pso->desc.dss->desc.StencilWriteMask; + depthstencil.front.reference = 0; // runtime supplied + depthstencil.front.compareOp = _ConvertComparisonFunc(pso->desc.dss->desc.FrontFace.StencilFunc); + depthstencil.front.passOp = _ConvertStencilOp(pso->desc.dss->desc.FrontFace.StencilPassOp); + depthstencil.front.failOp = _ConvertStencilOp(pso->desc.dss->desc.FrontFace.StencilFailOp); + depthstencil.front.depthFailOp = _ConvertStencilOp(pso->desc.dss->desc.FrontFace.StencilDepthFailOp); + + depthstencil.back.compareMask = pso->desc.dss->desc.StencilReadMask; + depthstencil.back.writeMask = pso->desc.dss->desc.StencilWriteMask; + depthstencil.back.reference = 0; // runtime supplied + depthstencil.back.compareOp = _ConvertComparisonFunc(pso->desc.dss->desc.BackFace.StencilFunc); + depthstencil.back.passOp = _ConvertStencilOp(pso->desc.dss->desc.BackFace.StencilPassOp); + depthstencil.back.failOp = _ConvertStencilOp(pso->desc.dss->desc.BackFace.StencilFailOp); + depthstencil.back.depthFailOp = _ConvertStencilOp(pso->desc.dss->desc.BackFace.StencilDepthFailOp); + + depthstencil.depthBoundsTestEnable = VK_FALSE; + } + + pipelineInfo.pDepthStencilState = &depthstencil; + + + // 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 (active_renderpass[cmd] != nullptr && active_renderpass[cmd]->desc.attachments.size() > 0) + { + multisampling.rasterizationSamples = (VkSampleCountFlagBits)active_renderpass[cmd]->desc.attachments[0].texture->desc.SampleCount; + } + multisampling.minSampleShading = 1.0f; + VkSampleMask samplemask = pso->desc.sampleMask; + multisampling.pSampleMask = &samplemask; + multisampling.alphaToCoverageEnable = VK_FALSE; + multisampling.alphaToOneEnable = VK_FALSE; + + pipelineInfo.pMultisampleState = &multisampling; + + + // Blending: + uint32_t numBlendAttachments = 0; + VkPipelineColorBlendAttachmentState colorBlendAttachments[8]; + const size_t blend_loopCount = active_renderpass[cmd] == nullptr ? 1 : active_renderpass[cmd]->desc.attachments.size(); + for (size_t i = 0; i < blend_loopCount; ++i) + { + if (active_renderpass[cmd] != nullptr && active_renderpass[cmd]->desc.attachments[i].type != RenderPassAttachment::RENDERTARGET) + { + continue; + } + + RenderTargetBlendStateDesc desc = pso->desc.bs->desc.RenderTarget[numBlendAttachments++]; + + colorBlendAttachments[i].blendEnable = desc.BlendEnable ? VK_TRUE : VK_FALSE; + + colorBlendAttachments[i].colorWriteMask = 0; + if (desc.RenderTargetWriteMask & COLOR_WRITE_ENABLE_RED) + { + colorBlendAttachments[i].colorWriteMask |= VK_COLOR_COMPONENT_R_BIT; + } + if (desc.RenderTargetWriteMask & COLOR_WRITE_ENABLE_GREEN) + { + colorBlendAttachments[i].colorWriteMask |= VK_COLOR_COMPONENT_G_BIT; + } + if (desc.RenderTargetWriteMask & COLOR_WRITE_ENABLE_BLUE) + { + colorBlendAttachments[i].colorWriteMask |= VK_COLOR_COMPONENT_B_BIT; + } + if (desc.RenderTargetWriteMask & COLOR_WRITE_ENABLE_ALPHA) + { + colorBlendAttachments[i].colorWriteMask |= VK_COLOR_COMPONENT_A_BIT; + } + + colorBlendAttachments[i].srcColorBlendFactor = _ConvertBlend(desc.SrcBlend); + colorBlendAttachments[i].dstColorBlendFactor = _ConvertBlend(desc.DestBlend); + colorBlendAttachments[i].colorBlendOp = _ConvertBlendOp(desc.BlendOp); + colorBlendAttachments[i].srcAlphaBlendFactor = _ConvertBlend(desc.SrcBlendAlpha); + colorBlendAttachments[i].dstAlphaBlendFactor = _ConvertBlend(desc.DestBlendAlpha); + colorBlendAttachments[i].alphaBlendOp = _ConvertBlendOp(desc.BlendOpAlpha); + } + + 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; + + + // Tessellation: + VkPipelineTessellationStateCreateInfo tessellationInfo = {}; + tessellationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; + tessellationInfo.patchControlPoints = 3; + + pipelineInfo.pTessellationState = &tessellationInfo; + + + + + // Dynamic state will be specified at runtime: + VkDynamicState dynamicStates[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_STENCIL_REFERENCE, + VK_DYNAMIC_STATE_BLEND_CONSTANTS + }; + + VkPipelineDynamicStateCreateInfo dynamicState = {}; + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamicState.dynamicStateCount = arraysize(dynamicStates); + dynamicState.pDynamicStates = dynamicStates; + + pipelineInfo.pDynamicState = &dynamicState; + + res = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); + assert(res == VK_SUCCESS); + + pipelines_worker[cmd].push_back(std::make_pair(pipeline_hash, pipeline)); + } + } + else + { + pipeline = it->second; + } + assert(pipeline != VK_NULL_HANDLE); + + vkCmdBindPipeline(GetDirectCommandList(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + } // Engine functions GraphicsDevice_Vulkan::GraphicsDevice_Vulkan(wiPlatform::window_type window, bool fullscreen, bool debuglayer) @@ -1886,7 +2337,6 @@ using namespace Vulkan_Internal; { VkImageCreateInfo imageInfo = {}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.imageType = VK_IMAGE_TYPE_2D; imageInfo.extent.width = 1; imageInfo.extent.height = 1; imageInfo.extent.depth = 1; @@ -1902,21 +2352,111 @@ using namespace Vulkan_Internal; VmaAllocationCreateInfo allocInfo = {}; allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - res = vmaCreateImage(allocationhandler->allocator, &imageInfo, &allocInfo, &nullImage, &nullImageAllocation, nullptr); + imageInfo.imageType = VK_IMAGE_TYPE_1D; + res = vmaCreateImage(allocationhandler->allocator, &imageInfo, &allocInfo, &nullImage1D, &nullImageAllocation1D, nullptr); assert(res == VK_SUCCESS); + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + imageInfo.arrayLayers = 6; + res = vmaCreateImage(allocationhandler->allocator, &imageInfo, &allocInfo, &nullImage2D, &nullImageAllocation2D, nullptr); + assert(res == VK_SUCCESS); + + imageInfo.imageType = VK_IMAGE_TYPE_3D; + imageInfo.flags = 0; + imageInfo.arrayLayers = 1; + res = vmaCreateImage(allocationhandler->allocator, &imageInfo, &allocInfo, &nullImage3D, &nullImageAllocation3D, nullptr); + assert(res == VK_SUCCESS); + + // Transitions: + copyQueueLock.lock(); + { + auto& frame = GetFrameResources(); + if (!copyQueueUse) + { + copyQueueUse = true; + + res = vkResetCommandPool(device, frame.copyCommandPool, 0); + assert(res == VK_SUCCESS); + + VkCommandBufferBeginInfo beginInfo = {}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; + beginInfo.pInheritanceInfo = nullptr; // Optional + + res = vkBeginCommandBuffer(frame.copyCommandBuffer, &beginInfo); + assert(res == VK_SUCCESS); + } + + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = imageInfo.initialLayout; + barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = nullImage1D; + barrier.subresourceRange.layerCount = 1; + frame.loadedimagetransitions.push_back(barrier); + barrier.image = nullImage2D; + barrier.subresourceRange.layerCount = 6; + frame.loadedimagetransitions.push_back(barrier); + barrier.image = nullImage3D; + barrier.subresourceRange.layerCount = 1; + frame.loadedimagetransitions.push_back(barrier); + } + copyQueueLock.unlock(); + VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.image = nullImage; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = 1; viewInfo.format = VK_FORMAT_R8G8B8A8_UNORM; - - res = vkCreateImageView(device, &viewInfo, nullptr, &nullImageView); + + viewInfo.image = nullImage1D; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D; + res = vkCreateImageView(device, &viewInfo, nullptr, &nullImageView1D); + assert(res == VK_SUCCESS); + + viewInfo.image = nullImage1D; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY; + res = vkCreateImageView(device, &viewInfo, nullptr, &nullImageView1DArray); + assert(res == VK_SUCCESS); + + viewInfo.image = nullImage2D; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + res = vkCreateImageView(device, &viewInfo, nullptr, &nullImageView2D); + assert(res == VK_SUCCESS); + + viewInfo.image = nullImage2D; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + res = vkCreateImageView(device, &viewInfo, nullptr, &nullImageView2DArray); + assert(res == VK_SUCCESS); + + viewInfo.image = nullImage2D; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE; + viewInfo.subresourceRange.layerCount = 6; + res = vkCreateImageView(device, &viewInfo, nullptr, &nullImageViewCube); + assert(res == VK_SUCCESS); + + viewInfo.image = nullImage2D; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; + viewInfo.subresourceRange.layerCount = 6; + res = vkCreateImageView(device, &viewInfo, nullptr, &nullImageViewCubeArray); + assert(res == VK_SUCCESS); + + viewInfo.image = nullImage3D; + viewInfo.subresourceRange.layerCount = 1; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_3D; + res = vkCreateImageView(device, &viewInfo, nullptr, &nullImageView3D); assert(res == VK_SUCCESS); } { @@ -2004,8 +2544,16 @@ using namespace Vulkan_Internal; vmaDestroyBuffer(allocationhandler->allocator, nullBuffer, nullBufferAllocation); vkDestroyBufferView(device, nullBufferView, nullptr); - vmaDestroyImage(allocationhandler->allocator, nullImage, nullImageAllocation); - vkDestroyImageView(device, nullImageView, nullptr); + vmaDestroyImage(allocationhandler->allocator, nullImage1D, nullImageAllocation1D); + vmaDestroyImage(allocationhandler->allocator, nullImage2D, nullImageAllocation2D); + vmaDestroyImage(allocationhandler->allocator, nullImage3D, nullImageAllocation3D); + vkDestroyImageView(device, nullImageView1D, nullptr); + vkDestroyImageView(device, nullImageView1DArray, nullptr); + vkDestroyImageView(device, nullImageView2D, nullptr); + vkDestroyImageView(device, nullImageView2DArray, nullptr); + vkDestroyImageView(device, nullImageViewCube, nullptr); + vkDestroyImageView(device, nullImageViewCubeArray, nullptr); + vkDestroyImageView(device, nullImageView3D, nullptr); vkDestroySampler(device, nullSampler, nullptr); DestroyDebugReportCallbackEXT(instance, callback, nullptr); @@ -2587,9 +3135,9 @@ using namespace Vulkan_Internal; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = pDesc->ArraySize; + barrier.subresourceRange.layerCount = imageInfo.arrayLayers; barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = pDesc->MipLevels; + barrier.subresourceRange.levelCount = imageInfo.mipLevels; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; @@ -2606,7 +3154,7 @@ using namespace Vulkan_Internal; vkCmdCopyBufferToImage(frame.copyCommandBuffer, upload_resource, internal_state->resource, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (uint32_t)copyRegions.size(), copyRegions.data()); barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.newLayout = _ConvertImageLayout(pTexture->desc.layout);; + barrier.newLayout = _ConvertImageLayout(pTexture->desc.layout); barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; @@ -2640,7 +3188,7 @@ using namespace Vulkan_Internal; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.image = internal_state->resource; barrier.oldLayout = imageInfo.initialLayout; - barrier.newLayout = _ConvertImageLayout(pTexture->desc.layout);; + barrier.newLayout = _ConvertImageLayout(pTexture->desc.layout); barrier.srcAccessMask = 0; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; if (pTexture->desc.BindFlags & BIND_DEPTH_STENCIL) @@ -2656,9 +3204,9 @@ using namespace Vulkan_Internal; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; } barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = pDesc->ArraySize; + barrier.subresourceRange.layerCount = imageInfo.arrayLayers; barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = pDesc->MipLevels; + barrier.subresourceRange.levelCount = imageInfo.mipLevels; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; frame.loadedimagetransitions.push_back(barrier); @@ -2759,6 +3307,7 @@ using namespace Vulkan_Internal; } std::vector& layoutBindings = internal_state->layoutBindings; + std::vector& imageViewTypes = internal_state->imageViewTypes; for (auto& x : resources.separate_samplers) { @@ -2768,18 +3317,59 @@ using namespace Vulkan_Internal; layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding); layoutBinding.descriptorCount = 1; layoutBindings.push_back(layoutBinding); + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM); } for (auto& x : resources.separate_images) { VkDescriptorSetLayoutBinding layoutBinding = {}; layoutBinding.stageFlags = internal_state->stageInfo.stage; - if (comp.get_type_from_variable(x.id).image.dim == spv::Dim::DimBuffer) - { - layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - } - else + auto image = comp.get_type_from_variable(x.id).image; + switch (image.dim) { + case spv::Dim1D: layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + if (image.arrayed) + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_1D_ARRAY); + } + else + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_1D); + } + break; + case spv::Dim2D: + layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + if (image.arrayed) + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_2D_ARRAY); + } + else + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_2D); + } + break; + case spv::Dim3D: + layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_3D); + break; + case spv::DimCube: + layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + if (image.arrayed) + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY); + } + else + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_CUBE); + } + break; + case spv::DimBuffer: + layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM); + break; + default: + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM); + break; } layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding); layoutBinding.descriptorCount = 1; @@ -2789,13 +3379,53 @@ using namespace Vulkan_Internal; { VkDescriptorSetLayoutBinding layoutBinding = {}; layoutBinding.stageFlags = internal_state->stageInfo.stage; - if (comp.get_type_from_variable(x.id).image.dim == spv::Dim::DimBuffer) - { - layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - } - else + auto image = comp.get_type_from_variable(x.id).image; + switch (image.dim) { + case spv::Dim1D: layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + if (image.arrayed) + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_1D_ARRAY); + } + else + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_1D); + } + break; + case spv::Dim2D: + layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + if (image.arrayed) + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_2D_ARRAY); + } + else + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_2D); + } + break; + case spv::Dim3D: + layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_3D); + break; + case spv::DimCube: + layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + if (image.arrayed) + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY); + } + else + { + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_CUBE); + } + break; + case spv::DimBuffer: + layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM); + break; + default: + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM); + break; } layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding); layoutBinding.descriptorCount = 1; @@ -2809,6 +3439,7 @@ using namespace Vulkan_Internal; layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding); layoutBinding.descriptorCount = 1; layoutBindings.push_back(layoutBinding); + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM); } for (auto& x : resources.storage_buffers) { @@ -2818,6 +3449,7 @@ using namespace Vulkan_Internal; layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding); layoutBinding.descriptorCount = 1; layoutBindings.push_back(layoutBinding); + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM); } for (auto& x : resources.acceleration_structures) { @@ -2827,6 +3459,7 @@ using namespace Vulkan_Internal; layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding); layoutBinding.descriptorCount = 1; layoutBindings.push_back(layoutBinding); + imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM); } if (stage == CS || stage == SHADERSTAGE_COUNT) @@ -3204,11 +3837,11 @@ using namespace Vulkan_Internal; renderpass->desc = *pDesc; renderpass->hash = 0; - wiHelper::hash_combine(renderpass->hash, pDesc->numAttachments); - for (uint32_t i = 0; i < pDesc->numAttachments; ++i) + wiHelper::hash_combine(renderpass->hash, pDesc->attachments.size()); + for (auto& attachment : pDesc->attachments) { - wiHelper::hash_combine(renderpass->hash, pDesc->attachments[i].texture->desc.Format); - wiHelper::hash_combine(renderpass->hash, pDesc->attachments[i].texture->desc.SampleCount); + wiHelper::hash_combine(renderpass->hash, attachment.texture->desc.Format); + wiHelper::hash_combine(renderpass->hash, attachment.texture->desc.SampleCount); } VkResult res; @@ -3224,17 +3857,17 @@ using namespace Vulkan_Internal; const RenderPassDesc& desc = renderpass->desc; uint32_t validAttachmentCount = 0; - for (uint32_t i = 0; i < renderpass->desc.numAttachments; ++i) + for (auto& attachment : renderpass->desc.attachments) { - const Texture* texture = desc.attachments[i].texture; + const Texture* texture = attachment.texture; const TextureDesc& texdesc = texture->desc; - int subresource = desc.attachments[i].subresource; + int subresource = attachment.subresource; auto texture_internal_state = to_internal(texture); attachmentDescriptions[validAttachmentCount].format = _ConvertFormat(texdesc.Format); attachmentDescriptions[validAttachmentCount].samples = (VkSampleCountFlagBits)texdesc.SampleCount; - switch (desc.attachments[i].loadop) + switch (attachment.loadop) { default: case RenderPassAttachment::LOADOP_LOAD: @@ -3248,7 +3881,7 @@ using namespace Vulkan_Internal; break; } - switch (desc.attachments[i].storeop) + switch (attachment.storeop) { default: case RenderPassAttachment::STOREOP_STORE: @@ -3262,10 +3895,10 @@ using namespace Vulkan_Internal; attachmentDescriptions[validAttachmentCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachmentDescriptions[validAttachmentCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachmentDescriptions[validAttachmentCount].initialLayout = _ConvertImageLayout(desc.attachments[i].initial_layout); - attachmentDescriptions[validAttachmentCount].finalLayout = _ConvertImageLayout(desc.attachments[i].final_layout); + attachmentDescriptions[validAttachmentCount].initialLayout = _ConvertImageLayout(attachment.initial_layout); + attachmentDescriptions[validAttachmentCount].finalLayout = _ConvertImageLayout(attachment.final_layout); - if (desc.attachments[i].type == RenderPassAttachment::RENDERTARGET) + if (attachment.type == RenderPassAttachment::RENDERTARGET) { if (subresource < 0 || texture_internal_state->subresources_rtv.empty()) { @@ -3282,11 +3915,11 @@ using namespace Vulkan_Internal; } colorAttachmentRefs[subpass.colorAttachmentCount].attachment = validAttachmentCount; - colorAttachmentRefs[subpass.colorAttachmentCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorAttachmentRefs[subpass.colorAttachmentCount].layout = _ConvertImageLayout(attachment.subpass_layout); subpass.colorAttachmentCount++; subpass.pColorAttachments = colorAttachmentRefs; } - else if (desc.attachments[i].type == RenderPassAttachment::DEPTH_STENCIL) + else if (attachment.type == RenderPassAttachment::DEPTH_STENCIL) { if (subresource < 0 || texture_internal_state->subresources_dsv.empty()) { @@ -3304,7 +3937,7 @@ using namespace Vulkan_Internal; if (IsFormatStencilSupport(texdesc.Format)) { - switch (desc.attachments[i].loadop) + switch (attachment.loadop) { default: case RenderPassAttachment::LOADOP_LOAD: @@ -3318,7 +3951,7 @@ using namespace Vulkan_Internal; break; } - switch (desc.attachments[i].storeop) + switch (attachment.storeop) { default: case RenderPassAttachment::STOREOP_STORE: @@ -3331,11 +3964,7 @@ using namespace Vulkan_Internal; } depthAttachmentRef.attachment = validAttachmentCount; - depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - if (attachmentDescriptions[validAttachmentCount].initialLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) - { - depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - } + depthAttachmentRef.layout = _ConvertImageLayout(attachment.subpass_layout); subpass.pDepthStencilAttachment = &depthAttachmentRef; } else @@ -3345,11 +3974,11 @@ using namespace Vulkan_Internal; validAttachmentCount++; } - renderpass->desc.numAttachments = validAttachmentCount; + assert(renderpass->desc.attachments.size() == validAttachmentCount); VkRenderPassCreateInfo renderPassInfo = {}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = renderpass->desc.numAttachments; + renderPassInfo.attachmentCount = validAttachmentCount; renderPassInfo.pAttachments = attachmentDescriptions; renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpass; @@ -3360,16 +3989,22 @@ using namespace Vulkan_Internal; VkFramebufferCreateInfo framebufferInfo = {}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.renderPass = internal_state->renderpass; - framebufferInfo.attachmentCount = renderpass->desc.numAttachments; + framebufferInfo.attachmentCount = validAttachmentCount; framebufferInfo.pAttachments = attachments; - if (desc.numAttachments > 0) + if (validAttachmentCount > 0) { const TextureDesc& texdesc = desc.attachments[0].texture->desc; framebufferInfo.width = texdesc.Width; framebufferInfo.height = texdesc.Height; framebufferInfo.layers = texdesc.MiscFlags & RESOURCE_MISC_TEXTURECUBE ? 6 : 1; // todo figure out better! can't use ArraySize here, it will crash! } + else + { + framebufferInfo.width = 1; + framebufferInfo.height = 1; + framebufferInfo.layers = 1; + } res = vkCreateFramebuffer(device, &framebufferInfo, nullptr, &internal_state->framebuffer); assert(res == VK_SUCCESS); @@ -3379,17 +4014,17 @@ using namespace Vulkan_Internal; internal_state->beginInfo.renderPass = internal_state->renderpass; internal_state->beginInfo.framebuffer = internal_state->framebuffer; - if (renderpass->desc.numAttachments > 0) + if (validAttachmentCount > 0) { const TextureDesc& texdesc = desc.attachments[0].texture->desc; internal_state->beginInfo.renderArea.offset = { 0, 0 }; internal_state->beginInfo.renderArea.extent.width = texdesc.Width; internal_state->beginInfo.renderArea.extent.height = texdesc.Height; - internal_state->beginInfo.clearValueCount = renderpass->desc.numAttachments; + internal_state->beginInfo.clearValueCount = validAttachmentCount; internal_state->beginInfo.pClearValues = internal_state->clearColors; - for (uint32_t i = 0; i < desc.numAttachments; ++i) + for (uint32_t i = 0; i < validAttachmentCount; ++i) { const ClearValue& clear = desc.attachments[i].texture->desc.clear; if (desc.attachments[i].type == RenderPassAttachment::RENDERTARGET) @@ -3775,6 +4410,7 @@ using namespace Vulkan_Internal; case wiGraphics::RTV: { VkImageView rtv; + view_desc.subresourceRange.levelCount = 1; VkResult res = vkCreateImageView(device, &view_desc, nullptr, &rtv); if (res == VK_SUCCESS) @@ -3795,6 +4431,7 @@ using namespace Vulkan_Internal; break; case wiGraphics::DSV: { + view_desc.subresourceRange.levelCount = 1; view_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; switch (texture->desc.Format) @@ -4184,6 +4821,7 @@ using namespace Vulkan_Internal; active_pso[cmd] = nullptr; active_cs[cmd] = nullptr; active_renderpass[cmd] = VK_NULL_HANDLE; + dirty_pso[cmd] = false; return cmd; } @@ -4382,386 +5020,7 @@ using namespace Vulkan_Internal; GetFrameResources().descriptors[cmd].dirty_graphics_compute[0] = true; active_pso[cmd] = pso; - - VkPipeline pipeline = VK_NULL_HANDLE; - auto it = pipelines_global.find(pipeline_hash); - if (it == pipelines_global.end()) - { - for (auto& x : pipelines_worker[cmd]) - { - if (pipeline_hash == x.first) - { - pipeline = x.second; - break; - } - } - - if (pipeline == VK_NULL_HANDLE) - { - VkResult res; - - VkGraphicsPipelineCreateInfo pipelineInfo = {}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.layout = to_internal(pso)->pipelineLayout; - pipelineInfo.renderPass = active_renderpass[cmd] == nullptr ? defaultRenderPass : to_internal(active_renderpass[cmd])->renderpass; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - - // Shaders: - - uint32_t shaderStageCount = 0; - VkPipelineShaderStageCreateInfo shaderStages[SHADERSTAGE_COUNT - 1]; - if (pso->desc.vs != nullptr && pso->desc.vs->IsValid()) - { - shaderStages[shaderStageCount++] = to_internal(pso->desc.vs)->stageInfo; - } - if (pso->desc.hs != nullptr && pso->desc.hs->IsValid()) - { - shaderStages[shaderStageCount++] = to_internal(pso->desc.hs)->stageInfo; - } - if (pso->desc.ds != nullptr && pso->desc.ds->IsValid()) - { - shaderStages[shaderStageCount++] = to_internal(pso->desc.ds)->stageInfo; - } - if (pso->desc.gs != nullptr && pso->desc.gs->IsValid()) - { - shaderStages[shaderStageCount++] = to_internal(pso->desc.gs)->stageInfo; - } - if (pso->desc.ps != nullptr && pso->desc.ps->IsValid()) - { - shaderStages[shaderStageCount++] = to_internal(pso->desc.ps)->stageInfo; - } - pipelineInfo.stageCount = shaderStageCount; - pipelineInfo.pStages = shaderStages; - - - // Fixed function states: - - // Input layout: - VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - std::vector bindings; - std::vector attributes; - if (pso->desc.il != nullptr) - { - uint32_t lastBinding = 0xFFFFFFFF; - for (auto& x : pso->desc.il->desc) - { - VkVertexInputBindingDescription bind = {}; - bind.binding = x.InputSlot; - bind.inputRate = x.InputSlotClass == INPUT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; - bind.stride = x.AlignedByteOffset; - if (bind.stride == InputLayoutDesc::APPEND_ALIGNED_ELEMENT) - { - // need to manually resolve this from the format spec. - bind.stride = GetFormatStride(x.Format); - } - - if (lastBinding != bind.binding) - { - bindings.push_back(bind); - lastBinding = bind.binding; - } - else - { - bindings.back().stride += bind.stride; - } - } - - uint32_t offset = 0; - uint32_t i = 0; - lastBinding = 0xFFFFFFFF; - for (auto& x : pso->desc.il->desc) - { - VkVertexInputAttributeDescription attr = {}; - attr.binding = x.InputSlot; - if (attr.binding != lastBinding) - { - lastBinding = attr.binding; - offset = 0; - } - attr.format = _ConvertFormat(x.Format); - attr.location = i; - attr.offset = x.AlignedByteOffset; - if (attr.offset == InputLayoutDesc::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; - - // Primitive type: - VkPipelineInputAssemblyStateCreateInfo inputAssembly = {}; - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - switch (pso->desc.pt) - { - case POINTLIST: - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - break; - case LINELIST: - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; - break; - case LINESTRIP: - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; - break; - case TRIANGLESTRIP: - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - break; - case TRIANGLELIST: - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - break; - case PATCHLIST: - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; - break; - default: - break; - } - inputAssembly.primitiveRestartEnable = VK_FALSE; - - pipelineInfo.pInputAssemblyState = &inputAssembly; - - - // Rasterizer: - VkPipelineRasterizationStateCreateInfo rasterizer = {}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_TRUE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_NONE; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - rasterizer.depthBiasConstantFactor = 0.0f; - rasterizer.depthBiasClamp = 0.0f; - rasterizer.depthBiasSlopeFactor = 0.0f; - - // depth clip will be enabled via Vulkan 1.1 extension VK_EXT_depth_clip_enable: - VkPipelineRasterizationDepthClipStateCreateInfoEXT depthclip = {}; - depthclip.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT; - depthclip.depthClipEnable = VK_TRUE; - rasterizer.pNext = &depthclip; - - if (pso->desc.rs != nullptr) - { - const RasterizerStateDesc& desc = pso->desc.rs->desc; - - switch (desc.FillMode) - { - case FILL_WIREFRAME: - rasterizer.polygonMode = VK_POLYGON_MODE_LINE; - break; - case FILL_SOLID: - default: - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - break; - } - - switch (desc.CullMode) - { - case CULL_BACK: - rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - break; - case CULL_FRONT: - rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT; - break; - case CULL_NONE: - default: - rasterizer.cullMode = VK_CULL_MODE_NONE; - break; - } - - rasterizer.frontFace = desc.FrontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE; - rasterizer.depthBiasEnable = desc.DepthBias != 0 || desc.SlopeScaledDepthBias != 0; - rasterizer.depthBiasConstantFactor = static_cast(desc.DepthBias); - rasterizer.depthBiasClamp = desc.DepthBiasClamp; - rasterizer.depthBiasSlopeFactor = desc.SlopeScaledDepthBias; - - // depth clip is extension in Vulkan 1.1: - depthclip.depthClipEnable = desc.DepthClipEnable ? VK_TRUE : VK_FALSE; - } - - pipelineInfo.pRasterizationState = &rasterizer; - - - // Viewport, Scissor: - VkViewport viewport = {}; - viewport.x = 0; - viewport.y = 0; - viewport.width = 65535; - viewport.height = 65535; - viewport.minDepth = 0; - viewport.maxDepth = 1; - - VkRect2D scissor = {}; - scissor.extent.width = 65535; - scissor.extent.height = 65535; - - VkPipelineViewportStateCreateInfo viewportState = {}; - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportState.viewportCount = 1; - viewportState.pViewports = &viewport; - viewportState.scissorCount = 1; - viewportState.pScissors = &scissor; - - pipelineInfo.pViewportState = &viewportState; - - - // Depth-Stencil: - VkPipelineDepthStencilStateCreateInfo depthstencil = {}; - depthstencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - if (pso->desc.dss != nullptr) - { - depthstencil.depthTestEnable = pso->desc.dss->desc.DepthEnable ? VK_TRUE : VK_FALSE; - depthstencil.depthWriteEnable = pso->desc.dss->desc.DepthWriteMask == DEPTH_WRITE_MASK_ZERO ? VK_FALSE : VK_TRUE; - depthstencil.depthCompareOp = _ConvertComparisonFunc(pso->desc.dss->desc.DepthFunc); - - depthstencil.stencilTestEnable = pso->desc.dss->desc.StencilEnable ? VK_TRUE : VK_FALSE; - - depthstencil.front.compareMask = pso->desc.dss->desc.StencilReadMask; - depthstencil.front.writeMask = pso->desc.dss->desc.StencilWriteMask; - depthstencil.front.reference = 0; // runtime supplied - depthstencil.front.compareOp = _ConvertComparisonFunc(pso->desc.dss->desc.FrontFace.StencilFunc); - depthstencil.front.passOp = _ConvertStencilOp(pso->desc.dss->desc.FrontFace.StencilPassOp); - depthstencil.front.failOp = _ConvertStencilOp(pso->desc.dss->desc.FrontFace.StencilFailOp); - depthstencil.front.depthFailOp = _ConvertStencilOp(pso->desc.dss->desc.FrontFace.StencilDepthFailOp); - - depthstencil.back.compareMask = pso->desc.dss->desc.StencilReadMask; - depthstencil.back.writeMask = pso->desc.dss->desc.StencilWriteMask; - depthstencil.back.reference = 0; // runtime supplied - depthstencil.back.compareOp = _ConvertComparisonFunc(pso->desc.dss->desc.BackFace.StencilFunc); - depthstencil.back.passOp = _ConvertStencilOp(pso->desc.dss->desc.BackFace.StencilPassOp); - depthstencil.back.failOp = _ConvertStencilOp(pso->desc.dss->desc.BackFace.StencilFailOp); - depthstencil.back.depthFailOp = _ConvertStencilOp(pso->desc.dss->desc.BackFace.StencilDepthFailOp); - - depthstencil.depthBoundsTestEnable = VK_FALSE; - } - - pipelineInfo.pDepthStencilState = &depthstencil; - - - // 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 (active_renderpass[cmd] != nullptr && active_renderpass[cmd]->desc.numAttachments > 0) - { - multisampling.rasterizationSamples = (VkSampleCountFlagBits)active_renderpass[cmd]->desc.attachments[0].texture->desc.SampleCount; - } - multisampling.minSampleShading = 1.0f; - VkSampleMask samplemask = pso->desc.sampleMask; - multisampling.pSampleMask = &samplemask; - multisampling.alphaToCoverageEnable = VK_FALSE; - multisampling.alphaToOneEnable = VK_FALSE; - - pipelineInfo.pMultisampleState = &multisampling; - - - // Blending: - uint32_t numBlendAttachments = 0; - VkPipelineColorBlendAttachmentState colorBlendAttachments[8]; - const uint32_t blend_loopCount = active_renderpass[cmd] == nullptr ? 1 : active_renderpass[cmd]->desc.numAttachments; - for (uint32_t i = 0; i < blend_loopCount; ++i) - { - if (active_renderpass[cmd] != nullptr && active_renderpass[cmd]->desc.attachments[i].type != RenderPassAttachment::RENDERTARGET) - { - continue; - } - - RenderTargetBlendStateDesc desc = pso->desc.bs->desc.RenderTarget[numBlendAttachments++]; - - colorBlendAttachments[i].blendEnable = desc.BlendEnable ? VK_TRUE : VK_FALSE; - - colorBlendAttachments[i].colorWriteMask = 0; - if (desc.RenderTargetWriteMask & COLOR_WRITE_ENABLE_RED) - { - colorBlendAttachments[i].colorWriteMask |= VK_COLOR_COMPONENT_R_BIT; - } - if (desc.RenderTargetWriteMask & COLOR_WRITE_ENABLE_GREEN) - { - colorBlendAttachments[i].colorWriteMask |= VK_COLOR_COMPONENT_G_BIT; - } - if (desc.RenderTargetWriteMask & COLOR_WRITE_ENABLE_BLUE) - { - colorBlendAttachments[i].colorWriteMask |= VK_COLOR_COMPONENT_B_BIT; - } - if (desc.RenderTargetWriteMask & COLOR_WRITE_ENABLE_ALPHA) - { - colorBlendAttachments[i].colorWriteMask |= VK_COLOR_COMPONENT_A_BIT; - } - - colorBlendAttachments[i].srcColorBlendFactor = _ConvertBlend(desc.SrcBlend); - colorBlendAttachments[i].dstColorBlendFactor = _ConvertBlend(desc.DestBlend); - colorBlendAttachments[i].colorBlendOp = _ConvertBlendOp(desc.BlendOp); - colorBlendAttachments[i].srcAlphaBlendFactor = _ConvertBlend(desc.SrcBlendAlpha); - colorBlendAttachments[i].dstAlphaBlendFactor = _ConvertBlend(desc.DestBlendAlpha); - colorBlendAttachments[i].alphaBlendOp = _ConvertBlendOp(desc.BlendOpAlpha); - } - - 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; - - - // Tessellation: - VkPipelineTessellationStateCreateInfo tessellationInfo = {}; - tessellationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; - tessellationInfo.patchControlPoints = 3; - - pipelineInfo.pTessellationState = &tessellationInfo; - - - - - // Dynamic state will be specified at runtime: - VkDynamicState dynamicStates[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_STENCIL_REFERENCE, - VK_DYNAMIC_STATE_BLEND_CONSTANTS - }; - - VkPipelineDynamicStateCreateInfo dynamicState = {}; - dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicState.dynamicStateCount = arraysize(dynamicStates); - dynamicState.pDynamicStates = dynamicStates; - - pipelineInfo.pDynamicState = &dynamicState; - - res = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); - assert(res == VK_SUCCESS); - - pipelines_worker[cmd].push_back(std::make_pair(pipeline_hash, pipeline)); - } - } - else - { - pipeline = it->second; - } - assert(pipeline != VK_NULL_HANDLE); - - vkCmdBindPipeline(GetDirectCommandList(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + dirty_pso[cmd] = true; } void GraphicsDevice_Vulkan::BindComputeShader(const Shader* cs, CommandList cmd) { @@ -4776,34 +5035,40 @@ using namespace Vulkan_Internal; } void GraphicsDevice_Vulkan::Draw(uint32_t vertexCount, uint32_t startVertexLocation, CommandList cmd) { + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); vkCmdDraw(GetDirectCommandList(cmd), static_cast(vertexCount), 1, startVertexLocation, 0); } void GraphicsDevice_Vulkan::DrawIndexed(uint32_t indexCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, CommandList cmd) { + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); vkCmdDrawIndexed(GetDirectCommandList(cmd), static_cast(indexCount), 1, startIndexLocation, baseVertexLocation, 0); } void GraphicsDevice_Vulkan::DrawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation, CommandList cmd) { + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); vkCmdDraw(GetDirectCommandList(cmd), static_cast(vertexCount), static_cast(instanceCount), startVertexLocation, startInstanceLocation); } void GraphicsDevice_Vulkan::DrawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, uint32_t startInstanceLocation, CommandList cmd) { + pso_validate(cmd); GetFrameResources().descriptors[cmd].validate(true, cmd); vkCmdDrawIndexed(GetDirectCommandList(cmd), static_cast(indexCount), static_cast(instanceCount), startIndexLocation, baseVertexLocation, startInstanceLocation); } void GraphicsDevice_Vulkan::DrawInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) { - GetFrameResources().descriptors[cmd].validate(true, cmd); auto internal_state = to_internal(args); + pso_validate(cmd); + GetFrameResources().descriptors[cmd].validate(true, cmd); vkCmdDrawIndirect(GetDirectCommandList(cmd), internal_state->resource, (VkDeviceSize)args_offset, 1, (uint32_t)sizeof(IndirectDrawArgsInstanced)); } void GraphicsDevice_Vulkan::DrawIndexedInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) { - GetFrameResources().descriptors[cmd].validate(true, cmd); auto internal_state = to_internal(args); + pso_validate(cmd); + GetFrameResources().descriptors[cmd].validate(true, cmd); vkCmdDrawIndexedIndirect(GetDirectCommandList(cmd), internal_state->resource, (VkDeviceSize)args_offset, 1, (uint32_t)sizeof(IndirectDrawArgsIndexedInstanced)); } void GraphicsDevice_Vulkan::Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, CommandList cmd) @@ -4940,6 +5205,8 @@ using namespace Vulkan_Internal; // barrier to transfer: + assert(active_renderpass[cmd] == nullptr); // must not be inside render pass + VkPipelineStageFlags stages = 0; VkBufferMemoryBarrier barrier = {}; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 9c4b049ea..cf6c3ec34 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -80,10 +80,20 @@ namespace wiGraphics VkBuffer nullBuffer = VK_NULL_HANDLE; VmaAllocation nullBufferAllocation = VK_NULL_HANDLE; VkBufferView nullBufferView = VK_NULL_HANDLE; - VkImage nullImage = VK_NULL_HANDLE; - VmaAllocation nullImageAllocation = VK_NULL_HANDLE; - VkImageView nullImageView = VK_NULL_HANDLE; VkSampler nullSampler = VK_NULL_HANDLE; + VmaAllocation nullImageAllocation1D = VK_NULL_HANDLE; + VmaAllocation nullImageAllocation2D = VK_NULL_HANDLE; + VmaAllocation nullImageAllocation3D = VK_NULL_HANDLE; + VkImage nullImage1D = VK_NULL_HANDLE; + VkImage nullImage2D = VK_NULL_HANDLE; + VkImage nullImage3D = VK_NULL_HANDLE; + VkImageView nullImageView1D = VK_NULL_HANDLE; + VkImageView nullImageView1DArray = VK_NULL_HANDLE; + VkImageView nullImageView2D = VK_NULL_HANDLE; + VkImageView nullImageView2DArray = VK_NULL_HANDLE; + VkImageView nullImageViewCube = VK_NULL_HANDLE; + VkImageView nullImageViewCubeArray = VK_NULL_HANDLE; + VkImageView nullImageView3D = VK_NULL_HANDLE; uint64_t timestamp_frequency = 0; VkQueryPool querypool_timestamp = VK_NULL_HANDLE; @@ -195,6 +205,9 @@ namespace wiGraphics const Shader* active_cs[COMMANDLIST_COUNT] = {}; const RenderPass* active_renderpass[COMMANDLIST_COUNT] = {}; + bool dirty_pso[COMMANDLIST_COUNT] = {}; + void pso_validate(CommandList cmd); + std::atomic cmd_count{ 0 }; static PFN_vkCreateRayTracingPipelinesKHR createRayTracingPipelinesKHR; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index ab6e98d5f..dcf1c313e 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -5411,10 +5411,12 @@ void SetShadowProps2D(int resolution, int count, int softShadowQuality) desc.BindFlags = BIND_DEPTH_STENCIL | BIND_SHADER_RESOURCE; desc.Format = FORMAT_R16_TYPELESS; + desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; device->CreateTexture(&desc, nullptr, &shadowMapArray_2D); desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; desc.Format = FORMAT_R8G8B8A8_UNORM; + desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; // RGB: Shadow tint (multiplicative), A: Refraction caustics(additive) desc.clear.color[0] = 1; desc.clear.color[1] = 1; @@ -5435,13 +5437,34 @@ void SetShadowProps2D(int resolution, int count, int softShadowQuality) RenderPassDesc renderpassdesc; - renderpassdesc.numAttachments = 1; - renderpassdesc.attachments[0] = { RenderPassAttachment::DEPTH_STENCIL, RenderPassAttachment::LOADOP_CLEAR,&shadowMapArray_2D, subresource_index }; + renderpassdesc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &shadowMapArray_2D, + RenderPassAttachment::LOADOP_CLEAR, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_SHADER_RESOURCE, + IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT_SHADER_RESOURCE + ) + ); + renderpassdesc.attachments.back().subresource = subresource_index; + device->CreateRenderPass(&renderpassdesc, &renderpasses_shadow2D[subresource_index]); - renderpassdesc.numAttachments = 2; - renderpassdesc.attachments[0] = { RenderPassAttachment::DEPTH_STENCIL, RenderPassAttachment::LOADOP_LOAD,&shadowMapArray_2D, subresource_index }; - renderpassdesc.attachments[1] = { RenderPassAttachment::RENDERTARGET, RenderPassAttachment::LOADOP_CLEAR,&shadowMapArray_Transparent, subresource_index }; + renderpassdesc.attachments.back().loadop = RenderPassAttachment::LOADOP_LOAD; + + renderpassdesc.attachments.push_back( + RenderPassAttachment::RenderTarget( + &shadowMapArray_Transparent, + RenderPassAttachment::LOADOP_CLEAR, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_SHADER_RESOURCE, + IMAGE_LAYOUT_RENDERTARGET, + IMAGE_LAYOUT_SHADER_RESOURCE + ) + ); + renderpassdesc.attachments.back().subresource = subresource_index; + device->CreateRenderPass(&renderpassdesc, &renderpasses_shadow2DTransparent[subresource_index]); } } @@ -5473,6 +5496,7 @@ void SetShadowPropsCube(int resolution, int count) desc.BindFlags = BIND_DEPTH_STENCIL | BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = RESOURCE_MISC_TEXTURECUBE; + desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; device->CreateTexture(&desc, nullptr, &shadowMapArray_Cube); renderpasses_shadowCube.resize(SHADOWCOUNT_CUBE); @@ -5484,8 +5508,17 @@ void SetShadowPropsCube(int resolution, int count) assert(subresource_index == i); RenderPassDesc renderpassdesc; - renderpassdesc.numAttachments = 1; - renderpassdesc.attachments[0] = { RenderPassAttachment::DEPTH_STENCIL, RenderPassAttachment::LOADOP_CLEAR,&shadowMapArray_Cube, subresource_index }; + renderpassdesc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &shadowMapArray_Cube, + RenderPassAttachment::LOADOP_CLEAR, + RenderPassAttachment::STOREOP_STORE, + IMAGE_LAYOUT_SHADER_RESOURCE, + IMAGE_LAYOUT_DEPTHSTENCIL, + IMAGE_LAYOUT_SHADER_RESOURCE + ) + ); + renderpassdesc.attachments.back().subresource = subresource_index; device->CreateRenderPass(&renderpassdesc, &renderpasses_shadowCube[subresource_index]); } } @@ -7134,9 +7167,16 @@ void ManageEnvProbes() assert(subresource_index == i); RenderPassDesc renderpassdesc; - renderpassdesc.numAttachments = 2; - renderpassdesc.attachments[0] = { RenderPassAttachment::RENDERTARGET, RenderPassAttachment::LOADOP_DONTCARE,&textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY], subresource_index }; - renderpassdesc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL, RenderPassAttachment::LOADOP_CLEAR,&envrenderingDepthBuffer, -1 }; + renderpassdesc.attachments.push_back(RenderPassAttachment::RenderTarget(&textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY], RenderPassAttachment::LOADOP_DONTCARE)); + renderpassdesc.attachments.back().subresource = subresource_index; + + renderpassdesc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &envrenderingDepthBuffer, + RenderPassAttachment::LOADOP_CLEAR + ) + ); + device->CreateRenderPass(&renderpassdesc, &renderpasses_envmap[subresource_index]); } for (uint32_t i = 0; i < textures[TEXTYPE_CUBEARRAY_ENVMAPARRAY].GetDesc().MipLevels; ++i) @@ -7378,9 +7418,16 @@ void ManageImpostors() assert(subresource_index == i); RenderPassDesc renderpassdesc; - renderpassdesc.numAttachments = 2; - renderpassdesc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&textures[TEXTYPE_2D_IMPOSTORARRAY], subresource_index }; - renderpassdesc.attachments[1] = { RenderPassAttachment::DEPTH_STENCIL,RenderPassAttachment::LOADOP_CLEAR,&impostorDepthStencil, subresource_index }; + renderpassdesc.attachments.push_back(RenderPassAttachment::RenderTarget(&textures[TEXTYPE_2D_IMPOSTORARRAY], RenderPassAttachment::LOADOP_CLEAR)); + renderpassdesc.attachments.back().subresource = subresource_index; + + renderpassdesc.attachments.push_back( + RenderPassAttachment::DepthStencil( + &impostorDepthStencil, + RenderPassAttachment::LOADOP_CLEAR + ) + ); + device->CreateRenderPass(&renderpassdesc, &renderpasses_impostor[subresource_index]); } } @@ -7571,7 +7618,6 @@ void VoxelRadiance(CommandList cmd) } RenderPassDesc renderpassdesc; - renderpassdesc.numAttachments = 0; device->CreateRenderPass(&renderpassdesc, &renderpass_voxelize); } if (voxelSceneData.secondaryBounceEnabled && !textures[TEXTYPE_3D_VOXELRADIANCE_HELPER].IsValid()) @@ -8792,13 +8838,12 @@ void ManageLightmapAtlas() RenderPassDesc renderpassdesc; - renderpassdesc.numAttachments = 1; - renderpassdesc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_CLEAR,&object.lightmap,-1 }; + renderpassdesc.attachments.push_back(RenderPassAttachment::RenderTarget(&object.lightmap, RenderPassAttachment::LOADOP_CLEAR)); + object.renderpass_lightmap_clear = RenderPass(); device->CreateRenderPass(&renderpassdesc, &object.renderpass_lightmap_clear); - renderpassdesc.numAttachments = 1; - renderpassdesc.attachments[0] = { RenderPassAttachment::RENDERTARGET,RenderPassAttachment::LOADOP_LOAD,&object.lightmap,-1 }; + renderpassdesc.attachments.back().loadop = RenderPassAttachment::LOADOP_LOAD; object.renderpass_lightmap_accumulate = RenderPass(); device->CreateRenderPass(&renderpassdesc, &object.renderpass_lightmap_accumulate); } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 675a3d8ea..64e199b08 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -7,9 +7,9 @@ namespace wiVersion // main engine core const int major = 0; // minor features, major updates, breaking API changes - const int minor = 45; + const int minor = 46; // minor bug fixes, alterations, refactors, updates - const int revision = 4; + const int revision = 0; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); diff --git a/WickedEngine/wiWidget.cpp b/WickedEngine/wiWidget.cpp index 395b77b4a..1986d2b66 100644 --- a/WickedEngine/wiWidget.cpp +++ b/WickedEngine/wiWidget.cpp @@ -2095,18 +2095,18 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const { wiWindow::Render(gui, cmd); - if (!IsVisible() || IsMinimized()) { return; } + GraphicsDevice* device = wiRenderer::GetDevice(); + struct Vertex { XMFLOAT4 pos; XMFLOAT4 col; }; - static wiGraphics::GPUBuffer vb_saturation; static wiGraphics::GPUBuffer vb_hue; static wiGraphics::GPUBuffer vb_picker_saturation; static wiGraphics::GPUBuffer vb_picker_hue; @@ -2137,17 +2137,6 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const vertices_saturation.push_back(vertices_saturation[0]); // inner wiMath::ConstructTriangleEquilateral(colorpicker_radius_triangle + 4, vertices_saturation[3].pos, vertices_saturation[5].pos, vertices_saturation[7].pos); // extrude outer vertices_saturation[9].pos = vertices_saturation[3].pos; // last outer - - GPUBufferDesc desc; - desc.BindFlags = BIND_VERTEX_BUFFER; - desc.ByteWidth = (uint32_t)(vertices_saturation.size() * sizeof(Vertex)); - desc.CPUAccessFlags = CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - desc.StructureByteStride = 0; - desc.Usage = USAGE_DYNAMIC; - SubresourceData data; - data.pSysMem = vertices_saturation.data(); - wiRenderer::GetDevice()->CreateBuffer(&desc, &data, &vb_saturation); } // hue { @@ -2214,7 +2203,7 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const desc.Usage = USAGE_IMMUTABLE; SubresourceData data; data.pSysMem = vertices.data(); - wiRenderer::GetDevice()->CreateBuffer(&desc, &data, &vb_hue); + device->CreateBuffer(&desc, &data, &vb_hue); } // saturation picker (small circle) { @@ -2241,7 +2230,7 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const desc.Usage = USAGE_IMMUTABLE; SubresourceData data; data.pSysMem = vertices.data(); - wiRenderer::GetDevice()->CreateBuffer(&desc, &data, &vb_picker_saturation); + device->CreateBuffer(&desc, &data, &vb_picker_saturation); } // hue picker (rectangle) { @@ -2282,7 +2271,7 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const desc.Usage = USAGE_IMMUTABLE; SubresourceData data; data.pSysMem = vertices; - wiRenderer::GetDevice()->CreateBuffer(&desc, &data, &vb_picker_hue); + device->CreateBuffer(&desc, &data, &vb_picker_hue); } // preview { @@ -2303,7 +2292,7 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const desc.Usage = USAGE_IMMUTABLE; SubresourceData data; data.pSysMem = vertices; - wiRenderer::GetDevice()->CreateBuffer(&desc, &data, &vb_preview); + device->CreateBuffer(&desc, &data, &vb_preview); } } @@ -2311,10 +2300,10 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const const wiColor final_color = GetPickColor(); const float angle = hue / 360.0f * XM_2PI; - const XMMATRIX Projection = wiRenderer::GetDevice()->GetScreenProjection(); + const XMMATRIX Projection = device->GetScreenProjection(); - wiRenderer::GetDevice()->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CBSLOT_RENDERER_MISC, cmd); - wiRenderer::GetDevice()->BindPipelineState(&PSO_colored, cmd); + device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CBSLOT_RENDERER_MISC, cmd); + device->BindPipelineState(&PSO_colored, cmd); ApplyScissor(scissorRect, cmd); @@ -2322,26 +2311,25 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const // render saturation triangle { - if (vb_saturation.IsValid() && !vertices_saturation.empty()) - { - hsv source; - source.h = hue; - source.s = 1; - source.v = 1; - rgb result = hsv2rgb(source); - vertices_saturation[0].col = XMFLOAT4(result.r, result.g, result.b, 1); + hsv source; + source.h = hue; + source.s = 1; + source.v = 1; + rgb result = hsv2rgb(source); + vertices_saturation[0].col = XMFLOAT4(result.r, result.g, result.b, 1); - vertices_saturation[3].col = vertices_saturation[0].col; vertices_saturation[3].col.w = 0; - vertices_saturation[4].col = vertices_saturation[0].col; - vertices_saturation[5].col = vertices_saturation[1].col; vertices_saturation[5].col.w = 0; - vertices_saturation[6].col = vertices_saturation[1].col; - vertices_saturation[7].col = vertices_saturation[2].col; vertices_saturation[7].col.w = 0; - vertices_saturation[8].col = vertices_saturation[2].col; - vertices_saturation[9].col = vertices_saturation[0].col; vertices_saturation[9].col.w = 0; - vertices_saturation[10].col = vertices_saturation[0].col; - - wiRenderer::GetDevice()->UpdateBuffer(&vb_saturation, vertices_saturation.data(), cmd, vb_saturation.GetDesc().ByteWidth); - } + vertices_saturation[3].col = vertices_saturation[0].col; vertices_saturation[3].col.w = 0; + vertices_saturation[4].col = vertices_saturation[0].col; + vertices_saturation[5].col = vertices_saturation[1].col; vertices_saturation[5].col.w = 0; + vertices_saturation[6].col = vertices_saturation[1].col; + vertices_saturation[7].col = vertices_saturation[2].col; vertices_saturation[7].col.w = 0; + vertices_saturation[8].col = vertices_saturation[2].col; + vertices_saturation[9].col = vertices_saturation[0].col; vertices_saturation[9].col.w = 0; + vertices_saturation[10].col = vertices_saturation[0].col; + + size_t alloc_size = sizeof(Vertex) * vertices_saturation.size(); + GraphicsDevice::GPUAllocation vb_saturation = device->AllocateGPU(alloc_size, cmd); + memcpy(vb_saturation.data, vertices_saturation.data(), alloc_size); XMStoreFloat4x4(&cb.g_xTransform, XMMatrixRotationZ(-angle) * @@ -2349,15 +2337,18 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const Projection ); cb.g_xColor = IsEnabled() ? float4(1, 1, 1, 1) : float4(0.5f, 0.5f, 0.5f, 1); - wiRenderer::GetDevice()->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); const GPUBuffer* vbs[] = { - &vb_saturation, + vb_saturation.buffer, }; const uint32_t strides[] = { sizeof(Vertex), }; - wiRenderer::GetDevice()->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); - wiRenderer::GetDevice()->Draw(vb_saturation.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); + const uint32_t offsets[] = { + vb_saturation.offset, + }; + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); + device->Draw((uint32_t)vertices_saturation.size(), 0, cmd); } // render hue circle @@ -2367,15 +2358,15 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const Projection ); cb.g_xColor = IsEnabled() ? float4(1, 1, 1, 1) : float4(0.5f, 0.5f, 0.5f, 1); - wiRenderer::GetDevice()->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); const GPUBuffer* vbs[] = { &vb_hue, }; const uint32_t strides[] = { sizeof(Vertex), }; - wiRenderer::GetDevice()->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); - wiRenderer::GetDevice()->Draw(vb_hue.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); + device->Draw(vb_hue.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); } // render hue picker @@ -2394,15 +2385,15 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const rgb result = hsv2rgb(source); cb.g_xColor = float4(1 - result.r, 1 - result.g, 1 - result.b, 1); - wiRenderer::GetDevice()->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); const GPUBuffer* vbs[] = { &vb_picker_hue, }; const uint32_t strides[] = { sizeof(Vertex), }; - wiRenderer::GetDevice()->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); - wiRenderer::GetDevice()->Draw(vb_picker_hue.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); + device->Draw(vb_picker_hue.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); } // render saturation picker @@ -2445,15 +2436,15 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const Projection ); cb.g_xColor = float4(1 - final_color.toFloat3().x, 1 - final_color.toFloat3().y, 1 - final_color.toFloat3().z, 1); - wiRenderer::GetDevice()->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); const GPUBuffer* vbs[] = { &vb_picker_saturation, }; const uint32_t strides[] = { sizeof(Vertex), }; - wiRenderer::GetDevice()->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); - wiRenderer::GetDevice()->Draw(vb_picker_saturation.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); + device->Draw(vb_picker_saturation.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); } // render preview @@ -2463,15 +2454,15 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const Projection ); cb.g_xColor = final_color.toFloat4(); - wiRenderer::GetDevice()->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); const GPUBuffer* vbs[] = { &vb_preview, }; const uint32_t strides[] = { sizeof(Vertex), }; - wiRenderer::GetDevice()->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); - wiRenderer::GetDevice()->Draw(vb_preview.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); + device->Draw(vb_preview.GetDesc().ByteWidth / sizeof(Vertex), 0, cmd); } } wiColor wiColorPicker::GetPickColor() const