diff --git a/Editor.xml b/Editor.xml
index bf02ceb6..328fa547 100644
--- a/Editor.xml
+++ b/Editor.xml
@@ -40,6 +40,6 @@
-
+
diff --git a/data/Shaders/default/default.hlsl b/data/Shaders/default/default.hlsl
index 02fa70eb..65049286 100644
--- a/data/Shaders/default/default.hlsl
+++ b/data/Shaders/default/default.hlsl
@@ -9,10 +9,8 @@
#include "system/lighting.hlsli"
#include "system/debugdisplay.hlsli"
#include "system/instancedata.hlsli"
-
-#if _ALPHABLEND
#include "system/transparentPass.hlsli"
-#endif
+#include "system/outlinemask.hlsli"
#include "default.hlsli"
@@ -22,6 +20,28 @@
#define EXPORT_VPOS 0
#endif
+// TODO: move to transparentPass.hlsli?
+void applyDepthTransparency(inout float _alpha, float2 _screenPos, float4 _vpos, float _invDepthFade)
+{
+ TransparentPassConstants transparentPassConstants;
+ transparentPassConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_TRANSPARENTPASS));
+
+ float linearDepthBuffer = getTexture2D(transparentPassConstants.getLinearDepth()).SampleLevel(nearestClamp, _screenPos.xy, 0).y;
+ float linearZ = -_vpos.z;
+ float alpha = saturate((linearDepthBuffer - linearZ) * _invDepthFade );
+ _alpha *= alpha;
+}
+
+bool linearDepthTest(float2 _screenPos, float4 _vpos)
+{
+ TransparentPassConstants transparentPassConstants;
+ transparentPassConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_TRANSPARENTPASS));
+
+ float linearDepthBuffer = getTexture2D(transparentPassConstants.getLinearDepth()).SampleLevel(nearestClamp, _screenPos.xy, 0).y;
+ float linearZ = -_vpos.z;
+ return linearZ < linearDepthBuffer + 0.01;
+}
+
struct VS_Output
{
float4 pos : Position;
@@ -49,7 +69,6 @@ VS_Output VS_Forward(uint _vertexID : VertexID)
Vertex vert;
vert.Load(getBuffer(rootConstants3D.getVertexBufferHandle()), rootConstants3D.getVertexFormat(), _vertexID, rootConstants3D.getVertexBufferOffset());
- //vert.Load(getBuffer(instanceData.getVertexBufferHandle()), instanceData.getVertexFormat(), _vertexID, instanceData.getVertexBufferOffset());
ViewConstants viewConstants;
viewConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_VIEWCONSTANTS));
@@ -177,13 +196,7 @@ PS_Output PS_Forward(VS_Output _input)
#endif
#if _ALPHABLEND
- TransparentPassConstants transparentPassConstants;
- transparentPassConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_TRANSPARENTPASS));
-
- float linearDepthBuffer = getTexture2D(transparentPassConstants.getLinearDepth()).SampleLevel(nearestClamp, screenPos.xy, 0).y;
- float linearZ = -_input.vpos.z;
- float alpha = saturate((linearDepthBuffer - linearZ) * materialData.getInvDepthFade());
- output.color0.a *= alpha;
+ applyDepthTransparency(output.color0.a, screenPos.xy, _input.vpos, materialData.getInvDepthFade());
#endif
#if _TOOLMODE && !_ZONLY
@@ -340,4 +353,60 @@ PS_OutputDeferred PS_Deferred(VS_Output _input)
#else
return output;
#endif
+}
+
+struct VS_Output_Outline
+{
+ float4 pos : Position;
+ float4 vpos : ViewPos;
+};
+
+//--------------------------------------------------------------------------------------
+VS_Output_Outline VS_Outline(uint _vertexID : VertexID)
+{
+ VS_Output_Outline output;
+
+ uint instanceDataOffset = rootConstants3D.getGPUInstanceDataOffset();
+ GPUInstanceData instanceData = getBuffer(RESERVEDSLOT_BUFSRV_INSTANCEDATA).Load(instanceDataOffset);
+
+ Vertex vert;
+ vert.Load(getBuffer(rootConstants3D.getVertexBufferHandle()), rootConstants3D.getVertexFormat(), _vertexID, rootConstants3D.getVertexBufferOffset());
+
+ ViewConstants viewConstants;
+ viewConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_VIEWCONSTANTS));
+
+ float4x4 view = viewConstants.getView();
+ float4x4 proj = viewConstants.getProj();
+
+ float3 modelPos = vert.getPos();
+ float3 worldPos = mul(float4(modelPos.xyz, 1.0f), rootConstants3D.getWorldMatrix()).xyz;
+ float4 viewPos = mul(float4(worldPos.xyz, 1.0f), view);
+
+ viewPos.z += WIREFRAME_DEPTHBIAS;
+ output.vpos = viewPos;
+ output.pos = mul(viewPos, proj);
+
+ return output;
+}
+
+struct PS_Output_Outline
+{
+ uint4 id : Color0;
+};
+
+PS_Output_Outline PS_Outline(VS_Output_Outline _input)
+{
+ ViewConstants viewConstants;
+ viewConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_VIEWCONSTANTS));
+
+ uint2 screenSize = viewConstants.getScreenSize();
+ float3 screenPos = _input.pos.xyz / float3(screenSize.xy, 1);
+
+ PS_Output_Outline output = (PS_Output_Outline)0;
+ output.id = rootConstants3D.getPickingID();
+
+ if (!linearDepthTest(screenPos.xy, _input.vpos))
+ output.id |= (uint)OutlineMaskFlags::DepthFail;
+
+ return output;
}
\ No newline at end of file
diff --git a/data/Shaders/default/default.hlsl.h b/data/Shaders/default/default.hlsl.h
index c405ff42..507b643b 100644
--- a/data/Shaders/default/default.hlsl.h
+++ b/data/Shaders/default/default.hlsl.h
@@ -44,6 +44,12 @@ namespace vg::gfx
deferred.vs = declVS("VS_Deferred");
deferred.ps = declPS("PS_Deferred");
}
+
+ auto & outline = declTechnique("Outline");
+ {
+ outline.vs = declVS("VS_Outline");
+ outline.ps = declPS("PS_Outline");
+ }
}
};
}
\ No newline at end of file
diff --git a/data/Shaders/postprocess/postprocess.hlsl b/data/Shaders/postprocess/postprocess.hlsl
index 3409b510..723a927d 100644
--- a/data/Shaders/postprocess/postprocess.hlsl
+++ b/data/Shaders/postprocess/postprocess.hlsl
@@ -6,6 +6,7 @@
#include "system/msaa.hlsli"
#include "system/instancedata.hlsli"
#include "system/gamma.hlsli"
+#include "system/outlinemask.hlsli"
#if _FXAA
#include "FXAA.hlsli"
@@ -405,6 +406,49 @@ void CS_PostProcessMain(int2 dispatchThreadID : SV_DispatchThreadID)
color = DebugRayTracing(color, uv, screenSize, viewConstants);
#endif
+ // outline
+ {
+
+ float2 pcf = (float2)0.0f;
+ for (int jj = -1; jj < 1; ++jj)
+ {
+ for (int ii = -1; ii < 1; ++ii)
+ {
+ uint4 center = getTexture2D_UInt4(postProcessConstants.getOutlineMask()).Load(int3(coords.x + ii, coords.y + jj, 0));
+
+ bool visibleOutline = false;
+ bool hiddenOutline = false;
+
+ for (int j = -1; j <= 1; ++j)
+ {
+ for (int i = -1; i <= 1; ++i)
+ {
+ uint4 sample = getTexture2D_UInt4(postProcessConstants.getOutlineMask()).Load(int3(coords.x + ii + i, coords.y + jj + j,0));
+
+ if ((sample.a & ~(uint)OutlineMaskFlags::DepthFail) != (center.a & ~(uint)OutlineMaskFlags::DepthFail))
+ {
+ if (0 != sample.a)
+ {
+ if (sample.a & (uint)OutlineMaskFlags::DepthFail)
+ hiddenOutline = true;
+ else
+ visibleOutline = true;
+ }
+ }
+ }
+ }
+
+ if (visibleOutline)
+ pcf += 1;
+
+ if (hiddenOutline)
+ pcf.y += 0.325;
+ }
+ }
+
+ color.rgb = lerp(color.rgb, float3(0,1,0), saturate((pcf.x + pcf.y) / 4.0f));
+ }
+
switch(viewConstants.getDisplayMode())
{
default:
@@ -452,6 +496,16 @@ void CS_PostProcessMain(int2 dispatchThreadID : SV_DispatchThreadID)
case DisplayMode::Lighting_EnvironmentSpecularBRDF:
color.rgb = getTexture2D(viewConstants.getSpecularBRDF()).SampleLevel(nearestClamp, uv, 0).rgb;
break;
+
+ case DisplayMode::PostProcess_OutlineMask:
+ {
+ uint sample = getTexture2D_UInt4(postProcessConstants.getOutlineMask()).Load(int3(coords,0)).a;
+ uint id = sample & (uint)~0x80000000;
+ float alpha = (sample & 0x80000000) ? 0.5 : 1.0;
+ color.rgb = (0 != id.x) ? frac(float3(id.x * 31.0, id.x * 17.0, id.x * 59.0) / 255.0) : float3(0,0,0);
+ color.rgb *= alpha;
+ }
+ break;
}
#endif // _TOOLMODE
diff --git a/data/Shaders/postprocess/postprocess.hlsli b/data/Shaders/postprocess/postprocess.hlsli
index 80eca628..cc6ecdd4 100644
--- a/data/Shaders/postprocess/postprocess.hlsli
+++ b/data/Shaders/postprocess/postprocess.hlsli
@@ -11,39 +11,45 @@ struct PostProcessConstants
#ifdef __cplusplus
PostProcessConstants()
{
- m_data = (uint4)0;
-
setScreenSize(uint2(0,0));
setSource(BINDLESS_TEXTURE_INVALID);
setRWBufferOut(BINDLESS_RWTEXTURE_INVALID);
setDepth(BINDLESS_TEXTURE_INVALID);
setStencil(BINDLESS_TEXTURE_INVALID);
setLinearDepth(BINDLESS_TEXTURE_INVALID);
+ setOutlineMask(BINDLESS_TEXTURE_INVALID);
}
#endif
- void setScreenSize (uint2 _size) { m_data.x = packUint16(_size.xy);}
- uint2 getScreenSize () { return unpackUint16(m_data.x); }
+ void setScreenSize (uint2 _size) { m_screensize = packUint16(_size.xy);}
+ uint2 getScreenSize () { return unpackUint16(m_screensize); }
+
+ void setSource (uint _color) { m_src_dst = packUint16low(m_src_dst, _color); }
+ uint getSource () { return unpackUint16low(m_src_dst); }
- void setSource (uint _color) { m_data.y = packUint16low(m_data.y, _color); }
- uint getSource () { return unpackUint16low(m_data.y); }
+ void setRWBufferOut (uint _rwbuffer){ m_src_dst = packUint16high(m_src_dst, _rwbuffer); }
+ uint getRWBufferOut () { return unpackUint16high(m_src_dst); }
- void setRWBufferOut (uint _rwbuffer){ m_data.y = packUint16high(m_data.y, _rwbuffer); }
- uint getRWBufferOut () { return unpackUint16high(m_data.y); }
+ void setDepth (uint _depth) { m_depth_stencil = packUint16low(m_depth_stencil, _depth); }
+ uint getDepth () { return unpackUint16low(m_depth_stencil); }
- void setDepth (uint _depth) { m_data.z = packUint16low(m_data.z, _depth); }
- uint getDepth () { return unpackUint16low(m_data.z); }
+ void setStencil (uint _stencil) { m_depth_stencil = packUint16high(m_depth_stencil, _stencil); }
+ uint getStencil () { return unpackUint16high(m_depth_stencil); }
- void setStencil (uint _stencil) { m_data.z = packUint16high(m_data.z, _stencil); }
- uint getStencil () { return unpackUint16high(m_data.z); }
+ void setLinearDepth (uint _linearZ) { m_depth_temp = packUint16low(m_depth_temp, _linearZ); }
+ uint getLinearDepth () { return unpackUint16low(m_depth_temp); }
- void setLinearDepth (uint _linearZ) { m_data.w = packUint16low(m_data.w, _linearZ); }
- uint getLinearDepth () { return unpackUint16low(m_data.w); }
+ void setTemp (uint _temp) { m_depth_temp = packUint16high(m_depth_temp, _temp); }
+ uint getTemp () { return unpackUint16high(m_depth_temp); }
- void setTemp (uint _temp) { m_data.w = packUint16high(m_data.w, _temp); }
- uint getTemp () { return unpackUint16high(m_data.w); }
+ void setOutlineMask (uint _outline) { m_outline_unused = packUint16low(m_outline_unused, _outline); }
+ uint getOutlineMask () { return unpackUint16low(m_outline_unused); }
- uint4 m_data;
+ uint m_screensize;
+ uint m_src_dst;
+ uint m_depth_stencil;
+ uint m_depth_temp;
+ uint m_outline_unused;
};
#define PostProcessConstantsCount sizeof(PostProcessConstants)/sizeof(u32)
diff --git a/data/Shaders/system/bindless.hlsli b/data/Shaders/system/bindless.hlsli
index 8b311cb0..ba413f00 100644
--- a/data/Shaders/system/bindless.hlsli
+++ b/data/Shaders/system/bindless.hlsli
@@ -22,7 +22,9 @@ DECL_DESCRIPTOR_RANGE_RO(Texture1D, g_Texture1D, BIND
DECL_DESCRIPTOR_RANGE_RO(Texture2D, g_Texture2D, BINDLESS_TEXTURE_BINDING_2D, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(TextureCube, g_TextureCube, BINDLESS_TEXTURE_BINDING_CUBE, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2DMS, g_Texture2DMS, BINDLESS_TEXTURE_BINDING_2DMS, BINDLESS_TEXTURE_START);
+DECL_DESCRIPTOR_RANGE_RO(Texture2D, g_Texture2D_UInt, BINDLESS_TEXTURE_BINDING_2D_UINT, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2D, g_Texture2D_UInt2, BINDLESS_TEXTURE_BINDING_2D_UINT2, BINDLESS_TEXTURE_START);
+DECL_DESCRIPTOR_RANGE_RO(Texture2D, g_Texture2D_UInt4, BINDLESS_TEXTURE_BINDING_2D_UINT4, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2DMS, g_Texture2DMS_UInt2, BINDLESS_TEXTURE_BINDING_2DMS_UINT2, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture3D, g_Texture3D, BINDLESS_TEXTURE_BINDING_3D, BINDLESS_TEXTURE_START);
@@ -52,7 +54,9 @@ DECL_DESCRIPTOR_RANGE_RO(RaytracingAccelerationStructure, g_TLAS, BINDLESS_TLAS_
#define getNonUniformTexture2D(_handle) (g_Texture2D[NonUniformResourceIndex(_handle - BINDLESS_TEXTURE_START)])
#define getTextureCube(_handle) (g_TextureCube[_handle - BINDLESS_TEXTURE_START])
#define getTexture2DMS(_handle) (g_Texture2DMS[_handle - BINDLESS_TEXTURE_START])
+#define getTexture2D_UInt(_handle) (g_Texture2D_UInt[_handle - BINDLESS_TEXTURE_START])
#define getTexture2D_UInt2(_handle) (g_Texture2D_UInt2[_handle - BINDLESS_TEXTURE_START])
+#define getTexture2D_UInt4(_handle) (g_Texture2D_UInt4[_handle - BINDLESS_TEXTURE_START])
#define getTexture2DMS_UInt2(_handle) (g_Texture2DMS_UInt2[_handle - BINDLESS_TEXTURE_START])
#define getTexture3D(_handle) (g_Texture3D[_handle - BINDLESS_TEXTURE_START])
diff --git a/data/Shaders/system/displaymodes.hlsli b/data/Shaders/system/displaymodes.hlsli
index 7add70de..12f598ec 100644
--- a/data/Shaders/system/displaymodes.hlsli
+++ b/data/Shaders/system/displaymodes.hlsli
@@ -66,7 +66,8 @@ vg_enum_class(DisplayMode, uint,
PostProcess_LinearDepth,
PostProcess_DepthOfField,
PostProcess_FXAAEdges,
- PostProcess_WorldPos
+ PostProcess_WorldPos,
+ PostProcess_OutlineMask
);
vg_enum(DisplayFlags, uint,
diff --git a/data/Shaders/system/editorpass.hlsli b/data/Shaders/system/editorpass.hlsli
new file mode 100644
index 00000000..84732ccd
--- /dev/null
+++ b/data/Shaders/system/editorpass.hlsli
@@ -0,0 +1,29 @@
+//#ifndef _EDITOR_PASS__HLSLI_
+//#define _EDITOR_PASS__HLSLI_
+//
+//#include "types.hlsli"
+//#include "packing.hlsli"
+//#include "displaymodes.hlsli"
+//
+//struct EditorPassConstants
+//{
+// #ifdef __cplusplus
+// EditorPassConstants()
+// {
+// m_data = 0;
+// setOutlineMask(BINDLESS_TEXTURE_INVALID);
+// }
+// #else
+// void Load(ByteAddressBuffer _buffer, uint _offset = 0)
+// {
+// m_data = _buffer.Load(_offset).m_data;
+// }
+// #endif
+//
+// uint m_data;
+//
+// void setOutlineMask (uint _outlineMask) { m_data = packUint16low(m_data, _outlineMask); }
+// uint getOutlineMask () { return unpackUint16low(m_data); }
+//};
+//
+//#endif // _EDITOR_PASS__HLSLI_
\ No newline at end of file
diff --git a/data/Shaders/system/outlinemask.hlsli b/data/Shaders/system/outlinemask.hlsli
new file mode 100644
index 00000000..81f1c4be
--- /dev/null
+++ b/data/Shaders/system/outlinemask.hlsli
@@ -0,0 +1,10 @@
+#ifndef _OUTLINEMASK__HLSLI_
+#define _OUTLINEMASK__HLSLI_
+
+#include "types.hlsli"
+
+vg_enum_class(OutlineMaskFlags, uint,
+ DepthFail = 0x8000
+);
+
+#endif // _OUTLINEMASK__HLSLI_
\ No newline at end of file
diff --git a/data/Shaders/system/table.hlsli b/data/Shaders/system/table.hlsli
index c759c960..93a36149 100644
--- a/data/Shaders/system/table.hlsli
+++ b/data/Shaders/system/table.hlsli
@@ -49,6 +49,7 @@ vg_enum_class(ReservedSlot, uint,
LastTexture = InvalidTexture2D,
// Buffer
+ EditorPassBufSrv = BINDLESS_BUFFER_INVALID - 7,
TransparentPassBufSrv = BINDLESS_BUFFER_INVALID - 6,
MaterialDataBufSrv = BINDLESS_BUFFER_INVALID - 5,
InstanceDataBufSrv = BINDLESS_BUFFER_INVALID - 4,
@@ -101,9 +102,11 @@ vg_enum_class(ReservedSlot, uint,
#define BINDLESS_TEXTURE_BINDING_1D 10
#define BINDLESS_TEXTURE_BINDING_2D 20
#define BINDLESS_TEXTURE_BINDING_2DMS 21
-#define BINDLESS_TEXTURE_BINDING_2D_UINT2 22
-#define BINDLESS_TEXTURE_BINDING_2DMS_UINT2 23
-#define BINDLESS_TEXTURE_BINDING_CUBE 24
+#define BINDLESS_TEXTURE_BINDING_2D_UINT 22
+#define BINDLESS_TEXTURE_BINDING_2D_UINT2 23
+#define BINDLESS_TEXTURE_BINDING_2D_UINT4 24
+#define BINDLESS_TEXTURE_BINDING_2DMS_UINT2 25
+#define BINDLESS_TEXTURE_BINDING_CUBE 26
#define BINDLESS_TEXTURE_BINDING_3D 30
#define BINDLESS_RWTEXTURE_BINDING_1D 210
@@ -118,7 +121,9 @@ vg_enum_class(ReservedSlot, uint,
#define BINDLESS_TEXTURE_BINDING_2D 0
#define BINDLESS_TEXTURE_BINDING_CUBE 0
#define BINDLESS_TEXTURE_BINDING_2DMS 0
+#define BINDLESS_TEXTURE_BINDING_2D_UINT 0
#define BINDLESS_TEXTURE_BINDING_2D_UINT2 0
+#define BINDLESS_TEXTURE_BINDING_2D_UINT4 0
#define BINDLESS_TEXTURE_BINDING_2DMS_UINT2 0
#define BINDLESS_TEXTURE_BINDING_3D 0
diff --git a/data/Shaders/system/transparentPass.hlsli b/data/Shaders/system/transparentPass.hlsli
index 4310c224..58fab323 100644
--- a/data/Shaders/system/transparentPass.hlsli
+++ b/data/Shaders/system/transparentPass.hlsli
@@ -10,8 +10,7 @@ struct TransparentPassConstants
#ifdef __cplusplus
TransparentPassConstants()
{
- m_data = (uint4)0;
-
+ m_data = 0;
setLinearDepth(BINDLESS_TEXTURE_INVALID);
}
#else
@@ -21,10 +20,10 @@ struct TransparentPassConstants
}
#endif
- uint4 m_data;
+ uint m_data;
- void setLinearDepth (uint _linearZ) { m_data.x = packUint16low(m_data.x, _linearZ); }
- uint getLinearDepth () { return unpackUint16low(m_data.x); }
+ void setLinearDepth (uint _linearZ) { m_data = packUint16low(m_data, _linearZ); }
+ uint getLinearDepth () { return unpackUint16low(m_data); }
};
#endif // _TRANSPARENT_PASS__HLSLI_
\ No newline at end of file
diff --git a/src/core/Scheduler/AssertMutex.h b/src/core/Scheduler/AssertMutex.h
new file mode 100644
index 00000000..4b635e22
--- /dev/null
+++ b/src/core/Scheduler/AssertMutex.h
@@ -0,0 +1,30 @@
+#pragma once
+
+namespace vg::core
+{
+ class AssertMutex
+ {
+ public:
+ inline AssertMutex(const char * _name) :
+ m_name(_name),
+ m_isEntered(false)
+ {
+ }
+
+ inline void lock()
+ {
+ bool expected = false;
+ if (!m_isEntered.compare_exchange_strong(expected, true))
+ VG_ASSERT(false, "AssertMutex \"%s\" already entered", m_name);
+ }
+
+ inline void unlock()
+ {
+ m_isEntered.store(false);
+ }
+
+ private:
+ const char * m_name;
+ core::atomic m_isEntered;
+ };
+}
\ No newline at end of file
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index c40fe77e..cdd6744e 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -159,6 +159,7 @@
+
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index d68753d8..e63699fe 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -465,6 +465,9 @@
Types
+
+ Scheduler
+
diff --git a/src/editor/ImGui/Window/ImGuiWindow.cpp b/src/editor/ImGui/Window/ImGuiWindow.cpp
index 036db635..c44285e7 100644
--- a/src/editor/ImGui/Window/ImGuiWindow.cpp
+++ b/src/editor/ImGui/Window/ImGuiWindow.cpp
@@ -3086,7 +3086,7 @@ namespace vg::editor
{
bool edited = false;
- sprintf_s(buffer, pString->c_str());
+ strcpy_s(buffer, pString->c_str());
if (ImGui::InputText(getPropertyLabel(_label, _index).c_str(), buffer, countof(buffer), getImGuiInputTextFlags(_propContext, _prop)))
edited = true;
diff --git a/src/editor/ImGui/Window/Statistics/ImGuiStatistics.hpp b/src/editor/ImGui/Window/Statistics/ImGuiStatistics.hpp
index b212384d..ca6c9066 100644
--- a/src/editor/ImGui/Window/Statistics/ImGuiStatistics.hpp
+++ b/src/editor/ImGui/Window/Statistics/ImGuiStatistics.hpp
@@ -69,8 +69,8 @@ namespace vg::editor
ImGui::Text("Decal");
ImGui::EndDisabled();
- ImGui::BeginDisabled(!stats.selected);
- ImGui::Text("Selected");
+ ImGui::BeginDisabled(!stats.outline);
+ ImGui::Text("Outline");
ImGui::EndDisabled();
}
ImGui::NextColumn();
@@ -93,8 +93,8 @@ namespace vg::editor
ImGui::Text("%u", stats.decal);
ImGui::EndDisabled();
- ImGui::BeginDisabled(!stats.selected);
- ImGui::Text("%u", stats.selected);
+ ImGui::BeginDisabled(!stats.outline);
+ ImGui::Text("%u", stats.outline);
ImGui::EndDisabled();
}
ImGui::Columns(1);
diff --git a/src/editor/ImGui/Window/View/ImGuiView.hpp b/src/editor/ImGui/Window/View/ImGuiView.hpp
index 5e20c199..4164f27d 100644
--- a/src/editor/ImGui/Window/View/ImGuiView.hpp
+++ b/src/editor/ImGui/Window/View/ImGuiView.hpp
@@ -578,11 +578,11 @@ namespace vg::editor
ImGui::SameLine();
ImGui::SetCursorPos(ImGui::GetWindowContentRegionMin() + pos);
- text = fmt::sprintf("Selected %u", stats.selected);
+ text = fmt::sprintf("Outline %u", stats.outline);
textSize = ImGui::CalcTextSize(text.c_str());
ImGui::GetWindowDrawList()->AddRectFilled(rectPos + pos, rectPos + pos + textSize, rectColor);
pos.y += style::font::DefaultFontHeight;
- ImGui::Text(text.c_str(), stats.selected);
+ ImGui::Text(text.c_str(), stats.outline);
// Lights
pos.y += style::font::DefaultFontHeight;
diff --git a/src/engine/World/Scene/Scene.hpp b/src/engine/World/Scene/Scene.hpp
index 0818ffae..67107fd0 100644
--- a/src/engine/World/Scene/Scene.hpp
+++ b/src/engine/World/Scene/Scene.hpp
@@ -17,7 +17,7 @@ namespace vg::engine
//--------------------------------------------------------------------------------------
Scene::~Scene()
{
-
+ // TODO: unselect all scene objects otherwise we might crash at exit?
}
//--------------------------------------------------------------------------------------
diff --git a/src/gfx/BindlessTable/BindlessTable.cpp b/src/gfx/BindlessTable/BindlessTable.cpp
index 4443eecd..885f65a8 100644
--- a/src/gfx/BindlessTable/BindlessTable.cpp
+++ b/src/gfx/BindlessTable/BindlessTable.cpp
@@ -31,7 +31,9 @@ namespace vg::gfx
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2D, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_CUBE, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2DMS, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
+ m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2D_UINT, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2D_UINT2, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
+ m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2D_UINT4, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2DMS_UINT2, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_3D, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
#endif
diff --git a/src/gfx/FrameGraph/FrameGraph.cpp b/src/gfx/FrameGraph/FrameGraph.cpp
index bf3a1a6f..425de572 100644
--- a/src/gfx/FrameGraph/FrameGraph.cpp
+++ b/src/gfx/FrameGraph/FrameGraph.cpp
@@ -848,15 +848,14 @@ namespace vg::gfx
}
//--------------------------------------------------------------------------------------
- void FrameGraph::prepareNode(const UserPassInfoNode & _node)
+ void FrameGraph::beforeAll(const UserPassInfoNode & _node)
{
for (auto & child : _node.m_children)
- prepareNode(child);
+ beforeAll(child);
if (!_node.m_renderPass)
return;
- // TODO: refactor as we always have only one SubPass per UserPass?
const auto & subPasses = _node.m_renderPass->getSubPasses();
VG_ASSERT(subPasses.size() == 1);
@@ -864,7 +863,27 @@ namespace vg::gfx
{
SubPass * subPass = subPasses[i];
const auto & userPassInfo = subPass->getUserPassesInfos()[0];
- userPassInfo.m_userPass->Prepare(userPassInfo.m_renderContext);
+ userPassInfo.m_userPass->BeforeAll(userPassInfo.m_renderContext);
+ }
+ }
+
+ //--------------------------------------------------------------------------------------
+ void FrameGraph::afterAll(const UserPassInfoNode & _node)
+ {
+ for (auto & child : _node.m_children)
+ afterAll(child);
+
+ if (!_node.m_renderPass)
+ return;
+
+ const auto & subPasses = _node.m_renderPass->getSubPasses();
+ VG_ASSERT(subPasses.size() == 1);
+
+ for (uint i = 0; i < subPasses.size(); ++i)
+ {
+ SubPass * subPass = subPasses[i];
+ const auto & userPassInfo = subPass->getUserPassesInfos()[0];
+ userPassInfo.m_userPass->AfterAll(userPassInfo.m_renderContext);
}
}
@@ -1087,11 +1106,10 @@ namespace vg::gfx
for (auto & node : m_userPassInfoTree.m_children)
gatherResources(node);
- // TODO: find a better name than "Prepare"?
{
- VG_PROFILE_CPU("Prepare");
+ VG_PROFILE_CPU("BeforeAll");
for (auto & node : m_userPassInfoTree.m_children)
- prepareNode(node);
+ beforeAll(node);
}
if (maxRenderJobCount > 0)
@@ -1491,6 +1509,12 @@ namespace vg::gfx
}
}
+ {
+ VG_PROFILE_CPU("AfterAll");
+ for (auto & node : m_userPassInfoTree.m_children)
+ afterAll(node);
+ }
+
// All textures and buffers remaining in pool should be marked as 'unused' at this point
for (uint i = 0; i < m_sharedTextures.size(); ++i)
{
diff --git a/src/gfx/FrameGraph/FrameGraph.h b/src/gfx/FrameGraph/FrameGraph.h
index daf85ea8..ee605abe 100644
--- a/src/gfx/FrameGraph/FrameGraph.h
+++ b/src/gfx/FrameGraph/FrameGraph.h
@@ -82,8 +82,9 @@ namespace vg::gfx
void buildNode (UserPassInfoNode & _node);
void gatherNodes (UserPassInfoNode & _node, core::vector & _nodes, core::u64 & _totalEstimatedCost);
void gatherResources (const UserPassInfoNode & _node);
- void prepareNode (const UserPassInfoNode & _node);
+ void beforeAll (const UserPassInfoNode & _node);
void renderNode (const UserPassInfoNode & _node, gfx::CommandList * _cmdList, bool _recur);
+ void afterAll (const UserPassInfoNode & _node);
Texture * createRenderTargetFromPool (const core::string & _name, const FrameGraphTextureResourceDesc & _textureResourceDesc, core::uint _createPassIndex);
Texture * createDepthStencilFromPool (const core::string & _name, const FrameGraphTextureResourceDesc & _textureResourceDesc, core::uint _createPassIndex);
diff --git a/src/gfx/FrameGraph/UserPass.h b/src/gfx/FrameGraph/UserPass.h
index d3724185..cedea786 100644
--- a/src/gfx/FrameGraph/UserPass.h
+++ b/src/gfx/FrameGraph/UserPass.h
@@ -31,7 +31,7 @@ namespace vg::gfx
virtual core::u64 GetCostEstimate (const RenderPassContext & _renderPassContext) const { return 1; }
// Called on main thread for all nodes before rendering using multiple threads (e.g., compute offsets used in other RenderJobs)
- virtual void Prepare (const RenderPassContext & _renderPassContext) {};
+ virtual void BeforeAll (const RenderPassContext & _renderPassContext) {};
// Called before entering RenderPass (e.g., write buffers from CPU to the GPU)
virtual void BeforeRender (const RenderPassContext & _renderPassContext, CommandList * _cmdList) {}
@@ -42,6 +42,9 @@ namespace vg::gfx
// Called after exiting RenderPass (e.g., read buffer from GPU to the CPU)
virtual void AfterRender (const RenderPassContext & _renderPassContext, CommandList * _cmdList) {};
+ // Called on main thread for all nodes after rendering using multiple threads (e.g., process GPU readback data)
+ virtual void AfterAll (const RenderPassContext & _renderPassContext) {};
+
// Descriptor for framegraph texture/buffer
const FrameGraphTextureResourceDesc * getTextureResourceDesc(const FrameGraphResourceID & _resID) const;
const FrameGraphBufferResourceDesc * getBufferResourceDesc(const FrameGraphResourceID & _resID) const;
diff --git a/src/gfx/Resource/Texture.inl b/src/gfx/Resource/Texture.inl
index 55a50147..7d7ad798 100644
--- a/src/gfx/Resource/Texture.inl
+++ b/src/gfx/Resource/Texture.inl
@@ -67,8 +67,11 @@ namespace vg::gfx
case PixelFormat::R10G10B10A2_unorm:
case PixelFormat::R16G16B16A16_unorm:
case PixelFormat::R16G16B16A16_float:
+ case PixelFormat::R16G16B16A16_uint:
case PixelFormat::R16G16_float:
case PixelFormat::R32G32B32A32_float:
+ case PixelFormat::R32_uint:
+ case PixelFormat::R32G32_uint:
return false;
case PixelFormat::D32S8:
diff --git a/src/gfx/Resource/Texture_consts.h b/src/gfx/Resource/Texture_consts.h
index efe2cafd..4c941915 100644
--- a/src/gfx/Resource/Texture_consts.h
+++ b/src/gfx/Resource/Texture_consts.h
@@ -25,8 +25,11 @@ namespace vg::gfx
R10G10B10A2_unorm,
R16G16B16A16_unorm,
R16G16B16A16_float,
+ R16G16B16A16_uint,
R16G16_float,
R32G32B32A32_float,
+ R32_uint,
+ R32G32_uint,
D32S8
);
diff --git a/src/gfx/Resource/dx12/Texture_dx12.hpp b/src/gfx/Resource/dx12/Texture_dx12.hpp
index 1125ed38..621d8891 100644
--- a/src/gfx/Resource/dx12/Texture_dx12.hpp
+++ b/src/gfx/Resource/dx12/Texture_dx12.hpp
@@ -24,12 +24,21 @@ namespace vg::gfx::dx12
case PixelFormat::R16G16B16A16_float:
return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ case PixelFormat::R16G16B16A16_uint:
+ return DXGI_FORMAT_R16G16B16A16_UINT;
+
case PixelFormat::R16G16_float:
return DXGI_FORMAT_R16G16_FLOAT;
case PixelFormat::R32G32B32A32_float:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ case PixelFormat::R32_uint:
+ return DXGI_FORMAT_R32_UINT;
+
+ case PixelFormat::R32G32_uint:
+ return DXGI_FORMAT_R32G32_UINT;
+
case PixelFormat::D32S8:
return DXGI_FORMAT_R32G8X24_TYPELESS;
}
diff --git a/src/gfx/Resource/vulkan/Texture_vulkan.hpp b/src/gfx/Resource/vulkan/Texture_vulkan.hpp
index 3d7b5437..94e6879d 100644
--- a/src/gfx/Resource/vulkan/Texture_vulkan.hpp
+++ b/src/gfx/Resource/vulkan/Texture_vulkan.hpp
@@ -27,12 +27,21 @@ namespace vg::gfx::vulkan
case PixelFormat::R16G16B16A16_float:
return VK_FORMAT_R16G16B16A16_SFLOAT;
+ case PixelFormat::R16G16B16A16_uint:
+ return VK_FORMAT_R16G16B16A16_UINT;
+
case PixelFormat::R16G16_float:
return VK_FORMAT_R16G16_SFLOAT;
case PixelFormat::R32G32B32A32_float:
return VK_FORMAT_R32G32B32A32_SFLOAT;
+ case PixelFormat::R32_uint:
+ return VK_FORMAT_R32_UINT;
+
+ case PixelFormat::R32G32_uint:
+ return VK_FORMAT_R32G32_UINT;
+
case PixelFormat::D32S8:
return VK_FORMAT_D32_SFLOAT_S8_UINT;
}
diff --git a/src/gfx/Shader/ComputeShaderKey.hpp b/src/gfx/Shader/ComputeShaderKey.hpp
index 29189a35..30e7914d 100644
--- a/src/gfx/Shader/ComputeShaderKey.hpp
+++ b/src/gfx/Shader/ComputeShaderKey.hpp
@@ -12,6 +12,7 @@ namespace vg::gfx
//--------------------------------------------------------------------------------------
void ComputeShaderKey::clear()
{
+ file = ComputeShaderKey::File(-1);
cs = ComputeShaderKey::CS(-1);
flags = ComputeShaderKey::File(0x0000);
}
diff --git a/src/gfx/Shader/ShaderKey.hpp b/src/gfx/Shader/ShaderKey.hpp
index ed9f6472..a2a0ef39 100644
--- a/src/gfx/Shader/ShaderKey.hpp
+++ b/src/gfx/Shader/ShaderKey.hpp
@@ -12,6 +12,7 @@ namespace vg::gfx
//--------------------------------------------------------------------------------------
void ShaderKey::clear()
{
+ file = ShaderKey::File(-1);
vs = ShaderKey::VS(-1);
hs = ShaderKey::HS(-1);
ds = ShaderKey::DS(-1);
diff --git a/src/renderer/IView.h b/src/renderer/IView.h
index 76be261d..5297426d 100644
--- a/src/renderer/IView.h
+++ b/src/renderer/IView.h
@@ -35,7 +35,7 @@ namespace vg::renderer
core::uint alphatest = 0;
core::uint transparent = 0;
core::uint decal = 0;
- core::uint selected = 0;
+ core::uint outline = 0;
core::uint directional = 0;
core::uint omni = 0;
core::uint spot = 0;
@@ -130,6 +130,7 @@ namespace vg::renderer
virtual bool IsLit () const = 0;
virtual bool IsUsingRayTracing () const = 0;
virtual bool IsComputePostProcessNeeded () const = 0;
+ virtual bool IsOutlinePassNeeded () const = 0;
virtual void SetPickingData (const PickingData & _pickingData) = 0;
virtual const PickingHit & GetPickingHit (core::uint _index) const = 0;
diff --git a/src/renderer/Instance/Mesh/MeshInstance.hpp b/src/renderer/Instance/Mesh/MeshInstance.hpp
index 1069f672..6b8cdbf0 100644
--- a/src/renderer/Instance/Mesh/MeshInstance.hpp
+++ b/src/renderer/Instance/Mesh/MeshInstance.hpp
@@ -164,7 +164,7 @@ namespace vg::renderer
const ObjectFlags objectFlags = this->getObjectFlags();
if (asBool(ObjectFlags::Selected & objectFlags))
- _cullingResult->m_output->add(GraphicInstanceListType::Selected, this);
+ _cullingResult->m_output->add(GraphicInstanceListType::Outline, this);
return true;
}
@@ -481,7 +481,7 @@ namespace vg::renderer
auto surfaceType = material->getSurfaceType();
- if (_renderContext.m_surfaceType != surfaceType && !_renderContext.m_wireframe)
+ if (_renderContext.m_surfaceType != surfaceType && !_renderContext.m_wireframe && !_renderContext.m_outline)
continue;
switch (_renderContext.m_shaderPass)
@@ -493,6 +493,7 @@ namespace vg::renderer
case ShaderPass::ZOnly:
case ShaderPass::Forward:
case ShaderPass::Deferred:
+ case ShaderPass::Outline:
material->Setup(_renderContext, _cmdList, &root3D, i);
break;
diff --git a/src/renderer/Job/Culling/ViewCullingJob.h b/src/renderer/Job/Culling/ViewCullingJob.h
index 4c37afaf..c17706ab 100644
--- a/src/renderer/Job/Culling/ViewCullingJob.h
+++ b/src/renderer/Job/Culling/ViewCullingJob.h
@@ -24,7 +24,7 @@ namespace vg::renderer
AlphaTest,
Transparent,
Decal,
- Selected
+ Outline
);
struct ViewCullingJobOutput
diff --git a/src/renderer/Job/Culling/ViewCullingJob.hpp b/src/renderer/Job/Culling/ViewCullingJob.hpp
index a472e922..0004e054 100644
--- a/src/renderer/Job/Culling/ViewCullingJob.hpp
+++ b/src/renderer/Job/Culling/ViewCullingJob.hpp
@@ -138,7 +138,7 @@ namespace vg::renderer
}
break;
- case GraphicInstanceListType::Selected:
+ case GraphicInstanceListType::Outline:
break;
}
}
diff --git a/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.hpp b/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.hpp
index 6658752a..f58edf5b 100644
--- a/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.hpp
+++ b/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.hpp
@@ -86,6 +86,7 @@ namespace vg::renderer
_root3D->setMatID(_index);
auto key = m_shaderKey[asInteger(_renderContext.m_shaderPass)];
+ VG_ASSERT(0xFF != key.file, "Undefined ShaderKey for pass \"%s\"", asString(_renderContext.m_shaderPass).c_str());
RasterizerState rs(FillMode::Solid, CullMode::Back);
@@ -166,6 +167,15 @@ namespace vg::renderer
key.setFlag(DefaultHLSLDesc::Toolmode, false);
}
break;
+
+ case ShaderPass::Outline:
+ {
+ BlendState bs(BlendFactor::One, BlendFactor::Zero, BlendOp::Add);
+ _cmdList->setBlendState(bs);
+
+ key.setFlag(DefaultHLSLDesc::Toolmode, false);
+ }
+ break;
}
CullMode cullMode;
diff --git a/src/renderer/Model/Material/MaterialModel.cpp b/src/renderer/Model/Material/MaterialModel.cpp
index a718f505..93f0a183 100644
--- a/src/renderer/Model/Material/MaterialModel.cpp
+++ b/src/renderer/Model/Material/MaterialModel.cpp
@@ -57,6 +57,7 @@ namespace vg::renderer
m_shaderKey[asInteger(ShaderPass::Forward)] = ShaderKey(shaderFile, "Forward");
m_shaderKey[asInteger(ShaderPass::Deferred)] = ShaderKey(shaderFile, "Deferred");
m_shaderKey[asInteger(ShaderPass::Transparent)] = ShaderKey(shaderFile, "Forward");
+ m_shaderKey[asInteger(ShaderPass::Outline)] = ShaderKey(shaderFile, "Outline");
}
//--------------------------------------------------------------------------------------
diff --git a/src/renderer/Model/Material/MaterialModel.h b/src/renderer/Model/Material/MaterialModel.h
index f39efbc9..70846aa6 100644
--- a/src/renderer/Model/Material/MaterialModel.h
+++ b/src/renderer/Model/Material/MaterialModel.h
@@ -29,7 +29,8 @@ namespace vg
ZOnly = 0,
Forward,
Deferred,
- Transparent
+ Transparent,
+ Outline
);
class MaterialModel : public IMaterialModel
diff --git a/src/renderer/Picking/PickingManager.cpp b/src/renderer/Picking/PickingManager.cpp
index 65b6d9aa..2ae5ccbd 100644
--- a/src/renderer/Picking/PickingManager.cpp
+++ b/src/renderer/Picking/PickingManager.cpp
@@ -47,6 +47,7 @@ namespace vg::renderer
// Alloc new slot
id = (PickingID)m_pickingID.size();
m_pickingID.push_back(_object);
+ VG_ASSERT(id < 32768); // Only 15 bits because upper bit is used for "ZTest" in Outline
return id;
}
diff --git a/src/renderer/RenderPass/Compute/ComputePostProcess/ComputePostProcessPass.hpp b/src/renderer/RenderPass/Compute/ComputePostProcess/ComputePostProcessPass.hpp
index 1d322c5a..94dae7a3 100644
--- a/src/renderer/RenderPass/Compute/ComputePostProcess/ComputePostProcessPass.hpp
+++ b/src/renderer/RenderPass/Compute/ComputePostProcess/ComputePostProcessPass.hpp
@@ -98,6 +98,12 @@ namespace vg::renderer
createRWTexture(dstID, uavDesc);
writeRWTexture(dstID);
}
+
+ if (view->IsOutlinePassNeeded())
+ {
+ const auto outlineMaskID = _renderPassContext.getFrameGraphID("OutlineMask");
+ readRenderTarget(outlineMaskID);
+ }
}
//--------------------------------------------------------------------------------------
@@ -291,6 +297,14 @@ namespace vg::renderer
postProcess.setStencil(stencil);
postProcess.setLinearDepth(linearDepth);
+ if (view->IsOutlinePassNeeded())
+ {
+ auto outlineMaskTex = getRenderTarget(_renderPassContext.getFrameGraphID("OutlineMask"));
+ auto outlineMask = outlineMaskTex->getTextureHandle();
+
+ postProcess.setOutlineMask(outlineMask);
+ }
+
_cmdList->setComputeRootConstants(0, (u32 *)&postProcess, PostProcessConstantsCount);
_cmdList->dispatch(threadGroupCount);
diff --git a/src/renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.h b/src/renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.h
index e6504d8e..0cf32a32 100644
--- a/src/renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.h
+++ b/src/renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.h
@@ -18,7 +18,7 @@ namespace vg::renderer
core::u64 GetCostEstimate (const gfx::RenderPassContext & _renderContext) const;
void Setup (const gfx::RenderPassContext & _renderContext) final override;
- void Prepare (const gfx::RenderPassContext & _renderContext) final override;
+ void BeforeAll (const gfx::RenderPassContext & _renderContext) final override;
void Render (const gfx::RenderPassContext & _renderContext, gfx::CommandList * _cmdList) const final override;
private:
diff --git a/src/renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.hpp b/src/renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.hpp
index 9142a084..4c793c02 100644
--- a/src/renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.hpp
+++ b/src/renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.hpp
@@ -63,7 +63,7 @@ namespace vg::renderer
}
//--------------------------------------------------------------------------------------
- void ComputeSkinningPass::Prepare(const RenderPassContext & _renderContext)
+ void ComputeSkinningPass::BeforeAll(const RenderPassContext & _renderContext)
{
VG_PROFILE_CPU("Skinning");
const auto & skinnedMeshes = Renderer::get()->getSharedCullingJobOutput()->m_skins;
diff --git a/src/renderer/RenderPass/RenderContext.h b/src/renderer/RenderPass/RenderContext.h
index a8b36ff1..60563350 100644
--- a/src/renderer/RenderPass/RenderContext.h
+++ b/src/renderer/RenderPass/RenderContext.h
@@ -20,7 +20,8 @@ namespace vg::renderer
m_shaderPass((ShaderPass)0),
m_toolmode(false),
m_raytracing(false),
- m_wireframe(false)
+ m_wireframe(false),
+ m_outline(false)
{
}
@@ -32,6 +33,7 @@ namespace vg::renderer
bool m_toolmode : 1;
bool m_raytracing : 1;
bool m_wireframe : 1;
+ bool m_outline : 1;
gfx::SurfaceType m_surfaceType = (gfx::SurfaceType)-1;
};
}
\ No newline at end of file
diff --git a/src/renderer/RenderPass/RenderObjects/Editor/EditorPass.h b/src/renderer/RenderPass/RenderObjects/Editor/EditorPass.h
index 0e6406fd..1e76cdf5 100644
--- a/src/renderer/RenderPass/RenderObjects/Editor/EditorPass.h
+++ b/src/renderer/RenderPass/RenderObjects/Editor/EditorPass.h
@@ -5,7 +5,7 @@
namespace vg::renderer
{
//--------------------------------------------------------------------------------------
- class EditorPass : public RenderObjectsPass
+ class EditorPass final : public RenderObjectsPass
{
public:
const char * GetClassName() const final { return "EditorPass"; }
@@ -13,12 +13,16 @@ namespace vg::renderer
EditorPass();
~EditorPass();
- void Setup (const gfx::RenderPassContext & _renderPassContext) override;
- void BeforeRender(const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) override;
- void Render (const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) const override;
- void AfterRender (const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) override;
+ void Setup (const gfx::RenderPassContext & _renderPassContext) final override;
+ void BeforeRender(const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) final override;
+ void Render (const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) const final override;
+ void AfterRender (const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) final override;
+ void AfterAll (const gfx::RenderPassContext & _renderPassContext) final override;
private:
+ //static gfx::Buffer * s_editorPassConstantsBuffer;
+
gfx::Buffer * m_toolmodeRWBufferStaging = nullptr;
+ PickingData m_pickingData;
};
}
\ No newline at end of file
diff --git a/src/renderer/RenderPass/RenderObjects/Editor/EditorPass.hpp b/src/renderer/RenderPass/RenderObjects/Editor/EditorPass.hpp
index f97eb290..26c4ee33 100644
--- a/src/renderer/RenderPass/RenderObjects/Editor/EditorPass.hpp
+++ b/src/renderer/RenderPass/RenderObjects/Editor/EditorPass.hpp
@@ -9,20 +9,36 @@
#include "renderer/Instance/GraphicInstance.h"
#include "Shaders/system/toolmode.hlsl.h"
+#include "Shaders/system/editorpass.hlsli"
namespace vg::renderer
{
+ //gfx::Buffer * EditorPass::s_editorPassConstantsBuffer = nullptr;
+
//--------------------------------------------------------------------------------------
EditorPass::EditorPass() :
RenderObjectsPass("EditorPass")
{
-
+ auto * device = Device::get();
+
+ //if (nullptr == s_editorPassConstantsBuffer)
+ //{
+ // BufferDesc editorPassConstantsBufferDesc = BufferDesc(Usage::Default, BindFlags::ShaderResource, CPUAccessFlags::Write, BufferFlags::None, sizeof(EditorPassConstants));
+ // s_editorPassConstantsBuffer = device->createBuffer(editorPassConstantsBufferDesc, "EditorPassConstants", nullptr, ReservedSlot::EditorPassBufSrv);
+ //}
+ //else
+ //{
+ // VG_SAFE_INCREASE_REFCOUNT(s_editorPassConstantsBuffer);
+ //}
}
//--------------------------------------------------------------------------------------
EditorPass::~EditorPass()
{
VG_SAFE_DELETE(m_toolmodeRWBufferStaging);
+
+ //if (s_editorPassConstantsBuffer && !s_editorPassConstantsBuffer->Release())
+ // s_editorPassConstantsBuffer = nullptr;
}
//--------------------------------------------------------------------------------------
@@ -31,8 +47,6 @@ namespace vg::renderer
writeRenderTarget(0, _renderPassContext.getFrameGraphID("Color"));
writeDepthStencil(_renderPassContext.getFrameGraphID("DepthStencil"));
writeRWBuffer(_renderPassContext.getFrameGraphID("ToolmodeRWBuffer"));
-
- readRenderTarget(_renderPassContext.getFrameGraphID("OutlineMask"));
readRWBuffer("SkinningRWBuffer");
}
@@ -40,6 +54,15 @@ namespace vg::renderer
void EditorPass::BeforeRender(const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList)
{
DebugDraw::get()->update(static_cast(_renderPassContext.getView()), _cmdList);
+
+ //auto OutlineMaskTex = getRenderTarget(_renderPassContext.getFrameGraphID("OutlineMask"));
+ //auto outlineMask = OutlineMaskTex->getTextureHandle();
+
+ //EditorPassConstants * constants = (EditorPassConstants *)_cmdList->map(s_editorPassConstantsBuffer, sizeof(EditorPassConstants)).data;
+ //{
+ // constants->setOutlineMask(outlineMask);
+ //}
+ //_cmdList->unmap(s_editorPassConstantsBuffer);
}
//--------------------------------------------------------------------------------------
@@ -84,17 +107,13 @@ namespace vg::renderer
DrawGraphicInstances(renderContext, _cmdList, GraphicInstanceListType::All);
}
- bool boudingBoxSelection = true;
- if (options->isAABBEnabled() || boudingBoxSelection)
+ if (options->isAABBEnabled())
{
const GraphicInstanceList & allInstances = view->getCullingJobResult().get(GraphicInstanceListType::All);
for (uint i = 0; i < allInstances.m_instances.size(); ++i)
{
auto * instance = (GraphicInstance*)allInstances.m_instances[i];
- if (boudingBoxSelection && !asBool(ObjectFlags::Selected & instance->getObjectFlags()))
- continue;
-
AABB aabb;
if (instance->TryGetAABB(aabb))
dbgDraw->drawAABB(_cmdList, aabb, instance->getGlobalMatrix());
@@ -109,7 +128,7 @@ namespace vg::renderer
//--------------------------------------------------------------------------------------
void EditorPass::AfterRender(const RenderPassContext & _renderPassContext, CommandList * _cmdList)
{
- auto * view = (IView*)(_renderPassContext.getViewMutable());
+ const auto * view = (IView*)(_renderPassContext.getView());
Buffer * toolmodeRWBuffer = getRWBuffer(_renderPassContext.getFrameGraphID("ToolmodeRWBuffer"));
// allocate staging copy
@@ -130,8 +149,15 @@ namespace vg::renderer
{
const ToolmodeRWBufferData * data = (ToolmodeRWBufferData *)result.data;
const PickingData * pickingData = &data->m_picking;
- view->SetPickingData(*pickingData);
+ m_pickingData = *pickingData; ;
}
m_toolmodeRWBufferStaging->getResource().unmap();
}
+
+ //--------------------------------------------------------------------------------------
+ void EditorPass::AfterAll(const gfx::RenderPassContext & _renderPassContext)
+ {
+ auto * view = (IView *)(_renderPassContext.getViewMutable());
+ view->SetPickingData(m_pickingData);
+ }
}
\ No newline at end of file
diff --git a/src/renderer/RenderPass/RenderObjects/Forward/ForwardTransparentPass.h b/src/renderer/RenderPass/RenderObjects/Forward/ForwardTransparentPass.h
index c3607563..157b720a 100644
--- a/src/renderer/RenderPass/RenderObjects/Forward/ForwardTransparentPass.h
+++ b/src/renderer/RenderPass/RenderObjects/Forward/ForwardTransparentPass.h
@@ -19,6 +19,6 @@ namespace vg::renderer
void Render (const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) const final override;
private:
- static gfx::Buffer * s_TransparentPassConstantsBuffer;
+ static gfx::Buffer * s_transparentPassConstantsBuffer;
};
}
\ No newline at end of file
diff --git a/src/renderer/RenderPass/RenderObjects/Forward/ForwardTransparentPass.hpp b/src/renderer/RenderPass/RenderObjects/Forward/ForwardTransparentPass.hpp
index a2d772bf..2756ee1e 100644
--- a/src/renderer/RenderPass/RenderObjects/Forward/ForwardTransparentPass.hpp
+++ b/src/renderer/RenderPass/RenderObjects/Forward/ForwardTransparentPass.hpp
@@ -9,7 +9,7 @@
namespace vg::renderer
{
- gfx::Buffer * ForwardTransparentPass::s_TransparentPassConstantsBuffer = nullptr;
+ gfx::Buffer * ForwardTransparentPass::s_transparentPassConstantsBuffer = nullptr;
//--------------------------------------------------------------------------------------
// Setup executed once, when pass is created
@@ -19,22 +19,22 @@ namespace vg::renderer
{
auto * device = Device::get();
- if (nullptr == s_TransparentPassConstantsBuffer)
+ if (nullptr == s_transparentPassConstantsBuffer)
{
- BufferDesc viewConstantsBufferDesc = BufferDesc(Usage::Default, BindFlags::ShaderResource, CPUAccessFlags::Write, BufferFlags::None, sizeof(TransparentPassConstants));
- s_TransparentPassConstantsBuffer = device->createBuffer(viewConstantsBufferDesc, "TransparentPassConstants", nullptr, ReservedSlot::TransparentPassBufSrv);
+ BufferDesc editorPassConstantsBufferDesc = BufferDesc(Usage::Default, BindFlags::ShaderResource, CPUAccessFlags::Write, BufferFlags::None, sizeof(TransparentPassConstants));
+ s_transparentPassConstantsBuffer = device->createBuffer(editorPassConstantsBufferDesc, "TransparentPassConstants", nullptr, ReservedSlot::TransparentPassBufSrv);
}
else
{
- VG_SAFE_INCREASE_REFCOUNT(s_TransparentPassConstantsBuffer);
+ VG_SAFE_INCREASE_REFCOUNT(s_transparentPassConstantsBuffer);
}
}
//--------------------------------------------------------------------------------------
ForwardTransparentPass::~ForwardTransparentPass()
{
- if (s_TransparentPassConstantsBuffer && !s_TransparentPassConstantsBuffer->Release())
- s_TransparentPassConstantsBuffer = nullptr;
+ if (s_transparentPassConstantsBuffer && !s_transparentPassConstantsBuffer->Release())
+ s_transparentPassConstantsBuffer = nullptr;
}
//--------------------------------------------------------------------------------------
@@ -67,11 +67,11 @@ namespace vg::renderer
auto linearDepthTex = getRenderTarget(_renderPassContext.getFrameGraphID("LinearDepth"));
auto linearDepth = linearDepthTex->getTextureHandle();
- TransparentPassConstants * constants = (TransparentPassConstants *)_cmdList->map(s_TransparentPassConstantsBuffer, sizeof(TransparentPassConstants)).data;
+ TransparentPassConstants * constants = (TransparentPassConstants *)_cmdList->map(s_transparentPassConstantsBuffer, sizeof(TransparentPassConstants)).data;
{
constants->setLinearDepth(linearDepth);
}
- _cmdList->unmap(s_TransparentPassConstantsBuffer);
+ _cmdList->unmap(s_transparentPassConstantsBuffer);
}
//--------------------------------------------------------------------------------------
diff --git a/src/renderer/RenderPass/RenderObjects/Misc/Outline/OutlineMaskPass.hpp b/src/renderer/RenderPass/RenderObjects/Misc/Outline/OutlineMaskPass.hpp
index 05efc53c..e0cc915b 100644
--- a/src/renderer/RenderPass/RenderObjects/Misc/Outline/OutlineMaskPass.hpp
+++ b/src/renderer/RenderPass/RenderObjects/Misc/Outline/OutlineMaskPass.hpp
@@ -19,7 +19,7 @@ namespace vg::renderer
core::u64 OutlineMaskPass::GetCostEstimate(const RenderPassContext & _renderPassContext) const
{
const View * view = static_cast(_renderPassContext.getView());
- return getListCostEstimate(view->getCullingJobResult(), GraphicInstanceListType::Selected);
+ return getListCostEstimate(view->getCullingJobResult(), GraphicInstanceListType::Outline);
}
//--------------------------------------------------------------------------------------
@@ -35,13 +35,21 @@ namespace vg::renderer
FrameGraphTextureResourceDesc outlineMaskResourceDesc = *depthStencilResourceDesc;
outlineMaskResourceDesc.type = TextureType::Texture2D;
outlineMaskResourceDesc.msaa = MSAA::None;
- outlineMaskResourceDesc.format = PixelFormat::R8G8B8A8_unorm;
+ outlineMaskResourceDesc.format = PixelFormat::R16G16B16A16_uint; // up to 4 outline masks, alpha channel used for editor selection outline
outlineMaskResourceDesc.clearColor = (float4)0.0f;
const auto outlineMaskID = _renderPassContext.getFrameGraphID("OutlineMask");
createRenderTarget(outlineMaskID, outlineMaskResourceDesc);
writeRenderTarget(0, outlineMaskID);
+ FrameGraphTextureResourceDesc outlineMaskDepthStencilResourceDesc = *depthStencilResourceDesc;
+ outlineMaskDepthStencilResourceDesc.type = TextureType::Texture2D;
+ outlineMaskDepthStencilResourceDesc.msaa = MSAA::None;
+
+ const auto outlineMaskDepthStencilID = _renderPassContext.getFrameGraphID("OutlineMaskDepthStencil");
+ createRenderTarget(outlineMaskDepthStencilID, outlineMaskDepthStencilResourceDesc);
+ writeDepthStencil(outlineMaskDepthStencilID);
+
const auto linearDepthID = _renderPassContext.getFrameGraphID("LinearDepth");
readRenderTarget(linearDepthID);
@@ -60,20 +68,19 @@ namespace vg::renderer
renderContext.m_proj = view->getProjMatrix();
renderContext.m_toolmode = view->getViewID().target == gfx::ViewTarget::Editor || options->isToolModeEnabled();
renderContext.m_raytracing = view->IsUsingRayTracing();
- renderContext.m_shaderPass = ShaderPass::Transparent;
+ renderContext.m_shaderPass = ShaderPass::Outline;
+ renderContext.m_outline = true;
RasterizerState rs(FillMode::Solid, CullMode::None);
BlendState bs(BlendFactor::One, BlendFactor::Zero, BlendOp::Add);
- const bool depthWrite = false;
-
- DepthStencilState ds(false, false, ComparisonFunc::LessEqual);
+ DepthStencilState ds(true, true, ComparisonFunc::LessEqual);
_cmdList->setPrimitiveTopology(PrimitiveTopology::TriangleList);
_cmdList->setRasterizerState(rs);
_cmdList->setBlendState(bs);
_cmdList->setDepthStencilState(ds);
- DrawGraphicInstances(renderContext, _cmdList, GraphicInstanceListType::Selected);
+ DrawGraphicInstances(renderContext, _cmdList, GraphicInstanceListType::Outline);
}
}
\ No newline at end of file
diff --git a/src/renderer/RenderPass/RenderObjects/RenderObjectsPass.hpp b/src/renderer/RenderPass/RenderObjects/RenderObjectsPass.hpp
index 7902b0ec..2022d5a4 100644
--- a/src/renderer/RenderPass/RenderObjects/RenderObjectsPass.hpp
+++ b/src/renderer/RenderPass/RenderObjects/RenderObjectsPass.hpp
@@ -47,7 +47,7 @@ namespace vg::renderer
break;
case GraphicInstanceListType::All:
- case GraphicInstanceListType::Selected:
+ case GraphicInstanceListType::Outline:
case GraphicInstanceListType::Opaque:
renderContext.m_surfaceType = gfx::SurfaceType::Opaque;
break;
diff --git a/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h b/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h
index 57769807..8ed59d63 100644
--- a/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h
+++ b/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h
@@ -19,7 +19,7 @@ namespace vg::renderer
~InstanceDataUpdatePass();
core::u64 GetCostEstimate (const gfx::RenderPassContext & _renderContext) const final override;
- void Prepare (const gfx::RenderPassContext & _renderContext) final override;
+ void BeforeAll (const gfx::RenderPassContext & _renderContext) final override;
void BeforeRender (const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) final override;
private:
diff --git a/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.hpp b/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.hpp
index a0521fc7..7d75bc6d 100644
--- a/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.hpp
+++ b/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.hpp
@@ -34,7 +34,7 @@ namespace vg::renderer
}
//--------------------------------------------------------------------------------------
- void InstanceDataUpdatePass::Prepare(const gfx::RenderPassContext & _renderContext)
+ void InstanceDataUpdatePass::BeforeAll(const gfx::RenderPassContext & _renderContext)
{
VG_PROFILE_CPU("InstanceData");
diff --git a/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.h b/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.h
index 92c5920e..ae1e5e73 100644
--- a/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.h
+++ b/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.h
@@ -18,7 +18,7 @@ namespace vg::renderer
MaterialDataUpdatePass();
~MaterialDataUpdatePass();
- void Prepare(const gfx::RenderPassContext & _renderContext) final override;
+ void BeforeAll(const gfx::RenderPassContext & _renderContext) final override;
void BeforeRender(const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) final override;
private:
diff --git a/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.hpp b/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.hpp
index dd592245..ea0adba4 100644
--- a/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.hpp
+++ b/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.hpp
@@ -23,7 +23,7 @@ namespace vg::renderer
}
//--------------------------------------------------------------------------------------
- void MaterialDataUpdatePass::Prepare(const gfx::RenderPassContext & _renderContext)
+ void MaterialDataUpdatePass::BeforeAll(const gfx::RenderPassContext & _renderContext)
{
MaterialManager * materialManager = MaterialManager::get();
materialManager->getMaterialsSafeCopy(m_materials);
diff --git a/src/renderer/View/Lit/LitView.hpp b/src/renderer/View/Lit/LitView.hpp
index bac6f9d5..2f1e802f 100644
--- a/src/renderer/View/Lit/LitView.hpp
+++ b/src/renderer/View/Lit/LitView.hpp
@@ -132,7 +132,7 @@ namespace vg::renderer
break;
}
- const bool outline = toolmode && true;
+ const bool outline = view->IsOutlinePassNeeded();
// Resolve/copy linear depth just before transparent pass because even in case of forward rendering we might want to add other passes writing Z (e.g., Skin, Water ...)
if (outline || options->isTransparencyEnabled() || view->IsComputePostProcessNeeded())
@@ -143,12 +143,11 @@ namespace vg::renderer
// Render editor display to "Color"
if (toolmode)
- {
- if (outline)
- _frameGraph.addUserPass(_renderPassContext, m_outlineMaskPass, "OutlineMask");
-
_frameGraph.addUserPass(_renderPassContext, m_editorPass, "Editor");
- }
+
+ // Render outline mask buffer
+ if (outline)
+ _frameGraph.addUserPass(_renderPassContext, m_outlineMaskPass, "OutlineMask");
// Apply PostProcess from "Color" and "DepthStencil" to "PostProcessUAV"
if (view->IsComputePostProcessNeeded())
diff --git a/src/renderer/View/View.cpp b/src/renderer/View/View.cpp
index 4f14f918..05f5bb03 100644
--- a/src/renderer/View/View.cpp
+++ b/src/renderer/View/View.cpp
@@ -2,6 +2,7 @@
#include "View.h"
#include "core/GameObject/GameObject.h"
#include "core/IInput.h"
+#include "core/Scheduler/Mutex.h"
#include "gfx/ITexture.h"
#include "gfx/Resource/Buffer.h"
#include "gfx/Raytracing/TLAS.h"
@@ -528,6 +529,13 @@ namespace vg::renderer
return options->isPostProcessEnabled() || (isToolmode() && IsUsingRayTracing() && options->anyRayTracingDebugDisplay());
}
+ //--------------------------------------------------------------------------------------
+ bool View::IsOutlinePassNeeded() const
+ {
+ const auto options = RendererOptions::get();
+ return IsComputePostProcessNeeded() && isToolmode();
+ }
+
//--------------------------------------------------------------------------------------
void View::setTLAS(TLAS * _tlas)
{
@@ -563,6 +571,8 @@ namespace vg::renderer
// Copy last picking results
m_rawPickingData = _pickingData;
+ lock_guard _(m_pickingHitsAssertMutex);
+
// Save hits
const uint counter = m_rawPickingData.m_counter.x;
m_pickingHits.clear();
@@ -599,6 +609,8 @@ namespace vg::renderer
//--------------------------------------------------------------------------------------
void View::AddPickingHit(const PickingHit & _hit)
{
+ lock_guard _(m_pickingHitsAssertMutex);
+
if (isToolmode())
m_pickingHits.insert(m_pickingHits.begin(), _hit);
}
@@ -606,6 +618,8 @@ namespace vg::renderer
//--------------------------------------------------------------------------------------
const PickingHit & View::GetPickingClosestHit() const
{
+ lock_guard _(m_pickingHitsAssertMutex);
+
VG_ASSERT(GetPickingHitCount() > 0);
return m_pickingHits[0];
}
@@ -613,12 +627,16 @@ namespace vg::renderer
//--------------------------------------------------------------------------------------
const PickingHit & View::GetPickingHit(uint _index) const
{
+ lock_guard _(m_pickingHitsAssertMutex);
+
return m_pickingHits[_index];
}
//--------------------------------------------------------------------------------------
uint View::GetPickingHitCount() const
{
+ lock_guard _(m_pickingHitsAssertMutex);
+
VG_ASSERT(m_pickingHits.size() <= PICKING_MAX_HITS);
return (uint)m_pickingHits.size();
}
@@ -644,7 +662,7 @@ namespace vg::renderer
stats.alphatest = (uint)m_cullingJobResult.get(GraphicInstanceListType::AlphaTest).m_instances.size();
stats.transparent = (uint)m_cullingJobResult.get(GraphicInstanceListType::Transparent).m_instances.size();
stats.decal = (uint)m_cullingJobResult.get(GraphicInstanceListType::Decal).m_instances.size();
- stats.selected = (uint)m_cullingJobResult.get(GraphicInstanceListType::Selected).m_instances.size();
+ stats.outline = (uint)m_cullingJobResult.get(GraphicInstanceListType::Outline).m_instances.size();
stats.directional = (uint)m_cullingJobResult.get(LightType::Directional).m_instances.size();
stats.omni = (uint)m_cullingJobResult.get(LightType::Omni).m_instances.size();
diff --git a/src/renderer/View/View.h b/src/renderer/View/View.h
index 3e002373..02a53142 100644
--- a/src/renderer/View/View.h
+++ b/src/renderer/View/View.h
@@ -1,8 +1,9 @@
#pragma once
-#include "renderer/IView.h"
+#include "core/Scheduler/AssertMutex.h"
#include "gfx/Resource/Texture.h"
#include "gfx/FrameGraph/FrameGraph_consts.h"
+#include "renderer/IView.h"
#include "renderer/Job/Culling/ViewCullingJob.h"
#include "shaders/system/picking.hlsli"
#include "Frustum.h"
@@ -96,6 +97,7 @@ namespace vg::renderer
bool IsUsingRayTracing () const override;
bool IsLit () const override;
bool IsComputePostProcessNeeded () const override;
+ bool IsOutlinePassNeeded () const override;
void setTLAS (gfx::TLAS * _tlas);
gfx::TLAS * getTLAS () const;
@@ -187,6 +189,7 @@ namespace vg::renderer
core::uint2 m_mouseOffset;
PickingData m_rawPickingData;
core::vector m_pickingHits;
+ mutable core::AssertMutex m_pickingHitsAssertMutex = core::AssertMutex("PickingHits");
gfx::TLAS * m_tlas = nullptr;
Frustum m_frustum;
ViewCullingJobOutput m_cullingJobResult;
diff --git a/src/version.h b/src/version.h
index 12fd67b5..5a0cc783 100644
--- a/src/version.h
+++ b/src/version.h
@@ -2,4 +2,4 @@
#define VG_FRAMEWORK_VERSION_MAJOR 0
#define VG_FRAMEWORK_VERSION_MINOR 46
-#define VG_FRAMEWORK_VERSION_PATCH 1
\ No newline at end of file
+#define VG_FRAMEWORK_VERSION_PATCH 2
\ No newline at end of file
diff --git a/vgframework.sln b/vgframework.sln
index cc23af6a..72b049fc 100644
--- a/vgframework.sln
+++ b/vgframework.sln
@@ -87,6 +87,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "system", "system", "{34ABDE
data\Shaders\system\depthbias.hlsli = data\Shaders\system\depthbias.hlsli
data\Shaders\system\depthstencil.hlsli = data\Shaders\system\depthstencil.hlsli
data\Shaders\system\displaymodes.hlsli = data\Shaders\system\displaymodes.hlsli
+ data\Shaders\system\editorpass.hlsli = data\Shaders\system\editorpass.hlsli
data\Shaders\system\environment.hlsli = data\Shaders\system\environment.hlsli
data\Shaders\system\gamma.hlsli = data\Shaders\system\gamma.hlsli
data\Shaders\system\instancedata.hlsli = data\Shaders\system\instancedata.hlsli
@@ -96,6 +97,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "system", "system", "{34ABDE
data\Shaders\system\material_consts.hlsli = data\Shaders\system\material_consts.hlsli
data\Shaders\system\msaa.hlsli = data\Shaders\system\msaa.hlsli
data\Shaders\system\packing.hlsli = data\Shaders\system\packing.hlsli
+ data\Shaders\system\outlinemask.hlsli = data\Shaders\system\outlinemask.hlsli
data\Shaders\system\pbr.hlsli = data\Shaders\system\pbr.hlsli
data\Shaders\system\picking.hlsl = data\Shaders\system\picking.hlsl
data\Shaders\system\picking.hlsli = data\Shaders\system\picking.hlsli