From: kgv Date: Thu, 4 Apr 2019 20:20:45 +0000 (+0300) Subject: 0030631: Visualization - Vulkan graphic driver prototype X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=4e025bb8e10544224cdeec20950a400faa0b6e6c;p=occt-copy.git 0030631: Visualization - Vulkan graphic driver prototype --- diff --git a/adm/MODULES b/adm/MODULES index e65fb379ee..82e10f8744 100644 --- a/adm/MODULES +++ b/adm/MODULES @@ -1,7 +1,7 @@ FoundationClasses TKernel TKMath ModelingData TKG2d TKG3d TKGeomBase TKBRep ModelingAlgorithms TKGeomAlgo TKTopAlgo TKPrim TKBO TKBool TKHLR TKFillet TKOffset TKFeat TKMesh TKXMesh TKShHealing -Visualization TKService TKV3d TKOpenGl TKMeshVS TKIVtk TKD3DHost +Visualization TKService TKV3d TKOpenGl TKMeshVS TKIVtk TKD3DHost TKVulkan ApplicationFramework TKCDF TKLCAF TKCAF TKBinL TKXmlL TKBin TKXml TKStdL TKStd TKTObj TKBinTObj TKXmlTObj TKVCAF DataExchange TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF Draw TKDraw TKTopTest TKViewerTest TKXSDRAW TKDCAF TKXDEDRAW TKTObjDRAW TKQADraw TKIVtkDraw DRAWEXE diff --git a/adm/UDLIST b/adm/UDLIST index 0c6b6360d2..2ccee5aff6 100644 --- a/adm/UDLIST +++ b/adm/UDLIST @@ -206,6 +206,7 @@ n Image n MeshVS n OpenGl n D3DHost +n Vulkan n Prs3d n PrsMgr n Select3D @@ -223,6 +224,7 @@ r Shaders t TKMeshVS t TKOpenGl t TKD3DHost +t TKVulkan t TKService t TKV3d n BinTObjDrivers diff --git a/adm/cmake/occt_csf.cmake b/adm/cmake/occt_csf.cmake index da796d18f7..09ec39282a 100644 --- a/adm/cmake/occt_csf.cmake +++ b/adm/cmake/occt_csf.cmake @@ -58,6 +58,9 @@ if (USE_TCL) endif() endif() +# Vulkan +set (CSF_vulkan "vulkan-1") + if (WIN32) set (CSF_advapi32 "advapi32.lib") set (CSF_gdi32 "gdi32.lib") diff --git a/adm/genproj.tcl b/adm/genproj.tcl index 9039a5a2a1..f04fd64abe 100644 --- a/adm/genproj.tcl +++ b/adm/genproj.tcl @@ -1339,6 +1339,8 @@ proc osutils:csfList { theOS theCsfLibsMap theCsfFrmsMap } { set aLibsMap(CSF_LIBLZMA) "liblzma" } + set aLibsMap(CSF_vulkan) "vulkan-1" + if { "$theOS" == "wnt" } { # WinAPI libraries set aLibsMap(CSF_kernel32) "kernel32" diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 1c78cae641..2e0b1fa60d 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -33,6 +33,10 @@ Graphic3d_Buffer.cxx Graphic3d_Buffer.hxx Graphic3d_BufferRange.hxx Graphic3d_BufferType.hxx +Graphic3d_BvhCStructureSet.cxx +Graphic3d_BvhCStructureSet.hxx +Graphic3d_BvhCStructureSetTrsfPers.cxx +Graphic3d_BvhCStructureSetTrsfPers.hxx Graphic3d_Camera.cxx Graphic3d_Camera.hxx Graphic3d_CameraTile.hxx @@ -44,6 +48,8 @@ Graphic3d_ClipPlane.hxx Graphic3d_CStructure.cxx Graphic3d_CStructure.hxx Graphic3d_CTexture.hxx +Graphic3d_CullingTool.cxx +Graphic3d_CullingTool.hxx Graphic3d_CView.cxx Graphic3d_CView.hxx Graphic3d_DataStructureManager.cxx @@ -78,6 +84,7 @@ Graphic3d_MapOfAspectsToAspects.hxx Graphic3d_MapIteratorOfMapOfStructure.hxx Graphic3d_MapOfObject.hxx Graphic3d_MapOfStructure.hxx +Graphic3d_MapOfZLayerSettings.hxx Graphic3d_MarkerImage.cxx Graphic3d_MarkerImage.hxx Graphic3d_Mat4.hxx @@ -173,5 +180,7 @@ Graphic3d_VerticalTextAlignment.hxx Graphic3d_ViewAffinity.cxx Graphic3d_ViewAffinity.hxx Graphic3d_WorldViewProjState.hxx +Graphic3d_Layer.cxx +Graphic3d_Layer.hxx Graphic3d_ZLayerId.hxx Graphic3d_ZLayerSettings.hxx diff --git a/src/Graphic3d/Graphic3d_BvhCStructureSet.cxx b/src/Graphic3d/Graphic3d_BvhCStructureSet.cxx new file mode 100644 index 0000000000..bff09f3a82 --- /dev/null +++ b/src/Graphic3d/Graphic3d_BvhCStructureSet.cxx @@ -0,0 +1,130 @@ +// Created on: 2013-12-25 +// Created by: Varvara POSKONINA +// Copyright (c) 1999-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_BvhCStructureSet, BVH_PrimitiveSet3d) + +// ======================================================================= +// function : Graphic3d_BvhCStructureSet +// purpose : +// ======================================================================= +Graphic3d_BvhCStructureSet::Graphic3d_BvhCStructureSet() +{ + myBuilder = new BVH_BinnedBuilder (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth); +} + +// ======================================================================= +// function : Size +// purpose : +// ======================================================================= +Standard_Integer Graphic3d_BvhCStructureSet::Size() const +{ + return myStructs.Size(); +} + +// ======================================================================= +// function : Box +// purpose : +// ======================================================================= +Graphic3d_BndBox3d Graphic3d_BvhCStructureSet::Box (const Standard_Integer theIdx) const +{ + return myStructs.FindKey (theIdx + 1)->BoundingBox(); +} + +// ======================================================================= +// function : Center +// purpose : +// ======================================================================= +Standard_Real Graphic3d_BvhCStructureSet::Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const +{ + Graphic3d_BndBox3d aBndBox = myStructs.FindKey (theIdx + 1)->BoundingBox(); + + const Standard_Real aMin = aBndBox.CornerMin()[theAxis]; + const Standard_Real aMax = aBndBox.CornerMax()[theAxis]; + const Standard_Real aCenter = (aMin + aMax) * 0.5; + return aCenter; +} + +// ======================================================================= +// function : Swap +// purpose : +// ======================================================================= +void Graphic3d_BvhCStructureSet::Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) +{ + myStructs.Swap (theIdx1 + 1, theIdx2 + 1); +} + +// ======================================================================= +// function : Add +// purpose : +// ======================================================================= +Standard_Boolean Graphic3d_BvhCStructureSet::Add (const Graphic3d_CStructure* theStruct) +{ + const Standard_Integer aSize = myStructs.Size(); + + if (myStructs.Add (theStruct) > aSize) // new structure? + { + MarkDirty(); + + return Standard_True; + } + + return Standard_False; +} + +// ======================================================================= +// function : Remove +// purpose : +// ======================================================================= +Standard_Boolean Graphic3d_BvhCStructureSet::Remove (const Graphic3d_CStructure* theStruct) +{ + const Standard_Integer anIndex = myStructs.FindIndex (theStruct); + + if (anIndex != 0) + { + myStructs.Swap (Size(), anIndex); + myStructs.RemoveLast(); + MarkDirty(); + + return Standard_True; + } + + return Standard_False; +} + +// ======================================================================= +// function : Clear +// purpose : +// ======================================================================= +void Graphic3d_BvhCStructureSet::Clear() +{ + myStructs.Clear(); + MarkDirty(); +} + +// ======================================================================= +// function : GetStructureById +// purpose : +// ======================================================================= +const Graphic3d_CStructure* Graphic3d_BvhCStructureSet::GetStructureById (Standard_Integer theId) +{ + return myStructs.FindKey (theId + 1); +} diff --git a/src/Graphic3d/Graphic3d_BvhCStructureSet.hxx b/src/Graphic3d/Graphic3d_BvhCStructureSet.hxx new file mode 100644 index 0000000000..a46145717a --- /dev/null +++ b/src/Graphic3d/Graphic3d_BvhCStructureSet.hxx @@ -0,0 +1,75 @@ +// Created on: 2013-12-25 +// Created by: Varvara POSKONINA +// Copyright (c) 1999-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_BvhCStructureSet_HeaderFile +#define _Graphic3d_BvhCStructureSet_HeaderFile + +#include +#include +#include + +class Graphic3d_CStructure; + +//! Set of OpenGl_Structures for building BVH tree. +class Graphic3d_BvhCStructureSet : public BVH_PrimitiveSet3d +{ + DEFINE_STANDARD_RTTIEXT(Graphic3d_BvhCStructureSet, BVH_PrimitiveSet3d) +protected: + + using BVH_PrimitiveSet3d::Box; + +public: + + //! Creates an empty primitive set for BVH clipping. + Graphic3d_BvhCStructureSet(); + + //! Returns total number of structures. + virtual Standard_Integer Size() const Standard_OVERRIDE; + + //! Returns AABB of the structure. + virtual Graphic3d_BndBox3d Box (const Standard_Integer theIdx) const Standard_OVERRIDE; + + //! Calculates center of the AABB along given axis. + virtual Standard_Real Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const Standard_OVERRIDE; + + //! Swaps structures with the given indices. + virtual void Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) Standard_OVERRIDE; + + //! Adds structure to the set. + //! @return true if structure added, otherwise returns false (structure already in the set). + Standard_Boolean Add (const Graphic3d_CStructure* theStruct); + + //! Removes the given structure from the set. + //! @return true if structure removed, otherwise returns false (structure is not in the set). + Standard_Boolean Remove (const Graphic3d_CStructure* theStruct); + + //! Cleans the whole primitive set. + void Clear(); + + //! Returns the structure corresponding to the given ID. + const Graphic3d_CStructure* GetStructureById (Standard_Integer theId); + + //! Access directly a collection of structures. + const NCollection_IndexedMap& Structures() const { return myStructs; } + +private: + + NCollection_IndexedMap myStructs; //!< Indexed map of structures. + +}; + +#endif // _Graphic3d_BvhCStructureSet_HeaderFile diff --git a/src/Graphic3d/Graphic3d_BvhCStructureSetTrsfPers.cxx b/src/Graphic3d/Graphic3d_BvhCStructureSetTrsfPers.cxx new file mode 100644 index 0000000000..95b0ff7322 --- /dev/null +++ b/src/Graphic3d/Graphic3d_BvhCStructureSetTrsfPers.cxx @@ -0,0 +1,173 @@ +// Created on: 2015-06-30 +// Created by: Anton POLETAEV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include + +// ======================================================================= +// function : Graphic3d_BvhCStructureSetTrsfPers +// purpose : +// ======================================================================= +Graphic3d_BvhCStructureSetTrsfPers::Graphic3d_BvhCStructureSetTrsfPers (const Handle(Select3D_BVHBuilder3d)& theBuilder) +: myIsDirty (Standard_False), + myBVH (new BVH_Tree()), + myBuilder (theBuilder) +{ + // +} + +// ======================================================================= +// function : Size +// purpose : +// ======================================================================= +Standard_Integer Graphic3d_BvhCStructureSetTrsfPers::Size() const +{ + return myStructs.Size(); +} + +// ======================================================================= +// function : Box +// purpose : +// ======================================================================= +Graphic3d_BndBox3d Graphic3d_BvhCStructureSetTrsfPers::Box (const Standard_Integer theIdx) const +{ + return *myStructBoxes (theIdx + 1); +} + +// ======================================================================= +// function : Center +// purpose : +// ======================================================================= +Standard_Real Graphic3d_BvhCStructureSetTrsfPers::Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const +{ + const Graphic3d_BndBox3d& aBndBox = *myStructBoxes (theIdx + 1); + return (aBndBox.CornerMin()[theAxis] + aBndBox.CornerMax()[theAxis]) * 0.5; +} + +// ======================================================================= +// function : Swap +// purpose : +// ======================================================================= +void Graphic3d_BvhCStructureSetTrsfPers::Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) +{ + const Standard_Integer aStructIdx1 = theIdx1 + 1; + const Standard_Integer aStructIdx2 = theIdx2 + 1; + + myStructs .Swap (aStructIdx1, aStructIdx2); + myStructBoxes.Swap (aStructIdx1, aStructIdx2); +} + +// ======================================================================= +// function : Add +// purpose : +// ======================================================================= +Standard_Boolean Graphic3d_BvhCStructureSetTrsfPers::Add (const Graphic3d_CStructure* theStruct) +{ + const Standard_Integer aSize = myStructs.Size(); + + if (myStructs.Add (theStruct) > aSize) // new structure? + { + MarkDirty(); + + return Standard_True; + } + + return Standard_False; +} + +// ======================================================================= +// function : Remove +// purpose : +// ======================================================================= +Standard_Boolean Graphic3d_BvhCStructureSetTrsfPers::Remove (const Graphic3d_CStructure* theStruct) +{ + const Standard_Integer anIndex = myStructs.FindIndex (theStruct); + + if (anIndex != 0) + { + myStructs.Swap (Size(), anIndex); + myStructs.RemoveLast(); + MarkDirty(); + + return Standard_True; + } + + return Standard_False; +} + +// ======================================================================= +// function : Clear +// purpose : +// ======================================================================= +void Graphic3d_BvhCStructureSetTrsfPers::Clear() +{ + myStructs.Clear(); + MarkDirty(); +} + +// ======================================================================= +// function : GetStructureById +// purpose : +// ======================================================================= +const Graphic3d_CStructure* Graphic3d_BvhCStructureSetTrsfPers::GetStructureById (Standard_Integer theId) +{ + return myStructs.FindKey (theId + 1); +} + +//======================================================================= +// function : BVH +// purpose : +//======================================================================= +const opencascade::handle >& Graphic3d_BvhCStructureSetTrsfPers::BVH (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMatrix, + const Graphic3d_Mat4d& theWorldViewMatrix, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight, + const Graphic3d_WorldViewProjState& theWVPState) +{ + if (!myIsDirty + && (myStructBoxesState.IsValid() + && !myStructBoxesState.IsChanged (theWVPState))) + { + return myBVH; + } + + myStructBoxes.ReSize (myStructs.Size()); + + for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Size(); ++aStructIdx) + { + const Graphic3d_CStructure* aStructure = myStructs (aStructIdx); + + Handle(HBndBox3d) aBoundingBox = new HBndBox3d(); + *aBoundingBox = aStructure->BoundingBox(); + if (!aStructure->TransformPersistence().IsNull()) + { + aStructure->TransformPersistence()->Apply (theCamera, theProjectionMatrix, theWorldViewMatrix, theViewportWidth, theViewportHeight, *aBoundingBox); + } + + myStructBoxes.Add (aBoundingBox); + } + + myBuilder->Build (this, myBVH.operator->(), BVH_Set::Box()); + + myStructBoxesState = theWVPState; + myStructBoxes.Clear(); + myIsDirty = Standard_False; + + return myBVH; +} diff --git a/src/Graphic3d/Graphic3d_BvhCStructureSetTrsfPers.hxx b/src/Graphic3d/Graphic3d_BvhCStructureSetTrsfPers.hxx new file mode 100644 index 0000000000..a7b9919794 --- /dev/null +++ b/src/Graphic3d/Graphic3d_BvhCStructureSetTrsfPers.hxx @@ -0,0 +1,120 @@ +// Created on: 2015-06-30 +// Created by: Anton POLETAEV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_BvhCStructureSetTrsfPers_HeaderFile +#define _Graphic3d_BvhCStructureSetTrsfPers_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include + +class Graphic3d_Camera; +class Graphic3d_CStructure; + +//! Set of transformation persistent OpenGl_Structure for building BVH tree. +//! Provides built-in mechanism to invalidate tree when world view projection state changes. +//! Due to frequent invalidation of BVH tree the choice of BVH tree builder is made +//! in favor of BVH linear builder (quick rebuild). +class Graphic3d_BvhCStructureSetTrsfPers : public BVH_Set +{ +private: + + typedef NCollection_Shared HBndBox3d; + +public: + + //! Creates an empty primitive set for BVH clipping. + Graphic3d_BvhCStructureSetTrsfPers (const Handle(Select3D_BVHBuilder3d)& theBuilder); + + //! Returns total number of structures. + virtual Standard_Integer Size() const Standard_OVERRIDE; + + //! Returns AABB of the structure. + virtual Graphic3d_BndBox3d Box (const Standard_Integer theIdx) const Standard_OVERRIDE; + + //! Calculates center of the AABB along given axis. + virtual Standard_Real Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const Standard_OVERRIDE; + + //! Swaps structures with the given indices. + virtual void Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) Standard_OVERRIDE; + + //! Adds structure to the set. + //! @return true if structure added, otherwise returns false (structure already in the set). + Standard_Boolean Add (const Graphic3d_CStructure* theStruct); + + //! Removes the given structure from the set. + //! @return true if structure removed, otherwise returns false (structure is not in the set). + Standard_Boolean Remove (const Graphic3d_CStructure* theStruct); + + //! Cleans the whole primitive set. + void Clear(); + + //! Returns the structure corresponding to the given ID. + const Graphic3d_CStructure* GetStructureById (Standard_Integer theId); + + //! Access directly a collection of structures. + const NCollection_IndexedMap& Structures() const { return myStructs; } + + //! Marks object state as outdated (needs BVH rebuilding). + void MarkDirty() + { + myIsDirty = Standard_True; + } + + //! Returns BVH tree for the given world view projection (builds it if necessary). + const opencascade::handle >& BVH (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMatrix, + const Graphic3d_Mat4d& theWorldViewMatrix, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight, + const Graphic3d_WorldViewProjState& theWVPState); + + //! Returns builder for bottom-level BVH. + const Handle(Select3D_BVHBuilder3d)& Builder() const { return myBuilder; } + + //! Assigns builder for bottom-level BVH. + void SetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder) { myBuilder = theBuilder; } + +private: + + //! Marks internal object state as outdated. + Standard_Boolean myIsDirty; + + //! Constructed bottom-level BVH. + opencascade::handle > myBVH; + + //! Builder for bottom-level BVH. + Handle(Select3D_BVHBuilder3d) myBuilder; + + //! Indexed map of structures. + NCollection_IndexedMap myStructs; + + //! Cached set of bounding boxes precomputed for transformation persistent selectable objects. + //! Cache exists only during computation of BVH Tree. Bounding boxes are world view projection + //! dependent and should by synchronized. + NCollection_IndexedMap myStructBoxes; + + //! State of world view projection used for generation of transformation persistence bounding boxes. + Graphic3d_WorldViewProjState myStructBoxesState; +}; + +#endif // _Graphic3d_BvhCStructureSetTrsfPers_HeaderFile diff --git a/src/Graphic3d/Graphic3d_CStructure.cxx b/src/Graphic3d/Graphic3d_CStructure.cxx index ecc6e8d23f..7168413023 100644 --- a/src/Graphic3d/Graphic3d_CStructure.cxx +++ b/src/Graphic3d/Graphic3d_CStructure.cxx @@ -19,7 +19,6 @@ #include #include - IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CStructure,Standard_Transient) //============================================================================= @@ -39,7 +38,8 @@ Graphic3d_CStructure::Graphic3d_CStructure (const Handle(Graphic3d_StructureMana IsForHighlight (Standard_False), IsMutable (Standard_False), Is2dText (Standard_False), - myGraphicDriver (theManager->GraphicDriver()) + myGraphicDriver (theManager->GraphicDriver()), + myIsCulled (Standard_True) { Id = myGraphicDriver->NewIdentification(); } diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx index 32a773e169..adfcbbe9ee 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -26,6 +26,7 @@ #include #include #include +#include class Graphic3d_GraphicDriver; class Graphic3d_StructureManager; @@ -33,6 +34,35 @@ class Graphic3d_StructureManager; //! Low-level graphic structure interface class Graphic3d_CStructure : public Standard_Transient { +protected: + + //! Auxiliary wrapper to iterate through structure list. + template + class SubclassStructIterator + { + public: + SubclassStructIterator (const NCollection_IndexedMap& theStructs) : myIter (theStructs) {} + Standard_Boolean More() const { return myIter.More(); } + void Next() { myIter.Next(); } + const Struct_t* Value() const { return (const Struct_t* )(myIter.Value()); } + Struct_t* ChangeValue() { return (Struct_t* )(myIter.Value()); } + private: + NCollection_IndexedMap::Iterator myIter; + }; + + //! Auxiliary wrapper to iterate through group sequence. + template + class SubclassGroupIterator + { + public: + SubclassGroupIterator (const Graphic3d_SequenceOfGroup& theGroups) : myIter (theGroups) {} + Standard_Boolean More() const { return myIter.More(); } + void Next() { myIter.Next(); } + const Group_t* Value() const { return (const Group_t* )(myIter.Value().get()); } + Group_t* ChangeValue() { return (Group_t* )(myIter.ChangeValue().get()); } + private: + Graphic3d_SequenceOfGroup::Iterator myIter; + }; public: @@ -103,6 +133,28 @@ public: //! highlight flag is set to true const Handle(Graphic3d_PresentationAttributes)& HighlightStyle() const { return myHighlightStyle; } +public: + + //! Returns FALSE if the structure hits the current view volume, otherwise returns TRUE. + Standard_Boolean IsCulled() const { return myIsCulled; } + + //! Marks structure as culled/not culled - note that IsAlwaysRendered() is ignored here! + void SetCulled (Standard_Boolean theIsCulled) const { myIsCulled = theIsCulled; } + + //! Marks structure as overlapping the current view volume one. + //! The method is called during traverse of BVH tree. + void MarkAsNotCulled() const { myIsCulled = Standard_False; } + + //! Checks if the structure should be included into BVH tree or not. + Standard_Boolean IsAlwaysRendered() const + { + return IsInfinite + || IsForHighlight + || IsMutable + || Is2dText + || (!myTrsfPers.IsNull() && myTrsfPers->IsTrihedronOr2d()); + } + public: //! Update structure visibility state @@ -133,6 +185,9 @@ public: //! Remove group from this structure virtual void RemoveGroup (const Handle(Graphic3d_Group)& theGroup) = 0; + //! Update render transformation matrix. + virtual void updateLayerTransformation() {} + public: int Id; @@ -168,6 +223,8 @@ protected: Handle(Graphic3d_SequenceOfHClipPlane) myClipPlanes; Handle(Graphic3d_PresentationAttributes) myHighlightStyle; //! Current highlight style; is set only if highlight flag is true + mutable Standard_Boolean myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse + public: DEFINE_STANDARD_RTTIEXT(Graphic3d_CStructure,Standard_Transient) // Type definition diff --git a/src/Graphic3d/Graphic3d_CView.cxx b/src/Graphic3d/Graphic3d_CView.cxx index e88505feb4..d5dac3a0e0 100644 --- a/src/Graphic3d/Graphic3d_CView.cxx +++ b/src/Graphic3d/Graphic3d_CView.cxx @@ -33,7 +33,9 @@ namespace //purpose : //======================================================================= Graphic3d_CView::Graphic3d_CView (const Handle(Graphic3d_StructureManager)& theMgr) -: myStructureManager (theMgr), +: myBgColor (Quantity_NOC_BLACK), + myStructureManager (theMgr), + myCamera (new Graphic3d_Camera()), myHiddenObjects (new Graphic3d_NMapOfTransient()), myIsInComputedMode (Standard_False), myIsActive (Standard_False), diff --git a/src/Graphic3d/Graphic3d_CView.hxx b/src/Graphic3d/Graphic3d_CView.hxx index 761e791c80..e409c5e5bf 100644 --- a/src/Graphic3d/Graphic3d_CView.hxx +++ b/src/Graphic3d/Graphic3d_CView.hxx @@ -87,6 +87,12 @@ public: //! Returns true if the view was removed. Standard_Boolean IsRemoved() const { return myIsRemoved; } + //! Returns camera object of the view. + virtual const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } + + //! Sets camera used by the view. + virtual void SetCamera (const Handle(Graphic3d_Camera)& theCamera) { myCamera = theCamera; } + public: //! Returns default Shading Model of the view; Graphic3d_TOSM_FRAGMENT by default. @@ -252,20 +258,6 @@ public: //! Returns True if the window associated to the view is defined. virtual Standard_Boolean IsDefined() const = 0; - //! Returns data of a graduated trihedron - virtual const Graphic3d_GraduatedTrihedron& GetGraduatedTrihedron() = 0; - - //! Displays Graduated Trihedron. - virtual void GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData) = 0; - - //! Erases Graduated Trihedron. - virtual void GraduatedTrihedronErase() = 0; - - //! Sets minimum and maximum points of scene bounding box for Graduated Trihedron stored in graphic view object. - //! @param theMin [in] the minimum point of scene. - //! @param theMax [in] the maximum point of scene. - virtual void GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax) = 0; - //! Dump active rendering buffer into specified memory buffer. virtual Standard_Boolean BufferDump (Image_PixMap& theImage, const Graphic3d_BufferType& theBufferType) = 0; @@ -352,10 +344,10 @@ public: Graphic3d_RenderingParams& ChangeRenderingParams() { return myRenderParams; } //! Returns background fill color. - virtual Aspect_Background Background() const = 0; + virtual Aspect_Background Background() const { return Aspect_Background (myBgColor.GetRGB()); } //! Sets background fill color. - virtual void SetBackground (const Aspect_Background& theBackground) = 0; + virtual void SetBackground (const Aspect_Background& theBackground) { myBgColor.SetRGB (theBackground.Color()); } //! Returns gradient background fill colors. virtual Aspect_GradientBackground GradientBackground() const = 0; @@ -387,12 +379,6 @@ public: //! Sets backfacing model for the view. virtual void SetBackfacingModel (const Graphic3d_TypeOfBackfacingModel theModel) = 0; - //! Returns camera object of the view. - virtual const Handle(Graphic3d_Camera)& Camera() const = 0; - - //! Sets camera used by the view. - virtual void SetCamera (const Handle(Graphic3d_Camera)& theCamera) = 0; - //! Returns list of lights of the view. virtual const Handle(Graphic3d_LightSet)& Lights() const = 0; @@ -421,6 +407,26 @@ public: //! Fills in the dictionary with statistic performance info. virtual void StatisticInformation (TColStd_IndexedDataMapOfStringString& theDict) const = 0; +public: //! @name obsolete Graduated Trihedron functionality + + //! Returns data of a graduated trihedron + virtual const Graphic3d_GraduatedTrihedron& GetGraduatedTrihedron() { return myGTrihedronData; } + + //! Displays Graduated Trihedron. + virtual void GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData) { (void )theTrihedronData; } + + //! Erases Graduated Trihedron. + virtual void GraduatedTrihedronErase() {} + + //! Sets minimum and maximum points of scene bounding box for Graduated Trihedron stored in graphic view object. + //! @param theMin [in] the minimum point of scene. + //! @param theMax [in] the maximum point of scene. + virtual void GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax) + { + (void )theMin; + (void )theMax; + } + private: //! Adds the structure to display lists of the view. @@ -448,7 +454,9 @@ protected: Standard_Integer myId; Graphic3d_RenderingParams myRenderParams; + Quantity_ColorRGBA myBgColor; Handle(Graphic3d_StructureManager) myStructureManager; + Handle(Graphic3d_Camera) myCamera; Graphic3d_SequenceOfStructure myStructsToCompute; Graphic3d_SequenceOfStructure myStructsComputed; Graphic3d_MapOfStructure myStructsDisplayed; @@ -459,6 +467,10 @@ protected: Graphic3d_TypeOfShadingModel myShadingModel; Graphic3d_TypeOfVisualization myVisualization; +protected: + + Graphic3d_GraduatedTrihedron myGTrihedronData; + }; #endif // _Graphic3d_CView_HeaderFile diff --git a/src/Graphic3d/Graphic3d_CullingTool.cxx b/src/Graphic3d/Graphic3d_CullingTool.cxx new file mode 100644 index 0000000000..c2a11be66a --- /dev/null +++ b/src/Graphic3d/Graphic3d_CullingTool.cxx @@ -0,0 +1,198 @@ +// Created on: 2013-12-25 +// Created by: Varvara POSKONINA +// Copyright (c) 1999-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include + +#include + +// ======================================================================= +// function : Graphic3d_CullingTool +// purpose : +// ======================================================================= +Graphic3d_CullingTool::Graphic3d_CullingTool() +: myClipVerts (0, Graphic3d_Camera::FrustumVerticesNB), + myIsProjectionParallel (Standard_True), + myCamScale (1.0), + myPixelSize (1.0) +{ + // +} + +// ======================================================================= +// function : SetViewVolume +// purpose : Retrieves view volume's planes equations and its vertices from projection and world-view matrices. +// ======================================================================= +void Graphic3d_CullingTool::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera) +{ + if (!myWorldViewProjState.IsChanged (theCamera->WorldViewProjState())) + return; + + myIsProjectionParallel = theCamera->IsOrthographic(); + const gp_Dir aCamDir = theCamera->Direction(); + + myCamera = theCamera; + myProjectionMat = theCamera->ProjectionMatrix(); + myWorldViewMat = theCamera->OrientationMatrix(); + myWorldViewProjState = theCamera->WorldViewProjState(); + myCamEye.SetValues (theCamera->Eye().X(), theCamera->Eye().Y(), theCamera->Eye().Z()); + myCamDir.SetValues (aCamDir.X(), aCamDir.Y(), aCamDir.Z()); + myCamScale = theCamera->IsOrthographic() + ? theCamera->Scale() + : 2.0 * Tan (theCamera->FOVy() * M_PI / 360.0); // same as theCamera->Scale()/theCamera->Distance() + + // Compute frustum points + theCamera->FrustumPoints (myClipVerts); + + // Compute frustum planes + // Vertices go in order: + // 0, 2, 1 + const Standard_Integer aLookup1[] = { 0, 1, 0 }; + const Standard_Integer aLookup2[] = { 0, 0, 1 }; + Standard_Integer aShifts[] = { 0, 0, 0 }; + + // Planes go in order: + // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR + for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx) + { + for (Standard_Integer i = 0; i < 2; ++i) + { + Graphic3d_Vec3d aPlanePnts[3]; + for (Standard_Integer aPntIter = 0; aPntIter < 3; ++aPntIter) + { + aShifts[aFaceIdx] = i; + aShifts[(aFaceIdx + 1) % 3] = aLookup1[aPntIter]; + aShifts[(aFaceIdx + 2) % 3] = aLookup2[aPntIter]; + + aPlanePnts[aPntIter] = myClipVerts[aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2]]; + } + + myClipPlanes[aFaceIdx * 2 + i].Origin = aPlanePnts[0]; + myClipPlanes[aFaceIdx * 2 + i].Normal = + Graphic3d_Vec3d::Cross (aPlanePnts[1] - aPlanePnts[0], + aPlanePnts[2] - aPlanePnts[0]).Normalized() * (i == 0 ? -1.f : 1.f); + } + } +} + +// ======================================================================= +// function : SetViewportSize +// purpose : +// ======================================================================= +void Graphic3d_CullingTool::SetViewportSize (Standard_Integer theViewportWidth, + Standard_Integer theViewportHeight, + Standard_Real theResolutionRatio) +{ + myViewportHeight = theViewportHeight > 0 ? theViewportHeight : 1; + myViewportWidth = theViewportWidth > 0 ? theViewportWidth : 1; + myPixelSize = Max (theResolutionRatio / myViewportHeight, + theResolutionRatio / myViewportWidth); +} + +// ======================================================================= +// function : SignedPlanePointDistance +// purpose : +// ======================================================================= +Standard_Real Graphic3d_CullingTool::SignedPlanePointDistance (const Graphic3d_Vec4d& theNormal, + const Graphic3d_Vec4d& thePnt) +{ + const Standard_Real aNormLength = std::sqrt (theNormal.x() * theNormal.x() + + theNormal.y() * theNormal.y() + + theNormal.z() * theNormal.z()); + + if (aNormLength < gp::Resolution()) + return 0.0; + + const Standard_Real anInvNormLength = 1.0 / aNormLength; + const Standard_Real aD = theNormal.w() * anInvNormLength; + const Standard_Real anA = theNormal.x() * anInvNormLength; + const Standard_Real aB = theNormal.y() * anInvNormLength; + const Standard_Real aC = theNormal.z() * anInvNormLength; + return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z()); +} + +// ======================================================================= +// function : SetCullingDistance +// purpose : +// ======================================================================= +void Graphic3d_CullingTool::SetCullingDistance (CullingContext& theCtx, + Standard_Real theDistance) const +{ + theCtx.DistCull = -1.0; + if (!myIsProjectionParallel) + { + theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance) + ? theDistance + : -1.0; + } +} + +// ======================================================================= +// function : SetCullingSize +// purpose : +// ======================================================================= +void Graphic3d_CullingTool::SetCullingSize (CullingContext& theCtx, + Standard_Real theSize) const +{ + theCtx.SizeCull2 = -1.0; + if (theSize > 0.0 && !Precision::IsInfinite (theSize)) + { + theCtx.SizeCull2 = myPixelSize * theSize; + theCtx.SizeCull2 *= myCamScale; + theCtx.SizeCull2 *= theCtx.SizeCull2; + } +} + +// ======================================================================= +// function : CacheClipPtsProjections +// purpose : +// ======================================================================= +void Graphic3d_CullingTool::CacheClipPtsProjections() +{ + // project frustum onto its own normals + const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1; + for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor) + { + Standard_Real aMaxProj = -std::numeric_limits::max(); + Standard_Real aMinProj = std::numeric_limits::max(); + for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter) + { + Standard_Real aProjection = myClipVerts[aCornerIter].Dot (myClipPlanes[aPlaneIter].Normal); + aMaxProj = Max (aProjection, aMaxProj); + aMinProj = Min (aProjection, aMinProj); + } + myMaxClipProjectionPts[aPlaneIter] = aMaxProj; + myMinClipProjectionPts[aPlaneIter] = aMinProj; + } + + // project frustum onto main axes + Graphic3d_Vec3d anAxes[] = { Graphic3d_Vec3d (1.0, 0.0, 0.0), + Graphic3d_Vec3d (0.0, 1.0, 0.0), + Graphic3d_Vec3d (0.0, 0.0, 1.0) }; + for (Standard_Integer aDim = 0; aDim < 3; ++aDim) + { + Standard_Real aMaxProj = -std::numeric_limits::max(); + Standard_Real aMinProj = std::numeric_limits::max(); + for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter) + { + Standard_Real aProjection = myClipVerts[aCornerIter].Dot (anAxes[aDim]); + aMaxProj = Max (aProjection, aMaxProj); + aMinProj = Min (aProjection, aMinProj); + } + myMaxOrthoProjectionPts[aDim] = aMaxProj; + myMinOrthoProjectionPts[aDim] = aMinProj; + } +} diff --git a/src/Graphic3d/Graphic3d_CullingTool.hxx b/src/Graphic3d/Graphic3d_CullingTool.hxx new file mode 100644 index 0000000000..f76a72b9a6 --- /dev/null +++ b/src/Graphic3d/Graphic3d_CullingTool.hxx @@ -0,0 +1,287 @@ +// Created on: 2013-12-25 +// Created by: Varvara POSKONINA +// Copyright (c) 1999-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_CullingTool_HeaderFile +#define _Graphic3d_CullingTool_HeaderFile + +#include +#include +#include + +//! Graphic3d_CullingTool class provides a possibility to store parameters of view volume, +//! such as its vertices and equations, and contains methods detecting if given AABB overlaps view volume. +class Graphic3d_CullingTool +{ +public: + //! Auxiliary structure holding non-persistent culling options. + struct CullingContext + { + Standard_Real DistCull; //!< culling distance + Standard_Real SizeCull2; //!< squared culling size + + //! Empty constructor. + CullingContext() : DistCull (-1.0), SizeCull2 (-1.0) {} + }; + + //! Auxiliary structure representing 3D plane. + struct Plane + { + //! Creates default plane. + Plane() + : Origin (0.0, 0.0, 0.0), + Normal (0.0, 0.0, 1.0) {} + + //! Creates plane with specific parameters. + Plane (const Graphic3d_Vec3d& theOrigin, + const Graphic3d_Vec3d& theNormal) + : Origin (theOrigin), + Normal (theNormal) {} + + Graphic3d_Vec3d Origin; + Graphic3d_Vec3d Normal; + }; + +public: + + //! Creates an empty selector object with parallel projection type by default. + Standard_EXPORT Graphic3d_CullingTool(); + + //! Retrieves view volume's planes equations and its vertices from projection and world-view matrices. + Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera); + + Standard_EXPORT void SetViewportSize (Standard_Integer theViewportWidth, + Standard_Integer theViewportHeight, + Standard_Real theResolutionRatio); + + //! Setup distance culling. + Standard_EXPORT void SetCullingDistance (CullingContext& theCtx, + Standard_Real theDistance) const; + + //! Setup size culling. + Standard_EXPORT void SetCullingSize (CullingContext& theCtx, + Standard_Real theSize) const; + + //! Caches view volume's vertices projections along its normals and AABBs dimensions. + //! Must be called at the beginning of each BVH tree traverse loop. + Standard_EXPORT void CacheClipPtsProjections(); + + //! Checks whether given AABB should be entirely culled or not. + //! @param theCtx [in] culling properties + //! @param theMinPt [in] maximum point of AABB + //! @param theMaxPt [in] minimum point of AABB + //! @return Standard_True, if AABB is in viewing area, Standard_False otherwise + bool IsCulled (const CullingContext& theCtx, + const Graphic3d_Vec3d& theMinPt, + const Graphic3d_Vec3d& theMaxPt) const + { + return isFullOut (theMinPt, theMaxPt) + || isTooDistant(theCtx, theMinPt, theMaxPt) + || isTooSmall (theCtx, theMinPt, theMaxPt); + } + + //! Return the camera definition. + const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } + + //! Returns current projection matrix. + const Graphic3d_Mat4d& ProjectionMatrix() const + { + return myProjectionMat; + } + + //! Returns current world view transformation matrix. + const Graphic3d_Mat4d& WorldViewMatrix() const + { + return myWorldViewMat; + } + + Standard_Integer ViewportWidth() const + { + return myViewportWidth; + } + + Standard_Integer ViewportHeight() const + { + return myViewportHeight; + } + + //! Returns state of current world view projection transformation matrices. + const Graphic3d_WorldViewProjState& WorldViewProjState() const + { + return myWorldViewProjState; + } + +protected: + + //! Calculates signed distance from plane to point. + //! @param theNormal [in] the plane's normal. + //! @param thePnt [in] + Standard_EXPORT Standard_Real SignedPlanePointDistance (const Graphic3d_Vec4d& theNormal, + const Graphic3d_Vec4d& thePnt); + + //! Detects if AABB overlaps view volume using separating axis theorem (SAT). + //! @param theMinPt [in] maximum point of AABB. + //! @param theMaxPt [in] minimum point of AABB. + //! @return FALSE, if AABB is in viewing area, TRUE otherwise. + bool isFullOut (const Graphic3d_Vec3d& theMinPt, + const Graphic3d_Vec3d& theMaxPt) const + { + // E1 + // |_ E0 + // / + // E2 + + // E0 test (x axis) + if (theMinPt.x() > myMaxOrthoProjectionPts[0] + || theMaxPt.x() < myMinOrthoProjectionPts[0]) + { + return true; + } + + // E1 test (y axis) + if (theMinPt.y() > myMaxOrthoProjectionPts[1] + || theMaxPt.y() < myMinOrthoProjectionPts[1]) + { + return true; + } + + // E2 test (z axis) + if (theMinPt.z() > myMaxOrthoProjectionPts[2] + || theMaxPt.z() < myMinOrthoProjectionPts[2]) + { + return true; + } + + const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1; + for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor) + { + // frustum normals + const Graphic3d_Vec3d anAxis = myClipPlanes[aPlaneIter].Normal; + + const Graphic3d_Vec3d aPVertex (anAxis.x() > 0.0 ? theMaxPt.x() : theMinPt.x(), + anAxis.y() > 0.0 ? theMaxPt.y() : theMinPt.y(), + anAxis.z() > 0.0 ? theMaxPt.z() : theMinPt.z()); + Standard_Real aPnt0 = aPVertex.Dot (anAxis); + + if (aPnt0 >= myMinClipProjectionPts[aPlaneIter] + && aPnt0 <= myMaxClipProjectionPts[aPlaneIter]) + { + continue; + } + + const Graphic3d_Vec3d aNVertex (anAxis.x() > 0.0 ? theMinPt.x() : theMaxPt.x(), + anAxis.y() > 0.0 ? theMinPt.y() : theMaxPt.y(), + anAxis.z() > 0.0 ? theMinPt.z() : theMaxPt.z()); + Standard_Real aPnt1 = aNVertex.Dot (anAxis); + + const Standard_Real aMin = aPnt0 < aPnt1 ? aPnt0 : aPnt1; + const Standard_Real aMax = aPnt0 > aPnt1 ? aPnt0 : aPnt1; + + if (aMin > myMaxClipProjectionPts[aPlaneIter] + || aMax < myMinClipProjectionPts[aPlaneIter]) + { + return true; + } + } + return false; + } + + //! Returns TRUE if given AABB should be discarded by distance culling criterion. + bool isTooDistant (const CullingContext& theCtx, + const Graphic3d_Vec3d& theMinPt, + const Graphic3d_Vec3d& theMaxPt) const + { + if (theCtx.DistCull <= 0.0) + { + return false; + } + + // check distance to the bounding sphere as fast approximation + const Graphic3d_Vec3d aSphereCenter = (theMinPt + theMaxPt) * 0.5; + const Standard_Real aSphereRadius = (theMaxPt - theMinPt).maxComp() * 0.5; + return (aSphereCenter - myCamEye).Modulus() - aSphereRadius > theCtx.DistCull; + } + + //! Returns TRUE if given AABB should be discarded by size culling criterion. + bool isTooSmall (const CullingContext& theCtx, + const Graphic3d_Vec3d& theMinPt, + const Graphic3d_Vec3d& theMaxPt) const + { + if (theCtx.SizeCull2 <= 0.0) + { + return false; + } + + const Standard_Real aBoxDiag2 = (theMaxPt - theMinPt).SquareModulus(); + if (myIsProjectionParallel) + { + return aBoxDiag2 < theCtx.SizeCull2; + } + + // note that distances behind the Eye (aBndDist < 0) are not scaled correctly here, + // but majority of such objects should be culled by frustum + const Graphic3d_Vec3d aBndCenter = (theMinPt + theMaxPt) * 0.5; + const Standard_Real aBndDist = (aBndCenter - myCamEye).Dot (myCamDir); + return aBoxDiag2 < theCtx.SizeCull2 * aBndDist * aBndDist; + } + +protected: + + //! Enumerates planes of view volume. + enum + { + Plane_Left, + Plane_Right, + Plane_Bottom, + Plane_Top, + Plane_Near, + Plane_Far, + PlanesNB + }; + +protected: + + Plane myClipPlanes[PlanesNB]; //!< Planes + NCollection_Array1 myClipVerts; //!< Vertices + + Handle(Graphic3d_Camera) myCamera; //!< camera definition + + // for caching clip points projections onto viewing area normals once per traverse + // ORDER: LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR + Standard_Real myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals + Standard_Real myMinClipProjectionPts[PlanesNB]; //!< Min view volume's vertices projections onto its normals + + // for caching clip points projections onto AABB normals once per traverse + // ORDER: E0, E1, E2 + Standard_Real myMaxOrthoProjectionPts[3]; //!< Max view volume's vertices projections onto normalized dimensions of AABB + Standard_Real myMinOrthoProjectionPts[3]; //!< Min view volume's vertices projections onto normalized dimensions of AABB + + Standard_Boolean myIsProjectionParallel; + + Graphic3d_Mat4d myProjectionMat; + Graphic3d_Mat4d myWorldViewMat; + + Standard_Integer myViewportWidth; + Standard_Integer myViewportHeight; + + Graphic3d_WorldViewProjState myWorldViewProjState; //!< State of world view projection matrices. + + Graphic3d_Vec3d myCamEye; //!< camera eye position for distance culling + Graphic3d_Vec3d myCamDir; //!< camera direction for size culling + Standard_Real myCamScale; //!< camera scale for size culling + Standard_Real myPixelSize; //!< pixel size for size culling + +}; + +#endif // _Graphic3d_CullingTool_HeaderFile diff --git a/src/Graphic3d/Graphic3d_GraphicDriver.cxx b/src/Graphic3d/Graphic3d_GraphicDriver.cxx index 773f49dcff..84213193a9 100644 --- a/src/Graphic3d/Graphic3d_GraphicDriver.cxx +++ b/src/Graphic3d/Graphic3d_GraphicDriver.cxx @@ -25,7 +25,71 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_GraphicDriver,Standard_Transient) Graphic3d_GraphicDriver::Graphic3d_GraphicDriver (const Handle(Aspect_DisplayConnection)& theDisp) : myDisplayConnection (theDisp) { - // + // default layers are always presented in display layer sequence it can not be removed + { + Graphic3d_ZLayerSettings aSettings; + aSettings.SetImmediate (Standard_False); + aSettings.SetEnvironmentTexture (Standard_False); + aSettings.SetEnableDepthTest (Standard_False); + aSettings.SetEnableDepthWrite (Standard_False); + aSettings.SetClearDepth (Standard_False); + aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); + myLayerIds.Add (Graphic3d_ZLayerId_BotOSD); + myLayerSeq.Append (Graphic3d_ZLayerId_BotOSD); + myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_BotOSD, aSettings); + } + + { + Graphic3d_ZLayerSettings aSettings; + aSettings.SetImmediate (Standard_False); + aSettings.SetEnvironmentTexture (Standard_True); + aSettings.SetEnableDepthTest (Standard_True); + aSettings.SetEnableDepthWrite (Standard_True); + aSettings.SetClearDepth (Standard_False); + aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); + myLayerIds.Add (Graphic3d_ZLayerId_Default); + myLayerSeq.Append (Graphic3d_ZLayerId_Default); + myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_Default, aSettings); + } + + { + Graphic3d_ZLayerSettings aSettings; + aSettings.SetImmediate (Standard_True); + aSettings.SetEnvironmentTexture (Standard_True); + aSettings.SetEnableDepthTest (Standard_True); + aSettings.SetEnableDepthWrite (Standard_True); + aSettings.SetClearDepth (Standard_False); + aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); + myLayerIds.Add (Graphic3d_ZLayerId_Top); + myLayerSeq.Append (Graphic3d_ZLayerId_Top); + myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_Top, aSettings); + } + + { + Graphic3d_ZLayerSettings aSettings; + aSettings.SetImmediate (Standard_True); + aSettings.SetEnvironmentTexture (Standard_True); + aSettings.SetEnableDepthTest (Standard_True); + aSettings.SetEnableDepthWrite (Standard_True); + aSettings.SetClearDepth (Standard_True); + aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); + myLayerIds.Add (Graphic3d_ZLayerId_Topmost); + myLayerSeq.Append (Graphic3d_ZLayerId_Topmost); + myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_Topmost, aSettings); + } + + { + Graphic3d_ZLayerSettings aSettings; + aSettings.SetImmediate (Standard_True); + aSettings.SetEnvironmentTexture (Standard_False); + aSettings.SetEnableDepthTest (Standard_False); + aSettings.SetEnableDepthWrite (Standard_False); + aSettings.SetClearDepth (Standard_False); + aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); + myLayerIds.Add (Graphic3d_ZLayerId_TopOSD); + myLayerSeq.Append (Graphic3d_ZLayerId_TopOSD); + myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_TopOSD, aSettings); + } } // ======================================================================= @@ -53,4 +117,83 @@ Standard_Integer Graphic3d_GraphicDriver::NewIdentification() void Graphic3d_GraphicDriver::RemoveIdentification(const Standard_Integer theId) { myStructGenId.Free(theId); -} \ No newline at end of file +} + +//======================================================================= +//function : ZLayerSettings +//purpose : +//======================================================================= +const Graphic3d_ZLayerSettings& Graphic3d_GraphicDriver::ZLayerSettings (const Graphic3d_ZLayerId theLayerId) const +{ + Standard_ASSERT_RAISE (myLayerIds.Contains (theLayerId), "Graphic3d_GraphicDriver::ZLayerSettings, Layer with theLayerId does not exist"); + return myMapOfZLayerSettings.Find (theLayerId); +} + +//======================================================================= +//function : addZLayerIndex +//purpose : +//======================================================================= +void Graphic3d_GraphicDriver::addZLayerIndex (const Graphic3d_ZLayerId theLayerId) +{ + // remove index + for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next()) + { + if (aLayerIt.Value() == theLayerId) + { + myLayerSeq.Remove (aLayerIt); + break; + } + } + + if (myMapOfZLayerSettings.Find (theLayerId).IsImmediate()) + { + myLayerSeq.Append (theLayerId); + return; + } + + for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next()) + { + const Graphic3d_ZLayerSettings& aSettings = myMapOfZLayerSettings.Find (aLayerIt.Value()); + if (aSettings.IsImmediate()) + { + aLayerIt.Previous(); + if (aLayerIt.More()) + { + myLayerSeq.InsertAfter (aLayerIt, theLayerId); + return; + } + + // first non-immediate layer + myLayerSeq.Prepend (theLayerId); + return; + } + } + + // no immediate layers + myLayerSeq.Append (theLayerId); +} + +//======================================================================= +//function : SetZLayerSettings +//purpose : +//======================================================================= +void Graphic3d_GraphicDriver::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, + const Graphic3d_ZLayerSettings& theSettings) +{ + Graphic3d_ZLayerSettings* aSettings = myMapOfZLayerSettings.ChangeSeek (theLayerId); + if (aSettings != NULL) + { + const bool isChanged = (aSettings->IsImmediate() != theSettings.IsImmediate()); + *aSettings = theSettings; + if (isChanged) + { + addZLayerIndex (theLayerId); + } + } + else + { + // abnormal case + myMapOfZLayerSettings.Bind (theLayerId, theSettings); + addZLayerIndex (theLayerId); + } +} diff --git a/src/Graphic3d/Graphic3d_GraphicDriver.hxx b/src/Graphic3d/Graphic3d_GraphicDriver.hxx index 5880b000ed..dd4fd3e040 100644 --- a/src/Graphic3d/Graphic3d_GraphicDriver.hxx +++ b/src/Graphic3d/Graphic3d_GraphicDriver.hxx @@ -42,9 +42,11 @@ #include #include #include +#include #include #include #include +#include #include class Aspect_DisplayConnection; @@ -122,13 +124,16 @@ public: virtual void RemoveZLayer (const Graphic3d_ZLayerId theLayerId) = 0; //! Returns list of Z layers defined for the graphical driver. - virtual void ZLayers (TColStd_SequenceOfInteger& theLayerSeq) const = 0; + virtual void ZLayers (TColStd_SequenceOfInteger& theLayerSeq) const + { + theLayerSeq.Assign (myLayerSeq); + } //! Sets the settings for a single Z layer. - virtual void SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, const Graphic3d_ZLayerSettings& theSettings) = 0; + Standard_EXPORT virtual void SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, const Graphic3d_ZLayerSettings& theSettings) = 0; //! Returns the settings of a single Z layer. - virtual const Graphic3d_ZLayerSettings& ZLayerSettings (const Graphic3d_ZLayerId theLayerId) const = 0; + Standard_EXPORT virtual const Graphic3d_ZLayerSettings& ZLayerSettings (const Graphic3d_ZLayerId theLayerId) const; //! Returns view associated with the window if it is exists and is activated. //! Returns Standard_True if the view associated to the window exists. @@ -150,10 +155,16 @@ protected: //! Initializes the Driver Standard_EXPORT Graphic3d_GraphicDriver(const Handle(Aspect_DisplayConnection)& theDisp); + //! Insert index layer at proper position. + Standard_EXPORT void addZLayerIndex (const Graphic3d_ZLayerId theLayerId); + protected: Handle(Aspect_DisplayConnection) myDisplayConnection; Aspect_GenId myStructGenId; + TColStd_MapOfInteger myLayerIds; + TColStd_SequenceOfInteger myLayerSeq; + Graphic3d_MapOfZLayerSettings myMapOfZLayerSettings; }; diff --git a/src/Graphic3d/Graphic3d_Layer.cxx b/src/Graphic3d/Graphic3d_Layer.cxx new file mode 100644 index 0000000000..fad60a392a --- /dev/null +++ b/src/Graphic3d/Graphic3d_Layer.cxx @@ -0,0 +1,626 @@ +// Copyright (c) 2011-2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Layer, Standard_Transient) + +// ======================================================================= +// function : Graphic3d_Layer +// purpose : +// ======================================================================= +Graphic3d_Layer::Graphic3d_Layer (Standard_Integer theNbPriorities, + const Handle(Select3D_BVHBuilder3d)& theBuilder) +: myArray (0, theNbPriorities - 1), + myNbStructures (0), + myNbStructuresNotCulled (0), + myBVHPrimitivesTrsfPers (theBuilder), + myBVHIsLeftChildQueuedFirst (Standard_True), + myIsBVHPrimitivesNeedsReset (Standard_False) +{ + myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true; +} + +// ======================================================================= +// function : ~Graphic3d_Layer +// purpose : +// ======================================================================= +Graphic3d_Layer::~Graphic3d_Layer() +{ + // +} + +// ======================================================================= +// function : Add +// purpose : +// ======================================================================= +void Graphic3d_Layer::Add (const Graphic3d_CStructure* theStruct, + Standard_Integer thePriority, + Standard_Boolean isForChangePriority) +{ + const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1); + if (theStruct == NULL) + { + return; + } + + myArray (anIndex).Add (theStruct); + if (theStruct->IsAlwaysRendered()) + { + theStruct->MarkAsNotCulled(); + if (!isForChangePriority) + { + myAlwaysRenderedMap.Add (theStruct); + } + } + else if (!isForChangePriority) + { + if (theStruct->TransformPersistence().IsNull()) + { + myBVHPrimitives.Add (theStruct); + } + else + { + myBVHPrimitivesTrsfPers.Add (theStruct); + } + } + ++myNbStructures; +} + +// ======================================================================= +// function : Remove +// purpose : +// ======================================================================= +bool Graphic3d_Layer::Remove (const Graphic3d_CStructure* theStruct, + Standard_Integer& thePriority, + Standard_Boolean isForChangePriority) +{ + if (theStruct == NULL) + { + thePriority = -1; + return false; + } + + const Standard_Integer aNbPriorities = myArray.Length(); + for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) + { + Graphic3d_IndexedMapOfStructure& aStructures = myArray (aPriorityIter); + const Standard_Integer anIndex = aStructures.FindIndex (theStruct); + if (anIndex == 0) + { + continue; + } + + aStructures.Swap (anIndex, aStructures.Size()); + aStructures.RemoveLast(); + + if (!isForChangePriority) + { + Standard_Boolean isAlwaysRend = theStruct->IsAlwaysRendered(); + if (!isAlwaysRend) + { + if (!myBVHPrimitives.Remove (theStruct)) + { + if (!myBVHPrimitivesTrsfPers.Remove (theStruct)) + { + isAlwaysRend = Standard_True; + } + } + } + if (isAlwaysRend) + { + const Standard_Integer anIndex2 = myAlwaysRenderedMap.FindIndex (theStruct); + if (anIndex2 != 0) + { + myAlwaysRenderedMap.Swap (myAlwaysRenderedMap.Size(), anIndex2); + myAlwaysRenderedMap.RemoveLast(); + } + } + } + --myNbStructures; + thePriority = aPriorityIter; + return true; + } + + thePriority = -1; + return false; +} + +// ======================================================================= +// function : InvalidateBVHData +// purpose : +// ======================================================================= +void Graphic3d_Layer::InvalidateBVHData() +{ + myIsBVHPrimitivesNeedsReset = Standard_True; +} + +//! Calculate a finite bounding box of infinite object as its middle point. +inline Graphic3d_BndBox3d centerOfinfiniteBndBox (const Graphic3d_BndBox3d& theBndBox) +{ + // bounding borders of infinite line has been calculated as own point in center of this line + const Graphic3d_Vec3d aDiagVec = theBndBox.CornerMax() - theBndBox.CornerMin(); + return aDiagVec.SquareModulus() >= 500000.0 * 500000.0 + ? Graphic3d_BndBox3d ((theBndBox.CornerMin() + theBndBox.CornerMax()) * 0.5) + : Graphic3d_BndBox3d(); +} + +//! Return true if at least one vertex coordinate out of float range. +inline bool isInfiniteBndBox (const Graphic3d_BndBox3d& theBndBox) +{ + return Abs (theBndBox.CornerMax().x()) >= ShortRealLast() + || Abs (theBndBox.CornerMax().y()) >= ShortRealLast() + || Abs (theBndBox.CornerMax().z()) >= ShortRealLast() + || Abs (theBndBox.CornerMin().x()) >= ShortRealLast() + || Abs (theBndBox.CornerMin().y()) >= ShortRealLast() + || Abs (theBndBox.CornerMin().z()) >= ShortRealLast(); +} + +// ======================================================================= +// function : BoundingBox +// purpose : +// ======================================================================= +Bnd_Box Graphic3d_Layer::BoundingBox (Standard_Integer theViewId, + const Handle(Graphic3d_Camera)& theCamera, + Standard_Integer theWindowWidth, + Standard_Integer theWindowHeight, + Standard_Boolean theToIncludeAuxiliary) const +{ + updateBVH(); + + const Standard_Integer aBoxId = !theToIncludeAuxiliary ? 0 : 1; + const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix(); + if (myIsBoundingBoxNeedsReset[aBoxId]) + { + // Recompute layer bounding box + myBoundingBox[aBoxId].SetVoid(); + + for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) + { + const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value(); + for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) + { + const Graphic3d_CStructure* aStructure = aStructIter.Value(); + if (!aStructure->IsVisible (theViewId)) + { + continue; + } + + // "FitAll" operation ignores object with transform persistence parameter + // but adds transform persistence point in a bounding box of layer (only zoom pers. objects). + if (!aStructure->TransformPersistence().IsNull()) + { + if (!theToIncludeAuxiliary + && aStructure->TransformPersistence()->IsZoomOrRotate()) + { + const gp_Pnt anAnchor = aStructure->TransformPersistence()->AnchorPoint(); + myBoundingBox[aBoxId].Add (anAnchor); + continue; + } + // Panning and 2d persistence apply changes to projection or/and its translation components. + // It makes them incompatible with z-fitting algorithm. Ignored by now. + else if (!theToIncludeAuxiliary + || aStructure->TransformPersistence()->IsTrihedronOr2d()) + { + continue; + } + } + + Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); + if (!aBox.IsValid()) + { + continue; + } + + if (aStructure->IsInfinite + && !theToIncludeAuxiliary) + { + // include center of infinite object + aBox = centerOfinfiniteBndBox (aBox); + } + + if (!aStructure->TransformPersistence().IsNull()) + { + aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); + } + + // skip too big boxes to prevent float overflow at camera parameters calculation + if (aBox.IsValid() + && !isInfiniteBndBox (aBox)) + { + myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z())); + myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z())); + } + } + } + + myIsBoundingBoxNeedsReset[aBoxId] = false; + } + + Bnd_Box aResBox = myBoundingBox[aBoxId]; + if (!theToIncludeAuxiliary + || myAlwaysRenderedMap.IsEmpty()) + { + return aResBox; + } + + // add transformation-persistent objects which depend on camera position (and thus can not be cached) for operations like Z-fit + for (NCollection_IndexedMap::Iterator aStructIter (myAlwaysRenderedMap); aStructIter.More(); aStructIter.Next()) + { + const Graphic3d_CStructure* aStructure = aStructIter.Value(); + if (!aStructure->IsVisible (theViewId)) + { + continue; + } + else if (aStructure->TransformPersistence().IsNull() + || !aStructure->TransformPersistence()->IsTrihedronOr2d()) + { + continue; + } + + Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); + if (!aBox.IsValid()) + { + continue; + } + + aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); + if (aBox.IsValid() + && !isInfiniteBndBox (aBox)) + { + aResBox.Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z())); + aResBox.Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z())); + } + } + + return aResBox; +} + +// ======================================================================= +// function : considerZoomPersistenceObjects +// purpose : +// ======================================================================= +Standard_Real Graphic3d_Layer::considerZoomPersistenceObjects (Standard_Integer theViewId, + const Handle(Graphic3d_Camera)& theCamera, + Standard_Integer theWindowWidth, + Standard_Integer theWindowHeight) const +{ + if (NbOfTransformPersistenceObjects() == 0) + { + return 1.0; + } + + const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix(); + Standard_Real aMaxCoef = -std::numeric_limits::max(); + + for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) + { + const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value(); + for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) + { + const Graphic3d_CStructure* aStructure = aStructIter.Value(); + if (!aStructure->IsVisible (theViewId) + || aStructure->TransformPersistence().IsNull() + || !aStructure->TransformPersistence()->IsZoomOrRotate()) + { + continue; + } + + Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); + if (!aBox.IsValid()) + { + continue; + } + + aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); + + const BVH_Vec3d& aCornerMin = aBox.CornerMin(); + const BVH_Vec3d& aCornerMax = aBox.CornerMax(); + const Standard_Integer aNbOfPoints = 8; + const gp_Pnt aPoints[aNbOfPoints] = { gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMin.z()), + gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMax.z()), + gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMin.z()), + gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMax.z()), + gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMin.z()), + gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMax.z()), + gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMin.z()), + gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMax.z()) }; + gp_Pnt aConvertedPoints[aNbOfPoints]; + Standard_Real aConvertedMinX = std::numeric_limits::max(); + Standard_Real aConvertedMaxX = -std::numeric_limits::max(); + Standard_Real aConvertedMinY = std::numeric_limits::max(); + Standard_Real aConvertedMaxY = -std::numeric_limits::max(); + for (Standard_Integer anIdx = 0; anIdx < aNbOfPoints; ++anIdx) + { + aConvertedPoints[anIdx] = theCamera->Project (aPoints[anIdx]); + + aConvertedMinX = Min (aConvertedMinX, aConvertedPoints[anIdx].X()); + aConvertedMaxX = Max (aConvertedMaxX, aConvertedPoints[anIdx].X()); + + aConvertedMinY = Min (aConvertedMinY, aConvertedPoints[anIdx].Y()); + aConvertedMaxY = Max (aConvertedMaxY, aConvertedPoints[anIdx].Y()); + } + + const Standard_Boolean isBigObject = (Abs (aConvertedMaxX - aConvertedMinX) > 2.0) // width of zoom pers. object greater than width of window + || (Abs (aConvertedMaxY - aConvertedMinY) > 2.0); // height of zoom pers. object greater than height of window + const Standard_Boolean isAlreadyInScreen = (aConvertedMinX > -1.0 && aConvertedMinX < 1.0) + && (aConvertedMaxX > -1.0 && aConvertedMaxX < 1.0) + && (aConvertedMinY > -1.0 && aConvertedMinY < 1.0) + && (aConvertedMaxY > -1.0 && aConvertedMaxY < 1.0); + if (isBigObject || isAlreadyInScreen) + { + continue; + } + + const gp_Pnt aTPPoint = aStructure->TransformPersistence()->AnchorPoint(); + gp_Pnt aConvertedTPPoint = theCamera->Project (aTPPoint); + aConvertedTPPoint.SetZ (0.0); + + if (aConvertedTPPoint.Coord().Modulus() < Precision::Confusion()) + { + continue; + } + + Standard_Real aShiftX = 0.0; + if (aConvertedMinX < -1.0) + { + aShiftX = ((aConvertedMaxX < -1.0) ? (-(1.0 + aConvertedMaxX) + (aConvertedMaxX - aConvertedMinX)) : -(1.0 + aConvertedMinX)); + } + else if (aConvertedMaxX > 1.0) + { + aShiftX = ((aConvertedMinX > 1.0) ? ((aConvertedMinX - 1.0) + (aConvertedMaxX - aConvertedMinX)) : (aConvertedMaxX - 1.0)); + } + + Standard_Real aShiftY = 0.0; + if (aConvertedMinY < -1.0) + { + aShiftY = ((aConvertedMaxY < -1.0) ? (-(1.0 + aConvertedMaxY) + (aConvertedMaxY - aConvertedMinY)) : -(1.0 + aConvertedMinY)); + } + else if (aConvertedMaxY > 1.0) + { + aShiftY = ((aConvertedMinY > 1.0) ? ((aConvertedMinY - 1.0) + (aConvertedMaxY - aConvertedMinY)) : (aConvertedMaxY - 1.0)); + } + + const Standard_Real aDifX = Abs (aConvertedTPPoint.X()) - aShiftX; + const Standard_Real aDifY = Abs (aConvertedTPPoint.Y()) - aShiftY; + if (aDifX > Precision::Confusion()) + { + aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.X()) / aDifX); + } + if (aDifY > Precision::Confusion()) + { + aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.Y()) / aDifY); + } + } + } + + return (aMaxCoef > 0.0) ? aMaxCoef : 1.0; +} + +// ======================================================================= +// function : updateBVH +// purpose : +// ======================================================================= +void Graphic3d_Layer::updateBVH() const +{ + if (!myIsBVHPrimitivesNeedsReset) + { + return; + } + + myBVHPrimitives.Clear(); + myBVHPrimitivesTrsfPers.Clear(); + myAlwaysRenderedMap.Clear(); + myIsBVHPrimitivesNeedsReset = Standard_False; + for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) + { + const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value(); + for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) + { + const Graphic3d_CStructure* aStruct = aStructIter.Value(); + if (aStruct->IsAlwaysRendered()) + { + aStruct->MarkAsNotCulled(); + myAlwaysRenderedMap.Add (aStruct); + } + else if (aStruct->TransformPersistence().IsNull()) + { + myBVHPrimitives.Add (aStruct); + } + else + { + myBVHPrimitivesTrsfPers.Add (aStruct); + } + } + } +} + +// ======================================================================= +// function : UpdateCulling +// purpose : +// ======================================================================= +void Graphic3d_Layer::UpdateCulling (Standard_Integer theViewId, + const Graphic3d_CullingTool& theSelector, + const Graphic3d_RenderingParams::FrustumCulling theFrustumCullingState) +{ + updateBVH(); + + myNbStructuresNotCulled = myNbStructures; + if (theFrustumCullingState != Graphic3d_RenderingParams::FrustumCulling_NoUpdate) + { + Standard_Boolean toTraverse = (theFrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On); + for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (myBVHPrimitives.Structures()); aStructIter.More(); aStructIter.Next()) + { + const Graphic3d_CStructure* aStruct = aStructIter.Value(); + aStruct->SetCulled (toTraverse); + } + for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (myBVHPrimitivesTrsfPers.Structures()); aStructIter.More(); aStructIter.Next()) + { + const Graphic3d_CStructure* aStruct = aStructIter.Value(); + aStruct->SetCulled (toTraverse); + } + } + + if (theFrustumCullingState != Graphic3d_RenderingParams::FrustumCulling_On) + { + return; + } + if (myBVHPrimitives .Size() == 0 + && myBVHPrimitivesTrsfPers.Size() == 0) + { + return; + } + + myNbStructuresNotCulled = myAlwaysRenderedMap.Extent(); + Graphic3d_CullingTool::CullingContext aCullCtx; + theSelector.SetCullingDistance(aCullCtx, myLayerSettings.CullingDistance()); + theSelector.SetCullingSize (aCullCtx, myLayerSettings.CullingSize()); + for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) + { + const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1; + opencascade::handle > aBVHTree; + if (isTrsfPers) + { + if (myBVHPrimitivesTrsfPers.Size() == 0) + continue; + + const Graphic3d_Mat4d& aProjection = theSelector.ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldView = theSelector.WorldViewMatrix(); + const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState(); + const Standard_Integer aViewportWidth = theSelector.ViewportWidth(); + const Standard_Integer aViewportHeight = theSelector.ViewportHeight(); + + aBVHTree = myBVHPrimitivesTrsfPers.BVH (theSelector.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); + } + else + { + if (myBVHPrimitives.Size() == 0) + continue; + + aBVHTree = myBVHPrimitives.BVH(); + } + + if (theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0))) + { + continue; + } + + Standard_Integer aStack[BVH_Constants_MaxTreeDepth]; + Standard_Integer aHead = -1; + Standard_Integer aNode = 0; // a root node + for (;;) + { + if (!aBVHTree->IsOuter (aNode)) + { + const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode); + const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode); + const Standard_Boolean isLeftChildIn = !theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx)); + const Standard_Boolean isRightChildIn = !theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx)); + if (isLeftChildIn + && isRightChildIn) + { + aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx; + aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx; + myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst; + } + else if (isLeftChildIn + || isRightChildIn) + { + aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; + } + else + { + if (aHead < 0) + { + break; + } + + aNode = aStack[aHead--]; + } + } + else + { + Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode); + const Graphic3d_CStructure* aStruct = isTrsfPers + ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx) + : myBVHPrimitives.GetStructureById (aIdx); + if (aStruct->IsVisible (theViewId)) + { + aStruct->MarkAsNotCulled(); + ++myNbStructuresNotCulled; + } + if (aHead < 0) + { + break; + } + + aNode = aStack[aHead--]; + } + } + } +} + +// ======================================================================= +// function : Append +// purpose : +// ======================================================================= +Standard_Boolean Graphic3d_Layer::Append (const Graphic3d_Layer& theOther) +{ + // the source priority list shouldn't have more priorities + const Standard_Integer aNbPriorities = theOther.NbPriorities(); + if (aNbPriorities > NbPriorities()) + { + return Standard_False; + } + + // add all structures to destination priority list + for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) + { + const Graphic3d_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter); + for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) + { + Add (aStructIter.Value(), aPriorityIter); + } + } + + return Standard_True; +} + +//======================================================================= +//function : SetLayerSettings +//purpose : +//======================================================================= +void Graphic3d_Layer::SetLayerSettings (const Graphic3d_ZLayerSettings& theSettings) +{ + const Standard_Boolean toUpdateTrsf = !myLayerSettings.Origin().IsEqual (theSettings.Origin(), gp::Resolution()); + myLayerSettings = theSettings; + if (!toUpdateTrsf) + { + return; + } + + for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) + { + Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.ChangeValue(); + for (Graphic3d_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) + { + Graphic3d_CStructure* aStructure = const_cast(aStructIter.Value()); + aStructure->updateLayerTransformation(); + } + } +} diff --git a/src/Graphic3d/Graphic3d_Layer.hxx b/src/Graphic3d/Graphic3d_Layer.hxx new file mode 100644 index 0000000000..dc947bc462 --- /dev/null +++ b/src/Graphic3d/Graphic3d_Layer.hxx @@ -0,0 +1,184 @@ +// Copyright (c) 2011-2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_Layer_HeaderFile +#define _Graphic3d_Layer_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include + +//! Defines index map of structures. +typedef NCollection_IndexedMap Graphic3d_IndexedMapOfStructure; + +//! Defines array of indexed maps of structures. +typedef NCollection_Array1 Graphic3d_ArrayOfIndexedMapOfStructure; + +class Graphic3d_CullingTool; + +//! Presentations list sorted within priorities. +class Graphic3d_Layer : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Graphic3d_Layer, Standard_Transient) +public: + + //! Initializes associated priority list and layer properties + Standard_EXPORT Graphic3d_Layer (Standard_Integer theNbPriorities, + const Handle(Select3D_BVHBuilder3d)& theBuilder); + + //! Destructor. + Standard_EXPORT virtual ~Graphic3d_Layer(); + + //! Returns BVH tree builder for frustom culling. + const Handle(Select3D_BVHBuilder3d)& FrustumCullingBVHBuilder() const { return myBVHPrimitivesTrsfPers.Builder(); } + + //! Assigns BVH tree builder for frustom culling. + void SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder) { myBVHPrimitivesTrsfPers.SetBuilder (theBuilder); } + + //! Return true if layer was marked with immediate flag. + Standard_Boolean IsImmediate() const { return myLayerSettings.IsImmediate(); } + + //! Returns settings of the layer object. + const Graphic3d_ZLayerSettings& LayerSettings() const { return myLayerSettings; }; + + //! Sets settings of the layer object. + Standard_EXPORT void SetLayerSettings (const Graphic3d_ZLayerSettings& theSettings); + + Standard_EXPORT void Add (const Graphic3d_CStructure* theStruct, + Standard_Integer thePriority, + Standard_Boolean isForChangePriority = Standard_False); + + //! Remove structure and returns its priority, if the structure is not found, method returns negative value + Standard_EXPORT bool Remove (const Graphic3d_CStructure* theStruct, + Standard_Integer& thePriority, + Standard_Boolean isForChangePriority = Standard_False); + + //! @return the number of structures + Standard_Integer NbStructures() const { return myNbStructures; } + + //! Number of NOT culled structures in the layer. + Standard_Integer NbStructuresNotCulled() const { return myNbStructuresNotCulled; } + + //! Returns the number of available priority levels + Standard_Integer NbPriorities() const { return myArray.Length(); } + + //! Append layer of acceptable type (with similar number of priorities or less). + //! Returns Standard_False if the list can not be accepted. + Standard_EXPORT Standard_Boolean Append (const Graphic3d_Layer& theOther); + + //! Returns array of structures. + const Graphic3d_ArrayOfIndexedMapOfStructure& ArrayOfStructures() const { return myArray; } + + //! Marks BVH tree for given priority list as dirty and + //! marks primitive set for rebuild. + Standard_EXPORT void InvalidateBVHData(); + + //! Marks cached bounding box as obsolete. + void InvalidateBoundingBox() const + { + myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true; + } + + //! Returns layer bounding box. + //! @param theViewId view index to consider View Affinity in structure + //! @param theCamera camera definition + //! @param theWindowWidth viewport width (for applying transformation-persistence) + //! @param theWindowHeight viewport height (for applying transformation-persistence) + //! @param theToIncludeAuxiliary consider also auxiliary presentations (with infinite flag or with trihedron transformation persistence) + //! @return computed bounding box + Standard_EXPORT Bnd_Box BoundingBox (Standard_Integer theViewId, + const Handle(Graphic3d_Camera)& theCamera, + Standard_Integer theWindowWidth, + Standard_Integer theWindowHeight, + Standard_Boolean theToIncludeAuxiliary) const; + + //! Returns zoom-scale factor. + Standard_EXPORT Standard_Real considerZoomPersistenceObjects (Standard_Integer theViewId, + const Handle(Graphic3d_Camera)& theCamera, + Standard_Integer theWindowWidth, + Standard_Integer theWindowHeight) const; + + //! Update culling state - should be called before rendering. + //! Traverses through BVH tree to determine which structures are in view volume. + Standard_EXPORT void UpdateCulling (Standard_Integer theViewId, + const Graphic3d_CullingTool& theSelector, + const Graphic3d_RenderingParams::FrustumCulling theFrustumCullingState); + + //! Returns TRUE if layer is empty or has been discarded entirely by culling test. + bool IsCulled() const { return myNbStructuresNotCulled == 0; } + + //! Returns number of transform persistence objects. + Standard_Integer NbOfTransformPersistenceObjects() const + { + return myBVHPrimitivesTrsfPers.Size(); + } + +public: + + //! Returns set of Graphic3d_CStructures structures for building BVH tree. + const Graphic3d_BvhCStructureSet& CullableStructuresBVH() const { return myBVHPrimitives; } + + //! Returns set of transform persistent Graphic3d_CStructures for building BVH tree. + const Graphic3d_BvhCStructureSetTrsfPers& CullableTrsfPersStructuresBVH() const { return myBVHPrimitivesTrsfPers; } + + //! Returns indexed map of always rendered structures. + const NCollection_IndexedMap& NonCullableStructures() const { return myAlwaysRenderedMap; } + +protected: + + //! Updates BVH trees if their state has been invalidated. + Standard_EXPORT void updateBVH() const; + +private: + + //! Array of Graphic3d_CStructures by priority rendered in layer. + Graphic3d_ArrayOfIndexedMapOfStructure myArray; + + //! Overall number of structures rendered in the layer. + Standard_Integer myNbStructures; + + //! Number of NOT culled structures in the layer. + Standard_Integer myNbStructuresNotCulled; + + //! Layer setting flags. + Graphic3d_ZLayerSettings myLayerSettings; + + //! Set of Graphic3d_CStructures structures for building BVH tree. + mutable Graphic3d_BvhCStructureSet myBVHPrimitives; + + //! Set of transform persistent Graphic3d_CStructures for building BVH tree. + mutable Graphic3d_BvhCStructureSetTrsfPers myBVHPrimitivesTrsfPers; + + //! Indexed map of always rendered structures. + mutable NCollection_IndexedMap myAlwaysRenderedMap; + + //! Is needed for implementation of stochastic order of BVH traverse. + Standard_Boolean myBVHIsLeftChildQueuedFirst; + + //! Defines if the primitive set for BVH is outdated. + mutable Standard_Boolean myIsBVHPrimitivesNeedsReset; + + //! Defines if the cached bounding box is outdated. + mutable bool myIsBoundingBoxNeedsReset[2]; + + //! Cached layer bounding box. + mutable Bnd_Box myBoundingBox[2]; + +}; + +#endif // _Graphic3d_Layer_HeaderFile diff --git a/src/Graphic3d/Graphic3d_MapOfZLayerSettings.hxx b/src/Graphic3d/Graphic3d_MapOfZLayerSettings.hxx new file mode 100644 index 0000000000..944d14aafd --- /dev/null +++ b/src/Graphic3d/Graphic3d_MapOfZLayerSettings.hxx @@ -0,0 +1,24 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_MapOfZLayerSettings_HeaderFile +#define _Vulkan_MapOfZLayerSettings_HeaderFile + +#include +#include +#include +#include + +typedef NCollection_DataMap Graphic3d_MapOfZLayerSettings; + +#endif // _Vulkan_MapOfZLayerSettings_HeaderFile diff --git a/src/Graphic3d/Graphic3d_ZLayerSettings.hxx b/src/Graphic3d/Graphic3d_ZLayerSettings.hxx index c7eab89702..25ee49ef3a 100644 --- a/src/Graphic3d/Graphic3d_ZLayerSettings.hxx +++ b/src/Graphic3d/Graphic3d_ZLayerSettings.hxx @@ -18,6 +18,7 @@ #include #include #include +#include #include enum Graphic3d_ZLayerSetting diff --git a/src/OS/Visualization.tcl b/src/OS/Visualization.tcl index 71885b3ccf..5de72ea204 100644 --- a/src/OS/Visualization.tcl +++ b/src/OS/Visualization.tcl @@ -18,6 +18,7 @@ proc Visualization:toolkits { } { set aResult [list TKService \ TKV3d \ TKOpenGl \ + TKVulkan \ TKMeshVS] if { [info exists ::env(HAVE_VTK)] && "$::env(HAVE_VTK)" == "true" } { diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index 99faeb209f..107ce004c4 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -39,7 +39,6 @@ OpenGl_View_Raytrace.cxx OpenGl_View_Redraw.cxx OpenGl_GraduatedTrihedron.hxx OpenGl_GraduatedTrihedron.cxx -OpenGl_MapOfZLayerSettings.hxx OpenGl_Material.hxx OpenGl_MaterialState.hxx OpenGl_Matrix.hxx @@ -63,12 +62,6 @@ OpenGl_Font.hxx OpenGl_Font.cxx OpenGl_BackgroundArray.cxx OpenGl_BackgroundArray.hxx -OpenGl_BVHClipPrimitiveSet.cxx -OpenGl_BVHClipPrimitiveSet.hxx -OpenGl_BVHClipPrimitiveTrsfPersSet.cxx -OpenGl_BVHClipPrimitiveTrsfPersSet.hxx -OpenGl_BVHTreeSelector.cxx -OpenGl_BVHTreeSelector.hxx OpenGl_CappingAlgo.cxx OpenGl_CappingAlgo.hxx OpenGl_CappingPlaneResource.cxx @@ -109,7 +102,6 @@ OpenGl_GraphicDriver.cxx OpenGl_GraphicDriver.hxx OpenGl_IndexBuffer.cxx OpenGl_IndexBuffer.hxx -OpenGl_Layer.cxx OpenGl_Layer.hxx OpenGl_RenderFilter.hxx OpenGl_Sampler.cxx diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx deleted file mode 100644 index 1fe7c08cc7..0000000000 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.cxx +++ /dev/null @@ -1,130 +0,0 @@ -// Created on: 2013-12-25 -// Created by: Varvara POSKONINA -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include - -#include -#include - -IMPLEMENT_STANDARD_RTTIEXT(OpenGl_BVHClipPrimitiveSet, BVH_PrimitiveSet3d) - -// ======================================================================= -// function : OpenGl_BVHClipPrimitiveSet -// purpose : -// ======================================================================= -OpenGl_BVHClipPrimitiveSet::OpenGl_BVHClipPrimitiveSet() -{ - myBuilder = new BVH_BinnedBuilder (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth); -} - -// ======================================================================= -// function : Size -// purpose : -// ======================================================================= -Standard_Integer OpenGl_BVHClipPrimitiveSet::Size() const -{ - return myStructs.Size(); -} - -// ======================================================================= -// function : Box -// purpose : -// ======================================================================= -Graphic3d_BndBox3d OpenGl_BVHClipPrimitiveSet::Box (const Standard_Integer theIdx) const -{ - return myStructs.FindKey (theIdx + 1)->BoundingBox(); -} - -// ======================================================================= -// function : Center -// purpose : -// ======================================================================= -Standard_Real OpenGl_BVHClipPrimitiveSet::Center (const Standard_Integer theIdx, - const Standard_Integer theAxis) const -{ - Graphic3d_BndBox3d aBndBox = myStructs.FindKey (theIdx + 1)->BoundingBox(); - - const Standard_Real aMin = aBndBox.CornerMin()[theAxis]; - const Standard_Real aMax = aBndBox.CornerMax()[theAxis]; - const Standard_Real aCenter = (aMin + aMax) * 0.5; - return aCenter; -} - -// ======================================================================= -// function : Swap -// purpose : -// ======================================================================= -void OpenGl_BVHClipPrimitiveSet::Swap (const Standard_Integer theIdx1, - const Standard_Integer theIdx2) -{ - myStructs.Swap (theIdx1 + 1, theIdx2 + 1); -} - -// ======================================================================= -// function : Add -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_BVHClipPrimitiveSet::Add (const OpenGl_Structure* theStruct) -{ - const Standard_Integer aSize = myStructs.Size(); - - if (myStructs.Add (theStruct) > aSize) // new structure? - { - MarkDirty(); - - return Standard_True; - } - - return Standard_False; -} - -// ======================================================================= -// function : Remove -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_BVHClipPrimitiveSet::Remove (const OpenGl_Structure* theStruct) -{ - const Standard_Integer anIndex = myStructs.FindIndex (theStruct); - - if (anIndex != 0) - { - myStructs.Swap (Size(), anIndex); - myStructs.RemoveLast(); - MarkDirty(); - - return Standard_True; - } - - return Standard_False; -} - -// ======================================================================= -// function : Clear -// purpose : -// ======================================================================= -void OpenGl_BVHClipPrimitiveSet::Clear() -{ - myStructs.Clear(); - MarkDirty(); -} - -// ======================================================================= -// function : GetStructureById -// purpose : -// ======================================================================= -const OpenGl_Structure* OpenGl_BVHClipPrimitiveSet::GetStructureById (Standard_Integer theId) -{ - return myStructs.FindKey (theId + 1); -} diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx b/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx deleted file mode 100644 index 902444c768..0000000000 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveSet.hxx +++ /dev/null @@ -1,75 +0,0 @@ -// Created on: 2013-12-25 -// Created by: Varvara POSKONINA -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _OpenGl_BVHClipPrimitiveSet_HeaderFile -#define _OpenGl_BVHClipPrimitiveSet_HeaderFile - -#include -#include -#include - -#include - -//! Set of OpenGl_Structures for building BVH tree. -class OpenGl_BVHClipPrimitiveSet : public BVH_PrimitiveSet3d -{ - DEFINE_STANDARD_RTTIEXT(OpenGl_BVHClipPrimitiveSet, BVH_PrimitiveSet3d) -protected: - - using BVH_PrimitiveSet3d::Box; - -public: - - //! Creates an empty primitive set for BVH clipping. - OpenGl_BVHClipPrimitiveSet(); - - //! Returns total number of structures. - virtual Standard_Integer Size() const Standard_OVERRIDE; - - //! Returns AABB of the structure. - virtual Graphic3d_BndBox3d Box (const Standard_Integer theIdx) const Standard_OVERRIDE; - - //! Calculates center of the AABB along given axis. - virtual Standard_Real Center (const Standard_Integer theIdx, - const Standard_Integer theAxis) const Standard_OVERRIDE; - - //! Swaps structures with the given indices. - virtual void Swap (const Standard_Integer theIdx1, - const Standard_Integer theIdx2) Standard_OVERRIDE; - - //! Adds structure to the set. - //! @return true if structure added, otherwise returns false (structure already in the set). - Standard_Boolean Add (const OpenGl_Structure* theStruct); - - //! Removes the given structure from the set. - //! @return true if structure removed, otherwise returns false (structure is not in the set). - Standard_Boolean Remove (const OpenGl_Structure* theStruct); - - //! Cleans the whole primitive set. - void Clear(); - - //! Returns the structure corresponding to the given ID. - const OpenGl_Structure* GetStructureById (Standard_Integer theId); - - //! Access directly a collection of structures. - const NCollection_IndexedMap& Structures() const { return myStructs; } - -private: - - NCollection_IndexedMap myStructs; //!< Indexed map of structures. - -}; - -#endif // _OpenGl_BVHClipPrimitiveSet_HeaderFile diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx deleted file mode 100644 index 82576bf861..0000000000 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.cxx +++ /dev/null @@ -1,172 +0,0 @@ -// Created on: 2015-06-30 -// Created by: Anton POLETAEV -// Copyright (c) 2015 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include - -// ======================================================================= -// function : OpenGl_BVHClipPrimitiveTrsfPersSet -// purpose : -// ======================================================================= -OpenGl_BVHClipPrimitiveTrsfPersSet::OpenGl_BVHClipPrimitiveTrsfPersSet (const Handle(Select3D_BVHBuilder3d)& theBuilder) -: myIsDirty (Standard_False), - myBVH (new BVH_Tree()), - myBuilder (theBuilder) -{ - // -} - -// ======================================================================= -// function : Size -// purpose : -// ======================================================================= -Standard_Integer OpenGl_BVHClipPrimitiveTrsfPersSet::Size() const -{ - return myStructs.Size(); -} - -// ======================================================================= -// function : Box -// purpose : -// ======================================================================= -Graphic3d_BndBox3d OpenGl_BVHClipPrimitiveTrsfPersSet::Box (const Standard_Integer theIdx) const -{ - return *myStructBoxes (theIdx + 1); -} - -// ======================================================================= -// function : Center -// purpose : -// ======================================================================= -Standard_Real OpenGl_BVHClipPrimitiveTrsfPersSet::Center (const Standard_Integer theIdx, - const Standard_Integer theAxis) const -{ - const Graphic3d_BndBox3d& aBndBox = *myStructBoxes (theIdx + 1); - return (aBndBox.CornerMin()[theAxis] + aBndBox.CornerMax()[theAxis]) * 0.5; -} - -// ======================================================================= -// function : Swap -// purpose : -// ======================================================================= -void OpenGl_BVHClipPrimitiveTrsfPersSet::Swap (const Standard_Integer theIdx1, - const Standard_Integer theIdx2) -{ - const Standard_Integer aStructIdx1 = theIdx1 + 1; - const Standard_Integer aStructIdx2 = theIdx2 + 1; - - myStructs .Swap (aStructIdx1, aStructIdx2); - myStructBoxes.Swap (aStructIdx1, aStructIdx2); -} - -// ======================================================================= -// function : Add -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_BVHClipPrimitiveTrsfPersSet::Add (const OpenGl_Structure* theStruct) -{ - const Standard_Integer aSize = myStructs.Size(); - - if (myStructs.Add (theStruct) > aSize) // new structure? - { - MarkDirty(); - - return Standard_True; - } - - return Standard_False; -} - -// ======================================================================= -// function : Remove -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_BVHClipPrimitiveTrsfPersSet::Remove (const OpenGl_Structure* theStruct) -{ - const Standard_Integer anIndex = myStructs.FindIndex (theStruct); - - if (anIndex != 0) - { - myStructs.Swap (Size(), anIndex); - myStructs.RemoveLast(); - MarkDirty(); - - return Standard_True; - } - - return Standard_False; -} - -// ======================================================================= -// function : Clear -// purpose : -// ======================================================================= -void OpenGl_BVHClipPrimitiveTrsfPersSet::Clear() -{ - myStructs.Clear(); - MarkDirty(); -} - -// ======================================================================= -// function : GetStructureById -// purpose : -// ======================================================================= -const OpenGl_Structure* OpenGl_BVHClipPrimitiveTrsfPersSet::GetStructureById (Standard_Integer theId) -{ - return myStructs.FindKey (theId + 1); -} - -//======================================================================= -// function : BVH -// purpose : -//======================================================================= -const opencascade::handle >& - OpenGl_BVHClipPrimitiveTrsfPersSet::BVH (const Handle(Graphic3d_Camera)& theCamera, - const OpenGl_Mat4d& theProjectionMatrix, - const OpenGl_Mat4d& theWorldViewMatrix, - const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight, - const Graphic3d_WorldViewProjState& theWVPState) -{ - if (!myIsDirty - && (myStructBoxesState.IsValid() - && !myStructBoxesState.IsChanged (theWVPState))) - { - return myBVH; - } - - myStructBoxes.ReSize (myStructs.Size()); - - for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Size(); ++aStructIdx) - { - const OpenGl_Structure* aStructure = myStructs (aStructIdx); - - Handle(HBndBox3d) aBoundingBox = new HBndBox3d(); - *aBoundingBox = aStructure->BoundingBox(); - if (!aStructure->TransformPersistence().IsNull()) - { - aStructure->TransformPersistence()->Apply (theCamera, theProjectionMatrix, theWorldViewMatrix, theViewportWidth, theViewportHeight, *aBoundingBox); - } - - myStructBoxes.Add (aBoundingBox); - } - - myBuilder->Build (this, myBVH.operator->(), BVH_Set::Box()); - - myStructBoxesState = theWVPState; - myStructBoxes.Clear(); - myIsDirty = Standard_False; - - return myBVH; -} diff --git a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx b/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx deleted file mode 100644 index 6eedd2b3f6..0000000000 --- a/src/OpenGl/OpenGl_BVHClipPrimitiveTrsfPersSet.hxx +++ /dev/null @@ -1,118 +0,0 @@ -// Created on: 2015-06-30 -// Created by: Anton POLETAEV -// Copyright (c) 2015 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _OpenGl_BVHClipPrimitiveTrsfPersSet_HeaderFile -#define _OpenGl_BVHClipPrimitiveTrsfPersSet_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//! Set of transformation persistent OpenGl_Structure for building BVH tree. -//! Provides built-in mechanism to invalidate tree when world view projection state changes. -//! Due to frequent invalidation of BVH tree the choice of BVH tree builder is made -//! in favor of BVH linear builder (quick rebuild). -class OpenGl_BVHClipPrimitiveTrsfPersSet : public BVH_Set -{ -private: - - typedef NCollection_Shared HBndBox3d; - -public: - - //! Creates an empty primitive set for BVH clipping. - OpenGl_BVHClipPrimitiveTrsfPersSet (const Handle(Select3D_BVHBuilder3d)& theBuilder); - - //! Returns total number of structures. - virtual Standard_Integer Size() const Standard_OVERRIDE; - - //! Returns AABB of the structure. - virtual Graphic3d_BndBox3d Box (const Standard_Integer theIdx) const Standard_OVERRIDE; - - //! Calculates center of the AABB along given axis. - virtual Standard_Real Center (const Standard_Integer theIdx, - const Standard_Integer theAxis) const Standard_OVERRIDE; - - //! Swaps structures with the given indices. - virtual void Swap (const Standard_Integer theIdx1, - const Standard_Integer theIdx2) Standard_OVERRIDE; - - //! Adds structure to the set. - //! @return true if structure added, otherwise returns false (structure already in the set). - Standard_Boolean Add (const OpenGl_Structure* theStruct); - - //! Removes the given structure from the set. - //! @return true if structure removed, otherwise returns false (structure is not in the set). - Standard_Boolean Remove (const OpenGl_Structure* theStruct); - - //! Cleans the whole primitive set. - void Clear(); - - //! Returns the structure corresponding to the given ID. - const OpenGl_Structure* GetStructureById (Standard_Integer theId); - - //! Access directly a collection of structures. - const NCollection_IndexedMap& Structures() const { return myStructs; } - - //! Marks object state as outdated (needs BVH rebuilding). - void MarkDirty() - { - myIsDirty = Standard_True; - } - - //! Returns BVH tree for the given world view projection (builds it if necessary). - const opencascade::handle >& BVH (const Handle(Graphic3d_Camera)& theCamera, - const OpenGl_Mat4d& theProjectionMatrix, - const OpenGl_Mat4d& theWorldViewMatrix, - const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight, - const Graphic3d_WorldViewProjState& theWVPState); - - //! Returns builder for bottom-level BVH. - const Handle(Select3D_BVHBuilder3d)& Builder() const { return myBuilder; } - - //! Assigns builder for bottom-level BVH. - void SetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder) { myBuilder = theBuilder; } - -private: - - //! Marks internal object state as outdated. - Standard_Boolean myIsDirty; - - //! Constructed bottom-level BVH. - opencascade::handle > myBVH; - - //! Builder for bottom-level BVH. - Handle(Select3D_BVHBuilder3d) myBuilder; - - //! Indexed map of structures. - NCollection_IndexedMap myStructs; - - //! Cached set of bounding boxes precomputed for transformation persistent selectable objects. - //! Cache exists only during computation of BVH Tree. Bounding boxes are world view projection - //! dependent and should by synchronized. - NCollection_IndexedMap myStructBoxes; - - //! State of world view projection used for generation of transformation persistence bounding boxes. - Graphic3d_WorldViewProjState myStructBoxesState; -}; - -#endif // _OpenGl_BVHClipPrimitiveTrsfPersSet_HeaderFile diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.cxx b/src/OpenGl/OpenGl_BVHTreeSelector.cxx deleted file mode 100644 index 95edcad41f..0000000000 --- a/src/OpenGl/OpenGl_BVHTreeSelector.cxx +++ /dev/null @@ -1,198 +0,0 @@ -// Created on: 2013-12-25 -// Created by: Varvara POSKONINA -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include - -#include -#include -#include - -// ======================================================================= -// function : OpenGl_BVHTreeSelector -// purpose : -// ======================================================================= -OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector() -: myClipVerts (0, Graphic3d_Camera::FrustumVerticesNB), - myIsProjectionParallel (Standard_True), - myCamScale (1.0), - myPixelSize (1.0) -{ - // -} - -// ======================================================================= -// function : SetViewVolume -// purpose : Retrieves view volume's planes equations and its vertices from projection and world-view matrices. -// ======================================================================= -void OpenGl_BVHTreeSelector::SetViewVolume (const Handle(Graphic3d_Camera)& theCamera) -{ - if (!myWorldViewProjState.IsChanged (theCamera->WorldViewProjState())) - return; - - myIsProjectionParallel = theCamera->IsOrthographic(); - const gp_Dir aCamDir = theCamera->Direction(); - - myCamera = theCamera; - myProjectionMat = theCamera->ProjectionMatrix(); - myWorldViewMat = theCamera->OrientationMatrix(); - myWorldViewProjState = theCamera->WorldViewProjState(); - myCamEye.SetValues (theCamera->Eye().X(), theCamera->Eye().Y(), theCamera->Eye().Z()); - myCamDir.SetValues (aCamDir.X(), aCamDir.Y(), aCamDir.Z()); - myCamScale = theCamera->IsOrthographic() - ? theCamera->Scale() - : 2.0 * Tan (theCamera->FOVy() * M_PI / 360.0); // same as theCamera->Scale()/theCamera->Distance() - - // Compute frustum points - theCamera->FrustumPoints (myClipVerts); - - // Compute frustum planes - // Vertices go in order: - // 0, 2, 1 - const Standard_Integer aLookup1[] = { 0, 1, 0 }; - const Standard_Integer aLookup2[] = { 0, 0, 1 }; - Standard_Integer aShifts[] = { 0, 0, 0 }; - - // Planes go in order: - // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR - for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx) - { - for (Standard_Integer i = 0; i < 2; ++i) - { - OpenGl_Vec3d aPlanePnts[3]; - for (Standard_Integer aPntIter = 0; aPntIter < 3; ++aPntIter) - { - aShifts[aFaceIdx] = i; - aShifts[(aFaceIdx + 1) % 3] = aLookup1[aPntIter]; - aShifts[(aFaceIdx + 2) % 3] = aLookup2[aPntIter]; - - aPlanePnts[aPntIter] = myClipVerts[aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2]]; - } - - myClipPlanes[aFaceIdx * 2 + i].Origin = aPlanePnts[0]; - myClipPlanes[aFaceIdx * 2 + i].Normal = - OpenGl_Vec3d::Cross (aPlanePnts[1] - aPlanePnts[0], - aPlanePnts[2] - aPlanePnts[0]).Normalized() * (i == 0 ? -1.f : 1.f); - } - } -} - -// ======================================================================= -// function : SetViewportSize -// purpose : -// ======================================================================= -void OpenGl_BVHTreeSelector::SetViewportSize (Standard_Integer theViewportWidth, - Standard_Integer theViewportHeight, - Standard_Real theResolutionRatio) -{ - myViewportHeight = theViewportHeight > 0 ? theViewportHeight : 1; - myViewportWidth = theViewportWidth > 0 ? theViewportWidth : 1; - myPixelSize = Max (theResolutionRatio / myViewportHeight, - theResolutionRatio / myViewportWidth); -} - -// ======================================================================= -// function : SignedPlanePointDistance -// purpose : -// ======================================================================= -Standard_Real OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec4d& theNormal, - const OpenGl_Vec4d& thePnt) -{ - const Standard_Real aNormLength = std::sqrt (theNormal.x() * theNormal.x() - + theNormal.y() * theNormal.y() - + theNormal.z() * theNormal.z()); - - if (aNormLength < gp::Resolution()) - return 0.0; - - const Standard_Real anInvNormLength = 1.0 / aNormLength; - const Standard_Real aD = theNormal.w() * anInvNormLength; - const Standard_Real anA = theNormal.x() * anInvNormLength; - const Standard_Real aB = theNormal.y() * anInvNormLength; - const Standard_Real aC = theNormal.z() * anInvNormLength; - return aD + (anA * thePnt.x() + aB * thePnt.y() + aC * thePnt.z()); -} - -// ======================================================================= -// function : SetCullingDistance -// purpose : -// ======================================================================= -void OpenGl_BVHTreeSelector::SetCullingDistance (CullingContext& theCtx, - Standard_Real theDistance) const -{ - theCtx.DistCull = -1.0; - if (!myIsProjectionParallel) - { - theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance) - ? theDistance - : -1.0; - } -} - -// ======================================================================= -// function : SetCullingSize -// purpose : -// ======================================================================= -void OpenGl_BVHTreeSelector::SetCullingSize (CullingContext& theCtx, - Standard_Real theSize) const -{ - theCtx.SizeCull2 = -1.0; - if (theSize > 0.0 && !Precision::IsInfinite (theSize)) - { - theCtx.SizeCull2 = myPixelSize * theSize; - theCtx.SizeCull2 *= myCamScale; - theCtx.SizeCull2 *= theCtx.SizeCull2; - } -} - -// ======================================================================= -// function : CacheClipPtsProjections -// purpose : -// ======================================================================= -void OpenGl_BVHTreeSelector::CacheClipPtsProjections() -{ - // project frustum onto its own normals - const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1; - for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor) - { - Standard_Real aMaxProj = -std::numeric_limits::max(); - Standard_Real aMinProj = std::numeric_limits::max(); - for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter) - { - Standard_Real aProjection = myClipVerts[aCornerIter].Dot (myClipPlanes[aPlaneIter].Normal); - aMaxProj = Max (aProjection, aMaxProj); - aMinProj = Min (aProjection, aMinProj); - } - myMaxClipProjectionPts[aPlaneIter] = aMaxProj; - myMinClipProjectionPts[aPlaneIter] = aMinProj; - } - - // project frustum onto main axes - OpenGl_Vec3d anAxes[] = { OpenGl_Vec3d (1.0, 0.0, 0.0), - OpenGl_Vec3d (0.0, 1.0, 0.0), - OpenGl_Vec3d (0.0, 0.0, 1.0) }; - for (Standard_Integer aDim = 0; aDim < 3; ++aDim) - { - Standard_Real aMaxProj = -std::numeric_limits::max(); - Standard_Real aMinProj = std::numeric_limits::max(); - for (Standard_Integer aCornerIter = 0; aCornerIter < Graphic3d_Camera::FrustumVerticesNB; ++aCornerIter) - { - Standard_Real aProjection = myClipVerts[aCornerIter].Dot (anAxes[aDim]); - aMaxProj = Max (aProjection, aMaxProj); - aMinProj = Min (aProjection, aMinProj); - } - myMaxOrthoProjectionPts[aDim] = aMaxProj; - myMinOrthoProjectionPts[aDim] = aMinProj; - } -} diff --git a/src/OpenGl/OpenGl_BVHTreeSelector.hxx b/src/OpenGl/OpenGl_BVHTreeSelector.hxx deleted file mode 100644 index 6cf9cfe83e..0000000000 --- a/src/OpenGl/OpenGl_BVHTreeSelector.hxx +++ /dev/null @@ -1,288 +0,0 @@ -// Created on: 2013-12-25 -// Created by: Varvara POSKONINA -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _OpenGl_BVHTreeSelector_HeaderFile -#define _OpenGl_BVHTreeSelector_HeaderFile - -#include -#include -#include - -//! BVHTreeSelector class provides a possibility to store parameters of view volume, -//! such as its vertices and equations, and contains methods detecting if given AABB overlaps -//! view volume. -class OpenGl_BVHTreeSelector -{ -public: - //! Auxiliary structure holding non-persistent culling options. - struct CullingContext - { - Standard_Real DistCull; //!< culling distance - Standard_Real SizeCull2; //!< squared culling size - - //! Empty constructor. - CullingContext() : DistCull (-1.0), SizeCull2 (-1.0) {} - }; - - //! Auxiliary structure representing 3D plane. - struct Plane - { - //! Creates default plane. - Plane() - : Origin (0.0, 0.0, 0.0), - Normal (0.0, 0.0, 1.0) {} - - //! Creates plane with specific parameters. - Plane (const OpenGl_Vec3d& theOrigin, - const OpenGl_Vec3d& theNormal) - : Origin (theOrigin), - Normal (theNormal) {} - - OpenGl_Vec3d Origin; - OpenGl_Vec3d Normal; - }; - -public: - - //! Creates an empty selector object with parallel projection type by default. - Standard_EXPORT OpenGl_BVHTreeSelector(); - - //! Retrieves view volume's planes equations and its vertices from projection and world-view matrices. - Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera); - - Standard_EXPORT void SetViewportSize (Standard_Integer theViewportWidth, - Standard_Integer theViewportHeight, - Standard_Real theResolutionRatio); - - //! Setup distance culling. - Standard_EXPORT void SetCullingDistance (CullingContext& theCtx, - Standard_Real theDistance) const; - - //! Setup size culling. - Standard_EXPORT void SetCullingSize (CullingContext& theCtx, - Standard_Real theSize) const; - - //! Caches view volume's vertices projections along its normals and AABBs dimensions. - //! Must be called at the beginning of each BVH tree traverse loop. - Standard_EXPORT void CacheClipPtsProjections(); - - //! Checks whether given AABB should be entirely culled or not. - //! @param theCtx [in] culling properties - //! @param theMinPt [in] maximum point of AABB - //! @param theMaxPt [in] minimum point of AABB - //! @return Standard_True, if AABB is in viewing area, Standard_False otherwise - bool IsCulled (const CullingContext& theCtx, - const OpenGl_Vec3d& theMinPt, - const OpenGl_Vec3d& theMaxPt) const - { - return isFullOut (theMinPt, theMaxPt) - || isTooDistant(theCtx, theMinPt, theMaxPt) - || isTooSmall (theCtx, theMinPt, theMaxPt); - } - - //! Return the camera definition. - const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } - - //! Returns current projection matrix. - const OpenGl_Mat4d& ProjectionMatrix() const - { - return myProjectionMat; - } - - //! Returns current world view transformation matrix. - const OpenGl_Mat4d& WorldViewMatrix() const - { - return myWorldViewMat; - } - - Standard_Integer ViewportWidth() const - { - return myViewportWidth; - } - - Standard_Integer ViewportHeight() const - { - return myViewportHeight; - } - - //! Returns state of current world view projection transformation matrices. - const Graphic3d_WorldViewProjState& WorldViewProjState() const - { - return myWorldViewProjState; - } - -protected: - - //! Calculates signed distance from plane to point. - //! @param theNormal [in] the plane's normal. - //! @param thePnt [in] - Standard_EXPORT Standard_Real SignedPlanePointDistance (const OpenGl_Vec4d& theNormal, - const OpenGl_Vec4d& thePnt); - - //! Detects if AABB overlaps view volume using separating axis theorem (SAT). - //! @param theMinPt [in] maximum point of AABB. - //! @param theMaxPt [in] minimum point of AABB. - //! @return FALSE, if AABB is in viewing area, TRUE otherwise. - bool isFullOut (const OpenGl_Vec3d& theMinPt, - const OpenGl_Vec3d& theMaxPt) const - { - // E1 - // |_ E0 - // / - // E2 - - // E0 test (x axis) - if (theMinPt.x() > myMaxOrthoProjectionPts[0] - || theMaxPt.x() < myMinOrthoProjectionPts[0]) - { - return true; - } - - // E1 test (y axis) - if (theMinPt.y() > myMaxOrthoProjectionPts[1] - || theMaxPt.y() < myMinOrthoProjectionPts[1]) - { - return true; - } - - // E2 test (z axis) - if (theMinPt.z() > myMaxOrthoProjectionPts[2] - || theMaxPt.z() < myMinOrthoProjectionPts[2]) - { - return true; - } - - const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1; - for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor) - { - // frustum normals - const OpenGl_Vec3d anAxis = myClipPlanes[aPlaneIter].Normal; - - const OpenGl_Vec3d aPVertex (anAxis.x() > 0.0 ? theMaxPt.x() : theMinPt.x(), - anAxis.y() > 0.0 ? theMaxPt.y() : theMinPt.y(), - anAxis.z() > 0.0 ? theMaxPt.z() : theMinPt.z()); - Standard_Real aPnt0 = aPVertex.Dot (anAxis); - - if (aPnt0 >= myMinClipProjectionPts[aPlaneIter] - && aPnt0 <= myMaxClipProjectionPts[aPlaneIter]) - { - continue; - } - - const OpenGl_Vec3d aNVertex (anAxis.x() > 0.0 ? theMinPt.x() : theMaxPt.x(), - anAxis.y() > 0.0 ? theMinPt.y() : theMaxPt.y(), - anAxis.z() > 0.0 ? theMinPt.z() : theMaxPt.z()); - Standard_Real aPnt1 = aNVertex.Dot (anAxis); - - const Standard_Real aMin = aPnt0 < aPnt1 ? aPnt0 : aPnt1; - const Standard_Real aMax = aPnt0 > aPnt1 ? aPnt0 : aPnt1; - - if (aMin > myMaxClipProjectionPts[aPlaneIter] - || aMax < myMinClipProjectionPts[aPlaneIter]) - { - return true; - } - } - return false; - } - - //! Returns TRUE if given AABB should be discarded by distance culling criterion. - bool isTooDistant (const CullingContext& theCtx, - const OpenGl_Vec3d& theMinPt, - const OpenGl_Vec3d& theMaxPt) const - { - if (theCtx.DistCull <= 0.0) - { - return false; - } - - // check distance to the bounding sphere as fast approximation - const Graphic3d_Vec3d aSphereCenter = (theMinPt + theMaxPt) * 0.5; - const Standard_Real aSphereRadius = (theMaxPt - theMinPt).maxComp() * 0.5; - return (aSphereCenter - myCamEye).Modulus() - aSphereRadius > theCtx.DistCull; - } - - //! Returns TRUE if given AABB should be discarded by size culling criterion. - bool isTooSmall (const CullingContext& theCtx, - const OpenGl_Vec3d& theMinPt, - const OpenGl_Vec3d& theMaxPt) const - { - if (theCtx.SizeCull2 <= 0.0) - { - return false; - } - - const Standard_Real aBoxDiag2 = (theMaxPt - theMinPt).SquareModulus(); - if (myIsProjectionParallel) - { - return aBoxDiag2 < theCtx.SizeCull2; - } - - // note that distances behind the Eye (aBndDist < 0) are not scaled correctly here, - // but majority of such objects should be culled by frustum - const OpenGl_Vec3d aBndCenter = (theMinPt + theMaxPt) * 0.5; - const Standard_Real aBndDist = (aBndCenter - myCamEye).Dot (myCamDir); - return aBoxDiag2 < theCtx.SizeCull2 * aBndDist * aBndDist; - } - -protected: - - //! Enumerates planes of view volume. - enum - { - Plane_Left, - Plane_Right, - Plane_Bottom, - Plane_Top, - Plane_Near, - Plane_Far, - PlanesNB - }; - -protected: - - Plane myClipPlanes[PlanesNB]; //!< Planes - NCollection_Array1 myClipVerts; //!< Vertices - - Handle(Graphic3d_Camera) myCamera; //!< camera definition - - // for caching clip points projections onto viewing area normals once per traverse - // ORDER: LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR - Standard_Real myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals - Standard_Real myMinClipProjectionPts[PlanesNB]; //!< Min view volume's vertices projections onto its normals - - // for caching clip points projections onto AABB normals once per traverse - // ORDER: E0, E1, E2 - Standard_Real myMaxOrthoProjectionPts[3]; //!< Max view volume's vertices projections onto normalized dimensions of AABB - Standard_Real myMinOrthoProjectionPts[3]; //!< Min view volume's vertices projections onto normalized dimensions of AABB - - Standard_Boolean myIsProjectionParallel; - - OpenGl_Mat4d myProjectionMat; - OpenGl_Mat4d myWorldViewMat; - - Standard_Integer myViewportWidth; - Standard_Integer myViewportHeight; - - Graphic3d_WorldViewProjState myWorldViewProjState; //!< State of world view projection matrices. - - Graphic3d_Vec3d myCamEye; //!< camera eye position for distance culling - Graphic3d_Vec3d myCamDir; //!< camera direction for size culling - Standard_Real myCamScale; //!< camera scale for size culling - Standard_Real myPixelSize; //!< pixel size for size culling - -}; - -#endif // _OpenGl_BVHTreeSelector_HeaderFile diff --git a/src/OpenGl/OpenGl_Caps.hxx b/src/OpenGl/OpenGl_Caps.hxx index 548a8bea70..6bdc98e92e 100755 --- a/src/OpenGl/OpenGl_Caps.hxx +++ b/src/OpenGl/OpenGl_Caps.hxx @@ -60,7 +60,7 @@ public: //! @name context creation parameters * (see OpenGl_Context - messages will be printed to standard output). * Affects performance - thus should not be turned on by products in released state. * - * OFF by default. Currently implemented only for Windows (WGL). + * OFF by default. */ Standard_Boolean contextDebug; diff --git a/src/OpenGl/OpenGl_FrameStats.cxx b/src/OpenGl/OpenGl_FrameStats.cxx index c43b16cce8..ff55ab0c94 100644 --- a/src/OpenGl/OpenGl_FrameStats.cxx +++ b/src/OpenGl/OpenGl_FrameStats.cxx @@ -186,12 +186,12 @@ void OpenGl_FrameStats::updateStatistics (const Handle(Graphic3d_CView)& theView // purpose : // ======================================================================= void OpenGl_FrameStats::updateStructures (Standard_Integer theViewId, - const OpenGl_IndexedMapOfStructure& theStructures, + const NCollection_IndexedMap& theStructures, Standard_Boolean theToCountElems, Standard_Boolean theToCountTris, Standard_Boolean theToCountMem) { - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (theStructures); aStructIter.More(); aStructIter.Next()) + for (OpenGl_Structure::StructIterator aStructIter (theStructures); aStructIter.More(); aStructIter.Next()) { const OpenGl_Structure* aStruct = aStructIter.Value(); const bool isStructHidden = aStruct->IsCulled() diff --git a/src/OpenGl/OpenGl_FrameStats.hxx b/src/OpenGl/OpenGl_FrameStats.hxx index 364d5738fd..ef1f58bec8 100644 --- a/src/OpenGl/OpenGl_FrameStats.hxx +++ b/src/OpenGl/OpenGl_FrameStats.hxx @@ -17,9 +17,7 @@ #include #include -class OpenGl_Workspace; -class OpenGl_Structure; -typedef NCollection_IndexedMap OpenGl_IndexedMapOfStructure; +class Graphic3d_CStructure; //! Class storing the frame statistics. class OpenGl_FrameStats : public Graphic3d_FrameStats @@ -48,7 +46,7 @@ protected: //! Updates counters for structures. Standard_EXPORT virtual void updateStructures (Standard_Integer theViewId, - const OpenGl_IndexedMapOfStructure& theStructures, + const NCollection_IndexedMap& theStructures, Standard_Boolean theToCountElems, Standard_Boolean theToCountTris, Standard_Boolean theToCountMem); diff --git a/src/OpenGl/OpenGl_GraphicDriver.cxx b/src/OpenGl/OpenGl_GraphicDriver.cxx index 35b0e61aca..03f02a636e 100644 --- a/src/OpenGl/OpenGl_GraphicDriver.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver.cxx @@ -139,72 +139,6 @@ OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnectio { throw Aspect_GraphicDeviceDefinitionError("OpenGl_GraphicDriver: default context can not be initialized!"); } - - // default layers are always presented in display layer sequence it can not be removed - { - Graphic3d_ZLayerSettings aSettings; - aSettings.SetImmediate (Standard_False); - aSettings.SetEnvironmentTexture (Standard_False); - aSettings.SetEnableDepthTest (Standard_False); - aSettings.SetEnableDepthWrite (Standard_False); - aSettings.SetClearDepth (Standard_False); - aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); - myLayerIds.Add (Graphic3d_ZLayerId_BotOSD); - myLayerSeq.Append (Graphic3d_ZLayerId_BotOSD); - myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_BotOSD, aSettings); - } - - { - Graphic3d_ZLayerSettings aSettings; - aSettings.SetImmediate (Standard_False); - aSettings.SetEnvironmentTexture (Standard_True); - aSettings.SetEnableDepthTest (Standard_True); - aSettings.SetEnableDepthWrite (Standard_True); - aSettings.SetClearDepth (Standard_False); - aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); - myLayerIds.Add (Graphic3d_ZLayerId_Default); - myLayerSeq.Append (Graphic3d_ZLayerId_Default); - myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_Default, aSettings); - } - - { - Graphic3d_ZLayerSettings aSettings; - aSettings.SetImmediate (Standard_True); - aSettings.SetEnvironmentTexture (Standard_True); - aSettings.SetEnableDepthTest (Standard_True); - aSettings.SetEnableDepthWrite (Standard_True); - aSettings.SetClearDepth (Standard_False); - aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); - myLayerIds.Add (Graphic3d_ZLayerId_Top); - myLayerSeq.Append (Graphic3d_ZLayerId_Top); - myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_Top, aSettings); - } - - { - Graphic3d_ZLayerSettings aSettings; - aSettings.SetImmediate (Standard_True); - aSettings.SetEnvironmentTexture (Standard_True); - aSettings.SetEnableDepthTest (Standard_True); - aSettings.SetEnableDepthWrite (Standard_True); - aSettings.SetClearDepth (Standard_True); - aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); - myLayerIds.Add (Graphic3d_ZLayerId_Topmost); - myLayerSeq.Append (Graphic3d_ZLayerId_Topmost); - myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_Topmost, aSettings); - } - - { - Graphic3d_ZLayerSettings aSettings; - aSettings.SetImmediate (Standard_True); - aSettings.SetEnvironmentTexture (Standard_False); - aSettings.SetEnableDepthTest (Standard_False); - aSettings.SetEnableDepthWrite (Standard_False); - aSettings.SetClearDepth (Standard_False); - aSettings.SetPolygonOffset (Graphic3d_PolygonOffset()); - myLayerIds.Add (Graphic3d_ZLayerId_TopOSD); - myLayerSeq.Append (Graphic3d_ZLayerId_TopOSD); - myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_TopOSD, aSettings); - } } // ======================================================================= @@ -570,50 +504,6 @@ void OpenGl_GraphicDriver::TextSize (const Handle(Graphic3d_CView)& theView, OpenGl_Text::StringSize(aCtx, aText, aTextAspect, aTextParam, theView->RenderingParams().Resolution, theWidth, theAscent, theDescent); } -//======================================================================= -//function : addZLayerIndex -//purpose : -//======================================================================= -void OpenGl_GraphicDriver::addZLayerIndex (const Graphic3d_ZLayerId theLayerId) -{ - // remove index - for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next()) - { - if (aLayerIt.Value() == theLayerId) - { - myLayerSeq.Remove (aLayerIt); - break; - } - } - - if (myMapOfZLayerSettings.Find (theLayerId).IsImmediate()) - { - myLayerSeq.Append (theLayerId); - return; - } - - for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next()) - { - const Graphic3d_ZLayerSettings& aSettings = myMapOfZLayerSettings.Find (aLayerIt.Value()); - if (aSettings.IsImmediate()) - { - aLayerIt.Previous(); - if (aLayerIt.More()) - { - myLayerSeq.InsertAfter (aLayerIt, theLayerId); - return; - } - - // first non-immediate layer - myLayerSeq.Prepend (theLayerId); - return; - } - } - - // no immediate layers - myLayerSeq.Append (theLayerId); -} - //======================================================================= //function : AddZLayer //purpose : @@ -686,15 +576,6 @@ void OpenGl_GraphicDriver::RemoveZLayer (const Graphic3d_ZLayerId theLayerId) myLayerIds.Remove (theLayerId); } -//======================================================================= -//function : ZLayers -//purpose : -//======================================================================= -void OpenGl_GraphicDriver::ZLayers (TColStd_SequenceOfInteger& theLayerSeq) const -{ - theLayerSeq.Assign (myLayerSeq); -} - //======================================================================= //function : SetZLayerSettings //purpose : @@ -702,22 +583,7 @@ void OpenGl_GraphicDriver::ZLayers (TColStd_SequenceOfInteger& theLayerSeq) cons void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, const Graphic3d_ZLayerSettings& theSettings) { - Graphic3d_ZLayerSettings* aSettings = myMapOfZLayerSettings.ChangeSeek (theLayerId); - if (aSettings != NULL) - { - const bool isChanged = (aSettings->IsImmediate() != theSettings.IsImmediate()); - *aSettings = theSettings; - if (isChanged) - { - addZLayerIndex (theLayerId); - } - } - else - { - // abnormal case - myMapOfZLayerSettings.Bind (theLayerId, theSettings); - addZLayerIndex (theLayerId); - } + base_type::SetZLayerSettings (theLayerId, theSettings); // Change Z layer settings in all managed views for (NCollection_Map::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next()) @@ -726,19 +592,6 @@ void OpenGl_GraphicDriver::SetZLayerSettings (const Graphic3d_ZLayerId theLayerI } } -//======================================================================= -//function : ZLayerSettings -//purpose : -//======================================================================= -const Graphic3d_ZLayerSettings& OpenGl_GraphicDriver::ZLayerSettings (const Graphic3d_ZLayerId theLayerId) const -{ - Standard_ASSERT_RAISE (myLayerIds.Contains (theLayerId), - "OpenGl_GraphicDriver::ZLayerSettings, " - "Layer with theLayerId does not exist"); - - return myMapOfZLayerSettings.Find (theLayerId); -} - // ======================================================================= // function : Structure // purpose : diff --git a/src/OpenGl/OpenGl_GraphicDriver.hxx b/src/OpenGl/OpenGl_GraphicDriver.hxx index af313e740c..4cdba035dd 100644 --- a/src/OpenGl/OpenGl_GraphicDriver.hxx +++ b/src/OpenGl/OpenGl_GraphicDriver.hxx @@ -20,39 +20,15 @@ #include #include -#include -#include -#include -#include #include -#include #include #include -#include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include class Aspect_Window; class Quantity_Color; -class Graphic3d_Vertex; -class TCollection_ExtendedString; -class Image_PixMap; -class OpenGl_Element; class OpenGl_Structure; -class OpenGl_Text; class OpenGl_View; class OpenGl_Window; @@ -143,15 +119,9 @@ public: //! (reserved for default layers that can not be removed). Standard_EXPORT void RemoveZLayer (const Graphic3d_ZLayerId theLayerId) Standard_OVERRIDE; - //! Returns list of Z layers defined for the graphical driver. - Standard_EXPORT void ZLayers (TColStd_SequenceOfInteger& theLayerSeq) const Standard_OVERRIDE; - //! Sets the settings for a single Z layer. Standard_EXPORT void SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, const Graphic3d_ZLayerSettings& theSettings) Standard_OVERRIDE; - //! Returns the settings of a single Z layer. - Standard_EXPORT virtual const Graphic3d_ZLayerSettings& ZLayerSettings (const Graphic3d_ZLayerId theLayerId) const Standard_OVERRIDE; - public: //! @return the visualization options @@ -191,9 +161,6 @@ public: void* getRawGlConfig() const { return myEglConfig; } #endif - //! Insert index layer at proper position. - Standard_EXPORT void addZLayerIndex (const Graphic3d_ZLayerId theLayerId); - //! Set device lost flag for redrawn views. Standard_EXPORT void setDeviceLost(); @@ -218,10 +185,6 @@ protected: NCollection_Map myMapOfView; NCollection_DataMap myMapOfStructure; - TColStd_MapOfInteger myLayerIds; - TColStd_SequenceOfInteger myLayerSeq; - OpenGl_MapOfZLayerSettings myMapOfZLayerSettings; - mutable OpenGl_StateCounter myStateCounter; //!< State counter for OpenGl structures. mutable OpenGl_StateCounter myUIDGenerator; //!< Unique ID counter for primitive arrays. diff --git a/src/OpenGl/OpenGl_Layer.cxx b/src/OpenGl/OpenGl_Layer.cxx deleted file mode 100644 index 53d0b5cea6..0000000000 --- a/src/OpenGl/OpenGl_Layer.cxx +++ /dev/null @@ -1,773 +0,0 @@ -// Created on: 2014-03-31 -// Created by: Danila ULYANOV -// Copyright (c) 2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include - -#include -#include -#include -#include -#include -#include - -IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Layer, Standard_Transient) - -// ======================================================================= -// function : OpenGl_Layer -// purpose : -// ======================================================================= -OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities, - const Handle(Select3D_BVHBuilder3d)& theBuilder) -: myArray (0, theNbPriorities - 1), - myNbStructures (0), - myNbStructuresNotCulled (0), - myBVHPrimitivesTrsfPers (theBuilder), - myBVHIsLeftChildQueuedFirst (Standard_True), - myIsBVHPrimitivesNeedsReset (Standard_False) -{ - myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true; -} - -// ======================================================================= -// function : ~OpenGl_Layer -// purpose : -// ======================================================================= -OpenGl_Layer::~OpenGl_Layer() -{ - // -} - -// ======================================================================= -// function : Add -// purpose : -// ======================================================================= -void OpenGl_Layer::Add (const OpenGl_Structure* theStruct, - const Standard_Integer thePriority, - Standard_Boolean isForChangePriority) -{ - const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1); - if (theStruct == NULL) - { - return; - } - - myArray (anIndex).Add (theStruct); - if (theStruct->IsAlwaysRendered()) - { - theStruct->MarkAsNotCulled(); - if (!isForChangePriority) - { - myAlwaysRenderedMap.Add (theStruct); - } - } - else if (!isForChangePriority) - { - if (theStruct->TransformPersistence().IsNull()) - { - myBVHPrimitives.Add (theStruct); - } - else - { - myBVHPrimitivesTrsfPers.Add (theStruct); - } - } - ++myNbStructures; -} - -// ======================================================================= -// function : Remove -// purpose : -// ======================================================================= -bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct, - Standard_Integer& thePriority, - Standard_Boolean isForChangePriority) -{ - if (theStruct == NULL) - { - thePriority = -1; - return false; - } - - const Standard_Integer aNbPriorities = myArray.Length(); - for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) - { - OpenGl_IndexedMapOfStructure& aStructures = myArray (aPriorityIter); - - const Standard_Integer anIndex = aStructures.FindIndex (theStruct); - if (anIndex != 0) - { - aStructures.Swap (anIndex, aStructures.Size()); - aStructures.RemoveLast(); - - if (!isForChangePriority) - { - Standard_Boolean isAlwaysRend = theStruct->IsAlwaysRendered(); - if (!isAlwaysRend) - { - if (!myBVHPrimitives.Remove (theStruct)) - { - if (!myBVHPrimitivesTrsfPers.Remove (theStruct)) - { - isAlwaysRend = Standard_True; - } - } - } - if (isAlwaysRend) - { - const Standard_Integer anIndex2 = myAlwaysRenderedMap.FindIndex (theStruct); - if (anIndex2 != 0) - { - myAlwaysRenderedMap.Swap (myAlwaysRenderedMap.Size(), anIndex2); - myAlwaysRenderedMap.RemoveLast(); - } - } - } - --myNbStructures; - thePriority = aPriorityIter; - return true; - } - } - - thePriority = -1; - return false; -} - -// ======================================================================= -// function : InvalidateBVHData -// purpose : -// ======================================================================= -void OpenGl_Layer::InvalidateBVHData() -{ - myIsBVHPrimitivesNeedsReset = Standard_True; -} - -//! Calculate a finite bounding box of infinite object as its middle point. -inline Graphic3d_BndBox3d centerOfinfiniteBndBox (const Graphic3d_BndBox3d& theBndBox) -{ - // bounding borders of infinite line has been calculated as own point in center of this line - const Graphic3d_Vec3d aDiagVec = theBndBox.CornerMax() - theBndBox.CornerMin(); - return aDiagVec.SquareModulus() >= 500000.0 * 500000.0 - ? Graphic3d_BndBox3d ((theBndBox.CornerMin() + theBndBox.CornerMax()) * 0.5) - : Graphic3d_BndBox3d(); -} - -//! Return true if at least one vertex coordinate out of float range. -inline bool isInfiniteBndBox (const Graphic3d_BndBox3d& theBndBox) -{ - return Abs (theBndBox.CornerMax().x()) >= ShortRealLast() - || Abs (theBndBox.CornerMax().y()) >= ShortRealLast() - || Abs (theBndBox.CornerMax().z()) >= ShortRealLast() - || Abs (theBndBox.CornerMin().x()) >= ShortRealLast() - || Abs (theBndBox.CornerMin().y()) >= ShortRealLast() - || Abs (theBndBox.CornerMin().z()) >= ShortRealLast(); -} - -// ======================================================================= -// function : BoundingBox -// purpose : -// ======================================================================= -Bnd_Box OpenGl_Layer::BoundingBox (const Standard_Integer theViewId, - const Handle(Graphic3d_Camera)& theCamera, - const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight, - const Standard_Boolean theToIncludeAuxiliary) const -{ - updateBVH(); - - const Standard_Integer aBoxId = !theToIncludeAuxiliary ? 0 : 1; - const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix(); - const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix(); - if (myIsBoundingBoxNeedsReset[aBoxId]) - { - // Recompute layer bounding box - myBoundingBox[aBoxId].SetVoid(); - - for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) - { - const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value(); - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStructure = aStructIter.Value(); - if (!aStructure->IsVisible (theViewId)) - { - continue; - } - - // "FitAll" operation ignores object with transform persistence parameter - // but adds transform persistence point in a bounding box of layer (only zoom pers. objects). - if (!aStructure->TransformPersistence().IsNull()) - { - if (!theToIncludeAuxiliary - && aStructure->TransformPersistence()->IsZoomOrRotate()) - { - const gp_Pnt anAnchor = aStructure->TransformPersistence()->AnchorPoint(); - myBoundingBox[aBoxId].Add (anAnchor); - continue; - } - // Panning and 2d persistence apply changes to projection or/and its translation components. - // It makes them incompatible with z-fitting algorithm. Ignored by now. - else if (!theToIncludeAuxiliary - || aStructure->TransformPersistence()->IsTrihedronOr2d()) - { - continue; - } - } - - Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); - if (!aBox.IsValid()) - { - continue; - } - - if (aStructure->IsInfinite - && !theToIncludeAuxiliary) - { - // include center of infinite object - aBox = centerOfinfiniteBndBox (aBox); - } - - if (!aStructure->TransformPersistence().IsNull()) - { - aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); - } - - // skip too big boxes to prevent float overflow at camera parameters calculation - if (aBox.IsValid() - && !isInfiniteBndBox (aBox)) - { - myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z())); - myBoundingBox[aBoxId].Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z())); - } - } - } - - myIsBoundingBoxNeedsReset[aBoxId] = false; - } - - Bnd_Box aResBox = myBoundingBox[aBoxId]; - if (!theToIncludeAuxiliary - || myAlwaysRenderedMap.IsEmpty()) - { - return aResBox; - } - - // add transformation-persistent objects which depend on camera position (and thus can not be cached) for operations like Z-fit - for (NCollection_IndexedMap::Iterator aStructIter (myAlwaysRenderedMap); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStructure = aStructIter.Value(); - if (!aStructure->IsVisible (theViewId)) - { - continue; - } - else if (aStructure->TransformPersistence().IsNull() - || !aStructure->TransformPersistence()->IsTrihedronOr2d()) - { - continue; - } - - Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); - if (!aBox.IsValid()) - { - continue; - } - - aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); - if (aBox.IsValid() - && !isInfiniteBndBox (aBox)) - { - aResBox.Add (gp_Pnt (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z())); - aResBox.Add (gp_Pnt (aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z())); - } - } - - return aResBox; -} - -// ======================================================================= -// function : considerZoomPersistenceObjects -// purpose : -// ======================================================================= -Standard_Real OpenGl_Layer::considerZoomPersistenceObjects (const Standard_Integer theViewId, - const Handle(Graphic3d_Camera)& theCamera, - Standard_Integer theWindowWidth, - Standard_Integer theWindowHeight) const -{ - if (NbOfTransformPersistenceObjects() == 0) - { - return 1.0; - } - - const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix(); - const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix(); - Standard_Real aMaxCoef = -std::numeric_limits::max(); - - for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) - { - const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value(); - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStructure = aStructIter.Value(); - if (!aStructure->IsVisible (theViewId) - || aStructure->TransformPersistence().IsNull() - || !aStructure->TransformPersistence()->IsZoomOrRotate()) - { - continue; - } - - Graphic3d_BndBox3d aBox = aStructure->BoundingBox(); - if (!aBox.IsValid()) - { - continue; - } - - aStructure->TransformPersistence()->Apply (theCamera, aProjectionMat, aWorldViewMat, theWindowWidth, theWindowHeight, aBox); - - const BVH_Vec3d& aCornerMin = aBox.CornerMin(); - const BVH_Vec3d& aCornerMax = aBox.CornerMax(); - const Standard_Integer aNbOfPoints = 8; - const gp_Pnt aPoints[aNbOfPoints] = { gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMin.z()), - gp_Pnt (aCornerMin.x(), aCornerMin.y(), aCornerMax.z()), - gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMin.z()), - gp_Pnt (aCornerMin.x(), aCornerMax.y(), aCornerMax.z()), - gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMin.z()), - gp_Pnt (aCornerMax.x(), aCornerMin.y(), aCornerMax.z()), - gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMin.z()), - gp_Pnt (aCornerMax.x(), aCornerMax.y(), aCornerMax.z()) }; - gp_Pnt aConvertedPoints[aNbOfPoints]; - Standard_Real aConvertedMinX = std::numeric_limits::max(); - Standard_Real aConvertedMaxX = -std::numeric_limits::max(); - Standard_Real aConvertedMinY = std::numeric_limits::max(); - Standard_Real aConvertedMaxY = -std::numeric_limits::max(); - for (Standard_Integer anIdx = 0; anIdx < aNbOfPoints; ++anIdx) - { - aConvertedPoints[anIdx] = theCamera->Project (aPoints[anIdx]); - - aConvertedMinX = Min (aConvertedMinX, aConvertedPoints[anIdx].X()); - aConvertedMaxX = Max (aConvertedMaxX, aConvertedPoints[anIdx].X()); - - aConvertedMinY = Min (aConvertedMinY, aConvertedPoints[anIdx].Y()); - aConvertedMaxY = Max (aConvertedMaxY, aConvertedPoints[anIdx].Y()); - } - - const Standard_Boolean isBigObject = (Abs (aConvertedMaxX - aConvertedMinX) > 2.0) // width of zoom pers. object greater than width of window - || (Abs (aConvertedMaxY - aConvertedMinY) > 2.0); // height of zoom pers. object greater than height of window - const Standard_Boolean isAlreadyInScreen = (aConvertedMinX > -1.0 && aConvertedMinX < 1.0) - && (aConvertedMaxX > -1.0 && aConvertedMaxX < 1.0) - && (aConvertedMinY > -1.0 && aConvertedMinY < 1.0) - && (aConvertedMaxY > -1.0 && aConvertedMaxY < 1.0); - if (isBigObject || isAlreadyInScreen) - { - continue; - } - - const gp_Pnt aTPPoint = aStructure->TransformPersistence()->AnchorPoint(); - gp_Pnt aConvertedTPPoint = theCamera->Project (aTPPoint); - aConvertedTPPoint.SetZ (0.0); - - if (aConvertedTPPoint.Coord().Modulus() < Precision::Confusion()) - { - continue; - } - - Standard_Real aShiftX = 0.0; - if (aConvertedMinX < -1.0) - { - aShiftX = ((aConvertedMaxX < -1.0) ? (-(1.0 + aConvertedMaxX) + (aConvertedMaxX - aConvertedMinX)) : -(1.0 + aConvertedMinX)); - } - else if (aConvertedMaxX > 1.0) - { - aShiftX = ((aConvertedMinX > 1.0) ? ((aConvertedMinX - 1.0) + (aConvertedMaxX - aConvertedMinX)) : (aConvertedMaxX - 1.0)); - } - - Standard_Real aShiftY = 0.0; - if (aConvertedMinY < -1.0) - { - aShiftY = ((aConvertedMaxY < -1.0) ? (-(1.0 + aConvertedMaxY) + (aConvertedMaxY - aConvertedMinY)) : -(1.0 + aConvertedMinY)); - } - else if (aConvertedMaxY > 1.0) - { - aShiftY = ((aConvertedMinY > 1.0) ? ((aConvertedMinY - 1.0) + (aConvertedMaxY - aConvertedMinY)) : (aConvertedMaxY - 1.0)); - } - - const Standard_Real aDifX = Abs (aConvertedTPPoint.X()) - aShiftX; - const Standard_Real aDifY = Abs (aConvertedTPPoint.Y()) - aShiftY; - if (aDifX > Precision::Confusion()) - { - aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.X()) / aDifX); - } - if (aDifY > Precision::Confusion()) - { - aMaxCoef = Max (aMaxCoef, Abs (aConvertedTPPoint.Y()) / aDifY); - } - } - } - - return (aMaxCoef > 0.0) ? aMaxCoef : 1.0; -} - -// ======================================================================= -// function : renderAll -// purpose : -// ======================================================================= -void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const -{ - const Standard_Integer aViewId = theWorkspace->View()->Identification(); - for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) - { - const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value(); - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStruct = aStructIter.Value(); - if (aStruct->IsCulled() - || !aStruct->IsVisible (aViewId)) - { - continue; - } - - aStruct->Render (theWorkspace); - } - } -} - -// ======================================================================= -// function : updateBVH -// purpose : -// ======================================================================= -void OpenGl_Layer::updateBVH() const -{ - if (!myIsBVHPrimitivesNeedsReset) - { - return; - } - - myBVHPrimitives.Clear(); - myBVHPrimitivesTrsfPers.Clear(); - myAlwaysRenderedMap.Clear(); - myIsBVHPrimitivesNeedsReset = Standard_False; - for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) - { - const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value(); - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStruct = aStructIter.Value(); - if (aStruct->IsAlwaysRendered()) - { - aStruct->MarkAsNotCulled(); - myAlwaysRenderedMap.Add (aStruct); - } - else if (aStruct->TransformPersistence().IsNull()) - { - myBVHPrimitives.Add (aStruct); - } - else - { - myBVHPrimitivesTrsfPers.Add (aStruct); - } - } - } -} - -// ======================================================================= -// function : UpdateCulling -// purpose : -// ======================================================================= -void OpenGl_Layer::UpdateCulling (const Standard_Integer theViewId, - const OpenGl_BVHTreeSelector& theSelector, - const Graphic3d_RenderingParams::FrustumCulling theFrustumCullingState) -{ - updateBVH(); - - myNbStructuresNotCulled = myNbStructures; - if (theFrustumCullingState != Graphic3d_RenderingParams::FrustumCulling_NoUpdate) - { - Standard_Boolean toTraverse = - (theFrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On); - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myBVHPrimitives.Structures()); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStruct = aStructIter.Value(); - aStruct->SetCulled (toTraverse); - } - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myBVHPrimitivesTrsfPers.Structures()); aStructIter.More(); aStructIter.Next()) - { - const OpenGl_Structure* aStruct = aStructIter.Value(); - aStruct->SetCulled (toTraverse); - } - } - - if (theFrustumCullingState != Graphic3d_RenderingParams::FrustumCulling_On) - { - return; - } - if (myBVHPrimitives .Size() == 0 - && myBVHPrimitivesTrsfPers.Size() == 0) - { - return; - } - - myNbStructuresNotCulled = myAlwaysRenderedMap.Extent(); - OpenGl_BVHTreeSelector::CullingContext aCullCtx; - theSelector.SetCullingDistance(aCullCtx, myLayerSettings.CullingDistance()); - theSelector.SetCullingSize (aCullCtx, myLayerSettings.CullingSize()); - for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) - { - const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1; - opencascade::handle > aBVHTree; - if (isTrsfPers) - { - if (myBVHPrimitivesTrsfPers.Size() == 0) - continue; - - const OpenGl_Mat4d& aProjection = theSelector.ProjectionMatrix(); - const OpenGl_Mat4d& aWorldView = theSelector.WorldViewMatrix(); - const Graphic3d_WorldViewProjState& aWVPState = theSelector.WorldViewProjState(); - const Standard_Integer aViewportWidth = theSelector.ViewportWidth(); - const Standard_Integer aViewportHeight = theSelector.ViewportHeight(); - - aBVHTree = myBVHPrimitivesTrsfPers.BVH (theSelector.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); - } - else - { - if (myBVHPrimitives.Size() == 0) - continue; - - aBVHTree = myBVHPrimitives.BVH(); - } - - if (theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0))) - { - continue; - } - - Standard_Integer aStack[BVH_Constants_MaxTreeDepth]; - Standard_Integer aHead = -1; - Standard_Integer aNode = 0; // a root node - for (;;) - { - if (!aBVHTree->IsOuter (aNode)) - { - const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode); - const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode); - const Standard_Boolean isLeftChildIn = !theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx)); - const Standard_Boolean isRightChildIn = !theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx)); - if (isLeftChildIn - && isRightChildIn) - { - aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx; - aStack[++aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx; - myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst; - } - else if (isLeftChildIn - || isRightChildIn) - { - aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx; - } - else - { - if (aHead < 0) - { - break; - } - - aNode = aStack[aHead--]; - } - } - else - { - Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode); - const OpenGl_Structure* aStruct = isTrsfPers - ? myBVHPrimitivesTrsfPers.GetStructureById (aIdx) - : myBVHPrimitives.GetStructureById (aIdx); - if (aStruct->IsVisible (theViewId)) - { - aStruct->MarkAsNotCulled(); - ++myNbStructuresNotCulled; - } - if (aHead < 0) - { - break; - } - - aNode = aStack[aHead--]; - } - } - } -} - -// ======================================================================= -// function : Append -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther) -{ - // the source priority list shouldn't have more priorities - const Standard_Integer aNbPriorities = theOther.NbPriorities(); - if (aNbPriorities > NbPriorities()) - { - return Standard_False; - } - - // add all structures to destination priority list - for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter) - { - const OpenGl_IndexedMapOfStructure& aStructures = theOther.myArray (aPriorityIter); - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) - { - Add (aStructIter.Value(), aPriorityIter); - } - } - - return Standard_True; -} - -//======================================================================= -//function : SetLayerSettings -//purpose : -//======================================================================= -void OpenGl_Layer::SetLayerSettings (const Graphic3d_ZLayerSettings& theSettings) -{ - const Standard_Boolean toUpdateTrsf = !myLayerSettings.Origin().IsEqual (theSettings.Origin(), gp::Resolution()); - myLayerSettings = theSettings; - if (toUpdateTrsf) - { - for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) - { - OpenGl_IndexedMapOfStructure& aStructures = aMapIter.ChangeValue(); - for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) - { - OpenGl_Structure* aStructure = const_cast (aStructIter.Value()); - aStructure->updateLayerTransformation(); - } - } - } -} - -//======================================================================= -//function : Render -//purpose : -//======================================================================= -void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace, - const OpenGl_GlobalLayerSettings& theDefaultSettings) const -{ - const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); - // myLayerSettings.ToClearDepth() is handled outside - - // handle depth test - if (myLayerSettings.ToEnableDepthTest()) - { - // assuming depth test is enabled by default - glDepthFunc (theDefaultSettings.DepthFunc); - } - else - { - glDepthFunc (GL_ALWAYS); - } - - // save environment texture - Handle(OpenGl_TextureSet) anEnvironmentTexture = theWorkspace->EnvironmentTexture(); - if (!myLayerSettings.UseEnvironmentTexture()) - { - theWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)()); - } - - // handle depth offset - const Graphic3d_PolygonOffset anAppliedOffsetParams = theWorkspace->SetDefaultPolygonOffset (myLayerSettings.PolygonOffset()); - - // handle depth write - theWorkspace->UseDepthWrite() = myLayerSettings.ToEnableDepthWrite() && theDefaultSettings.DepthMask == GL_TRUE; - glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE); - - const Standard_Boolean hasLocalCS = !myLayerSettings.OriginTransformation().IsNull(); - const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); - Handle(Graphic3d_LightSet) aLightsBack = aManager->LightSourceState().LightSources(); - const bool hasOwnLights = aCtx->ColorMask() && !myLayerSettings.Lights().IsNull() && myLayerSettings.Lights() != aLightsBack; - if (hasOwnLights) - { - myLayerSettings.Lights()->UpdateRevision(); - aManager->UpdateLightSourceStateTo (myLayerSettings.Lights()); - } - - const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera(); - if (hasLocalCS) - { - // Apply local camera transformation. - // The vertex position is computed by the following formula in GLSL program: - // gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex; - // where: - // occProjectionMatrix - matrix defining orthographic/perspective/stereographic projection - // occWorldViewMatrix - world-view matrix defining Camera position and orientation - // occModelWorldMatrix - model-world matrix defining Object transformation from local coordinate system to the world coordinate system - // occVertex - input vertex position - // - // Since double precision is quite expensive on modern GPUs, and not available on old hardware, - // all these values are passed with single float precision to the shader. - // As result, single precision become insufficient for handling objects far from the world origin. - // - // Several approaches can be used to solve precision issues: - // - [Broute force] migrate to double precision for all matrices and vertex position. - // This is too expensive for most hardware. - // - Store only translation part with double precision and pass it to GLSL program. - // This requires modified GLSL programs for computing transformation - // and extra packing mechanism for hardware not supporting double precision natively. - // This solution is less expensive then previous one. - // - Move translation part of occModelWorldMatrix into occWorldViewMatrix. - // The main idea here is that while moving Camera towards the object, - // Camera translation part and Object translation part will compensate each other - // to fit into single float precision. - // But this operation should be performed with double precision - this is why we are moving - // translation part of occModelWorldMatrix to occWorldViewMatrix. - // - // All approaches might be useful in different scenarios, but for the moment we consider the last one as main scenario. - // Here we do the trick: - // - OpenGl_Layer defines the Local Origin, which is expected to be the center of objects stored within it. - // This Local Origin is included into occWorldViewMatrix during rendering. - // - OpenGl_Structure defines Object local transformation occModelWorldMatrix with subtracted Local Origin of the Layer. - // This means that Object itself should be defined within either Local Transformation equal or near to Local Origin of the Layer. - theWorkspace->View()->SetLocalOrigin (myLayerSettings.Origin()); - - NCollection_Mat4 aWorldView = aWorldCamera->OrientationMatrix(); - Graphic3d_TransformUtils::Translate (aWorldView, myLayerSettings.Origin().X(), myLayerSettings.Origin().Y(), myLayerSettings.Origin().Z()); - - NCollection_Mat4 aWorldViewF; - aWorldViewF.ConvertFrom (aWorldView); - aCtx->WorldViewState.SetCurrent (aWorldViewF); - aCtx->ShaderManager()->UpdateClippingState(); - aCtx->ShaderManager()->UpdateLightSourceState(); - } - - // render priority list - renderAll (theWorkspace); - - if (hasOwnLights) - { - aManager->UpdateLightSourceStateTo (aLightsBack); - } - if (hasLocalCS) - { - aCtx->ShaderManager()->RevertClippingState(); - aCtx->ShaderManager()->UpdateLightSourceState(); - - aCtx->WorldViewState.SetCurrent (aWorldCamera->OrientationMatrixF()); - theWorkspace->View() ->SetLocalOrigin (gp_XYZ (0.0, 0.0, 0.0)); - } - - // always restore polygon offset between layers rendering - theWorkspace->SetDefaultPolygonOffset (anAppliedOffsetParams); - - // restore environment texture - if (!myLayerSettings.UseEnvironmentTexture()) - { - theWorkspace->SetEnvironmentTexture (anEnvironmentTexture); - } -} diff --git a/src/OpenGl/OpenGl_Layer.hxx b/src/OpenGl/OpenGl_Layer.hxx index 8fe3f46ec6..09a2e91538 100644 --- a/src/OpenGl/OpenGl_Layer.hxx +++ b/src/OpenGl/OpenGl_Layer.hxx @@ -16,185 +16,8 @@ #ifndef _OpenGl_Layer_Header #define _OpenGl_Layer_Header -#include -#include +#include -#include -#include -#include - -#include -#include -#include - - -struct OpenGl_GlobalLayerSettings -{ - GLint DepthFunc; - GLboolean DepthMask; -}; - -//! Defines index map of OpenGL structures. -typedef NCollection_IndexedMap OpenGl_IndexedMapOfStructure; - -//! Defines array of indexed maps of OpenGL structures. -typedef NCollection_Array1 OpenGl_ArrayOfIndexedMapOfStructure; - -//! Presentations list sorted within priorities. -class OpenGl_Layer : public Standard_Transient -{ - DEFINE_STANDARD_RTTIEXT(OpenGl_Layer, Standard_Transient) -public: - - //! Initializes associated priority list and layer properties - OpenGl_Layer (const Standard_Integer theNbPriorities, - const Handle(Select3D_BVHBuilder3d)& theBuilder); - - //! Destructor. - virtual ~OpenGl_Layer(); - - //! Returns BVH tree builder for frustom culling. - const Handle(Select3D_BVHBuilder3d)& FrustumCullingBVHBuilder() const { return myBVHPrimitivesTrsfPers.Builder(); } - - //! Assigns BVH tree builder for frustom culling. - void SetFrustumCullingBVHBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder) { myBVHPrimitivesTrsfPers.SetBuilder (theBuilder); } - - //! Return true if layer was marked with immediate flag. - Standard_Boolean IsImmediate() const { return myLayerSettings.IsImmediate(); } - - //! Returns settings of the layer object. - const Graphic3d_ZLayerSettings& LayerSettings() const { return myLayerSettings; }; - - //! Sets settings of the layer object. - void SetLayerSettings (const Graphic3d_ZLayerSettings& theSettings); - - void Add (const OpenGl_Structure* theStruct, - const Standard_Integer thePriority, - Standard_Boolean isForChangePriority = Standard_False); - - //! Remove structure and returns its priority, if the structure is not found, method returns negative value - bool Remove (const OpenGl_Structure* theStruct, - Standard_Integer& thePriority, - Standard_Boolean isForChangePriority = Standard_False); - - //! @return the number of structures - Standard_Integer NbStructures() const { return myNbStructures; } - - //! Number of NOT culled structures in the layer. - Standard_Integer NbStructuresNotCulled() const { return myNbStructuresNotCulled; } - - //! Returns the number of available priority levels - Standard_Integer NbPriorities() const { return myArray.Length(); } - - //! Append layer of acceptable type (with similar number of priorities or less). - //! Returns Standard_False if the list can not be accepted. - Standard_Boolean Append (const OpenGl_Layer& theOther); - - //! Returns array of OpenGL structures. - const OpenGl_ArrayOfIndexedMapOfStructure& ArrayOfStructures() const { return myArray; } - - //! Marks BVH tree for given priority list as dirty and - //! marks primitive set for rebuild. - void InvalidateBVHData(); - - //! Marks cached bounding box as obsolete. - void InvalidateBoundingBox() const - { - myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true; - } - - //! Returns layer bounding box. - //! @param theViewId view index to consider View Affinity in structure - //! @param theCamera camera definition - //! @param theWindowWidth viewport width (for applying transformation-persistence) - //! @param theWindowHeight viewport height (for applying transformation-persistence) - //! @param theToIncludeAuxiliary consider also auxiliary presentations (with infinite flag or with trihedron transformation persistence) - //! @return computed bounding box - Bnd_Box BoundingBox (const Standard_Integer theViewId, - const Handle(Graphic3d_Camera)& theCamera, - const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight, - const Standard_Boolean theToIncludeAuxiliary) const; - - //! Returns zoom-scale factor. - Standard_Real considerZoomPersistenceObjects (const Standard_Integer theViewId, - const Handle(Graphic3d_Camera)& theCamera, - const Standard_Integer theWindowWidth, - const Standard_Integer theWindowHeight) const; - - //! Update culling state - should be called before rendering. - //! Traverses through BVH tree to determine which structures are in view volume. - void UpdateCulling (const Standard_Integer theViewId, - const OpenGl_BVHTreeSelector& theSelector, - const Graphic3d_RenderingParams::FrustumCulling theFrustumCullingState); - - //! Returns TRUE if layer is empty or has been discarded entirely by culling test. - bool IsCulled() const { return myNbStructuresNotCulled == 0; } - - // Render all structures. - void Render (const Handle(OpenGl_Workspace)& theWorkspace, - const OpenGl_GlobalLayerSettings& theDefaultSettings) const; - - //! Returns number of transform persistence objects. - Standard_Integer NbOfTransformPersistenceObjects() const - { - return myBVHPrimitivesTrsfPers.Size(); - } - -public: - - //! Returns set of OpenGl_Structures structures for building BVH tree. - const OpenGl_BVHClipPrimitiveSet& CullableStructuresBVH() const { return myBVHPrimitives; } - - //! Returns set of transform persistent OpenGl_Structures for building BVH tree. - const OpenGl_BVHClipPrimitiveTrsfPersSet& CullableTrsfPersStructuresBVH() const { return myBVHPrimitivesTrsfPers; } - - //! Returns indexed map of always rendered structures. - const NCollection_IndexedMap& NonCullableStructures() const { return myAlwaysRenderedMap; } - -protected: - - //! Updates BVH trees if their state has been invalidated. - Standard_EXPORT void updateBVH() const; - - //! Iterates through the hierarchical list of existing structures and renders them all. - Standard_EXPORT void renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const; - -private: - - //! Array of OpenGl_Structures by priority rendered in layer. - OpenGl_ArrayOfIndexedMapOfStructure myArray; - - //! Overall number of structures rendered in the layer. - Standard_Integer myNbStructures; - - //! Number of NOT culled structures in the layer. - Standard_Integer myNbStructuresNotCulled; - - //! Layer setting flags. - Graphic3d_ZLayerSettings myLayerSettings; - - //! Set of OpenGl_Structures structures for building BVH tree. - mutable OpenGl_BVHClipPrimitiveSet myBVHPrimitives; - - //! Set of transform persistent OpenGl_Structures for building BVH tree. - mutable OpenGl_BVHClipPrimitiveTrsfPersSet myBVHPrimitivesTrsfPers; - - //! Indexed map of always rendered structures. - mutable NCollection_IndexedMap myAlwaysRenderedMap; - - //! Is needed for implementation of stochastic order of BVH traverse. - Standard_Boolean myBVHIsLeftChildQueuedFirst; - - //! Defines if the primitive set for BVH is outdated. - mutable Standard_Boolean myIsBVHPrimitivesNeedsReset; - - //! Defines if the cached bounding box is outdated. - mutable bool myIsBoundingBoxNeedsReset[2]; - - //! Cached layer bounding box. - mutable Bnd_Box myBoundingBox[2]; - -}; +typedef Graphic3d_Layer OpenGl_Layer; #endif //_OpenGl_Layer_Header diff --git a/src/OpenGl/OpenGl_LayerList.cxx b/src/OpenGl/OpenGl_LayerList.cxx index 2948219289..4aee97b5e0 100644 --- a/src/OpenGl/OpenGl_LayerList.cxx +++ b/src/OpenGl/OpenGl_LayerList.cxx @@ -137,6 +137,12 @@ namespace }; } +struct OpenGl_GlobalLayerSettings +{ + GLint DepthFunc; + GLboolean DepthMask; +}; + //======================================================================= //function : OpenGl_LayerList //purpose : Constructor @@ -519,7 +525,7 @@ void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspa aTimer.Start(); const Standard_Integer aViewId = theWorkspace->View()->Identification(); - const OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector(); + const Graphic3d_CullingTool& aSelector = theWorkspace->View()->BVHTreeSelector(); for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next()) { OpenGl_Layer& aLayer = *anIts.ChangeValue(); @@ -535,6 +541,143 @@ void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspa aStats->ActiveDataFrame()[Graphic3d_FrameStatsTimer_CpuCulling] = aTimer.UserTimeCPU(); } +//======================================================================= +//function : renderLayer +//purpose : +//======================================================================= +void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace, + const OpenGl_GlobalLayerSettings& theDefaultSettings, + const Graphic3d_Layer& theLayer) const +{ + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); + + const Graphic3d_ZLayerSettings& aLayerSettings = theLayer.LayerSettings(); + // aLayerSettings.ToClearDepth() is handled outside + + // handle depth test + if (aLayerSettings.ToEnableDepthTest()) + { + // assuming depth test is enabled by default + glDepthFunc (theDefaultSettings.DepthFunc); + } + else + { + glDepthFunc (GL_ALWAYS); + } + + // save environment texture + Handle(OpenGl_TextureSet) anEnvironmentTexture = theWorkspace->EnvironmentTexture(); + if (!aLayerSettings.UseEnvironmentTexture()) + { + theWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)()); + } + + // handle depth offset + const Graphic3d_PolygonOffset anAppliedOffsetParams = theWorkspace->SetDefaultPolygonOffset (aLayerSettings.PolygonOffset()); + + // handle depth write + theWorkspace->UseDepthWrite() = aLayerSettings.ToEnableDepthWrite() && theDefaultSettings.DepthMask == GL_TRUE; + glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE); + + const Standard_Boolean hasLocalCS = !aLayerSettings.OriginTransformation().IsNull(); + const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); + Handle(Graphic3d_LightSet) aLightsBack = aManager->LightSourceState().LightSources(); + const bool hasOwnLights = aCtx->ColorMask() && !aLayerSettings.Lights().IsNull() && aLayerSettings.Lights() != aLightsBack; + if (hasOwnLights) + { + aLayerSettings.Lights()->UpdateRevision(); + aManager->UpdateLightSourceStateTo (aLayerSettings.Lights()); + } + + const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera(); + if (hasLocalCS) + { + // Apply local camera transformation. + // The vertex position is computed by the following formula in GLSL program: + // gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex; + // where: + // occProjectionMatrix - matrix defining orthographic/perspective/stereographic projection + // occWorldViewMatrix - world-view matrix defining Camera position and orientation + // occModelWorldMatrix - model-world matrix defining Object transformation from local coordinate system to the world coordinate system + // occVertex - input vertex position + // + // Since double precision is quite expensive on modern GPUs, and not available on old hardware, + // all these values are passed with single float precision to the shader. + // As result, single precision become insufficient for handling objects far from the world origin. + // + // Several approaches can be used to solve precision issues: + // - [Broute force] migrate to double precision for all matrices and vertex position. + // This is too expensive for most hardware. + // - Store only translation part with double precision and pass it to GLSL program. + // This requires modified GLSL programs for computing transformation + // and extra packing mechanism for hardware not supporting double precision natively. + // This solution is less expensive then previous one. + // - Move translation part of occModelWorldMatrix into occWorldViewMatrix. + // The main idea here is that while moving Camera towards the object, + // Camera translation part and Object translation part will compensate each other + // to fit into single float precision. + // But this operation should be performed with double precision - this is why we are moving + // translation part of occModelWorldMatrix to occWorldViewMatrix. + // + // All approaches might be useful in different scenarios, but for the moment we consider the last one as main scenario. + // Here we do the trick: + // - OpenGl_Layer defines the Local Origin, which is expected to be the center of objects stored within it. + // This Local Origin is included into occWorldViewMatrix during rendering. + // - OpenGl_Structure defines Object local transformation occModelWorldMatrix with subtracted Local Origin of the Layer. + // This means that Object itself should be defined within either Local Transformation equal or near to Local Origin of the Layer. + theWorkspace->View()->SetLocalOrigin (aLayerSettings.Origin()); + + NCollection_Mat4 aWorldView = aWorldCamera->OrientationMatrix(); + Graphic3d_TransformUtils::Translate (aWorldView, aLayerSettings.Origin().X(), aLayerSettings.Origin().Y(), aLayerSettings.Origin().Z()); + + NCollection_Mat4 aWorldViewF; + aWorldViewF.ConvertFrom (aWorldView); + aCtx->WorldViewState.SetCurrent (aWorldViewF); + aCtx->ShaderManager()->UpdateClippingState(); + aCtx->ShaderManager()->UpdateLightSourceState(); + } + + // render priority list + const Standard_Integer aViewId = theWorkspace->View()->Identification(); + for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aMapIter (theLayer.ArrayOfStructures()); aMapIter.More(); aMapIter.Next()) + { + const Graphic3d_IndexedMapOfStructure& aStructures = aMapIter.Value(); + for (OpenGl_Structure::StructIterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) + { + const OpenGl_Structure* aStruct = aStructIter.Value(); + if (aStruct->IsCulled() + || !aStruct->IsVisible (aViewId)) + { + continue; + } + + aStruct->Render (theWorkspace); + } + } + + if (hasOwnLights) + { + aManager->UpdateLightSourceStateTo (aLightsBack); + } + if (hasLocalCS) + { + aCtx->ShaderManager()->RevertClippingState(); + aCtx->ShaderManager()->UpdateLightSourceState(); + + aCtx->WorldViewState.SetCurrent (aWorldCamera->OrientationMatrixF()); + theWorkspace->View() ->SetLocalOrigin (gp_XYZ (0.0, 0.0, 0.0)); + } + + // always restore polygon offset between layers rendering + theWorkspace->SetDefaultPolygonOffset (anAppliedOffsetParams); + + // restore environment texture + if (!aLayerSettings.UseEnvironmentTexture()) + { + theWorkspace->SetEnvironmentTexture (anEnvironmentTexture); + } +} + //======================================================================= //function : Render //purpose : @@ -652,7 +795,7 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace, // the transparency post-processing stack. theWorkspace->ResetSkippedCounter(); - aLayer.Render (theWorkspace, aDefaultSettings); + renderLayer (theWorkspace, aDefaultSettings, aLayer); if (aPassIter != 0 && theWorkspace->NbSkippedTransparentElements() > 0) @@ -751,7 +894,7 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theW for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter) { - (*theLayerIter)->Render (theWorkspace, aGlobalSettings); + renderLayer (theWorkspace, aGlobalSettings, *(*theLayerIter)); } // Revert state of rendering. diff --git a/src/OpenGl/OpenGl_LayerList.hxx b/src/OpenGl/OpenGl_LayerList.hxx index 3701607734..813bc47807 100644 --- a/src/OpenGl/OpenGl_LayerList.hxx +++ b/src/OpenGl/OpenGl_LayerList.hxx @@ -19,12 +19,15 @@ #include #include +#include #include #include #include #include class OpenGl_Structure; +class OpenGl_Workspace; +struct OpenGl_GlobalLayerSettings; typedef NCollection_Sequence OpenGl_SequenceOfLayers; typedef NCollection_DataMap OpenGl_LayerSeqIds; @@ -124,14 +127,14 @@ protected: class OpenGl_LayerStack { public: - typedef NCollection_Array1::iterator iterator; + typedef NCollection_Array1::iterator iterator; //! Reallocate internal buffer of the stack. void Allocate (Standard_Integer theSize) { if (theSize > 0) { - myStackSpace = new NCollection_Array1 (1, theSize); + myStackSpace = new NCollection_Array1 (1, theSize); myStackSpace->Init (NULL); myBackPtr = myStackSpace->begin(); } @@ -185,6 +188,11 @@ protected: OpenGl_FrameBuffer* theReadDrawFbo, OpenGl_FrameBuffer* theOitAccumFbo) const; + // Render structures within specified layer. + void renderLayer (const Handle(OpenGl_Workspace)& theWorkspace, + const OpenGl_GlobalLayerSettings& theDefaultSettings, + const Graphic3d_Layer& theLayer) const; + protected: // number of structures temporary put to default layer diff --git a/src/OpenGl/OpenGl_MapOfZLayerSettings.hxx b/src/OpenGl/OpenGl_MapOfZLayerSettings.hxx deleted file mode 100644 index 09977a00e7..0000000000 --- a/src/OpenGl/OpenGl_MapOfZLayerSettings.hxx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _OpenGl_MapOfZLayerSettings_HeaderFile -#define _OpenGl_MapOfZLayerSettings_HeaderFile - -#include -#include -#include -#include - -typedef NCollection_DataMap OpenGl_MapOfZLayerSettings; - -#endif // _OpenGl_MapOfZLayerSettings_HeaderFile diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index d31a32e1ef..e3188fef8f 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -107,7 +107,6 @@ OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& th myInstancedStructure (NULL), myIsRaytracable (Standard_False), myModificationState (0), - myIsCulled (Standard_True), myIsMirrored (Standard_False) { updateLayerTransformation(); diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index da00070e47..58c3a0e29f 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -29,33 +29,23 @@ #include -class OpenGl_Structure; class OpenGl_GraphicDriver; +DEFINE_STANDARD_HANDLE(OpenGl_Structure, Graphic3d_CStructure) typedef NCollection_List OpenGl_ListOfStructure; //! Implementation of low-level graphic structure. class OpenGl_Structure : public Graphic3d_CStructure { friend class OpenGl_Group; - + DEFINE_STANDARD_RTTIEXT(OpenGl_Structure, Graphic3d_CStructure) public: - //! Auxiliary wrapper to iterate OpenGl_Group sequence. - class GroupIterator - { - - public: - GroupIterator (const Graphic3d_SequenceOfGroup& theGroups) : myIter (theGroups) {} - Standard_Boolean More() const { return myIter.More(); } - void Next() { myIter.Next(); } - const OpenGl_Group* Value() const { return (const OpenGl_Group* )(myIter.Value().operator->()); } - OpenGl_Group* ChangeValue() { return (OpenGl_Group* )(myIter.ChangeValue().operator->()); } + //! Auxiliary wrapper to iterate OpenGl_Structure sequence. + typedef SubclassStructIterator StructIterator; - private: - Graphic3d_SequenceOfGroup::Iterator myIter; - - }; + //! Auxiliary wrapper to iterate OpenGl_Group sequence. + typedef SubclassGroupIterator GroupIterator; public: @@ -115,28 +105,6 @@ public: //! Releases structure resources. virtual void Release (const Handle(OpenGl_Context)& theGlCtx); - //! Marks structure as culled/not culled - note that IsAlwaysRendered() is ignored here! - void SetCulled (Standard_Boolean theIsCulled) const { myIsCulled = theIsCulled; } - - //! Marks structure as overlapping the current view volume one. - //! The method is called during traverse of BVH tree. - void MarkAsNotCulled() const { myIsCulled = Standard_False; } - - //! Returns Standard_False if the structure hits the current view volume, otherwise - //! returns Standard_True. The default value for all structures before each traverse - //! of BVH tree is Standard_True. - Standard_Boolean IsCulled() const { return myIsCulled; } - - //! Checks if the structure should be included into BVH tree or not. - Standard_Boolean IsAlwaysRendered() const - { - return IsInfinite - || IsForHighlight - || IsMutable - || Is2dText - || (!myTrsfPers.IsNull() && myTrsfPers->IsTrihedronOr2d()); - } - //! This method releases GL resources without actual elements destruction. //! As result structure could be correctly destroyed layer without GL context //! (after last window was closed for example). @@ -158,7 +126,7 @@ public: Standard_Boolean IsRaytracable() const; //! Update render transformation matrix. - Standard_EXPORT void updateLayerTransformation(); + Standard_EXPORT virtual void updateLayerTransformation() Standard_OVERRIDE; protected: @@ -184,16 +152,8 @@ protected: mutable Standard_Boolean myIsRaytracable; mutable Standard_Size myModificationState; - mutable Standard_Boolean myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse. - Standard_Boolean myIsMirrored; //!< Used to tell OpenGl to interpret polygons in clockwise order. -public: - - DEFINE_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure) // Type definition - }; -DEFINE_STANDARD_HANDLE(OpenGl_Structure, Graphic3d_CStructure) - #endif // OpenGl_Structure_Header diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 14495041f5..a3a388b8f7 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -51,8 +51,6 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr, myCaps (theCaps), myWasRedrawnGL (Standard_False), myBackfacing (Graphic3d_TOBM_AUTOMATIC), - myBgColor (Quantity_NOC_BLACK), - myCamera (new Graphic3d_Camera()), myToShowGradTrihedron (false), myZLayers (Structure_MAX_PRIORITY - Structure_MIN_PRIORITY + 1), myStateCounter (theCounter), @@ -192,15 +190,6 @@ void OpenGl_View::Remove() Graphic3d_CView::Remove(); } -// ======================================================================= -// function : SetTextureEnv -// purpose : -// ======================================================================= -void OpenGl_View::SetCamera(const Handle(Graphic3d_Camera)& theCamera) -{ - myCamera = theCamera; -} - // ======================================================================= // function : SetLocalOrigin // purpose : @@ -420,24 +409,6 @@ Standard_Boolean OpenGl_View::BufferDump (Image_PixMap& theImage, const Graphic3 #endif } -// ======================================================================= -// function : Background -// purpose : -// ======================================================================= -Aspect_Background OpenGl_View::Background() const -{ - return Aspect_Background (myBgColor.GetRGB()); -} - -// ======================================================================= -// function : SetBackground -// purpose : -// ======================================================================= -void OpenGl_View::SetBackground (const Aspect_Background& theBackground) -{ - myBgColor.SetRGB (theBackground.Color()); -} - // ======================================================================= // function : GradientBackground // purpose : diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 15a3b9e82c..44ead7cef8 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -37,7 +38,6 @@ #include #include -#include #include #include #include @@ -127,21 +127,6 @@ public: //! Return true if view content cache has been invalidated. virtual Standard_Boolean IsInvalidated() Standard_OVERRIDE { return !myBackBufferRestored; } - //! Returns data of a graduated trihedron - const Graphic3d_GraduatedTrihedron& GetGraduatedTrihedron() Standard_OVERRIDE - { return myGTrihedronData; } - - //! Displays Graduated Trihedron. - Standard_EXPORT virtual void GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData) Standard_OVERRIDE; - - //! Erases Graduated Trihedron. - Standard_EXPORT virtual void GraduatedTrihedronErase() Standard_OVERRIDE; - - //! Sets minimum and maximum points of scene bounding box for Graduated Trihedron stored in graphic view object. - //! @param theMin [in] the minimum point of scene. - //! @param theMax [in] the maximum point of scene. - Standard_EXPORT virtual void GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax) Standard_OVERRIDE; - //! Dump active rendering buffer into specified memory buffer. //! In Ray-Tracing allow to get a raw HDR buffer using Graphic3d_BT_RGB_RayTraceHdrLeft buffer type, //! only Left view will be dumped ignoring stereoscopic parameter. @@ -211,12 +196,6 @@ public: public: - //! Returns background fill color. - Standard_EXPORT virtual Aspect_Background Background() const Standard_OVERRIDE; - - //! Sets background fill color. - Standard_EXPORT virtual void SetBackground (const Aspect_Background& theBackground) Standard_OVERRIDE; - //! Returns gradient background fill colors. Standard_EXPORT virtual Aspect_GradientBackground GradientBackground() const Standard_OVERRIDE; @@ -247,18 +226,12 @@ public: //! Sets backfacing model for the view. virtual void SetBackfacingModel (const Graphic3d_TypeOfBackfacingModel theModel) Standard_OVERRIDE { myBackfacing = theModel; } - //! Returns camera object of the view. - virtual const Handle(Graphic3d_Camera)& Camera() const Standard_OVERRIDE { return myCamera; } - //! Returns local camera origin currently set for rendering, might be modified during rendering. const gp_XYZ& LocalOrigin() const { return myLocalOrigin; } //! Setup local camera origin currently set for rendering. Standard_EXPORT void SetLocalOrigin (const gp_XYZ& theOrigin); - //! Sets camera used by the view. - Standard_EXPORT virtual void SetCamera (const Handle(Graphic3d_Camera)& theCamera) Standard_OVERRIDE; - //! Returns list of lights of the view. virtual const Handle(Graphic3d_LightSet)& Lights() const Standard_OVERRIDE { return myLights; } @@ -319,7 +292,7 @@ public: //! Returns selector for BVH tree, providing a possibility to store information //! about current view volume and to detect which objects are overlapping it. - const OpenGl_BVHTreeSelector& BVHTreeSelector() const { return myBVHSelector; } + const Graphic3d_CullingTool& BVHTreeSelector() const { return myBVHSelector; } //! Returns true if there are immediate structures to display bool HasImmediateStructures() const @@ -327,6 +300,19 @@ public: return myZLayers.NbImmediateStructures() != 0; } +public: //! @name obsolete Graduated Trihedron functionality + + //! Displays Graduated Trihedron. + Standard_EXPORT virtual void GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData) Standard_OVERRIDE; + + //! Erases Graduated Trihedron. + Standard_EXPORT virtual void GraduatedTrihedronErase() Standard_OVERRIDE; + + //! Sets minimum and maximum points of scene bounding box for Graduated Trihedron stored in graphic view object. + //! @param theMin [in] the minimum point of scene. + //! @param theMax [in] the maximum point of scene. + Standard_EXPORT virtual void GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax) Standard_OVERRIDE; + protected: //! @name Internal methods for managing GL resources //! Initializes OpenGl resource for environment texture. @@ -458,9 +444,7 @@ protected: Standard_Boolean myWasRedrawnGL; Graphic3d_TypeOfBackfacingModel myBackfacing; - Quantity_ColorRGBA myBgColor; Handle(Graphic3d_SequenceOfHClipPlane) myClipPlanes; - Handle(Graphic3d_Camera) myCamera; gp_XYZ myLocalOrigin; Handle(OpenGl_FrameBuffer) myFBO; Standard_Boolean myToShowGradTrihedron; @@ -484,7 +468,7 @@ protected: StateInfo myLastLightSourceState; //! Is needed for selection of overlapping objects and storage of the current view volume - OpenGl_BVHTreeSelector myBVHSelector; + Graphic3d_CullingTool myBVHSelector; OpenGl_GraduatedTrihedron myGraduatedTrihedron; OpenGl_FrameStatsPrs myFrameStatsPrs; diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index d0ee3b22b1..35013cd66d 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -111,11 +111,11 @@ Standard_Boolean OpenGl_View::updateRaytraceGeometry (const RaytraceUpdateMode if (aLayer.NbStructures() != 0) { - const OpenGl_ArrayOfIndexedMapOfStructure& aStructArray = aLayer.ArrayOfStructures(); + const Graphic3d_ArrayOfIndexedMapOfStructure& aStructArray = aLayer.ArrayOfStructures(); for (Standard_Integer anIndex = 0; anIndex < aStructArray.Length(); ++anIndex) { - for (OpenGl_IndexedMapOfStructure::Iterator aStructIt (aStructArray (anIndex)); aStructIt.More(); aStructIt.Next()) + for (OpenGl_Structure::StructIterator aStructIt (aStructArray.Value (anIndex)); aStructIt.More(); aStructIt.Next()) { const OpenGl_Structure* aStructure = aStructIt.Value(); diff --git a/src/TKViewerTest/EXTERNLIB b/src/TKViewerTest/EXTERNLIB index 9181318b93..475712cbeb 100755 --- a/src/TKViewerTest/EXTERNLIB +++ b/src/TKViewerTest/EXTERNLIB @@ -18,6 +18,7 @@ TKMesh TKV3d TKDraw TKOpenGl +TKVulkan CSF_TclLibs CSF_TclTkLibs CSF_XwLibs diff --git a/src/TKVulkan/CMakeLists.txt b/src/TKVulkan/CMakeLists.txt new file mode 100644 index 0000000000..89337e58ba --- /dev/null +++ b/src/TKVulkan/CMakeLists.txt @@ -0,0 +1,3 @@ +project(TKVulkan) + +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit) diff --git a/src/TKVulkan/EXTERNLIB b/src/TKVulkan/EXTERNLIB new file mode 100644 index 0000000000..6684eca605 --- /dev/null +++ b/src/TKVulkan/EXTERNLIB @@ -0,0 +1,13 @@ +TKernel +TKService +TKMath +TKV3d +CSF_TBB +CSF_FREETYPE +CSF_vulkan +CSF_user32 +CSF_gdi32 +CSF_XwLibs +CSF_Appkit +CSF_IOKit +CSF_objc diff --git a/src/TKVulkan/FILES b/src/TKVulkan/FILES new file mode 100644 index 0000000000..ca4f0e567b --- /dev/null +++ b/src/TKVulkan/FILES @@ -0,0 +1,2 @@ +EXTERNLIB +PACKAGES diff --git a/src/TKVulkan/PACKAGES b/src/TKVulkan/PACKAGES new file mode 100644 index 0000000000..7357e85901 --- /dev/null +++ b/src/TKVulkan/PACKAGES @@ -0,0 +1 @@ +Vulkan diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 3056b3ca6a..55eccf70e3 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -82,6 +82,9 @@ #include #include +#include +#include + #ifdef _WIN32 #undef DrawText #endif @@ -602,7 +605,7 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft theViewToClone->Window()->Size (aPxWidth, aPxHeight); } - Handle(OpenGl_GraphicDriver) aGraphicDriver; + Handle(Graphic3d_GraphicDriver) aGraphicDriver; ViewerTest_Names aViewNames(theViewName); if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ())) aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName(ViewerTest_myViews, "View")); @@ -638,15 +641,28 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft // alternatively we can disable buffer swap at all, but this might be inappropriate for testing //ViewerTest_myDefaultCaps.buffersNoSwap = true; } - aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection()); - aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps; + + if (theDisplayName == "vulkan") + { + /// TODO + Handle(Vulkan_GraphicDriver) aVkDriver = new Vulkan_GraphicDriver ("Draw Harness", OCC_VERSION_HEX, GetDisplayConnection()); + aVkDriver->Options()->contextDebug = true; + //aVkDriver->Options()->contextDebug = ViewerTest_myDefaultCaps.contextDebug; + aGraphicDriver = aVkDriver; + } + else + { + Handle(OpenGl_GraphicDriver) aGlDriver = new OpenGl_GraphicDriver (GetDisplayConnection()); + aGlDriver->ChangeOptions() = ViewerTest_myDefaultCaps; + aGraphicDriver = aGlDriver; + } ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver); toCreateViewer = Standard_True; } else { - aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName())); + aGraphicDriver = ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()); } //Dispose the window if input parameters are default @@ -983,7 +999,7 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX)) if (!aDisplayName.IsEmpty()) { - aDisplayName.Clear(); + ////aDisplayName.Clear(); std::cout << "Warning: display parameter will be ignored.\n"; } #endif @@ -12474,6 +12490,22 @@ static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/, return 0; } +//=============================================================================================== +//function : VkInit +//purpose : +//=============================================================================================== +static int VkInit (Draw_Interpretor& , + Standard_Integer theArgsNb, + const char** theArgVec) +{ + (void )theArgsNb; + (void )theArgVec; + Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection(); + Handle(Vulkan_GraphicDriver) aDriver = new Vulkan_GraphicDriver ("Draw Harness", OCC_VERSION_HEX, aDisp); + aDriver->InitContext(); + return 0; +} + //======================================================================= //function : ViewerCommands //purpose : @@ -12483,6 +12515,9 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) { const char *group = "ZeViewer"; + +theCommands.Add("vkinit", "vkinit", __FILE__,VkInit,group); /// + theCommands.Add("vinit", "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]" "\n\t\t: [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]" diff --git a/src/Vulkan/FILES b/src/Vulkan/FILES new file mode 100644 index 0000000000..c3178d83d9 --- /dev/null +++ b/src/Vulkan/FILES @@ -0,0 +1,37 @@ +Vulkan_Buffer.cxx +Vulkan_Buffer.hxx +Vulkan_Caps.cxx +Vulkan_Caps.hxx +Vulkan_Device.cxx +Vulkan_Device.hxx +Vulkan_Fence.cxx +Vulkan_Fence.hxx +Vulkan_FrameStats.cxx +Vulkan_FrameStats.hxx +Vulkan_ForwardDecl.hxx +Vulkan_GraphicDriver.cxx +Vulkan_GraphicDriver.hxx +Vulkan_Group.cxx +Vulkan_Group.hxx +Vulkan_Pipeline.cxx +Vulkan_Pipeline.hxx +Vulkan_PipelineCache.cxx +Vulkan_PipelineCache.hxx +Vulkan_PipelineLayout.cxx +Vulkan_PipelineLayout.hxx +Vulkan_RenderPass.cxx +Vulkan_RenderPass.hxx +Vulkan_Structure.cxx +Vulkan_Structure.hxx +Vulkan_StructureShadow.cxx +Vulkan_StructureShadow.hxx +Vulkan_Shader.cxx +Vulkan_Shader.hxx +Vulkan_Surface.cxx +Vulkan_Surface.hxx +Vulkan_View.cxx +Vulkan_View.hxx +Vulkan_Window.cxx +Vulkan_Window.hxx +Vulkan_TestShader_fs_spv.pxx +Vulkan_TestShader_vs_spv.pxx diff --git a/src/Vulkan/Vulkan_Buffer.cxx b/src/Vulkan/Vulkan_Buffer.cxx new file mode 100644 index 0000000000..e3b25d2fce --- /dev/null +++ b/src/Vulkan/Vulkan_Buffer.cxx @@ -0,0 +1,160 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Buffer, Standard_Transient) + +// ======================================================================= +// function : Vulkan_Buffer +// purpose : +// ======================================================================= +Vulkan_Buffer::Vulkan_Buffer() +: myVkBuffer (NULL), + myVkMemory (NULL), + mySize (0) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_Buffer +// purpose : +// ======================================================================= +Vulkan_Buffer::~Vulkan_Buffer() +{ + Release (Handle(Vulkan_Device)()); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_Buffer::Release (const Handle(Vulkan_Device)& theDevice) +{ + mySize = 0; + if (myVkBuffer != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_Buffer destroyed without Vulkan context",); + vkDestroyBuffer (theDevice->Device(), myVkBuffer, theDevice->HostAllocator()); + myVkBuffer = NULL; + } + if (myVkMemory != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_Buffer destroyed without Vulkan context",); + vkFreeMemory (theDevice->Device(), myVkMemory, theDevice->HostAllocator()); + myVkMemory = NULL; + } +} + +// ======================================================================= +// function : Create +// purpose : +// ======================================================================= +bool Vulkan_Buffer::Create (const Handle(Vulkan_Device)& theDevice, + Standard_Size theSize, + Vulkan_BufferType theType) +{ + if (myVkBuffer != NULL + && mySize == theSize) + { + return true; + } + + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL) + { + return false; + } + + VkBufferCreateInfo aVkBuffInfo; + aVkBuffInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + aVkBuffInfo.pNext = NULL; + aVkBuffInfo.flags = 0; + aVkBuffInfo.size = theSize; + aVkBuffInfo.usage = 0; + aVkBuffInfo.sharingMode = VkSharingMode::VK_SHARING_MODE_EXCLUSIVE; + aVkBuffInfo.queueFamilyIndexCount = 0; + aVkBuffInfo.pQueueFamilyIndices = NULL; + switch (theType) + { + case Vulkan_BufferType_Uniform: aVkBuffInfo.usage = VkBufferUsageFlagBits::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break; + case Vulkan_BufferType_Vertex: aVkBuffInfo.usage = VkBufferUsageFlagBits::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; break; + case Vulkan_BufferType_Index: aVkBuffInfo.usage = VkBufferUsageFlagBits::VK_BUFFER_USAGE_INDEX_BUFFER_BIT; break; + } + + VkResult aRes = vkCreateBuffer (theDevice->Device(), &aVkBuffInfo, theDevice->HostAllocator(), &myVkBuffer); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Buffer, failed to create buffer: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + mySize = theSize; + return true; +} + +// ======================================================================= +// function : init +// purpose : +// ======================================================================= +bool Vulkan_Buffer::init (const Handle(Vulkan_Device)& theDevice, + const void* theData, + Standard_Size theNbBytes, + Vulkan_BufferType theType) +{ + if (!Create (theDevice, theNbBytes, theType)) + { + return false; + } + + if (myVkMemory == NULL) + { + VkMemoryRequirements aVkMemReqs; + vkGetBufferMemoryRequirements (theDevice->Device(), myVkBuffer, &aVkMemReqs); + myVkMemory = theDevice->AllocateDeviceMemory (aVkMemReqs); + if (myVkMemory == NULL) + { + return false; + } + } + + if (theData != NULL) + { + void* aDataPtr = NULL; + VkResult aRes = vkMapMemory (theDevice->Device(), myVkMemory, 0, theNbBytes, 0, &aDataPtr); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Buffer, failed to map device memory: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + memcpy (aDataPtr, theData, theNbBytes); + vkUnmapMemory(theDevice->Device(), myVkMemory); + } + + VkResult aRes = vkBindBufferMemory (theDevice->Device(), myVkBuffer, myVkMemory, 0); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Buffer, failed to bind buffer memory: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + return true; +} diff --git a/src/Vulkan/Vulkan_Buffer.hxx b/src/Vulkan/Vulkan_Buffer.hxx new file mode 100644 index 0000000000..8e875ac517 --- /dev/null +++ b/src/Vulkan/Vulkan_Buffer.hxx @@ -0,0 +1,87 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Buffer_HeaderFile +#define _Vulkan_Buffer_HeaderFile + +#include +#include +#include + +class Vulkan_Device; + +enum Vulkan_BufferType +{ + Vulkan_BufferType_Uniform, //!< VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT + Vulkan_BufferType_Vertex, //!< VK_BUFFER_USAGE_VERTEX_BUFFER_BIT + Vulkan_BufferType_Index, //!< VK_BUFFER_USAGE_VERTEX_BUFFER_BIT +}; + +//! This class defines an Vulkan buffer. +class Vulkan_Buffer : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_Buffer, Standard_Transient) +public: + + //! Constructor. + Standard_EXPORT Vulkan_Buffer(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_Buffer(); + + //! Return object. + VkBuffer Buffer() const { return myVkBuffer; } + + //! Release the object, @sa vkDestroyBuffer(). + Standard_EXPORT void Release (const Handle(Vulkan_Device)& theDevice); + + //! Create the object, @sa vkCreateBuffer(). + Standard_EXPORT bool Create (const Handle(Vulkan_Device)& theDevice, + Standard_Size theSize, + Vulkan_BufferType theType); + + //! Init the object. + bool Init (const Handle(Vulkan_Device)& theDevice, + const Graphic3d_Vec2* theData, + Standard_Size theLen) + { + const Standard_Size aSize = sizeof(*theData) * theLen; + return init (theDevice, theData, aSize, Vulkan_BufferType_Vertex); + } + + //! Init the object. + bool Init (const Handle(Vulkan_Device)& theDevice, + const Graphic3d_Vec3* theData, + Standard_Size theLen) + { + const Standard_Size aSize = sizeof(*theData) * theLen; + return init (theDevice, theData, aSize, Vulkan_BufferType_Vertex); + } + +//protected: + + //! Init the object. + Standard_EXPORT bool init (const Handle(Vulkan_Device)& theDevice, + const void* theData, + Standard_Size theNbBytes, + Vulkan_BufferType theType); + +protected: + + VkBuffer myVkBuffer; + VkDeviceMemory myVkMemory; + Standard_Size mySize; + +}; + +#endif // _Vulkan_Buffer_HeaderFile diff --git a/src/Vulkan/Vulkan_Caps.cxx b/src/Vulkan/Vulkan_Caps.cxx new file mode 100644 index 0000000000..2af26d86b8 --- /dev/null +++ b/src/Vulkan/Vulkan_Caps.cxx @@ -0,0 +1,60 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Caps, Standard_Transient) + +// ======================================================================= +// function : Vulkan_Caps +// purpose : +// ======================================================================= +Vulkan_Caps::Vulkan_Caps() +: swapInterval (1), + buffersNoSwap (Standard_False), +#ifdef OCCT_DEBUG + contextDebug (Standard_True), +#else + contextDebug (Standard_False), +#endif + contextNoAccel (Standard_False), + glslWarnings (Standard_False), + suppressExtraMsg (Standard_True) +{ + // +} + +// ======================================================================= +// function : operator= +// purpose : +// ======================================================================= +Vulkan_Caps& Vulkan_Caps::operator= (const Vulkan_Caps& theCopy) +{ + swapInterval = theCopy.swapInterval; + buffersNoSwap = theCopy.buffersNoSwap; + contextDebug = theCopy.contextDebug; + contextNoAccel = theCopy.contextNoAccel; + contextDevice = theCopy.contextDevice; + glslWarnings = theCopy.glslWarnings; + suppressExtraMsg = theCopy.suppressExtraMsg; + return *this; +} + +// ======================================================================= +// function : ~Vulkan_Caps +// purpose : +// ======================================================================= +Vulkan_Caps::~Vulkan_Caps() +{ + // +} diff --git a/src/Vulkan/Vulkan_Caps.hxx b/src/Vulkan/Vulkan_Caps.hxx new file mode 100644 index 0000000000..a4eb62e06f --- /dev/null +++ b/src/Vulkan/Vulkan_Caps.hxx @@ -0,0 +1,85 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Caps_HeaderFile +#define _Vulkan_Caps_HeaderFile + +#include +#include +#include + +//! Class to define graphic driver capabilities. +//! Notice that these options will be ignored if particular functionality does not provided by Vulkan driver +class Vulkan_Caps : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_Caps, Standard_Transient) +public: //! @name flags to disable particular functionality, should be used only for testing purposes! + + Standard_Integer swapInterval; //!< controls swap interval - 0 for VSync off and 1 for VSync on, 1 by default + +public: //! @name context creation parameters + + //! Specify that driver should not swap back/front buffers at the end of frame. + //! Useful when OCCT Viewer is integrated into existing Vulkan rendering pipeline as part, + //! thus swapping part is performed outside. + //! + //! OFF by default. + Standard_Boolean buffersNoSwap; + + //! Request debug Vulkan context. This flag requires support of necessary layers in Vulkan driver. + //! + //! When turned on Vulkan driver emits error and warning messages to provided callback. + //! Affects performance - thus should not be turned on by products in released state. + //! + //! OFF by default. + Standard_Boolean contextDebug; + + //! Disable hardware acceleration. + //! + //! Flags to intentionally look for VK_PHYSICAL_DEVICE_TYPE_CPU devices. + //! + //! OFF by default. + Standard_Boolean contextNoAccel; + + //! Look for device with specified name. + //! + //! EMPTY by default. + TCollection_AsciiString contextDevice; + +public: //! @name flags to activate verbose output + + //! Print GLSL program compilation/linkage warnings, if any. OFF by default. + Standard_Boolean glslWarnings; + + //! Suppress redundant messages from debug Vulkan context. ON by default. + Standard_Boolean suppressExtraMsg; + +public: //! @name class methods + + //! Default constructor - initialize with most optimal values. + Standard_EXPORT Vulkan_Caps(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_Caps(); + + //! Copy maker. + Standard_EXPORT Vulkan_Caps& operator= (const Vulkan_Caps& theCopy); + +private: + + //! Not implemented + Vulkan_Caps (const Vulkan_Caps& ); + +}; + +#endif // _Vulkan_Caps_HeaderFile diff --git a/src/Vulkan/Vulkan_Device.cxx b/src/Vulkan/Vulkan_Device.cxx new file mode 100644 index 0000000000..93e03850cf --- /dev/null +++ b/src/Vulkan/Vulkan_Device.cxx @@ -0,0 +1,852 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#if defined(_WIN32) + #include + + #define VK_USE_PLATFORM_WIN32_KHR 1 +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Device, Standard_Transient) + +namespace +{ + //! Return object type. + static TCollection_AsciiString debugVkObjectType (VkDebugReportObjectTypeEXT theObjectType) + { + switch (theObjectType) + { + case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT: + return "UNKNOWN"; + case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT: + return "Instance"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT: + return "Physical device"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT: + return "Device"; + case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT: + return "Queue"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT: + return "Semaphore"; + case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT: + return "Command Buffer"; + case VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT: + return "Fence"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: + return "Device memory"; + case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: + return "Buffer"; + case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: + return "Image"; + case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: + return "Event"; + case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: + return "Query pool"; + case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: + return "Buffer view"; + case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: + return "Image view"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT: + return "Shader module"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT: + return "Pipeline cache"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT: + return "Pipeline layout"; + case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: + return "Render pass"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: + return "Pipeline"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT: + return "Descriptor set layout"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: + return "Sampler"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: + return "Descriptor pool"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: + return "Descriptor set"; + case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: + return "Framebuffer"; + case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: + return "Command pool"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT: + return "Surface"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: + return "Swapchain"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT: + return "Debug report"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT: + return "Display"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT: + return "Display mode"; + case VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT: + return "Object table"; + case VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT: + return "Indirect commands layout"; + case VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT: + return "Validation cache"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT: + return "Sampler YCBCR conversion"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT: + return "Descriptor update template"; + case VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT: + return "Acceleration structure"; + default: + return TCollection_AsciiString ("Unknown #") + (int )theObjectType; + } + } + + //! Format physical device type. + static const char* formatVkDeviceType (VkPhysicalDeviceType theType) + { + switch (theType) + { + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return "Integrated GPU"; + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return "Discrete GPU"; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return "Virtual GPU"; + case VK_PHYSICAL_DEVICE_TYPE_CPU: return "CPU"; + default: + return "UNKNOWN"; + } + } + + //! Return physical device priority. + static int fastestVkDeviceType (VkPhysicalDeviceType theType) + { + switch (theType) + { + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return 2; + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return 3; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return 1; + case VK_PHYSICAL_DEVICE_TYPE_CPU: return 0; + default: + return 0; + } + } + + //! Return message type. + static const char* debugVkMessageType (VkDebugReportFlagsEXT theFlags) + { + if ((theFlags & VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) + { + return "Error"; + } + if ((theFlags & VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) + { + return "Warning"; + } + if ((theFlags & VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) + { + return "Info"; + } + if ((theFlags & VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) + { + return "Performance"; + } + if ((theFlags & VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) + { + return "Debug"; + } + return ""; + } + + //! Vulkan debug callback redirection to Message::DefaultMessenger(). + static VkBool32 VKAPI_CALL debugVkCallback (VkDebugReportFlagsEXT theFlags, + VkDebugReportObjectTypeEXT theObjectType, + uint64_t theObject, + size_t theLocation, + int32_t theMessageCode, + const char* theLayerPrefix, + const char* theMessage, + void* theUserData) + { + (void )theUserData; + (void )theObject; + (void )theLocation; + Message_Gravity aGrav = (theFlags & VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0 + ? Message_Alarm + : ((theFlags & VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0 + ? Message_Warning + : Message_Info); + const TCollection_AsciiString aLayer = theLayerPrefix; + if (aLayer == "Loader Message" + && theObjectType == VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT + && (theFlags & VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) + { + return VK_FALSE; + } + + TCollection_AsciiString aMsg; + aMsg += "TKVulkan."; aMsg += aLayer; + aMsg += " | Type: "; aMsg += debugVkMessageType (theFlags); + aMsg += " | ID: "; aMsg += theMessageCode; + //aMsg += " | Location: "; aMsg += (int )theLocation; + aMsg += " | Object: "; aMsg += debugVkObjectType (theObjectType); + aMsg += " | Message:\n "; + aMsg += theMessage; + Message::DefaultMessenger()->Send (aMsg, aGrav); + return VK_FALSE; + } + + //! Add key-value pair to the dictionary. + static void addInfo (TColStd_IndexedDataMapOfStringString& theDict, + const TCollection_AsciiString& theKey, + const TCollection_AsciiString& theValue) + { + theDict.ChangeFromIndex (theDict.Add (theKey, theValue)) = theValue; + } +} + +// ======================================================================= +// function : FormatVkError +// purpose : +// ======================================================================= +TCollection_AsciiString Vulkan_Device::FormatVkError (int theErr) +{ + switch (theErr) + { + case VK_SUCCESS: + return "Success"; + case VK_NOT_READY: + return "Not ready"; + case VK_TIMEOUT: + return "Timeout"; + case VK_EVENT_SET: + return "Event set"; + case VK_EVENT_RESET: + return "Event reset"; + case VK_INCOMPLETE: + return "Incomplete"; + case VK_ERROR_OUT_OF_HOST_MEMORY: + return "Error, out of host memory"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: + return "Error, out of device memory"; + case VK_ERROR_INITIALIZATION_FAILED: + return "Error, initialization failed"; + case VK_ERROR_DEVICE_LOST: + return "Error, device lost"; + case VK_ERROR_MEMORY_MAP_FAILED: + return "Error, memory map failed"; + case VK_ERROR_LAYER_NOT_PRESENT: + return "Error, layer not present"; + case VK_ERROR_EXTENSION_NOT_PRESENT: + return "Error, extension not present"; + case VK_ERROR_FEATURE_NOT_PRESENT: + return "Error, feature not present"; + case VK_ERROR_INCOMPATIBLE_DRIVER: + return "Error, incompatible driver"; + case VK_ERROR_TOO_MANY_OBJECTS: + return "Error, too many objects"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: + return "Error, format not supported"; + case VK_ERROR_FRAGMENTED_POOL: + return "Error, fragmented pool"; + case VK_ERROR_OUT_OF_POOL_MEMORY: + return "Error, out of pool memory"; + case VK_ERROR_INVALID_EXTERNAL_HANDLE: + return "Error, invalid external handle"; + case VK_ERROR_SURFACE_LOST_KHR: + return "Error, surface lost"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: + return "Error, native window in use"; + case VK_SUBOPTIMAL_KHR: + return "Error, suboptimal"; + case VK_ERROR_OUT_OF_DATE_KHR: + return "Error, out of date"; + case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: + return "Error, incompatible display"; + case VK_ERROR_VALIDATION_FAILED_EXT: + return "Error, validation failed"; + case VK_ERROR_INVALID_SHADER_NV: + return "Error, invalid shader"; + case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: + return "Error, invalid DRM format"; + case VK_ERROR_FRAGMENTATION_EXT: + return "Error, fragmentation"; + case VK_ERROR_NOT_PERMITTED_EXT: + return "Error, not permitted"; + case VK_ERROR_INVALID_DEVICE_ADDRESS_EXT: + return "Error, invalid device address"; + default: + return TCollection_AsciiString("Error #") + theErr; + } +} + +// ======================================================================= +// function : Vulkan_Device +// purpose : +// ======================================================================= +Vulkan_Device::Vulkan_Device (const TCollection_AsciiString& theAppName, + const uint32_t theAppVersion, + const TCollection_AsciiString& theEngineName, + const uint32_t theEngineVersion) +: myAppName (theAppName), + myEngineName (theEngineName), + myAppVersion (theAppVersion), + myEngineVersion (theEngineVersion), + myVkInstance (NULL), + myVkDevice (NULL), + myVkDeviceMemory (new VkPhysicalDeviceMemoryProperties()), + myFrameStats (new Vulkan_FrameStats()), + myIsOwnContext (false) +{ + memset (myVkDeviceMemory.get(), 0, sizeof(VkPhysicalDeviceMemoryProperties)); +} + +// ======================================================================= +// function : ~Vulkan_Device +// purpose : +// ======================================================================= +Vulkan_Device::~Vulkan_Device() +{ + Release(); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_Device::Release() +{ + myIsOwnContext = Standard_False; + memset (myVkDeviceMemory.get(), 0, sizeof(VkPhysicalDeviceMemoryProperties)); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +bool Vulkan_Device::Init (const Handle(Vulkan_Caps)& theCaps) +{ + Release(); + myIsOwnContext = true; + + Handle(Vulkan_Caps) aCaps = theCaps; + if (aCaps.IsNull()) + { + aCaps = new Vulkan_Caps(); + } + + NCollection_Map anAllLayers; + { + uint32_t aNbLayers = 0; + if (vkEnumerateInstanceLayerProperties (&aNbLayers, NULL) == VK_SUCCESS + && aNbLayers != 0) + { + std::vector aLayers (aNbLayers); + if (vkEnumerateInstanceLayerProperties (&aNbLayers, aLayers.data()) == VK_SUCCESS) + { + for (uint32_t aLayerIter = 0; aLayerIter < aNbLayers; ++aLayerIter) + { + const VkLayerProperties& aLayerProps = aLayers[aLayerIter]; + anAllLayers.Add (aLayerProps.layerName); + } + } + } + } + + NCollection_Map anAllInstExtensions; + { + uint32_t aNbExts = 0; + if (vkEnumerateInstanceExtensionProperties (NULL, &aNbExts, NULL) == VK_SUCCESS + && aNbExts != 0) + { + std::vector anExts (aNbExts); + if (vkEnumerateInstanceExtensionProperties (NULL, &aNbExts, anExts.data()) == VK_SUCCESS) + { + for (uint32_t anExtIter = 0; anExtIter < aNbExts; ++anExtIter) + { + const VkExtensionProperties& anExtProps = anExts[anExtIter]; + anAllInstExtensions.Add (anExtProps.extensionName); + } + } + } + } + + // layers should be the same for instance and for device, while extensions may differ + std::vector aLayers, anInstExtensions; + anInstExtensions.push_back (VK_KHR_SURFACE_EXTENSION_NAME); +#ifdef _WIN32 + anInstExtensions.push_back (VK_KHR_WIN32_SURFACE_EXTENSION_NAME); +#endif + if (aCaps->contextDebug) + { + if (anAllInstExtensions.Contains (VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) + { + anInstExtensions.push_back (VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + } + + // VK_LAYER_LUNARG_standard_validation is a meta layer enabling several standard validation layers (LunarG SDK): + // - VK_LAYER_GOOGLE_threading, VK_LAYER_GOOGLE_unique_objects, + // VK_LAYER_LUNARG_parameter_validation, VK_LAYER_LUNARG_core_validation, + // VK_LAYER_LUNARG_device_limits, VK_LAYER_LUNARG_image, + // VK_LAYER_LUNARG_object_tracker, VK_LAYER_LUNARG_swapchain + if (anAllLayers.Contains ("VK_LAYER_LUNARG_standard_validation")) + { + aLayers.push_back ("VK_LAYER_LUNARG_standard_validation"); + } + //aLayers.push_back ("VK_LAYER_GOOGLE_threading"); // validate usage from multiple threads + //aLayers.push_back ("VK_LAYER_GOOGLE_unique_objects"); + //aLayers.push_back ("VK_LAYER_LUNARG_parameter_validation"); // validate API parameter values + //aLayers.push_back ("VK_LAYER_LUNARG_core_validation"); + //aLayers.push_back ("VK_LAYER_LUNARG_device_limits"); // detects missing device limits checks + //aLayers.push_back ("VK_LAYER_LUNARG_image"); // validate texture/render formats + //aLayers.push_back ("VK_LAYER_LUNARG_object_tracker"); // detect usage of invalid objects + //aLayers.push_back ("VK_LAYER_LUNARG_swapchain"); // validate usage of swapchain extensions + + // trace API calls + //if (anAllLayers.Contains ("VK_LAYER_LUNARG_api_dump")) + //{ + // aLayers.push_back ("VK_LAYER_LUNARG_api_dump"); + //} + // dump frames to image files + //if (anAllLayers.Contains ("VK_LAYER_LUNARG_screenshot")) + //{ + // aLayers.push_back ("VK_LAYER_LUNARG_screenshot"); + //} + } + + //aLayers.push_back ("VK_LAYER_NV_optimus"); + //aLayers.push_back ("VK_LAYER_VALVE_steam_overlay"); + + VkApplicationInfo anAppInfo; + anAppInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_APPLICATION_INFO; + anAppInfo.pNext = NULL; + anAppInfo.pApplicationName = myAppName.ToCString(); + anAppInfo.applicationVersion = myAppVersion; + anAppInfo.pEngineName = myEngineName.ToCString(); + anAppInfo.engineVersion = myEngineVersion; + anAppInfo.apiVersion = VK_MAKE_VERSION(1, 0, 21); + + VkInstanceCreateInfo anInstInfo; + anInstInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + anInstInfo.pNext = NULL; + anInstInfo.flags = 0; + anInstInfo.pApplicationInfo = &anAppInfo; + anInstInfo.enabledLayerCount = (uint32_t )aLayers.size(); + anInstInfo.ppEnabledLayerNames = aLayers.data(); + anInstInfo.enabledExtensionCount = (uint32_t )anInstExtensions.size(); + anInstInfo.ppEnabledExtensionNames = anInstExtensions.data(); + + VkResult aRes = vkCreateInstance (&anInstInfo, NULL, &myVkInstance); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Device, unable creating Vulkan instance: ") + FormatVkError (aRes), Message_Fail); + return false; + } + + if (aCaps->contextDebug) + { + if (PFN_vkCreateDebugReportCallbackEXT aVkCreateDebugCallback = (PFN_vkCreateDebugReportCallbackEXT )vkGetInstanceProcAddr (myVkInstance, "vkCreateDebugReportCallbackEXT")) + { + VkDebugReportCallbackCreateInfoEXT aCallbackInfo; + aCallbackInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; + aCallbackInfo.pNext = NULL; + aCallbackInfo.flags = VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_INFORMATION_BIT_EXT + | VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_WARNING_BIT_EXT + | VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT + | VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_ERROR_BIT_EXT + | VkDebugReportFlagBitsEXT::VK_DEBUG_REPORT_DEBUG_BIT_EXT; + aCallbackInfo.pfnCallback = debugVkCallback; + aCallbackInfo.pUserData = NULL; + + VkDebugReportCallbackEXT aDebReportObj = NULL; + aRes = aVkCreateDebugCallback (myVkInstance, &aCallbackInfo, NULL, &aDebReportObj); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Device, unable registering debug report callback: ") + FormatVkError (aRes), Message_Warning); + } + } + } + + { + uint32_t aNbDevices = 0; + aRes = vkEnumeratePhysicalDevices (myVkInstance, &aNbDevices, NULL); + if (aRes != VkResult::VK_SUCCESS + || aNbDevices == 0) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Device, unable to list physical devices: ") + FormatVkError (aRes), Message_Warning); + return false; + } + + std::vector aDevices (aNbDevices); + aRes = vkEnumeratePhysicalDevices (myVkInstance, &aNbDevices, aDevices.data()); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Device, unable to list physical devices: ") + FormatVkError (aRes), Message_Warning); + return false; + } + myVkPhysDevice = aDevices[0]; + int aSelPriority = aCaps->contextNoAccel ? IntegerLast() : -IntegerLast(); + TCollection_AsciiString aDevNameToFind = aCaps->contextDevice; + aDevNameToFind.LowerCase(); + if (aDevNameToFind.IsIntegerValue() + && aDevNameToFind.IntegerValue() >= 0 + && aDevNameToFind.IntegerValue() < (int )aNbDevices) + { + myVkPhysDevice = aDevices[aDevNameToFind.IntegerValue()]; + } + else + { + uint32_t aVendorToFind = 0; + if (aDevNameToFind == "amd") + { + aVendorToFind = VendorId_AMD; + aDevNameToFind.Clear(); + } + else if (aDevNameToFind == "nvidia") + { + aVendorToFind = VendorId_NVIDIA; + aDevNameToFind.Clear(); + } + else if (aDevNameToFind == "intel") + { + aVendorToFind = VendorId_INTEL; + aDevNameToFind.Clear(); + } + + for (uint32_t aDevIter = 0; aDevIter < aNbDevices; ++aDevIter) + { + const VkPhysicalDevice& aPhysDev = aDevices[aDevIter]; + + VkPhysicalDeviceProperties aDevProps; + memset (&aDevProps, 0, sizeof(aDevProps)); + vkGetPhysicalDeviceProperties (aPhysDev, &aDevProps); + if (!aDevNameToFind.IsEmpty()) + { + TCollection_AsciiString aName (aDevProps.deviceName); + aName.LowerCase(); + if (aName.Search (aDevNameToFind) != -1) + { + myVkPhysDevice = aDevices[aDevIter]; + break; + } + } + else if (aVendorToFind != 0 + && aDevProps.vendorID == aVendorToFind) + { + myVkPhysDevice = aDevices[aDevIter]; + break; + } + + const int aPriority = fastestVkDeviceType (aDevProps.deviceType); + if (aCaps->contextNoAccel) + { + if (aPriority < aSelPriority) + { + aSelPriority = aPriority; + myVkPhysDevice = aDevices[aDevIter]; + } + } + else + { + if (aPriority > aSelPriority) + { + aSelPriority = aPriority; + myVkPhysDevice = aDevices[aDevIter]; + } + } + } + } + } + + NCollection_Map anAllDevExtensions; + { + uint32_t aNbExts = 0; + if (vkEnumerateDeviceExtensionProperties (myVkPhysDevice, NULL, &aNbExts, NULL) == VK_SUCCESS + && aNbExts != 0) + { + std::vector anExts (aNbExts); + if (vkEnumerateDeviceExtensionProperties (myVkPhysDevice, NULL, &aNbExts, anExts.data()) == VK_SUCCESS) + { + for (uint32_t anExtIter = 0; anExtIter < aNbExts; ++anExtIter) + { + const VkExtensionProperties& anExtProps = anExts[anExtIter]; + anAllDevExtensions.Add (anExtProps.extensionName); + } + } + } + } + + std::vector aDevExtensions; + aDevExtensions.push_back (VK_KHR_SWAPCHAIN_EXTENSION_NAME); + + std::vector aPhysDevQueueFamilyProps; + { + uint32_t aNbProps = 0; + vkGetPhysicalDeviceQueueFamilyProperties (myVkPhysDevice, &aNbProps, NULL); + if (aNbProps != 0) + { + aPhysDevQueueFamilyProps.resize (aNbProps); + vkGetPhysicalDeviceQueueFamilyProperties (myVkPhysDevice, &aNbProps, aPhysDevQueueFamilyProps.data()); + } + } + + { + std::vector aDevQueueInfos (1); + std::vector< std::vector > aDevQueuesPriorities (aDevQueueInfos.size(), std::vector (1, 0.0f)); + for (uint32_t aQueueIter = 0; aQueueIter < (uint32_t )aDevQueueInfos.size(); ++aQueueIter) + { + std::vector& aDevQueuePriorities = aDevQueuesPriorities[aQueueIter]; + VkDeviceQueueCreateInfo& aDevQueueInfo = aDevQueueInfos[aQueueIter]; + aDevQueueInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + aDevQueueInfo.pNext = NULL; + aDevQueueInfo.flags = 0; + aDevQueueInfo.queueFamilyIndex = aQueueIter; + aDevQueueInfo.queueCount = (uint32_t )aDevQueuePriorities.size(); + aDevQueueInfo.pQueuePriorities = aDevQueuePriorities.data(); + } + + VkPhysicalDeviceFeatures aPhysDevFeatures; + memset (&aPhysDevFeatures, 0, sizeof(aPhysDevFeatures)); + + VkDeviceCreateInfo aDevInfo; + aDevInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + aDevInfo.pNext = NULL; + aDevInfo.flags = 0; + aDevInfo.queueCreateInfoCount = (uint32_t )aDevQueueInfos.size(); + aDevInfo.pQueueCreateInfos = aDevQueueInfos.data(); + aDevInfo.enabledLayerCount = (uint32_t )aLayers.size(); + aDevInfo.ppEnabledLayerNames = aLayers.data(); + aDevInfo.enabledExtensionCount = (uint32_t )aDevExtensions.size(); + aDevInfo.ppEnabledExtensionNames = aDevExtensions.data(); + aDevInfo.pEnabledFeatures = &aPhysDevFeatures; + aRes = vkCreateDevice (myVkPhysDevice, &aDevInfo, NULL, &myVkDevice); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Device, unable to create device: ") + FormatVkError (aRes), Message_Warning); + return false; + } + } + + vkGetPhysicalDeviceMemoryProperties (myVkPhysDevice, myVkDeviceMemory.get()); + return true; +} + +// ======================================================================= +// function : AllocateDeviceMemory +// purpose : +// ======================================================================= +VkDeviceMemory Vulkan_Device::AllocateDeviceMemory (const VkMemoryRequirements& theReqs) +{ + if (myVkInstance == NULL) + { + return NULL; + } + + VkMemoryAllocateInfo aVkAllocInfo; + aVkAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + aVkAllocInfo.pNext = NULL; + aVkAllocInfo.allocationSize = theReqs.size; + aVkAllocInfo.memoryTypeIndex = uint32_t(-1); + for (uint32_t aTypeIter = 0; aTypeIter < myVkDeviceMemory->memoryTypeCount; ++aTypeIter) + { + const uint32_t aBit = (uint32_t(1) << aTypeIter); + if ((theReqs.memoryTypeBits & aBit) != 0) + { + if ((myVkDeviceMemory->memoryTypes[aTypeIter].propertyFlags & VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) + { + aVkAllocInfo.memoryTypeIndex = aTypeIter; + break; + } + } + } + if (aVkAllocInfo.memoryTypeIndex == uint32_t(-1)) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Device, failed to get correct memory type"), Message_Fail); + return NULL; + } + + VkDeviceMemory aVkDevMem = NULL; + VkResult aRes = vkAllocateMemory (myVkDevice, &aVkAllocInfo, myVkHostAllocator.get(), &aVkDevMem); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Device, failed to allocate device memory [") + + int(theReqs.size) + "]:" + FormatVkError (aRes), Message_Fail); + return NULL; + } + return aVkDevMem; +} + +// ======================================================================= +// function : DiagnosticInformation +// purpose : +// ======================================================================= +void Vulkan_Device::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const +{ + if (myVkInstance == NULL) + { + return; + } + + uint32_t aNbDevices = 0; + if (vkEnumeratePhysicalDevices (myVkInstance, &aNbDevices, NULL) == VkResult::VK_SUCCESS + && aNbDevices > 1) + { + std::vector aDevices (aNbDevices); + if (vkEnumeratePhysicalDevices (myVkInstance, &aNbDevices, aDevices.data()) == VkResult::VK_SUCCESS) + { + TCollection_AsciiString aDevListStr; + for (uint32_t aDevIter = 0; aDevIter < aNbDevices; ++aDevIter) + { + const VkPhysicalDevice& aPhysDev = aDevices[aDevIter]; + VkPhysicalDeviceProperties aDevProps; + memset (&aDevProps, 0, sizeof(aDevProps)); + vkGetPhysicalDeviceProperties (aPhysDev, &aDevProps); + aDevListStr += aDevProps.deviceName; + aDevListStr += " "; + } + addInfo (theDict, "VKDeviceList", aDevListStr); + } + } + + if (myVkPhysDevice != NULL + && (theFlags & Graphic3d_DiagnosticInfo_Device) != 0) + { + VkPhysicalDeviceProperties aDevProps; + memset (&aDevProps, 0, sizeof(aDevProps)); + vkGetPhysicalDeviceProperties (myVkPhysDevice, &aDevProps); + addInfo (theDict, "VKDevice", aDevProps.deviceName); + addInfo (theDict, "VKDeviceType", formatVkDeviceType (aDevProps.deviceType)); + + TCollection_AsciiString aVendor (int(aDevProps.vendorID)); + switch ((int )aDevProps.vendorID) + { + case VendorId_AMD: aVendor = "AMD"; break; + case VendorId_NVIDIA: aVendor = "NVIDIA"; break; + case VendorId_INTEL: aVendor = "INTEL"; break; + } + addInfo (theDict, "VKDeviceVendor", aVendor); + } + + if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) + { + TCollection_AsciiString aLayerStr; + uint32_t aNbLayers = 0; + if ((theFlags & Graphic3d_DiagnosticInfo_NativePlatform) != 0 + && vkEnumerateInstanceLayerProperties (&aNbLayers, NULL) == VK_SUCCESS + && aNbLayers != 0) + { + std::vector aLayers (aNbLayers); + if (vkEnumerateInstanceLayerProperties (&aNbLayers, aLayers.data()) == VK_SUCCESS) + { + for (uint32_t aLayerIter = 0; aLayerIter < aNbLayers; ++aLayerIter) + { + const VkLayerProperties& aLayerProps = aLayers[aLayerIter]; + aLayerStr += aLayerProps.layerName; + aLayerStr += " "; + } + addInfo (theDict, "VKLayers", aLayerStr); + } + } + + TCollection_AsciiString anInstExtsStr; + uint32_t aNbExts = 0; + if ((theFlags & Graphic3d_DiagnosticInfo_NativePlatform) != 0 + && vkEnumerateInstanceExtensionProperties (NULL, &aNbExts, NULL) == VK_SUCCESS + && aNbExts != 0) + { + std::vector anExts (aNbExts); + if (vkEnumerateInstanceExtensionProperties (NULL, &aNbExts, anExts.data()) == VK_SUCCESS) + { + for (uint32_t anExtIter = 0; anExtIter < aNbExts; ++anExtIter) + { + const VkExtensionProperties& anExtProps = anExts[anExtIter]; + anInstExtsStr += anExtProps.extensionName; + anInstExtsStr += " "; + } + addInfo (theDict, "VKExtensions", anInstExtsStr); + } + } + + TCollection_AsciiString aDevExtsStr; + if (myVkPhysDevice != NULL + && (theFlags & Graphic3d_DiagnosticInfo_Device) != 0 + && vkEnumerateDeviceExtensionProperties (myVkPhysDevice, NULL, &aNbExts, NULL) == VK_SUCCESS + && aNbExts != 0) + { + std::vector anExts (aNbExts); + if (vkEnumerateDeviceExtensionProperties (myVkPhysDevice, NULL, &aNbExts, anExts.data()) == VK_SUCCESS) + { + for (uint32_t anExtIter = 0; anExtIter < aNbExts; ++anExtIter) + { + const VkExtensionProperties& anExtProps = anExts[anExtIter]; + aDevExtsStr += anExtProps.extensionName; + aDevExtsStr += " "; + } + addInfo (theDict, "VKDeviceExtensions", aDevExtsStr); + } + } + } + + if (myVkPhysDevice != NULL + && (theFlags & Graphic3d_DiagnosticInfo_Limits) != 0) + { + VkPhysicalDeviceProperties aProps; + memset (&aProps, 0, sizeof(aProps)); + vkGetPhysicalDeviceProperties (myVkPhysDevice, &aProps); + const VkPhysicalDeviceLimits& aLimits = aProps.limits; + addInfo (theDict, "Max texture size", TCollection_AsciiString((int )aLimits.maxImageDimension2D)); + addInfo (theDict, "Max FBO dump size", TCollection_AsciiString() + int(aLimits.maxFramebufferWidth) + "x" + int(aLimits.maxFramebufferHeight)); + } + + if (myVkPhysDevice != NULL + && (theFlags & Graphic3d_DiagnosticInfo_Memory) != 0) + { + uint64_t aDedicated = 0; + int aNbDedicatedHeaps = 0; + TCollection_AsciiString aDedicatedHeaps; + TColStd_PackedMapOfInteger aDedicatedHeapsMap; + for (uint32_t aTypeIter = 0; aTypeIter < myVkDeviceMemory->memoryTypeCount; ++aTypeIter) + { + const VkMemoryType& aMemInfo = myVkDeviceMemory->memoryTypes[aTypeIter]; + if ((aMemInfo.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) + { + continue; + } + + if (aDedicatedHeapsMap.Add (aMemInfo.heapIndex)) + { + const VkMemoryHeap& aHeap = myVkDeviceMemory->memoryHeaps[aMemInfo.heapIndex]; + aDedicated += aHeap.size; + if (!aDedicatedHeaps.IsEmpty()) + { + aDedicatedHeaps += ", "; + } + aDedicatedHeaps += TCollection_AsciiString(int(aHeap.size / (1024 * 1024))) + " MiB"; + ++aNbDedicatedHeaps; + } + } + if (aDedicated != 0) + { + addInfo (theDict, "GPU memory", TCollection_AsciiString() + int(aDedicated / (1024 * 1024)) + " MiB"); + if (aNbDedicatedHeaps > 1) + { + addInfo (theDict, "GPU heaps", aDedicatedHeaps); + } + } + } +} diff --git a/src/Vulkan/Vulkan_Device.hxx b/src/Vulkan/Vulkan_Device.hxx new file mode 100644 index 0000000000..0d51dd2caf --- /dev/null +++ b/src/Vulkan/Vulkan_Device.hxx @@ -0,0 +1,119 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Device_HeaderFile +#define _Vulkan_Device_HeaderFile + +#include +#include +#include +#include +#include + +#include + +class Vulkan_Caps; +class Vulkan_FrameStats; + +//! This class defines an Vulkan graphic driver +class Vulkan_Device : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_Device, Standard_Transient) +public: + + //! Format VkResult enumeration. + Standard_EXPORT static TCollection_AsciiString FormatVkError (int theErr); + + //! Enumeration of known vendor ids. + enum VendorId + { + VendorId_AMD = 0x1002, + VendorId_NVIDIA = 0x10DE, + VendorId_INTEL = 0x8086, + }; + +public: + + //! Constructor. + //! @param theAppName application name to be passed to driver + //! @param theAppVersion application version to be passed to driver + //! @param theEngineName engine name to be passed to driver + //! @param theEngineVersion engine version to be passed to driver + Standard_EXPORT Vulkan_Device (const TCollection_AsciiString& theAppName, + const uint32_t theAppVersion, + const TCollection_AsciiString& theEngineName, + const uint32_t theEngineVersion); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_Device(); + + //! Release object. + Standard_EXPORT void Release(); + + //! Perform initialization. + Standard_EXPORT bool Init (const Handle(Vulkan_Caps)& theCaps); + + //! Return vulkan instance. + VkInstance Instance() const { return myVkInstance; } + + //! Return device. + VkDevice Device() const { return myVkDevice; } + + //! Return physical device. + VkPhysicalDevice PhysicalDevice() const { return myVkPhysDevice; } + + //! Return custom allocator. + const VkAllocationCallbacks* HostAllocator() const { return myVkHostAllocator.get(); } + + //! Return application identifier specified at construction time. + const TCollection_AsciiString& ApplicationName() const { return myAppName; } + + //! Return engine identifier specified at construction time. + const TCollection_AsciiString& EngineName() const { return myEngineName; } + + //! Return application version specified at construction time. + uint32_t ApplicationVersion() const { return myAppVersion; } + + //! Return engine version specified at construction time. + uint32_t EngineVersion() const { return myEngineVersion; } + + //! Return frame stats. + const Handle(Vulkan_FrameStats)& FrameStats() const { return myFrameStats; } + + //! Allocate device memory. + Standard_EXPORT VkDeviceMemory AllocateDeviceMemory (const VkMemoryRequirements& theReqs); + + //! Fill map with diagnostics information. + Standard_EXPORT void DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const; + +protected: + + TCollection_AsciiString myAppName; //!< application identifier to be passed to driver + TCollection_AsciiString myEngineName; //!< engine identifier to be passed to driver + uint32_t myAppVersion; //!< application version to be passed to driver + uint32_t myEngineVersion; //!< engine version to be passed to driver + + VkInstance myVkInstance; //!< vulkan instance + VkPhysicalDevice myVkPhysDevice; //!< physical device + VkDevice myVkDevice; //!< device + std::shared_ptr + myVkHostAllocator; //!< optional host memory allocator + std::shared_ptr + myVkDeviceMemory; + Handle(Vulkan_FrameStats) myFrameStats; + Standard_Boolean myIsOwnContext; //!< indicates that Vulkan pointers should be released or not (allocated externally) + +}; + +#endif // _Vulkan_Device_HeaderFile diff --git a/src/Vulkan/Vulkan_Fence.cxx b/src/Vulkan/Vulkan_Fence.cxx new file mode 100644 index 0000000000..92c4002fb7 --- /dev/null +++ b/src/Vulkan/Vulkan_Fence.cxx @@ -0,0 +1,128 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Fence, Standard_Transient) + +// ======================================================================= +// function : Vulkan_Fence +// purpose : +// ======================================================================= +Vulkan_Fence::Vulkan_Fence() +: myVkFence (NULL) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_Fence +// purpose : +// ======================================================================= +Vulkan_Fence::~Vulkan_Fence() +{ + Release (Handle(Vulkan_Device)()); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_Fence::Release (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkFence != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_Fence destroyed without Vulkan context",); + vkDestroyFence (theDevice->Device(), myVkFence, theDevice->HostAllocator()); + myVkFence = NULL; + } +} + +// ======================================================================= +// function : Create +// purpose : +// ======================================================================= +bool Vulkan_Fence::Create (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkFence != NULL) + { + return true; + } + + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL) + { + return false; + } + + VkFenceCreateInfo aVkFenceInfo; + aVkFenceInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + aVkFenceInfo.pNext = NULL; + aVkFenceInfo.flags = 0; + + VkResult aRes = vkCreateFence (theDevice->Device(), &aVkFenceInfo, theDevice->HostAllocator(), &myVkFence); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Fence, failed to create fence: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + return true; +} + +// ======================================================================= +// function : Wait +// purpose : +// ======================================================================= +bool Vulkan_Fence::Wait (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkFence == NULL) + { + return false; + } + + VkResult aRes = vkWaitForFences (theDevice->Device(), 1, &myVkFence, VK_TRUE, UINT64_MAX); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Fence, failed to wait for fence: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + return true; +} + +// ======================================================================= +// function : Reset +// purpose : +// ======================================================================= +bool Vulkan_Fence::Reset (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkFence == NULL) + { + return false; + } + + VkResult aRes = vkResetFences (theDevice->Device(), 1, &myVkFence); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Fence, failed to reset fence: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + return true; +} diff --git a/src/Vulkan/Vulkan_Fence.hxx b/src/Vulkan/Vulkan_Fence.hxx new file mode 100644 index 0000000000..a999710b63 --- /dev/null +++ b/src/Vulkan/Vulkan_Fence.hxx @@ -0,0 +1,55 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Fence_HeaderFile +#define _Vulkan_Fence_HeaderFile + +#include +#include + +class Vulkan_Device; + +//! This class defines an Vulkan fence. +class Vulkan_Fence : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_Fence, Standard_Transient) +public: + + //! Constructor. + Standard_EXPORT Vulkan_Fence(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_Fence(); + + //! Release the object, @sa vkDestroyFence(). + Standard_EXPORT void Release (const Handle(Vulkan_Device)& theDevice); + + //! Create the object, @sa vkCreateFence(). + Standard_EXPORT bool Create (const Handle(Vulkan_Device)& theDevice); + + //! Return object. + VkFence Fence() const { return myVkFence; } + + //! Wait for the fence, @sa vkWaitForFences(). + Standard_EXPORT bool Wait (const Handle(Vulkan_Device)& theDevice); + + //! Reset the fence, @sa vkResetFences(). + Standard_EXPORT bool Reset (const Handle(Vulkan_Device)& theDevice); + +protected: + + VkFence myVkFence; + +}; + +#endif // _Vulkan_Fence_HeaderFile diff --git a/src/Vulkan/Vulkan_ForwardDecl.hxx b/src/Vulkan/Vulkan_ForwardDecl.hxx new file mode 100644 index 0000000000..cf0b633fa8 --- /dev/null +++ b/src/Vulkan/Vulkan_ForwardDecl.hxx @@ -0,0 +1,63 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_ForwardDecl_HeaderFile +#define _Vulkan_ForwardDecl_HeaderFile + +#ifndef VK_DEFINE_HANDLE + #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; + + #if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE) + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; + #else + #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; + #endif + #endif + + VK_DEFINE_HANDLE(VkInstance) + VK_DEFINE_HANDLE(VkPhysicalDevice) + VK_DEFINE_HANDLE(VkDevice) + VK_DEFINE_HANDLE(VkQueue) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) + VK_DEFINE_HANDLE(VkCommandBuffer) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) + + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) + VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) + + struct VkAllocationCallbacks; + struct VkMemoryRequirements; + struct VkPhysicalDeviceMemoryProperties; + struct VkSurfaceFormatKHR; +#endif + +#endif // _Vulkan_ForwardDecl_HeaderFile diff --git a/src/Vulkan/Vulkan_FrameStats.cxx b/src/Vulkan/Vulkan_FrameStats.cxx new file mode 100644 index 0000000000..574c066f66 --- /dev/null +++ b/src/Vulkan/Vulkan_FrameStats.cxx @@ -0,0 +1,316 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_FrameStats, Graphic3d_FrameStats) + +namespace +{ + //! Return estimated data size. + /**static Standard_Size estimatedDataSize (const Handle(OpenGl_Resource)& theRes) + { + return !theRes.IsNull() ? theRes->EstimatedDataSize() : 0; + }*/ +} + +// ======================================================================= +// function : Vulkan_FrameStats +// purpose : +// ======================================================================= +Vulkan_FrameStats::Vulkan_FrameStats() +{ + // +} + +// ======================================================================= +// function : ~Vulkan_FrameStats +// purpose : +// ======================================================================= +Vulkan_FrameStats::~Vulkan_FrameStats() +{ + // +} + +// ======================================================================= +// function : IsFrameUpdated +// purpose : +// ======================================================================= +bool Vulkan_FrameStats::IsFrameUpdated (Handle(Vulkan_FrameStats)& thePrev) const +{ + const Graphic3d_FrameStatsData& aFrame = LastDataFrame(); + if (thePrev.IsNull()) + { + thePrev = new Vulkan_FrameStats(); + } + // check just a couple of major counters + else if (myLastFrameIndex == thePrev->myLastFrameIndex + && Abs (aFrame.FrameRate() - thePrev->myCountersTmp.FrameRate()) <= 0.001 + && Abs (aFrame.FrameRateCpu() - thePrev->myCountersTmp.FrameRateCpu()) <= 0.001 + && aFrame[Graphic3d_FrameStatsCounter_NbLayers] == thePrev->myCountersTmp[Graphic3d_FrameStatsCounter_NbLayers] + && aFrame[Graphic3d_FrameStatsCounter_NbLayersNotCulled] == thePrev->myCountersTmp[Graphic3d_FrameStatsCounter_NbLayersNotCulled] + && aFrame[Graphic3d_FrameStatsCounter_NbStructs] == thePrev->myCountersTmp[Graphic3d_FrameStatsCounter_NbStructs] + && aFrame[Graphic3d_FrameStatsCounter_NbStructsNotCulled] == thePrev->myCountersTmp[Graphic3d_FrameStatsCounter_NbStructsNotCulled]) + { + return false; + } + + thePrev->myLastFrameIndex = myLastFrameIndex; + thePrev->myCountersTmp = aFrame; + return true; +} + +// ======================================================================= +// function : updateStatistics +// purpose : +// ======================================================================= +void Vulkan_FrameStats::updateStatistics (const Handle(Graphic3d_CView)& theView, + bool theIsImmediateOnly) +{ + const Vulkan_View* aView = dynamic_cast (theView.get()); + if (aView == NULL) + { + myCounters.SetValue (myLastFrameIndex, myCountersTmp); + myCountersTmp.Reset(); + return; + } + + const Graphic3d_RenderingParams::PerfCounters aBits = theView->RenderingParams().CollectedStats; + const Standard_Boolean toCountMem = (aBits & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0; + const Standard_Boolean toCountTris = (aBits & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0 + || (aBits & Graphic3d_RenderingParams::PerfCounters_Points) != 0; + const Standard_Boolean toCountElems = (aBits & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0 || toCountTris || toCountMem; + const Standard_Boolean toCountGroups = (aBits & Graphic3d_RenderingParams::PerfCounters_Groups) != 0 || toCountElems; + const Standard_Boolean toCountStructs = (aBits & Graphic3d_RenderingParams::PerfCounters_Structures) != 0 + || (aBits & Graphic3d_RenderingParams::PerfCounters_Layers) != 0 || toCountGroups; + + /// TODO + ///myCountersTmp[Graphic3d_FrameStatsCounter_NbLayers] = aView->LayerList().Layers().Size(); + if (toCountStructs + || (aBits & Graphic3d_RenderingParams::PerfCounters_Layers) != 0) + { + const Standard_Integer aViewId = aView->Identification(); + /// TODO + /*for (OpenGl_SequenceOfLayers::Iterator aLayerIter (aView->LayerList().Layers()); aLayerIter.More(); aLayerIter.Next()) + { + const Handle(OpenGl_Layer)& aLayer = aLayerIter.Value(); + myCountersTmp[Graphic3d_FrameStatsCounter_NbStructs] += aLayer->NbStructures(); + if (theIsImmediateOnly && !aLayer->LayerSettings().IsImmediate()) + { + continue; + } + + if (!aLayer->IsCulled()) + { + ++myCountersTmp[Graphic3d_FrameStatsCounter_NbLayersNotCulled]; + } + myCountersTmp[Graphic3d_FrameStatsCounter_NbStructsNotCulled] += aLayer->NbStructuresNotCulled(); + if (toCountGroups) + { + updateStructures (aViewId, aLayer->CullableStructuresBVH().Structures(), toCountElems, toCountTris, toCountMem); + updateStructures (aViewId, aLayer->CullableTrsfPersStructuresBVH().Structures(), toCountElems, toCountTris, toCountMem); + updateStructures (aViewId, aLayer->NonCullableStructures(), toCountElems, toCountTris, toCountMem); + } + }*/ + } + if (toCountMem) + { + // TODO + /**for (OpenGl_Context::OpenGl_ResourcesMap::Iterator aResIter (aView->GlWindow()->GetGlContext()->SharedResources()); + aResIter.More(); aResIter.Next()) + { + myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesTextures] += aResIter.Value()->EstimatedDataSize(); + } + + { + Standard_Size& aMemFbos = myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesFbos]; + // main FBOs + aMemFbos += estimatedDataSize (aView->myMainSceneFbos[0]); + aMemFbos += estimatedDataSize (aView->myMainSceneFbos[1]); + aMemFbos += estimatedDataSize (aView->myImmediateSceneFbos[0]); + aMemFbos += estimatedDataSize (aView->myImmediateSceneFbos[1]); + // OIT FBOs + aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[0]); + aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[1]); + aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[0]); + aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[1]); + // dump FBO + aMemFbos += estimatedDataSize (aView->myFBO); + // RayTracing FBO + aMemFbos += estimatedDataSize (aView->myOpenGlFBO); + aMemFbos += estimatedDataSize (aView->myOpenGlFBO2); + aMemFbos += estimatedDataSize (aView->myRaytraceFBO1[0]); + aMemFbos += estimatedDataSize (aView->myRaytraceFBO1[1]); + aMemFbos += estimatedDataSize (aView->myRaytraceFBO2[0]); + aMemFbos += estimatedDataSize (aView->myRaytraceFBO2[1]); + // also RayTracing + aMemFbos += estimatedDataSize (aView->myRaytraceOutputTexture[0]); + aMemFbos += estimatedDataSize (aView->myRaytraceOutputTexture[1]); + aMemFbos += estimatedDataSize (aView->myRaytraceVisualErrorTexture[0]); + aMemFbos += estimatedDataSize (aView->myRaytraceVisualErrorTexture[1]); + aMemFbos += estimatedDataSize (aView->myRaytraceTileOffsetsTexture[0]); + aMemFbos += estimatedDataSize (aView->myRaytraceTileOffsetsTexture[1]); + aMemFbos += estimatedDataSize (aView->myRaytraceTileSamplesTexture[0]); + aMemFbos += estimatedDataSize (aView->myRaytraceTileSamplesTexture[1]); + }*/ + } +} + +// ======================================================================= +// function : updateStructures +// purpose : +// ======================================================================= +void Vulkan_FrameStats::updateStructures (Standard_Integer theViewId, + const NCollection_IndexedMap& theStructures, + Standard_Boolean theToCountElems, + Standard_Boolean theToCountTris, + Standard_Boolean theToCountMem) +{ + for (Vulkan_Structure::StructIterator aStructIter (theStructures); aStructIter.More(); aStructIter.Next()) + { + const Vulkan_Structure* aStruct = aStructIter.Value(); + const bool isStructHidden = aStruct->IsCulled() + || !aStruct->IsVisible (theViewId); + for (; aStruct != NULL; aStruct = aStruct->InstancedStructure()) + { + if (isStructHidden) + { + if (theToCountMem) + { + for (Vulkan_Structure::GroupIterator aGroupIter (aStruct->Groups()); aGroupIter.More(); aGroupIter.Next()) + { + const Vulkan_Group* aGroup = aGroupIter.Value(); + // TODO + /**for (const OpenGl_ElementNode* aNodeIter = aGroup->FirstNode(); aNodeIter != NULL; aNodeIter = aNodeIter->next) + { + if (const OpenGl_PrimitiveArray* aPrim = dynamic_cast (aNodeIter->elem)) + { + myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom] += estimatedDataSize (aPrim->AttributesVbo()); + myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom] += estimatedDataSize (aPrim->IndexVbo()); + } + }*/ + } + } + continue; + } + + myCountersTmp[Graphic3d_FrameStatsCounter_NbGroupsNotCulled] += aStruct->Groups().Size(); + if (!theToCountElems) + { + continue; + } + + for (Vulkan_Structure::GroupIterator aGroupIter (aStruct->Groups()); aGroupIter.More(); aGroupIter.Next()) + { + const Vulkan_Group* aGroup = aGroupIter.Value(); + // TODO + /**for (const OpenGl_ElementNode* aNodeIter = aGroup->FirstNode(); aNodeIter != NULL; aNodeIter = aNodeIter->next) + { + if (const OpenGl_PrimitiveArray* aPrim = dynamic_cast (aNodeIter->elem)) + { + ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsNotCulled]; + if (theToCountMem) + { + myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom] += estimatedDataSize (aPrim->AttributesVbo()); + myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom] += estimatedDataSize (aPrim->IndexVbo()); + } + + if (aPrim->IsFillDrawMode()) + { + ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled]; + if (!theToCountTris) + { + continue; + } + + const Handle(OpenGl_VertexBuffer)& anAttribs = aPrim->AttributesVbo(); + if (anAttribs.IsNull() + || !anAttribs->IsValid()) + { + continue; + } + + const Handle(OpenGl_VertexBuffer)& anIndices = aPrim->IndexVbo(); + const Standard_Integer aNbIndices = !anIndices.IsNull() ? anIndices->GetElemsNb() : anAttribs->GetElemsNb(); + const Standard_Integer aNbBounds = !aPrim->Bounds().IsNull() ? aPrim->Bounds()->NbBounds : 1; + switch (aPrim->DrawMode()) + { + case GL_TRIANGLES: + { + myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 3; + break; + } + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + { + myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 2 * aNbBounds; + break; + } + case GL_TRIANGLES_ADJACENCY: + { + myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 6; + break; + } + case GL_TRIANGLE_STRIP_ADJACENCY: + { + myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 4 * aNbBounds; + break; + } + #if !defined(GL_ES_VERSION_2_0) + case GL_QUADS: + { + myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 2; + break; + } + case GL_QUAD_STRIP: + { + myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += (aNbIndices / 2 - aNbBounds) * 2; + break; + } + #endif + } + } + else if (aPrim->DrawMode() == GL_POINTS) + { + ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled]; + if (theToCountTris) + { + const Handle(OpenGl_VertexBuffer)& anAttribs = aPrim->AttributesVbo(); + if (!anAttribs.IsNull() + && anAttribs->IsValid()) + { + const Handle(OpenGl_VertexBuffer)& anIndices = aPrim->IndexVbo(); + const Standard_Integer aNbIndices = !anIndices.IsNull() ? anIndices->GetElemsNb() : anAttribs->GetElemsNb(); + myCountersTmp[Graphic3d_FrameStatsCounter_NbPointsNotCulled] += aNbIndices; + } + } + } + else + { + ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled]; + } + } + else if (const OpenGl_Text* aText = dynamic_cast (aNodeIter->elem)) + { + (void )aText; + ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsNotCulled]; + ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled]; + } + }*/ + } + } + } +} diff --git a/src/Vulkan/Vulkan_FrameStats.hxx b/src/Vulkan/Vulkan_FrameStats.hxx new file mode 100644 index 0000000000..1f22325ea1 --- /dev/null +++ b/src/Vulkan/Vulkan_FrameStats.hxx @@ -0,0 +1,58 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_FrameStats_HeaderFile +#define _Vulkan_FrameStats_HeaderFile + +#include +#include + +class Graphic3d_CStructure; + +//! Class storing the frame statistics. +class Vulkan_FrameStats : public Graphic3d_FrameStats +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_FrameStats, Graphic3d_FrameStats) +public: + + //! Default constructor. + Standard_EXPORT Vulkan_FrameStats(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_FrameStats(); + +public: + + //! Copy stats values into another instance (create new instance, if not exists). + //! The main use of this method is to track changes in statistics (e.g. in conjunction with IsEqual() method). + //! @return TRUE if frame data has been changed so that the presentation should be updated + Standard_EXPORT virtual bool IsFrameUpdated (Handle(Vulkan_FrameStats)& thePrev) const; + +protected: + + //! Method to collect statistics from the View; called by FrameEnd(). + Standard_EXPORT virtual void updateStatistics (const Handle(Graphic3d_CView)& theView, + bool theIsImmediateOnly) Standard_OVERRIDE; + + //! Updates counters for structures. + Standard_EXPORT virtual void updateStructures (Standard_Integer theViewId, + const NCollection_IndexedMap& theStructures, + Standard_Boolean theToCountElems, + Standard_Boolean theToCountTris, + Standard_Boolean theToCountMem); + +}; + +DEFINE_STANDARD_HANDLE(Vulkan_FrameStats, Graphic3d_FrameStats) + +#endif // _Vulkan_FrameStats_HeaderFile diff --git a/src/Vulkan/Vulkan_GraphicDriver.cxx b/src/Vulkan/Vulkan_GraphicDriver.cxx new file mode 100644 index 0000000000..e4b89f4b23 --- /dev/null +++ b/src/Vulkan/Vulkan_GraphicDriver.cxx @@ -0,0 +1,355 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_GraphicDriver, Graphic3d_GraphicDriver) + +// ======================================================================= +// function : Vulkan_GraphicDriver +// purpose : +// ======================================================================= +Vulkan_GraphicDriver::Vulkan_GraphicDriver (const TCollection_AsciiString& theAppName, + const uint32_t theAppVersion, + const Handle(Aspect_DisplayConnection)& theDisp) +: Graphic3d_GraphicDriver (theDisp), + myVkDevice (new Vulkan_Device (theAppName, theAppVersion, "Open CASCADE Technology", OCC_VERSION_HEX)), + myCaps (new Vulkan_Caps()), + myMapOfView (1, NCollection_BaseAllocator::CommonBaseAllocator()), + myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator()) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_GraphicDriver +// purpose : +// ======================================================================= +Vulkan_GraphicDriver::~Vulkan_GraphicDriver() +{ + ReleaseContext(); +} + +// ======================================================================= +// function : ReleaseContext +// purpose : +// ======================================================================= +void Vulkan_GraphicDriver::ReleaseContext() +{ + myVkDevice->Release(); +} + +// ======================================================================= +// function : InitContext +// purpose : +// ======================================================================= +Standard_Boolean Vulkan_GraphicDriver::InitContext() +{ + ReleaseContext(); + return myVkDevice->Init (myCaps); +} + +// ======================================================================= +// function : InquireLimit +// purpose : +// ======================================================================= +Standard_Integer Vulkan_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit theType) const +{ + return 0; +} + +// ======================================================================= +// function : DefaultTextHeight +// purpose : +// ======================================================================= +Standard_ShortReal Vulkan_GraphicDriver::DefaultTextHeight() const +{ + return 16.; +} + +// ======================================================================= +// function : MemoryInfo +// purpose : +// ======================================================================= +Standard_Boolean Vulkan_GraphicDriver::MemoryInfo (Standard_Size& theFreeBytes, + TCollection_AsciiString& theInfo) const +{ + return false; +} + +// ======================================================================= +// function : TextSize +// purpose : +// ======================================================================= +void Vulkan_GraphicDriver::TextSize (const Handle(Graphic3d_CView)& theView, + const Standard_CString theText, + const Standard_ShortReal theHeight, + Standard_ShortReal& theWidth, + Standard_ShortReal& theAscent, + Standard_ShortReal& theDescent) const +{ +} + +//======================================================================= +//function : AddZLayer +//purpose : +//======================================================================= +void Vulkan_GraphicDriver::AddZLayer (const Graphic3d_ZLayerId theLayerId) +{ + if (theLayerId < 1) + { + Standard_ASSERT_RAISE (theLayerId > 0, "Vulkan_GraphicDriver::AddZLayer, negative and zero IDs are reserved"); + } + + myLayerIds.Add (theLayerId); + + // Default z-layer settings + myMapOfZLayerSettings.Bind (theLayerId, Graphic3d_ZLayerSettings()); + addZLayerIndex (theLayerId); + + // Add layer to all views + for (NCollection_Map::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next()) + { + aViewIt.Value()->AddZLayer (theLayerId); + } +} + +//======================================================================= +//function : RemoveZLayer +//purpose : +//======================================================================= +void Vulkan_GraphicDriver::RemoveZLayer (const Graphic3d_ZLayerId theLayerId) +{ + Standard_ASSERT_RAISE (theLayerId > 0, + "Vulkan_GraphicDriver::AddZLayer, negative and zero IDs are reserved and can not be removed"); + + Standard_ASSERT_RAISE (myLayerIds.Contains (theLayerId), + "Vulkan_GraphicDriver::RemoveZLayer, Layer with theLayerId does not exist"); + + // Remove layer from all of the views + for (NCollection_Map::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next()) + { + aViewIt.Value()->RemoveZLayer (theLayerId); + } + + // Unset Z layer for all of the structures. + for (NCollection_DataMap::Iterator aStructIt (myMapOfStructure); aStructIt.More(); aStructIt.Next()) + { + Vulkan_Structure* aStruct = aStructIt.ChangeValue(); + if (aStruct->ZLayer() == theLayerId) + { + aStruct->SetZLayer (Graphic3d_ZLayerId_Default); + } + } + + // Remove index + for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next()) + { + if (aLayerIt.Value() == theLayerId) + { + myLayerSeq.Remove (aLayerIt); + break; + } + } + + myMapOfZLayerSettings.UnBind (theLayerId); + myLayerIds.Remove (theLayerId); +} + +//======================================================================= +//function : SetZLayerSettings +//purpose : +//======================================================================= +void Vulkan_GraphicDriver::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, + const Graphic3d_ZLayerSettings& theSettings) +{ + base_type::SetZLayerSettings (theLayerId, theSettings); + + // Change Z layer settings in all managed views + for (NCollection_Map::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next()) + { + aViewIt.Value()->SetZLayerSettings (theLayerId, theSettings); + } +} + +// ======================================================================= +// function : Structure +// purpose : +// ======================================================================= +Handle(Graphic3d_CStructure) Vulkan_GraphicDriver::CreateStructure (const Handle(Graphic3d_StructureManager)& theManager) +{ + Handle(Vulkan_Structure) aStructure = new Vulkan_Structure (theManager); + myMapOfStructure.Bind (aStructure->Id, aStructure.get()); + return aStructure; +} + +// ======================================================================= +// function : Structure +// purpose : +// ======================================================================= +void Vulkan_GraphicDriver::RemoveStructure (Handle(Graphic3d_CStructure)& theCStructure) +{ + Vulkan_Structure* aStructure = NULL; + if (!myMapOfStructure.Find (theCStructure->Id, aStructure)) + { + return; + } + + myMapOfStructure.UnBind (theCStructure->Id); + /// TODO aStructure->Release (GetSharedContext()); + theCStructure.Nullify(); +} + +// ======================================================================= +// function : View +// purpose : +// ======================================================================= +Handle(Graphic3d_CView) Vulkan_GraphicDriver::CreateView (const Handle(Graphic3d_StructureManager)& theMgr) +{ + Handle(Vulkan_View) aView = new Vulkan_View (theMgr, this); + + myMapOfView.Add (aView); + + for (TColStd_SequenceOfInteger::Iterator aLayerIt (myLayerSeq); aLayerIt.More(); aLayerIt.Next()) + { + const Graphic3d_ZLayerId aLayerID = aLayerIt.Value(); + const Graphic3d_ZLayerSettings& aSettings = myMapOfZLayerSettings.Find (aLayerID); + aView->AddZLayer (aLayerID); + aView->SetZLayerSettings (aLayerID, aSettings); + } + + return aView; +} + +// ======================================================================= +// function : RemoveView +// purpose : +// ======================================================================= +void Vulkan_GraphicDriver::RemoveView (const Handle(Graphic3d_CView)& theView) +{ + /**Handle(Vulkan_Context) aCtx = GetSharedContext(); + Handle(Vulkan_View) aView = Handle(Vulkan_View)::DownCast (theView); + if (aView.IsNull()) + { + return; + } + + if (!myMapOfView.Remove (aView)) + { + return; + } + + Handle(Vulkan_Window) aWindow = aView->GlWindow(); + if (!aWindow.IsNull() + && aWindow->GetGlContext()->MakeCurrent()) + { + aCtx = aWindow->GetGlContext(); + } + else + { + // try to hijack another context if any + const Handle(Vulkan_Context)& anOtherCtx = GetSharedContext(); + if (!anOtherCtx.IsNull() + && anOtherCtx != aWindow->GetGlContext()) + { + aCtx = anOtherCtx; + aCtx->MakeCurrent(); + } + } + + aView->ReleaseGlResources (aCtx); + if (myMapOfView.IsEmpty()) + { + // The last view removed but some objects still present. + // Release GL resources now without object destruction. + for (NCollection_DataMap::Iterator aStructIt (myMapOfStructure); + aStructIt.More (); aStructIt.Next()) + { + Vulkan_Structure* aStruct = aStructIt.ChangeValue(); + aStruct->ReleaseGlResources (aCtx); + } + + if (!myMapOfStructure.IsEmpty()) + { + aView->StructureManager()->SetDeviceLost(); + } + }*/ +} + +//======================================================================= +//function : ViewExists +//purpose : +//======================================================================= +Standard_Boolean Vulkan_GraphicDriver::ViewExists (const Handle(Aspect_Window)& theWindow, + Handle(Graphic3d_CView)& theView) +{ + // Parse the list of views to find a view with the specified window +/*#if defined(_WIN32) && !defined(OCCT_UWP) + const Handle(WNT_Window) aWindowToFind = Handle(WNT_Window)::DownCast (theWindow); + Aspect_Handle aWindowIdToFind = aWindowToFind->HWindow(); +#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) + const Handle(Cocoa_Window) aWindowToFind = Handle(Cocoa_Window)::DownCast (theWindow); + #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE + UIView* aWindowIdToFind = aWindowToFind->HView(); + #else + NSView* aWindowIdToFind = aWindowToFind->HView(); + #endif +#elif defined(__ANDROID__) || defined(__QNX__) || defined(OCCT_UWP) + (void )theWindow; + int aWindowIdToFind = -1; +#else + const Handle(Xw_Window) aWindowToFind = Handle(Xw_Window)::DownCast (theWindow); + int aWindowIdToFind = int (aWindowToFind->XWindow()); +#endif + for (NCollection_Map::Iterator aViewIt (myMapOfView); aViewIt.More(); aViewIt.Next()) + { + const Handle(Vulkan_View)& aView = aViewIt.Value(); + if (aView->IsDefined() + && aView->IsActive()) + { + const Handle(Aspect_Window) anAspectWindow = aView->Window(); + + #if defined(_WIN32) && !defined(OCCT_UWP) + const Handle(WNT_Window) aWindow = Handle(WNT_Window)::DownCast (anAspectWindow); + Aspect_Handle aWindowIdOfView = aWindow->HWindow(); + #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) + const Handle(Cocoa_Window) aWindow = Handle(Cocoa_Window)::DownCast (anAspectWindow); + #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE + UIView* aWindowIdOfView = aWindow->HView(); + #else + NSView* aWindowIdOfView = aWindow->HView(); + #endif + #elif defined(__ANDROID__) || defined(__QNX__) || defined(OCCT_UWP) + int aWindowIdOfView = 0; + #else + const Handle(Xw_Window) aWindow = Handle(Xw_Window)::DownCast (anAspectWindow); + int aWindowIdOfView = int(aWindow->XWindow()); + #endif + if (aWindowIdOfView == aWindowIdToFind) + { + theView = aView; + return true; + } + } + }*/ + return false; +} diff --git a/src/Vulkan/Vulkan_GraphicDriver.hxx b/src/Vulkan/Vulkan_GraphicDriver.hxx new file mode 100644 index 0000000000..b96cc8be50 --- /dev/null +++ b/src/Vulkan/Vulkan_GraphicDriver.hxx @@ -0,0 +1,122 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_GraphicDriver_HeaderFile +#define _Vulkan_GraphicDriver_HeaderFile + +#include + +class Vulkan_Caps; +class Vulkan_Device; +class Vulkan_Structure; +class Vulkan_View; +class Vulkan_Window; + +typedef struct VkInstance_T* VkInstance; +typedef struct VkPhysicalDevice_T* VkPhysicalDevice; +typedef struct VkDevice_T* VkDevice; + +//! This class defines an Vulkan graphic driver +class Vulkan_GraphicDriver : public Graphic3d_GraphicDriver +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_GraphicDriver, Graphic3d_GraphicDriver) +public: + + //! Constructor. + //! @param theAppName application name to be passed to Vulkan + //! @param theAppVersion application version to be passed to Vulkan + //! @param theDisp connection to display, required on Linux but optional on other systems + Standard_EXPORT Vulkan_GraphicDriver (const TCollection_AsciiString& theAppName, + const uint32_t theAppVersion, + const Handle(Aspect_DisplayConnection)& theDisp); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_GraphicDriver(); + + //! Release default context. + Standard_EXPORT void ReleaseContext(); + + //! @return the visualization options + Standard_EXPORT const Handle(Vulkan_Caps)& Options() const { return myCaps; } + + //! Perform initialization of default OpenGL context. + Standard_EXPORT Standard_Boolean InitContext(); + + //! Request limit of graphic resource of specific type. + Standard_EXPORT virtual Standard_Integer InquireLimit (const Graphic3d_TypeOfLimit theType) const Standard_OVERRIDE; + +public: + + Standard_EXPORT virtual Handle(Graphic3d_CStructure) CreateStructure (const Handle(Graphic3d_StructureManager)& theManager) Standard_OVERRIDE; + + Standard_EXPORT virtual void RemoveStructure (Handle(Graphic3d_CStructure)& theCStructure) Standard_OVERRIDE; + + Standard_EXPORT virtual Handle(Graphic3d_CView) CreateView (const Handle(Graphic3d_StructureManager)& theMgr) Standard_OVERRIDE; + + Standard_EXPORT virtual void RemoveView (const Handle(Graphic3d_CView)& theView) Standard_OVERRIDE; + +public: + + Standard_EXPORT virtual void TextSize (const Handle(Graphic3d_CView)& theView, + const Standard_CString theText, + const Standard_ShortReal theHeight, + Standard_ShortReal& theWidth, + Standard_ShortReal& theAscent, + Standard_ShortReal& theDescent) const Standard_OVERRIDE; + + Standard_EXPORT virtual Standard_ShortReal DefaultTextHeight() const Standard_OVERRIDE; + + Standard_EXPORT virtual Standard_Boolean ViewExists (const Handle(Aspect_Window)& theWindow, + Handle(Graphic3d_CView)& theView) Standard_OVERRIDE; + +public: + + //! Adds a new top-level z layer with ID theLayerId for all views. Z layers allow drawing structures in higher layers + //! in foreground of structures in lower layers. To add a structure to desired layer on display it is necessary to + //! set the layer index for the structure. The passed theLayerId should be not less than 0 (reserved for default layers). + Standard_EXPORT virtual void AddZLayer (const Graphic3d_ZLayerId theLayerId) Standard_OVERRIDE; + + //! Removes Z layer. All structures displayed at the moment in layer will be displayed in + //! default layer (the bottom-level z layer). By default, there are always default + //! bottom-level layer that can't be removed. The passed theLayerId should be not less than 0 + //! (reserved for default layers that can not be removed). + Standard_EXPORT virtual void RemoveZLayer (const Graphic3d_ZLayerId theLayerId) Standard_OVERRIDE; + + //! Sets the settings for a single Z layer. + Standard_EXPORT virtual void SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, const Graphic3d_ZLayerSettings& theSettings) Standard_OVERRIDE; + +public: + + //! Obsolete method. + virtual void EnableVBO (const Standard_Boolean ) Standard_OVERRIDE {} + + //! Returns information about GPU memory usage. + //! Please read OpenGl_Context::MemoryInfo() for more description. + Standard_EXPORT virtual Standard_Boolean MemoryInfo (Standard_Size& theFreeBytes, + TCollection_AsciiString& theInfo) const Standard_OVERRIDE; + +public: + + const Handle(Vulkan_Device)& Device() const { return myVkDevice; } + +protected: + + Handle(Vulkan_Device) myVkDevice; + + Handle(Vulkan_Caps) myCaps; + NCollection_Map myMapOfView; + NCollection_DataMap myMapOfStructure; + +}; + +#endif // _Vulkan_GraphicDriver_HeaderFile diff --git a/src/Vulkan/Vulkan_Group.cxx b/src/Vulkan/Vulkan_Group.cxx new file mode 100644 index 0000000000..2805551fb2 --- /dev/null +++ b/src/Vulkan/Vulkan_Group.cxx @@ -0,0 +1,345 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Group, Graphic3d_Group) + +namespace +{ + //! Render element if it passes the filtering procedure. This method should + //! be used for elements which can be used in scope of rendering algorithms. + //! E.g. elements of groups during recursive rendering. + //! If render filter is null, pure rendering is performed. + //! @param theWorkspace [in] the rendering workspace. + //! @param theFilter [in] the rendering filter to check whether the element + //! should be rendered or not. + //! @return True if element passes the check and renders, + /*static bool renderFiltered (const Handle(OpenGl_Workspace)& theWorkspace, + OpenGl_Element* theElement) + { + if (!theWorkspace->ShouldRender (theElement)) + { + return false; + } + + theElement->Render (theWorkspace); + return true; + }*/ +} + +// ======================================================================= +// function : Vulkan_Group +// purpose : +// ======================================================================= +Vulkan_Group::Vulkan_Group (const Handle(Graphic3d_Structure)& theStruct) +: Graphic3d_Group (theStruct) + //myAspects(NULL), + //myFirst(NULL), + //myLast(NULL) +{ + const Vulkan_Structure* aStruct = dynamic_cast(myStructure->CStructure().get()); + if (aStruct == NULL) + { + throw Graphic3d_GroupDefinitionError("Vulkan_Group should be created by Vulkan_Structure!"); + } +} + +// ======================================================================= +// function : ~Vulkan_Group +// purpose : +// ======================================================================= +Vulkan_Group::~Vulkan_Group() +{ + /// TODO + ///Release (Handle(OpenGl_Context)()); +} + +// ======================================================================= +// function : SetGroupPrimitivesAspect +// purpose : +// ======================================================================= +void Vulkan_Group::SetGroupPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect) +{ + if (IsDeleted()) + { + return; + } + + /*if (myAspects == NULL) + { + myAspects = new OpenGl_Aspects (theAspect); + } + else + { + myAspects->SetAspect (theAspect); + }*/ + + Update(); +} + +// ======================================================================= +// function : SetPrimitivesAspect +// purpose : +// ======================================================================= +void Vulkan_Group::SetPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect) +{ + /*if (myAspects == NULL) + { + SetGroupPrimitivesAspect (theAspect); + return; + } + else if (IsDeleted()) + { + return; + } + + OpenGl_Aspects* anAspects = new OpenGl_Aspects (theAspect); + AddElement (anAspects);*/ + Update(); +} + +// ======================================================================= +// function : SynchronizeAspects +// purpose : +// ======================================================================= +void Vulkan_Group::SynchronizeAspects() +{ + /*if (myAspects != NULL) + { + myAspects->SynchronizeAspects(); + if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL) + { + aStruct->UpdateStateIfRaytracable (Standard_False); + } + } + for (OpenGl_ElementNode* aNode = myFirst; aNode != NULL; aNode = aNode->next) + { + aNode->elem->SynchronizeAspects(); + }*/ +} + +// ======================================================================= +// function : ReplaceAspects +// purpose : +// ======================================================================= +void Vulkan_Group::ReplaceAspects (const Graphic3d_MapOfAspectsToAspects& theMap) +{ + if (theMap.IsEmpty()) + { + return; + } + + /*Handle(Graphic3d_Aspects) anAspect; + if (myAspects != NULL + && theMap.Find (myAspects->Aspect(), anAspect)) + { + myAspects->SetAspect (anAspect); + if (OpenGl_Structure* aStruct = myIsRaytracable ? GlStruct() : NULL) + { + aStruct->UpdateStateIfRaytracable (Standard_False); + } + } + for (OpenGl_ElementNode* aNode = myFirst; aNode != NULL; aNode = aNode->next) + { + OpenGl_Aspects* aGlAspect = dynamic_cast (aNode->elem); + if (aGlAspect != NULL + && theMap.Find (aGlAspect->Aspect(), anAspect)) + { + aGlAspect->SetAspect (anAspect); + } + }*/ +} + +// ======================================================================= +// function : AddPrimitiveArray +// purpose : +// ======================================================================= +void Vulkan_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType, + const Handle(Graphic3d_IndexBuffer)& theIndices, + const Handle(Graphic3d_Buffer)& theAttribs, + const Handle(Graphic3d_BoundBuffer)& theBounds, + const Standard_Boolean theToEvalMinMax) +{ + if (IsDeleted() + || theAttribs.IsNull()) + { + return; + } + + Vulkan_PrimitiveArray aPrimArray; + aPrimArray.Indices = theIndices; + aPrimArray.Attribs = theAttribs; + aPrimArray.Bounds = theBounds; + aPrimArray.Type = theType; + myElements.Append (aPrimArray); + + //OpenGl_Structure* aStruct = GlStruct(); + //const OpenGl_GraphicDriver* aDriver = aStruct->GlDriver(); + + //OpenGl_PrimitiveArray* anArray = new OpenGl_PrimitiveArray (aDriver, theType, theIndices, theAttribs, theBounds); + //AddElement (anArray); + + Graphic3d_Group::AddPrimitiveArray (theType, theIndices, theAttribs, theBounds, theToEvalMinMax); +} + +// ======================================================================= +// function : Text +// purpose : +// ======================================================================= +void Vulkan_Group::Text (const Standard_CString theTextUtf, + const Graphic3d_Vertex& thePoint, + const Standard_Real theHeight, + const Standard_Real theAngle, + const Graphic3d_TextPath theTp, + const Graphic3d_HorizontalTextAlignment theHta, + const Graphic3d_VerticalTextAlignment theVta, + const Standard_Boolean theToEvalMinMax) +{ + if (IsDeleted()) + { + return; + } + + Graphic3d_Group::Text (theTextUtf, thePoint, theHeight, theAngle, + theTp, theHta, theVta, theToEvalMinMax); +} + +// ======================================================================= +// function : Text +// purpose : +// ======================================================================= +void Vulkan_Group::Text (const Standard_CString theTextUtf, + const gp_Ax2& theOrientation, + const Standard_Real theHeight, + const Standard_Real theAngle, + const Graphic3d_TextPath theTp, + const Graphic3d_HorizontalTextAlignment theHTA, + const Graphic3d_VerticalTextAlignment theVTA, + const Standard_Boolean theToEvalMinMax, + const Standard_Boolean theHasOwnAnchor) +{ + if (IsDeleted()) + { + return; + } + + Graphic3d_Group::Text (theTextUtf, + theOrientation, + theHeight, + theAngle, + theTp, + theHTA, + theVTA, + theToEvalMinMax, + theHasOwnAnchor); +} + +// ======================================================================= +// function : SetFlippingOptions +// purpose : +// ======================================================================= +void Vulkan_Group::SetFlippingOptions (const Standard_Boolean , + const gp_Ax2& ) +{ + // +} + +// ======================================================================= +// function : SetStencilTestOptions +// purpose : +// ======================================================================= +void Vulkan_Group::SetStencilTestOptions (const Standard_Boolean ) +{ + // +} + +// ======================================================================= +// function : AddElement +// purpose : +// ======================================================================= +/*void Vulkan_Group::AddElement (OpenGl_Element* theElem) +{ + OpenGl_ElementNode *aNode = new OpenGl_ElementNode(); + + aNode->elem = theElem; + aNode->next = NULL; + (myLast? myLast->next : myFirst) = aNode; + myLast = aNode; +}*/ + +// ======================================================================= +// function : Render +// purpose : +// ======================================================================= +/*void Vulkan_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const +{ + // Setup aspects + theWorkspace->SetAllowFaceCulling (myIsClosed + && !theWorkspace->GetGlContext()->Clipping().IsClippingOrCappingOn()); + const OpenGl_Aspects* aBackAspects = theWorkspace->Aspects(); + const bool isAspectSet = myAspects != NULL && renderFiltered (theWorkspace, myAspects); + + // Render group elements + for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next) + { + renderFiltered (theWorkspace, aNodeIter->elem); + } + + // Restore aspects + if (isAspectSet) + theWorkspace->SetAspects (aBackAspects); +}*/ + +// ======================================================================= +// function : Clear +// purpose : +// ======================================================================= +void Vulkan_Group::Clear (const Standard_Boolean theToUpdateStructureMgr) +{ + if (IsDeleted()) + { + return; + } + + myElements.Clear(); + /*OpenGl_Structure* aStruct = GlStruct(); + const Handle(OpenGl_Context)& aCtx = aStruct->GlDriver()->GetSharedContext(); + + Release (aCtx); + Graphic3d_Group::Clear (theToUpdateStructureMgr);*/ +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +/*void Vulkan_Group::Release (const Handle(OpenGl_Context)& theGlCtx) +{ + // Delete elements + while (myFirst != NULL) + { + OpenGl_ElementNode* aNext = myFirst->next; + OpenGl_Element::Destroy (theGlCtx.get(), myFirst->elem); + delete myFirst; + myFirst = aNext; + } + myLast = NULL; + + OpenGl_Element::Destroy (theGlCtx.get(), myAspects); +}*/ diff --git a/src/Vulkan/Vulkan_Group.hxx b/src/Vulkan/Vulkan_Group.hxx new file mode 100644 index 0000000000..641f946fa2 --- /dev/null +++ b/src/Vulkan/Vulkan_Group.hxx @@ -0,0 +1,140 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Group_HeaderFile +#define _Vulkan_Group_HeaderFile + +#include + +#include +#include + +struct OpenGl_ElementNode +{ + OpenGl_Element* elem; + OpenGl_ElementNode* next; + DEFINE_STANDARD_ALLOC +}; + + +class Vulkan_Buffer; +struct Vulkan_PrimitiveArray +{ + Handle(Graphic3d_IndexBuffer) Indices; + Handle(Graphic3d_Buffer) Attribs; + Handle(Graphic3d_BoundBuffer) Bounds; + + Handle(Vulkan_Buffer) VboAttribs; + Handle(Vulkan_Buffer) VboIndices; + Graphic3d_TypeOfPrimitiveArray Type; +}; +typedef NCollection_List Vulkan_ListOfElements; + +//! Implementation of low-level graphic group. +class Vulkan_Group : public Graphic3d_Group +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_Group, Graphic3d_Group) +public: + + //! Create empty group. + //! Will throw exception if not created by OpenGl_Structure. + Standard_EXPORT Vulkan_Group (const Handle(Graphic3d_Structure)& theStruct); + + Standard_EXPORT virtual void Clear (const Standard_Boolean theToUpdateStructureMgr) Standard_OVERRIDE; + + //! Return line aspect. + virtual Handle(Graphic3d_Aspects) Aspects() const Standard_OVERRIDE + { + return Handle(Graphic3d_Aspects)(); + /*return myAspects != NULL + ? myAspects->Aspect() + : Handle(Graphic3d_Aspects)();*/ + } + + //! Update aspect. + Standard_EXPORT virtual void SetGroupPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect) Standard_OVERRIDE; + + //! Append aspect as an element. + Standard_EXPORT virtual void SetPrimitivesAspect (const Handle(Graphic3d_Aspects)& theAspect) Standard_OVERRIDE; + + //! Update presentation aspects after their modification. + Standard_EXPORT virtual void SynchronizeAspects() Standard_OVERRIDE; + + //! Replace aspects specified in the replacement map. + Standard_EXPORT virtual void ReplaceAspects (const Graphic3d_MapOfAspectsToAspects& theMap) Standard_OVERRIDE; + + //! Add primitive array element + Standard_EXPORT virtual void AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType, + const Handle(Graphic3d_IndexBuffer)& theIndices, + const Handle(Graphic3d_Buffer)& theAttribs, + const Handle(Graphic3d_BoundBuffer)& theBounds, + const Standard_Boolean theToEvalMinMax) Standard_OVERRIDE; + + //! Add text element + Standard_EXPORT virtual void Text (const Standard_CString theTextUtf, + const Graphic3d_Vertex& thePoint, + const Standard_Real theHeight, + const Standard_Real theAngle, + const Graphic3d_TextPath theTp, + const Graphic3d_HorizontalTextAlignment theHta, + const Graphic3d_VerticalTextAlignment theVta, + const Standard_Boolean theToEvalMinMax) Standard_OVERRIDE; + + //! Add text element in 3D space. + Standard_EXPORT virtual void Text (const Standard_CString theTextUtf, + const gp_Ax2& theOrientation, + const Standard_Real theHeight, + const Standard_Real theAngle, + const Graphic3d_TextPath theTp, + const Graphic3d_HorizontalTextAlignment theHTA, + const Graphic3d_VerticalTextAlignment theVTA, + const Standard_Boolean theToEvalMinMax, + const Standard_Boolean theHasOwnAnchor = Standard_True) Standard_OVERRIDE; + + //! Add flipping element + Standard_EXPORT virtual void SetFlippingOptions (const Standard_Boolean theIsEnabled, + const gp_Ax2& theRefPlane) Standard_OVERRIDE; + + //! Add stencil test element + Standard_EXPORT virtual void SetStencilTestOptions (const Standard_Boolean theIsEnabled) Standard_OVERRIDE; + +public: + + //Vulkan_Structure* VkStruct() const { return (Vulkan_Structure* )(myStructure->CStructure().get()); } + + //Standard_EXPORT void AddElement (OpenGl_Element* theElem); + + //Standard_EXPORT virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; + //Standard_EXPORT virtual void Release (const Handle(OpenGl_Context)& theGlCtx); + + //! Returns first OpenGL element node of the group. + ///const OpenGl_ElementNode* FirstNode() const { return myFirst; } + + //! Returns OpenGL aspect. + ///const OpenGl_Aspects* GlAspects() const { return myAspects; } + +protected: + + Standard_EXPORT virtual ~Vulkan_Group(); + +///protected: +public: + + Vulkan_ListOfElements myElements; + //OpenGl_Aspects* myAspects; + //OpenGl_ElementNode* myFirst; + //OpenGl_ElementNode* myLast; + +}; + +#endif // _Vulkan_Group_HeaderFile diff --git a/src/Vulkan/Vulkan_Pipeline.cxx b/src/Vulkan/Vulkan_Pipeline.cxx new file mode 100644 index 0000000000..5f0ce95df4 --- /dev/null +++ b/src/Vulkan/Vulkan_Pipeline.cxx @@ -0,0 +1,290 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Pipeline, Standard_Transient) + +// ======================================================================= +// function : Vulkan_Pipeline +// purpose : +// ======================================================================= +Vulkan_Pipeline::Vulkan_Pipeline() +: myVkPipeline (NULL) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_Pipeline +// purpose : +// ======================================================================= +Vulkan_Pipeline::~Vulkan_Pipeline() +{ + Release (Handle(Vulkan_Device)()); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_Pipeline::Release (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkPipeline != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_Pipeline destroyed without Vulkan context",); + vkDestroyPipeline (theDevice->Device(), myVkPipeline, theDevice->HostAllocator()); + myVkPipeline = NULL; + } + if (!myPipelineLayout.IsNull()) + { + myPipelineLayout->Release (theDevice); + myPipelineLayout.Nullify(); + } + if (!myPipelineCache.IsNull()) + { + myPipelineCache->Release (theDevice); + myPipelineCache.Nullify(); + } + myShaderVert.Nullify(); + myShaderFrag.Nullify(); +} + +// ======================================================================= +// function : Create +// purpose : +// ======================================================================= +bool Vulkan_Pipeline::Create (const Handle(Vulkan_Device)& theDevice, + const Handle(Vulkan_RenderPass)& theRenderPass, + const Handle(Vulkan_PipelineLayout)& theLayout, + const Handle(Vulkan_Shader)& theShaderVert, + const Handle(Vulkan_Shader)& theShaderFrag, + const Graphic3d_Vec2u& theViewport) +{ + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL + || theShaderVert.IsNull() + || theShaderVert->Shader() == NULL + || theShaderFrag.IsNull() + || theShaderFrag->Shader() == NULL) + { + return false; + } + + myShaderVert = theShaderVert; + myShaderFrag = theShaderFrag; + myPipelineLayout = theLayout; + /*if (myPipelineLayout.IsNull()) + { + myPipelineLayout = new Vulkan_PipelineLayout(); + if (!myPipelineLayout->Create (theDevice, NULL)) + { + return false; + } + }*/ + if (myPipelineCache.IsNull()) + { + myPipelineCache = new Vulkan_PipelineCache(); + if (!myPipelineCache->Create (theDevice)) + { + return false; + } + } + + std::vector aVkShaderStages (2); + aVkShaderStages[0].sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + aVkShaderStages[0].pNext = NULL; + aVkShaderStages[0].flags = 0; + aVkShaderStages[0].stage = VkShaderStageFlagBits::VK_SHADER_STAGE_VERTEX_BIT; + aVkShaderStages[0].module = theShaderVert->Shader(); + aVkShaderStages[0].pName = "main"; + aVkShaderStages[0].pSpecializationInfo = NULL; + + aVkShaderStages[1].sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + aVkShaderStages[1].pNext = NULL; + aVkShaderStages[1].flags = 0; + aVkShaderStages[1].stage = VkShaderStageFlagBits::VK_SHADER_STAGE_FRAGMENT_BIT; + aVkShaderStages[1].module = theShaderFrag->Shader(); + aVkShaderStages[1].pName = "main"; + aVkShaderStages[1].pSpecializationInfo = NULL; + + VkVertexInputBindingDescription aVkVertexInputBinding; + aVkVertexInputBinding.binding = 0; + aVkVertexInputBinding.stride = sizeof(float) * 3 * 2; /// TODO Pos+Norm + aVkVertexInputBinding.inputRate = VkVertexInputRate::VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription aVkVertexInputAttribute; + aVkVertexInputAttribute.location = 0; + aVkVertexInputAttribute.binding = 0; + aVkVertexInputAttribute.format = VkFormat::VK_FORMAT_R32G32B32_SFLOAT; + aVkVertexInputAttribute.offset = 0; + + VkPipelineVertexInputStateCreateInfo aVkVertexInput; + aVkVertexInput.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + aVkVertexInput.pNext = NULL; + aVkVertexInput.flags = 0; + aVkVertexInput.vertexBindingDescriptionCount = 1; + aVkVertexInput.pVertexBindingDescriptions = &aVkVertexInputBinding; + aVkVertexInput.vertexAttributeDescriptionCount = 1; + aVkVertexInput.pVertexAttributeDescriptions = &aVkVertexInputAttribute; + + VkPipelineInputAssemblyStateCreateInfo aVkInputAssembly; + aVkInputAssembly.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + aVkInputAssembly.pNext = NULL; + aVkInputAssembly.flags = 0; + aVkInputAssembly.topology = VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + aVkInputAssembly.primitiveRestartEnable = VK_FALSE; + + const VkViewport aVkViewport + { + 0.0f, 0.0f, + (float)theViewport.x(), (float)theViewport.y(), + 0.0f, 1.0f + }; + const VkRect2D aVkScissor + { + {0, 0}, + {theViewport.x(), theViewport.y()} + }; + + VkPipelineViewportStateCreateInfo aVkViewportState; + aVkViewportState.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + aVkViewportState.pNext = NULL; + aVkViewportState.flags = 0; + aVkViewportState.viewportCount = 1; + aVkViewportState.pViewports = &aVkViewport; + aVkViewportState.scissorCount = 1; + aVkViewportState.pScissors = &aVkScissor; + + VkPipelineRasterizationStateCreateInfo aVkRasterState; + aVkRasterState.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + aVkRasterState.pNext = NULL; + aVkRasterState.flags = 0; + aVkRasterState.depthClampEnable = VK_FALSE; + aVkRasterState.rasterizerDiscardEnable = VK_FALSE; + aVkRasterState.polygonMode = VkPolygonMode::VK_POLYGON_MODE_FILL; + aVkRasterState.cullMode = VkCullModeFlagBits::VK_CULL_MODE_NONE; + aVkRasterState.frontFace = VkFrontFace::VK_FRONT_FACE_COUNTER_CLOCKWISE; + aVkRasterState.depthBiasEnable = VK_FALSE; + aVkRasterState.depthBiasConstantFactor = 0.0f; + aVkRasterState.depthBiasClamp = 0.0f; + aVkRasterState.depthBiasSlopeFactor = 0.0f; + aVkRasterState.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo aVkMultisample; + aVkMultisample.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + aVkMultisample.pNext = NULL; + aVkMultisample.flags = 0; + aVkMultisample.rasterizationSamples = VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT; + aVkMultisample.sampleShadingEnable = VK_FALSE; + aVkMultisample.minSampleShading = 0; + aVkMultisample.pSampleMask = NULL; + aVkMultisample.alphaToCoverageEnable = VK_FALSE; + aVkMultisample.alphaToOneEnable = VK_FALSE; + + VkPipelineDepthStencilStateCreateInfo aVkDepthStencil; + aVkDepthStencil.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + aVkDepthStencil.pNext = NULL; + aVkDepthStencil.flags = 0; + aVkDepthStencil.depthTestEnable = VK_FALSE; + aVkDepthStencil.depthWriteEnable = VK_FALSE; + aVkDepthStencil.depthCompareOp = VkCompareOp::VK_COMPARE_OP_ALWAYS; + aVkDepthStencil.depthBoundsTestEnable = VK_FALSE; + aVkDepthStencil.stencilTestEnable = VK_FALSE; + aVkDepthStencil.front.failOp = VkStencilOp::VK_STENCIL_OP_KEEP; + aVkDepthStencil.front.passOp = VkStencilOp::VK_STENCIL_OP_KEEP; + aVkDepthStencil.front.depthFailOp = VkStencilOp::VK_STENCIL_OP_KEEP; + aVkDepthStencil.front.compareOp = VkCompareOp::VK_COMPARE_OP_ALWAYS; + aVkDepthStencil.front.compareMask = 0; + aVkDepthStencil.front.writeMask = 0; + aVkDepthStencil.front.reference = 0; + aVkDepthStencil.back.failOp = VkStencilOp::VK_STENCIL_OP_KEEP; + aVkDepthStencil.back.passOp = VkStencilOp::VK_STENCIL_OP_KEEP; + aVkDepthStencil.back.depthFailOp = VkStencilOp::VK_STENCIL_OP_KEEP; + aVkDepthStencil.back.compareOp = VkCompareOp::VK_COMPARE_OP_ALWAYS; + aVkDepthStencil.back.compareMask = 0; + aVkDepthStencil.back.writeMask = 0; + aVkDepthStencil.back.reference = 0; + aVkDepthStencil.minDepthBounds = 0.0f; + aVkDepthStencil.maxDepthBounds = 0.0f; + + VkPipelineColorBlendAttachmentState aVkBlendAttachments; + aVkBlendAttachments.blendEnable = VK_FALSE; + aVkBlendAttachments.srcColorBlendFactor = VkBlendFactor::VK_BLEND_FACTOR_ONE; + aVkBlendAttachments.dstColorBlendFactor = VkBlendFactor::VK_BLEND_FACTOR_ONE; + aVkBlendAttachments.colorBlendOp = VkBlendOp::VK_BLEND_OP_ADD; + aVkBlendAttachments.srcAlphaBlendFactor = VkBlendFactor::VK_BLEND_FACTOR_ONE; + aVkBlendAttachments.dstAlphaBlendFactor = VkBlendFactor::VK_BLEND_FACTOR_ONE; + aVkBlendAttachments.alphaBlendOp = VkBlendOp::VK_BLEND_OP_ADD; + aVkBlendAttachments.colorWriteMask = VkColorComponentFlagBits::VK_COLOR_COMPONENT_R_BIT | VkColorComponentFlagBits::VK_COLOR_COMPONENT_G_BIT | VkColorComponentFlagBits::VK_COLOR_COMPONENT_B_BIT; + + VkPipelineColorBlendStateCreateInfo aVkBlendState; + aVkBlendState.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + aVkBlendState.pNext = NULL; + aVkBlendState.flags = 0; + aVkBlendState.logicOpEnable = VK_FALSE; + aVkBlendState.logicOp = VkLogicOp::VK_LOGIC_OP_CLEAR; + aVkBlendState.attachmentCount = 1; + aVkBlendState.pAttachments = &aVkBlendAttachments; + aVkBlendState.blendConstants; + aVkBlendState.blendConstants[0] = 1.0f; + aVkBlendState.blendConstants[1] = 1.0f; + aVkBlendState.blendConstants[2] = 1.0f; + aVkBlendState.blendConstants[3] = 1.0f; + + VkGraphicsPipelineCreateInfo aVkPipeInfo; + aVkPipeInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + aVkPipeInfo.pNext = NULL; + aVkPipeInfo.flags = 0; + aVkPipeInfo.stageCount = (uint32_t )aVkShaderStages.size(); + aVkPipeInfo.pStages = aVkShaderStages.data(); + aVkPipeInfo.pVertexInputState = &aVkVertexInput; + aVkPipeInfo.pInputAssemblyState = &aVkInputAssembly; + aVkPipeInfo.pTessellationState = VK_NULL_HANDLE; + aVkPipeInfo.pViewportState = &aVkViewportState; + aVkPipeInfo.pRasterizationState = &aVkRasterState; + aVkPipeInfo.pMultisampleState = &aVkMultisample; + aVkPipeInfo.pDepthStencilState = &aVkDepthStencil; + aVkPipeInfo.pColorBlendState = &aVkBlendState; + aVkPipeInfo.pDynamicState = NULL; + aVkPipeInfo.layout = myPipelineLayout->PipelineLayout(); + aVkPipeInfo.renderPass = theRenderPass->RenderPass(); + aVkPipeInfo.subpass = 0; + aVkPipeInfo.basePipelineIndex = 0; + aVkPipeInfo.basePipelineHandle = VK_NULL_HANDLE; + + VkResult aRes = vkCreateGraphicsPipelines (theDevice->Device(), + !myPipelineCache.IsNull() ? myPipelineCache->PipelineCache() : NULL, + 1, &aVkPipeInfo, + theDevice->HostAllocator(), &myVkPipeline); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Pipeline, failed to create pipeline: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + return true; +} diff --git a/src/Vulkan/Vulkan_Pipeline.hxx b/src/Vulkan/Vulkan_Pipeline.hxx new file mode 100644 index 0000000000..829f347b3b --- /dev/null +++ b/src/Vulkan/Vulkan_Pipeline.hxx @@ -0,0 +1,65 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Pipeline_HeaderFile +#define _Vulkan_Pipeline_HeaderFile + +#include +#include +#include + +class Vulkan_Device; +class Vulkan_PipelineCache; +class Vulkan_PipelineLayout; +class Vulkan_RenderPass; +class Vulkan_Shader; + +//! This class defines an Vulkan Pipeline. +class Vulkan_Pipeline : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_Pipeline, Standard_Transient) +public: + + //! Constructor. + Standard_EXPORT Vulkan_Pipeline(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_Pipeline(); + + //! Release the object, @sa vkDestroyPipeline(). + Standard_EXPORT void Release (const Handle(Vulkan_Device)& theDevice); + + //! Create the object, @sa vkCreateGraphicsPipelines(). + Standard_EXPORT bool Create (const Handle(Vulkan_Device)& theDevice, + const Handle(Vulkan_RenderPass)& theRenderPass, + const Handle(Vulkan_PipelineLayout)& theLayout, + const Handle(Vulkan_Shader)& theShaderVert, + const Handle(Vulkan_Shader)& theShaderFrag, + const Graphic3d_Vec2u& theViewport); + + //! Return object. + VkPipeline Pipeline() const { return myVkPipeline; } + + const Handle(Vulkan_PipelineLayout)& PipelineLayout() const { return myPipelineLayout; } + +protected: + + Handle(Vulkan_Shader) myShaderVert; + Handle(Vulkan_Shader) myShaderFrag; + Handle(Vulkan_PipelineCache) myPipelineCache; + Handle(Vulkan_PipelineLayout) myPipelineLayout; + VkPipeline myVkPipeline; + +}; + +#endif // _Vulkan_Pipeline_HeaderFile diff --git a/src/Vulkan/Vulkan_PipelineCache.cxx b/src/Vulkan/Vulkan_PipelineCache.cxx new file mode 100644 index 0000000000..176eec99bd --- /dev/null +++ b/src/Vulkan/Vulkan_PipelineCache.cxx @@ -0,0 +1,89 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_PipelineCache, Standard_Transient) + +// ======================================================================= +// function : Vulkan_PipelineCache +// purpose : +// ======================================================================= +Vulkan_PipelineCache::Vulkan_PipelineCache() +: myVkPipelineCache (NULL) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_PipelineCache +// purpose : +// ======================================================================= +Vulkan_PipelineCache::~Vulkan_PipelineCache() +{ + Release (Handle(Vulkan_Device)()); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_PipelineCache::Release (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkPipelineCache != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_PipelineCache destroyed without Vulkan context",); + vkDestroyPipelineCache (theDevice->Device(), myVkPipelineCache, theDevice->HostAllocator()); + myVkPipelineCache = NULL; + } +} + +// ======================================================================= +// function : Create +// purpose : +// ======================================================================= +bool Vulkan_PipelineCache::Create (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkPipelineCache != NULL) + { + return true; + } + + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL) + { + return false; + } + + VkPipelineCacheCreateInfo aVkPipelineCacheInfo; + aVkPipelineCacheInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + aVkPipelineCacheInfo.pNext = NULL; + aVkPipelineCacheInfo.flags = 0; + aVkPipelineCacheInfo.initialDataSize = 0; + aVkPipelineCacheInfo.pInitialData = NULL; + + VkResult aRes = vkCreatePipelineCache (theDevice->Device(), &aVkPipelineCacheInfo, theDevice->HostAllocator(), &myVkPipelineCache); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_PipelineCache, failed to create pipeline cache: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + return true; +} diff --git a/src/Vulkan/Vulkan_PipelineCache.hxx b/src/Vulkan/Vulkan_PipelineCache.hxx new file mode 100644 index 0000000000..7f16953e8d --- /dev/null +++ b/src/Vulkan/Vulkan_PipelineCache.hxx @@ -0,0 +1,49 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_PipelineCache_HeaderFile +#define _Vulkan_PipelineCache_HeaderFile + +#include +#include + +class Vulkan_Device; + +//! This class defines an Vulkan Pipeline Cache. +class Vulkan_PipelineCache : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_PipelineCache, Standard_Transient) +public: + + //! Constructor. + Standard_EXPORT Vulkan_PipelineCache(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_PipelineCache(); + + //! Release the object, @sa vkDestroyPipelineCache(). + Standard_EXPORT void Release (const Handle(Vulkan_Device)& theDevice); + + //! Create the object, @sa vkCreatePipelineCache(). + Standard_EXPORT bool Create (const Handle(Vulkan_Device)& theDevice); + + //! Return object. + VkPipelineCache PipelineCache() const { return myVkPipelineCache; } + +protected: + + VkPipelineCache myVkPipelineCache; + +}; + +#endif // _Vulkan_PipelineCache_HeaderFile diff --git a/src/Vulkan/Vulkan_PipelineLayout.cxx b/src/Vulkan/Vulkan_PipelineLayout.cxx new file mode 100644 index 0000000000..42f10f84db --- /dev/null +++ b/src/Vulkan/Vulkan_PipelineLayout.cxx @@ -0,0 +1,93 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_PipelineLayout, Standard_Transient) + +// ======================================================================= +// function : Vulkan_PipelineLayout +// purpose : +// ======================================================================= +Vulkan_PipelineLayout::Vulkan_PipelineLayout() +: myVkPipelineLayout (NULL) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_PipelineLayout +// purpose : +// ======================================================================= +Vulkan_PipelineLayout::~Vulkan_PipelineLayout() +{ + Release (Handle(Vulkan_Device)()); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_PipelineLayout::Release (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkPipelineLayout != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_PipelineLayout destroyed without Vulkan context",); + vkDestroyPipelineLayout (theDevice->Device(), myVkPipelineLayout, theDevice->HostAllocator()); + myVkPipelineLayout = NULL; + } +} + +// ======================================================================= +// function : Create +// purpose : +// ======================================================================= +bool Vulkan_PipelineLayout::Create (const Handle(Vulkan_Device)& theDevice, + const VkDescriptorSetLayout& theDescSetLayout) +{ + if (myVkPipelineLayout != NULL) + { + return true; + } + + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL) + { + return false; + } + + VkPipelineLayoutCreateInfo aVkPipelineLayoutInfo; + aVkPipelineLayoutInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + aVkPipelineLayoutInfo.pNext = NULL; + aVkPipelineLayoutInfo.flags = 0; + aVkPipelineLayoutInfo.setLayoutCount = theDescSetLayout != NULL ? 1 : 0; + aVkPipelineLayoutInfo.pSetLayouts = &theDescSetLayout; + aVkPipelineLayoutInfo.pushConstantRangeCount = 0; + aVkPipelineLayoutInfo.pPushConstantRanges = NULL; + + VkResult aRes = vkCreatePipelineLayout (theDevice->Device(), &aVkPipelineLayoutInfo, theDevice->HostAllocator(), &myVkPipelineLayout); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_PipelineLayout, failed to create pipeline layout: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + return true; +} diff --git a/src/Vulkan/Vulkan_PipelineLayout.hxx b/src/Vulkan/Vulkan_PipelineLayout.hxx new file mode 100644 index 0000000000..93eff2131d --- /dev/null +++ b/src/Vulkan/Vulkan_PipelineLayout.hxx @@ -0,0 +1,50 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_PipelineLayout_HeaderFile +#define _Vulkan_PipelineLayout_HeaderFile + +#include +#include + +class Vulkan_Device; + +//! This class defines an Vulkan Pipeline Layout. +class Vulkan_PipelineLayout : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_PipelineLayout, Standard_Transient) +public: + + //! Constructor. + Standard_EXPORT Vulkan_PipelineLayout(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_PipelineLayout(); + + //! Release the object, @sa vkDestroyPipelineLayout(). + Standard_EXPORT void Release (const Handle(Vulkan_Device)& theDevice); + + //! Create the object, @sa vkCreatePipelineLayout(). + Standard_EXPORT bool Create (const Handle(Vulkan_Device)& theDevice, + const VkDescriptorSetLayout& theDescSetLayout); + + //! Return object. + VkPipelineLayout PipelineLayout() const { return myVkPipelineLayout; } + +protected: + + VkPipelineLayout myVkPipelineLayout; + +}; + +#endif // _Vulkan_PipelineLayout_HeaderFile diff --git a/src/Vulkan/Vulkan_RenderPass.cxx b/src/Vulkan/Vulkan_RenderPass.cxx new file mode 100644 index 0000000000..190a3a52d0 --- /dev/null +++ b/src/Vulkan/Vulkan_RenderPass.cxx @@ -0,0 +1,118 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_RenderPass, Standard_Transient) + +// ======================================================================= +// function : Vulkan_RenderPass +// purpose : +// ======================================================================= +Vulkan_RenderPass::Vulkan_RenderPass() +: myVkRenderPass (NULL) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_RenderPass +// purpose : +// ======================================================================= +Vulkan_RenderPass::~Vulkan_RenderPass() +{ + Release (Handle(Vulkan_Device)()); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_RenderPass::Release (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkRenderPass != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_RenderPass destroyed without Vulkan context",); + vkDestroyRenderPass (theDevice->Device(), myVkRenderPass, theDevice->HostAllocator()); + myVkRenderPass = NULL; + } +} + +// ======================================================================= +// function : Create +// purpose : +// ======================================================================= +bool Vulkan_RenderPass::Create (const Handle(Vulkan_Device)& theDevice, + const Handle(Vulkan_Surface)& theSurface) +{ + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL) + { + return false; + } + + VkAttachmentDescription aVkAttachDesc; + aVkAttachDesc.flags = 0; + aVkAttachDesc.format = !theSurface.IsNull() ? theSurface->SurfaceFormat().format : VK_FORMAT_UNDEFINED; + aVkAttachDesc.samples = VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT; + aVkAttachDesc.loadOp = VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_CLEAR; + aVkAttachDesc.storeOp = VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_STORE; + aVkAttachDesc.stencilLoadOp = VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_DONT_CARE; + aVkAttachDesc.stencilStoreOp = VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_DONT_CARE; + aVkAttachDesc.initialLayout = VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED; + aVkAttachDesc.finalLayout = VkImageLayout::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference aVkAttachRef; + aVkAttachRef.attachment = 0; + aVkAttachRef.layout = VkImageLayout::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription aVkSubpassDesc; + aVkSubpassDesc.flags = 0; + aVkSubpassDesc.pipelineBindPoint = VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS; + aVkSubpassDesc.inputAttachmentCount = 0; + aVkSubpassDesc.pInputAttachments = NULL; + aVkSubpassDesc.colorAttachmentCount = 1; + aVkSubpassDesc.pColorAttachments = &aVkAttachRef; + aVkSubpassDesc.pResolveAttachments = NULL; + aVkSubpassDesc.pDepthStencilAttachment = NULL; + aVkSubpassDesc.preserveAttachmentCount = 0; + aVkSubpassDesc.pPreserveAttachments = NULL; + + VkRenderPassCreateInfo aVkRenderPassInfo; + aVkRenderPassInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + aVkRenderPassInfo.pNext = NULL; + aVkRenderPassInfo.flags = 0; + aVkRenderPassInfo.attachmentCount = 1; + aVkRenderPassInfo.pAttachments = &aVkAttachDesc; + aVkRenderPassInfo.subpassCount = 1; + aVkRenderPassInfo.pSubpasses = &aVkSubpassDesc; + aVkRenderPassInfo.dependencyCount = 0; + aVkRenderPassInfo.pDependencies = NULL; + + VkResult aRes = vkCreateRenderPass (theDevice->Device(), &aVkRenderPassInfo, theDevice->HostAllocator(), &myVkRenderPass); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_RenderPass, failed to create render pass: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + return true; +} diff --git a/src/Vulkan/Vulkan_RenderPass.hxx b/src/Vulkan/Vulkan_RenderPass.hxx new file mode 100644 index 0000000000..677a1b8020 --- /dev/null +++ b/src/Vulkan/Vulkan_RenderPass.hxx @@ -0,0 +1,51 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_RenderPass_HeaderFile +#define _Vulkan_RenderPass_HeaderFile + +#include +#include + +class Vulkan_Device; +class Vulkan_Surface; + +//! This class defines an Vulkan Render Pass. +class Vulkan_RenderPass : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_RenderPass, Standard_Transient) +public: + + //! Constructor. + Standard_EXPORT Vulkan_RenderPass(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_RenderPass(); + + //! Release the object, @sa vkDestroyRenderPass(). + Standard_EXPORT void Release (const Handle(Vulkan_Device)& theDevice); + + //! Create the object, @sa vkCreatePipelineCache(). + Standard_EXPORT bool Create (const Handle(Vulkan_Device)& theDevice, + const Handle(Vulkan_Surface)& theSurface); + + //! Return object. + VkRenderPass RenderPass() const { return myVkRenderPass; } + +protected: + + VkRenderPass myVkRenderPass; + +}; + +#endif // _Vulkan_RenderPass_HeaderFile diff --git a/src/Vulkan/Vulkan_Shader.cxx b/src/Vulkan/Vulkan_Shader.cxx new file mode 100644 index 0000000000..226ccd6e20 --- /dev/null +++ b/src/Vulkan/Vulkan_Shader.cxx @@ -0,0 +1,160 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Shader, Standard_Transient) + +// ======================================================================= +// function : Vulkan_Shader +// purpose : +// ======================================================================= +Vulkan_Shader::Vulkan_Shader() +: myVkShader (NULL) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_Shader +// purpose : +// ======================================================================= +Vulkan_Shader::~Vulkan_Shader() +{ + Release (Handle(Vulkan_Device)()); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_Shader::Release (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkShader != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_Shader destroyed without Vulkan context",); + vkDestroyShaderModule (theDevice->Device(), myVkShader, theDevice->HostAllocator()); + myVkShader = NULL; + } +} + +// ======================================================================= +// function : Create +// purpose : +// ======================================================================= +bool Vulkan_Shader::Create (const Handle(Vulkan_Device)& theDevice, + const uint32_t* theCode, + uint32_t theNbBytes) +{ + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL) + { + return false; + } + + VkShaderModuleCreateInfo aVkShaderInfo; + aVkShaderInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + aVkShaderInfo.pNext = NULL; + aVkShaderInfo.flags = 0; + aVkShaderInfo.pCode = theCode; + aVkShaderInfo.codeSize = theNbBytes; + + VkResult aRes = vkCreateShaderModule (theDevice->Device(), &aVkShaderInfo, theDevice->HostAllocator(), &myVkShader); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Shader, failed to create shader: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + return true; +} + +namespace +{ + //! File sentry. + struct FileSentry + { + FILE* File; + + operator FILE*() const { return File; } + + FileSentry (const TCollection_AsciiString& theFilePath) + : File (OSD_OpenFile (theFilePath.ToCString(), "rb")) {} + + ~FileSentry() + { + if (File != NULL) + { + fclose (File); + } + } + }; +} + +// ======================================================================= +// function : CreateFromFile +// purpose : +// ======================================================================= +bool Vulkan_Shader::CreateFromFile (const Handle(Vulkan_Device)& theDevice, + const TCollection_AsciiString& theFilePath) +{ + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL) + { + return false; + } + + FileSentry aFile (theFilePath.ToCString()); + if (aFile.File == NULL) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Shader, unable to open file '") + theFilePath + "'"); + return false; + } + + uint32_t aFileLen = 0; + if (fseek (aFile, 0, SEEK_END) == 0) + { + aFileLen = (uint32_t )ftell (aFile); + if (fseek (aFile, 0, SEEK_SET) != 0) + { + aFileLen = 0; + } + } + if (aFileLen % 4 != 0 + || aFileLen == 0) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Shader, file '") + theFilePath + "' has wrong length " + (int )aFileLen); + return false; + } + + std::vector aCode (aFileLen / 4); + if (fread (aCode.data(), 1, aFileLen, aFile) != aFileLen) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Shader, unable to read file '") + theFilePath + "'"); + return false; + } + + return Create (theDevice, aCode.data(), aFileLen); +} diff --git a/src/Vulkan/Vulkan_Shader.hxx b/src/Vulkan/Vulkan_Shader.hxx new file mode 100644 index 0000000000..fa1086e4b2 --- /dev/null +++ b/src/Vulkan/Vulkan_Shader.hxx @@ -0,0 +1,56 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Shader_HeaderFile +#define _Vulkan_Shader_HeaderFile + +#include +#include + +class Vulkan_Device; +class TCollection_AsciiString; + +//! This class defines an Vulkan shader. +class Vulkan_Shader : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_Shader, Standard_Transient) +public: + + //! Constructor. + Standard_EXPORT Vulkan_Shader(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_Shader(); + + //! Release the object, @sa vkDestroyShaderModule(). + Standard_EXPORT void Release (const Handle(Vulkan_Device)& theDevice); + + //! Create the object, @sa vkCreateShaderModule(). + Standard_EXPORT bool Create (const Handle(Vulkan_Device)& theDevice, + const uint32_t* theCode, + uint32_t theNbBytes); + + //! Create the object, @sa vkCreateShaderModule(). + Standard_EXPORT bool CreateFromFile (const Handle(Vulkan_Device)& theDevice, + const TCollection_AsciiString& theFilePath); + + //! Return shader. + VkShaderModule Shader() const { return myVkShader; } + +protected: + + VkShaderModule myVkShader; + +}; + +#endif // _Vulkan_Shader_HeaderFile diff --git a/src/Vulkan/Vulkan_Structure.cxx b/src/Vulkan/Vulkan_Structure.cxx new file mode 100644 index 0000000000..0bd02de478 --- /dev/null +++ b/src/Vulkan/Vulkan_Structure.cxx @@ -0,0 +1,467 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Structure, Graphic3d_CStructure) + +// ======================================================================= +// function : Vulkan_Structure +// purpose : +// ======================================================================= +Vulkan_Structure::Vulkan_Structure (const Handle(Graphic3d_StructureManager)& theManager) +: Graphic3d_CStructure (theManager), + myInstancedStructure (NULL), + myIsMirrored (Standard_False) +{ + updateLayerTransformation(); +} + +// ======================================================================= +// function : ~Vulkan_Structure +// purpose : +// ======================================================================= +Vulkan_Structure::~Vulkan_Structure() +{ + /// TODO + ///Release (Handle(OpenGl_Context)()); +} + +// ======================================================================= +// function : SetZLayer +// purpose : +// ======================================================================= +void Vulkan_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex) +{ + Graphic3d_CStructure::SetZLayer (theLayerIndex); + updateLayerTransformation(); +} + +// ======================================================================= +// function : SetTransformation +// purpose : +// ======================================================================= +void Vulkan_Structure::SetTransformation (const Handle(Geom_Transformation)& theTrsf) +{ + myTrsf = theTrsf; + myIsMirrored = Standard_False; + if (!myTrsf.IsNull()) + { + // Determinant of transform matrix less then 0 means that mirror transform applied. + const Standard_Real aDet = myTrsf->Value(1, 1) * (myTrsf->Value (2, 2) * myTrsf->Value (3, 3) - myTrsf->Value (3, 2) * myTrsf->Value (2, 3)) + - myTrsf->Value(1, 2) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 3) - myTrsf->Value (3, 1) * myTrsf->Value (2, 3)) + + myTrsf->Value(1, 3) * (myTrsf->Value (2, 1) * myTrsf->Value (3, 2) - myTrsf->Value (3, 1) * myTrsf->Value (2, 2)); + myIsMirrored = aDet < 0.0; + } + + updateLayerTransformation(); +} + +// ======================================================================= +// function : SetTransformPersistence +// purpose : +// ======================================================================= +void Vulkan_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) +{ + myTrsfPers = theTrsfPers; + updateLayerTransformation(); +} + +// ======================================================================= +// function : updateLayerTransformation +// purpose : +// ======================================================================= +void Vulkan_Structure::updateLayerTransformation() +{ + gp_Trsf aRenderTrsf; + if (!myTrsf.IsNull()) + { + aRenderTrsf = myTrsf->Trsf(); + } + + const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer); + if (!aLayer.OriginTransformation().IsNull() + && myTrsfPers.IsNull()) + { + aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin()); + } + aRenderTrsf.GetMat4 (myRenderTrsf); +} + +// ======================================================================= +// function : GraphicHighlight +// purpose : +// ======================================================================= +void Vulkan_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle) +{ + myHighlightStyle = theStyle; + highlight = 1; +} + +// ======================================================================= +// function : GraphicUnhighlight +// purpose : +// ======================================================================= +void Vulkan_Structure::GraphicUnhighlight() +{ + highlight = 0; + myHighlightStyle.Nullify(); +} + +// ======================================================================= +// function : OnVisibilityChanged +// purpose : +// ======================================================================= +void Vulkan_Structure::OnVisibilityChanged() +{ + // +} + +// ======================================================================= +// function : Connect +// purpose : +// ======================================================================= +void Vulkan_Structure::Connect (Graphic3d_CStructure& theStructure) +{ + Vulkan_Structure* aStruct = static_cast (&theStructure); + Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct, + "Error! Instanced structure is already defined"); + myInstancedStructure = aStruct; +} + +// ======================================================================= +// function : Disconnect +// purpose : +// ======================================================================= +void Vulkan_Structure::Disconnect (Graphic3d_CStructure& theStructure) +{ + Vulkan_Structure* aStruct = static_cast (&theStructure); + if (myInstancedStructure == aStruct) + { + myInstancedStructure = NULL; + } +} + +// ======================================================================= +// function : NewGroup +// purpose : +// ======================================================================= +Handle(Graphic3d_Group) Vulkan_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct) +{ + Handle(Vulkan_Group) aGroup = new Vulkan_Group (theStruct); + myGroups.Append (aGroup); + return aGroup; +} + +// ======================================================================= +// function : RemoveGroup +// purpose : +// ======================================================================= +void Vulkan_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup) +{ + if (theGroup.IsNull()) + { + return; + } + + for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) + { + // Check for the given group + if (aGroupIter.Value() == theGroup) + { + theGroup->Clear (Standard_False); + myGroups.Remove (aGroupIter); + return; + } + } +} + +// ======================================================================= +// function : Clear +// purpose : +// ======================================================================= +void Vulkan_Structure::Clear() +{ + myGroups.Clear(); + ///Clear (VkDriver()->GetSharedContext()); +} + +// ======================================================================= +// function : Clear +// purpose : +// ======================================================================= +/*void Vulkan_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx) +{ + Standard_Boolean aRaytracableGroupDeleted (Standard_False); + + // Release groups + for (Vulkan_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) + { + aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable(); + + // Delete objects + aGroupIter.ChangeValue()->Release (theGlCtx); + } + myGroups.Clear(); + + if (aRaytracableGroupDeleted) + { + myIsRaytracable = Standard_False; + } + + Is2dText = Standard_False; + IsForHighlight = Standard_False; +}*/ + +// ======================================================================= +// function : renderGeometry +// purpose : +// ======================================================================= +/*void Vulkan_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace, + bool& theHasClosed) const +{ + if (myInstancedStructure != NULL) + { + myInstancedStructure->renderGeometry (theWorkspace, theHasClosed); + } + + for (Vulkan_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) + { + theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed(); + aGroupIter.Value()->Render (theWorkspace); + } +}*/ + +// ======================================================================= +// function : Render +// purpose : +// ======================================================================= +/*void Vulkan_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const +{ + // Process the structure only if visible + if (!visible) + { + return; + } + + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); + + // Render named status + if (highlight && !myHighlightStyle.IsNull() && myHighlightStyle->Method() != Aspect_TOHM_BOUNDBOX) + { + theWorkspace->SetHighlightStyle (myHighlightStyle); + } + + // Apply local transformation + aCtx->ModelWorldState.Push(); + OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent(); + aModelWorld = myRenderTrsf; + + const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled(); + if (!myTrsfPers.IsNull()) + { + aCtx->WorldViewState.Push(); + OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent(); + myTrsfPers->Apply (theWorkspace->View()->Camera(), + aCtx->ProjectionState.Current(), aWorldView, + aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]); + } + + // Take into account transform persistence + aCtx->ApplyModelViewMatrix(); + + // remember aspects + const OpenGl_Aspects* aPrevAspectFace = theWorkspace->Aspects(); + + // Apply correction for mirror transform + if (myIsMirrored) + { + aCtx->core11fwd->glFrontFace (GL_CW); + } + + // Collect clipping planes of structure scope + aCtx->ChangeClipping().SetLocalPlanes (myClipPlanes); + + // True if structure is fully clipped + bool isClipped = false; + bool hasDisabled = false; + if (aCtx->Clipping().IsClippingOrCappingOn()) + { + const Graphic3d_BndBox3d& aBBox = BoundingBox(); + if (!myClipPlanes.IsNull() + && myClipPlanes->ToOverrideGlobal()) + { + aCtx->ChangeClipping().DisableGlobal(); + hasDisabled = aCtx->Clipping().HasDisabled(); + } + else if (!myTrsfPers.IsNull()) + { + if (myTrsfPers->IsZoomOrRotate()) + { + // Zoom/rotate persistence object lives in two worlds at the same time. + // Global clipping planes can not be trivially applied without being converted + // into local space of transformation persistence object. + // As more simple alternative - just clip entire object by its anchor point defined in the world space. + const gp_Pnt anAnchor = myTrsfPers->AnchorPoint(); + for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More() && aPlaneIt.IsGlobal(); aPlaneIt.Next()) + { + const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); + if (!aPlane->IsOn()) + { + continue; + } + + // check for clipping + const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0); + if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out) + { + isClipped = true; + break; + } + } + } + + aCtx->ChangeClipping().DisableGlobal(); + hasDisabled = aCtx->Clipping().HasDisabled(); + } + + // Set of clipping planes that do not intersect the structure, + // and thus can be disabled to improve rendering performance + if (aBBox.IsValid() + && myTrsfPers.IsNull()) + { + for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next()) + { + const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); + if (aPlaneIt.IsDisabled()) + { + continue; + } + + const Graphic3d_ClipState aBoxState = aPlane->ProbeBox (aBBox); + if (aBoxState == Graphic3d_ClipState_Out) + { + isClipped = true; + break; + } + else if (aBoxState == Graphic3d_ClipState_In) + { + aCtx->ChangeClipping().SetEnabled (aPlaneIt, false); + hasDisabled = true; + } + } + } + + if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty()) + || hasDisabled) + { + // Set OCCT state uniform variables + aCtx->ShaderManager()->UpdateClippingState(); + } + } + + // Render groups + bool hasClosedPrims = false; + if (!isClipped) + { + renderGeometry (theWorkspace, hasClosedPrims); + } + + // Reset correction for mirror transform + if (myIsMirrored) + { + aCtx->core11fwd->glFrontFace (GL_CCW); + } + + // Render capping for structure groups + if (hasClosedPrims + && aCtx->Clipping().IsCappingOn()) + { + OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this); + } + + // Revert structure clippings + if (hasDisabled) + { + // enable planes that were previously disabled + aCtx->ChangeClipping().RestoreDisabled(); + } + aCtx->ChangeClipping().SetLocalPlanes (Handle(Graphic3d_SequenceOfHClipPlane)()); + if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty()) + || hasDisabled) + { + // Set OCCT state uniform variables + aCtx->ShaderManager()->RevertClippingState(); + } + + // Restore local transformation + aCtx->ModelWorldState.Pop(); + aCtx->SetGlNormalizeEnabled (anOldGlNormalize); + + // Restore aspects + theWorkspace->SetAspects (aPrevAspectFace); + + // Apply highlight box + if (!isClipped + && !myHighlightStyle.IsNull() + && myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX) + { + aCtx->ApplyModelViewMatrix(); + theWorkspace->SetHighlightStyle (myHighlightStyle); + renderBoundingBox (theWorkspace); + } + + if (!myTrsfPers.IsNull()) + { + aCtx->WorldViewState.Pop(); + } + + // Restore named status + theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)()); +}*/ + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +/*void Vulkan_Structure::Release (const Handle(OpenGl_Context)& theGlCtx) +{ + // Release groups + Clear (theGlCtx); + myHighlightStyle.Nullify(); +}*/ + +// ======================================================================= +// function : ReleaseGlResources +// purpose : +// ======================================================================= +/*void Vulkan_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx) +{ + for (Vulkan_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) + { + aGroupIter.ChangeValue()->Release (theGlCtx); + } +}*/ + +//======================================================================= +//function : ShadowLink +//purpose : +//======================================================================= +Handle(Graphic3d_CStructure) Vulkan_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const +{ + return new Vulkan_StructureShadow (theManager, this); +} diff --git a/src/Vulkan/Vulkan_Structure.hxx b/src/Vulkan/Vulkan_Structure.hxx new file mode 100644 index 0000000000..4e072a6c16 --- /dev/null +++ b/src/Vulkan/Vulkan_Structure.hxx @@ -0,0 +1,122 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Structure_HeaderFile +#define _Vulkan_Structure_HeaderFile + +#include + +//! Implementation of low-level graphic structure. +class Vulkan_Structure : public Graphic3d_CStructure +{ + friend class Vulkan_Group; + DEFINE_STANDARD_RTTIEXT(Vulkan_Structure, Graphic3d_CStructure) +public: + + //! Auxiliary wrapper to iterate OpenGl_Structure sequence. + typedef SubclassStructIterator StructIterator; + + //! Auxiliary wrapper to iterate OpenGl_Group sequence. + typedef SubclassGroupIterator GroupIterator; + +public: + + //! Create empty structure + Standard_EXPORT Vulkan_Structure (const Handle(Graphic3d_StructureManager)& theManager); + + //! Setup structure graphic state + Standard_EXPORT virtual void OnVisibilityChanged() Standard_OVERRIDE; + + //! Clear graphic data + Standard_EXPORT virtual void Clear() Standard_OVERRIDE; + + //! Connect other structure to this one + Standard_EXPORT virtual void Connect (Graphic3d_CStructure& theStructure) Standard_OVERRIDE; + + //! Disconnect other structure to this one + Standard_EXPORT virtual void Disconnect (Graphic3d_CStructure& theStructure) Standard_OVERRIDE; + + //! Synchronize structure transformation + Standard_EXPORT virtual void SetTransformation (const Handle(Geom_Transformation)& theTrsf) Standard_OVERRIDE; + + //! Set transformation persistence. + Standard_EXPORT virtual void SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) Standard_OVERRIDE; + + //! Set z layer ID to display the structure in specified layer + Standard_EXPORT virtual void SetZLayer(const Graphic3d_ZLayerId theLayerIndex) Standard_OVERRIDE; + + //! Highlights structure according to the given style and updates corresponding class fields + //! (highlight status and style) + Standard_EXPORT virtual void GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle) Standard_OVERRIDE; + + //! Unighlights structure and updates corresponding class fields (highlight status and style) + Standard_EXPORT virtual void GraphicUnhighlight() Standard_OVERRIDE; + + //! Create shadow link to this structure + Standard_EXPORT virtual Handle(Graphic3d_CStructure) ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const Standard_OVERRIDE; + + //! Create new group within this structure + Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup (const Handle(Graphic3d_Structure)& theStruct) Standard_OVERRIDE; + + //! Remove group from this structure + Standard_EXPORT virtual void RemoveGroup (const Handle(Graphic3d_Group)& theGroup) Standard_OVERRIDE; + +public: + + //! Access graphic driver + /**Vulkan_GraphicDriver* VkDriver() const + { + return (Vulkan_GraphicDriver* )myGraphicDriver.get(); + } + + Standard_EXPORT void Clear (const Handle(OpenGl_Context)& theGlCtx); + + //! Renders the structure. + virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const; + + //! Releases structure resources. + virtual void Release (const Handle(OpenGl_Context)& theGlCtx); + + //! This method releases GL resources without actual elements destruction. + //! As result structure could be correctly destroyed layer without GL context + //! (after last window was closed for example). + //! + //! Notice however that reusage of this structure after calling this method is incorrect + //! and will lead to broken visualization due to loosed data. + Standard_EXPORT void ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx);*/ + + //! Returns instanced OpenGL structure. + const Vulkan_Structure* InstancedStructure() const { return myInstancedStructure; } + + //! Update render transformation matrix. + Standard_EXPORT virtual void updateLayerTransformation() Standard_OVERRIDE; + +protected: + + Standard_EXPORT virtual ~Vulkan_Structure(); + + //! Renders groups of structure without applying any attributes (i.e. transform, material etc). + //! @param theWorkspace current workspace + //! @param theHasClosed flag will be set to TRUE if structure contains at least one group of closed primitives + /*Standard_EXPORT void renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace, + bool& theHasClosed) const;*/ + +protected: + + Vulkan_Structure* myInstancedStructure; + Graphic3d_Mat4 myRenderTrsf; //!< transformation, actually used for rendering (includes Local Origin shift) + Standard_Boolean myIsMirrored; //!< Used to tell OpenGl to interpret polygons in clockwise order. + +}; + +#endif // _Vulkan_Structure_HeaderFile diff --git a/src/Vulkan/Vulkan_StructureShadow.cxx b/src/Vulkan/Vulkan_StructureShadow.cxx new file mode 100644 index 0000000000..b98915f434 --- /dev/null +++ b/src/Vulkan/Vulkan_StructureShadow.cxx @@ -0,0 +1,60 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_StructureShadow, Vulkan_Structure) + +//======================================================================= +//function : Vulkan_StructureShadow +//purpose : +//======================================================================= +Vulkan_StructureShadow::Vulkan_StructureShadow (const Handle(Graphic3d_StructureManager)& theManager, + const Handle(Vulkan_Structure)& theStructure) +: Vulkan_Structure (theManager) +{ + Handle(Vulkan_StructureShadow) aShadow = Handle(Vulkan_StructureShadow)::DownCast (theStructure); + myParent = aShadow.IsNull() ? theStructure : aShadow->myParent; + + ContainsFacet = myParent->ContainsFacet; + IsInfinite = myParent->IsInfinite; + myBndBox = myParent->BoundingBox(); + + Vulkan_Structure::SetTransformation (myParent->Transformation()); + myInstancedStructure = const_cast (myParent->InstancedStructure()); + myTrsfPers = myParent->TransformPersistence(); + + // reuse instanced structure API + myInstancedStructure = myParent.operator->(); +} + +// ======================================================================= +// function : Connect +// purpose : +// ======================================================================= +void Vulkan_StructureShadow::Connect (Graphic3d_CStructure& ) +{ + throw Standard_ProgramError("Error! Vulkan_StructureShadow::Connect() should not be called!"); +} + +// ======================================================================= +// function : Disconnect +// purpose : +// ======================================================================= +void Vulkan_StructureShadow::Disconnect (Graphic3d_CStructure& ) +{ + throw Standard_ProgramError("Error! Vulkan_StructureShadow::Disconnect() should not be called!"); +} diff --git a/src/Vulkan/Vulkan_StructureShadow.hxx b/src/Vulkan/Vulkan_StructureShadow.hxx new file mode 100644 index 0000000000..e5886b8756 --- /dev/null +++ b/src/Vulkan/Vulkan_StructureShadow.hxx @@ -0,0 +1,43 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_StructureShadow_HeaderFile +#define _Vulkan_StructureShadow_HeaderFile + +#include + +//! Dummy structure which just redirects to groups of another structure. +class Vulkan_StructureShadow : public Vulkan_Structure +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_StructureShadow, Vulkan_Structure) +public: + + //! Create empty structure + Standard_EXPORT Vulkan_StructureShadow (const Handle(Graphic3d_StructureManager)& theManager, + const Handle(Vulkan_Structure)& theStructure); + +public: + + //! Raise exception on API misuse. + virtual void Connect (Graphic3d_CStructure& ) Standard_OVERRIDE; + + //! Raise exception on API misuse. + virtual void Disconnect (Graphic3d_CStructure& ) Standard_OVERRIDE; + +private: + + Handle(Vulkan_Structure) myParent; + +}; + +#endif // _Vulkan_StructureShadow_HeaderFile diff --git a/src/Vulkan/Vulkan_Surface.cxx b/src/Vulkan/Vulkan_Surface.cxx new file mode 100644 index 0000000000..0fc570125b --- /dev/null +++ b/src/Vulkan/Vulkan_Surface.cxx @@ -0,0 +1,316 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#if defined(_WIN32) + #include + + #define VK_USE_PLATFORM_WIN32_KHR 1 +#endif + +#include + +#include +#include +#include +#include +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_Surface, Standard_Transient) + +// ======================================================================= +// function : Vulkan_Surface +// purpose : +// ======================================================================= +Vulkan_Surface::Vulkan_Surface() +: mySwapFence (new Vulkan_Fence()), + myVkSurface (NULL), + myVkSwapChain (NULL), + myVkFormat (new VkSurfaceFormatKHR()) +{ + // +} + +// ======================================================================= +// function : ~Vulkan_Surface +// purpose : +// ======================================================================= +Vulkan_Surface::~Vulkan_Surface() +{ + Release (Handle(Vulkan_Device)()); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Vulkan_Surface::Release (const Handle(Vulkan_Device)& theDevice) +{ + mySwapFence->Release (theDevice); + for (size_t anImgIter = 0; anImgIter < myVkImageViews.size(); ++anImgIter) + { + VkImageView& aVkImageView = myVkImageViews[anImgIter]; + if (aVkImageView != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_Surface destroyed without Vulkan context",); + vkDestroyImageView (theDevice->Device(), aVkImageView, theDevice->HostAllocator()); + aVkImageView = NULL; + } + } + myVkImages.clear(); + myVkImageViews.clear(); + if (myVkSwapChain != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_Surface destroyed without Vulkan context",); + vkDestroySwapchainKHR (theDevice->Device(), myVkSwapChain, theDevice->HostAllocator()); + myVkSwapChain = NULL; + } + if (myVkSurface != NULL) + { + Standard_ASSERT_RETURN (!theDevice.IsNull(), "Vulkan_Surface destroyed without Vulkan context",); + vkDestroySurfaceKHR (theDevice->Instance(), myVkSurface, theDevice->HostAllocator()); + myVkSurface = NULL; + } +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +bool Vulkan_Surface::Init (const Handle(Vulkan_Device)& theDevice, + const Handle(Aspect_Window)& theWindow) +{ + Release (theDevice); + if (theDevice.IsNull() + || theDevice->Device() == NULL + || theWindow.IsNull()) + { + return false; + } + + if (!mySwapFence->Create (theDevice)) + { + return false; + } + +#if defined(_WIN32) + VkWin32SurfaceCreateInfoKHR aVkWin32SurfInfo; + aVkWin32SurfInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + aVkWin32SurfInfo.pNext = NULL; + aVkWin32SurfInfo.flags = 0; + aVkWin32SurfInfo.hinstance = GetModuleHandleW (NULL); + aVkWin32SurfInfo.hwnd = (HWND )theWindow->NativeHandle(); + + VkResult aRes = vkCreateWin32SurfaceKHR (theDevice->Instance(), &aVkWin32SurfInfo, theDevice->HostAllocator(), &myVkSurface); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, unable to create surface: ") + Vulkan_Device::FormatVkError (aRes)); + Release (theDevice); + return false; + } +#else + int NOT_IMPLEMENTED = 0; + return false; +#endif + + VkBool32 isSupported = VK_FALSE; + aRes = vkGetPhysicalDeviceSurfaceSupportKHR (theDevice->PhysicalDevice(), 0, myVkSurface, &isSupported); + if (aRes != VkResult::VK_SUCCESS || isSupported == VK_FALSE) + { + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, surface not supported: ") + Vulkan_Device::FormatVkError (aRes)); + } + else + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, surface not supported")); + } + Release (theDevice); + return false; + } + + VkSurfaceCapabilitiesKHR aVkSurfCaps; + aRes = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (theDevice->PhysicalDevice(), myVkSurface, &aVkSurfCaps); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, failed to get surface capabilities: ") + Vulkan_Device::FormatVkError (aRes)); + Release (theDevice); + return false; + } + + if (!findFormat (theDevice, *myVkFormat)) + { + Release (theDevice); + return false; + } + + { + VkSwapchainCreateInfoKHR aSwapChainInfo; + aSwapChainInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + aSwapChainInfo.pNext = NULL; + aSwapChainInfo.flags = 0; + aSwapChainInfo.surface = myVkSurface; + aSwapChainInfo.minImageCount = 2; + aSwapChainInfo.imageFormat = myVkFormat->format; + aSwapChainInfo.imageColorSpace = myVkFormat->colorSpace; + aSwapChainInfo.imageExtent = VkExtent2D { aVkSurfCaps.currentExtent.width, aVkSurfCaps.currentExtent.height }; + aSwapChainInfo.imageArrayLayers = 1; + aSwapChainInfo.imageUsage = VkImageUsageFlagBits::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + aSwapChainInfo.imageSharingMode = VkSharingMode::VK_SHARING_MODE_EXCLUSIVE; + aSwapChainInfo.queueFamilyIndexCount = 0; + aSwapChainInfo.pQueueFamilyIndices = NULL; + aSwapChainInfo.preTransform = VkSurfaceTransformFlagBitsKHR::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + aSwapChainInfo.compositeAlpha = VkCompositeAlphaFlagBitsKHR::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + aSwapChainInfo.presentMode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR; + aSwapChainInfo.clipped = VK_TRUE; + aSwapChainInfo.oldSwapchain = VK_NULL_HANDLE; + + aRes = vkCreateSwapchainKHR (theDevice->Device(), &aSwapChainInfo, theDevice->HostAllocator(), &myVkSwapChain); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, failed to create swapchain: ") + Vulkan_Device::FormatVkError (aRes)); + Release (theDevice); + return false; + } + } + + { + uint32_t aNbSwapChainImages = 0; + aRes = vkGetSwapchainImagesKHR (theDevice->Device(), myVkSwapChain, &aNbSwapChainImages, NULL); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, failed to get swapchain images count: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + myVkImages.resize (aNbSwapChainImages, NULL); + aRes = vkGetSwapchainImagesKHR (theDevice->Device(), myVkSwapChain, &aNbSwapChainImages, myVkImages.data()); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, failed to get swapchain images: ") + Vulkan_Device::FormatVkError (aRes)); + Release (theDevice); + return false; + } + } + + myVkImageViews.resize (myVkImages.size(), NULL); + for (uint32_t anImgIter = 0; anImgIter < myVkImages.size(); ++anImgIter) + { + VkImageView& aVkImageView = myVkImageViews[anImgIter]; + + VkImageViewCreateInfo aVkImgViewInfo; + aVkImgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + aVkImgViewInfo.pNext = NULL; + aVkImgViewInfo.flags = 0; + aVkImgViewInfo.image = myVkImages[anImgIter]; + aVkImgViewInfo.viewType = VkImageViewType::VK_IMAGE_VIEW_TYPE_2D; + aVkImgViewInfo.format = myVkFormat->format; + aVkImgViewInfo.components = + { + VkComponentSwizzle::VK_COMPONENT_SWIZZLE_R, + VkComponentSwizzle::VK_COMPONENT_SWIZZLE_G, + VkComponentSwizzle::VK_COMPONENT_SWIZZLE_B, + VkComponentSwizzle::VK_COMPONENT_SWIZZLE_A + }; + aVkImgViewInfo.subresourceRange.aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT; + aVkImgViewInfo.subresourceRange.baseMipLevel = 0; + aVkImgViewInfo.subresourceRange.levelCount = 1; + aVkImgViewInfo.subresourceRange.baseArrayLayer = 0; + aVkImgViewInfo.subresourceRange.layerCount = 1; + + aRes = vkCreateImageView (theDevice->Device(), &aVkImgViewInfo, theDevice->HostAllocator(), &aVkImageView); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, failed to create image view: ") + Vulkan_Device::FormatVkError (aRes)); + Release (theDevice); + return false; + } + } + + return true; +} + +// ======================================================================= +// function : findFormat +// purpose : +// ======================================================================= +bool Vulkan_Surface::findFormat (const Handle(Vulkan_Device)& theDevice, + VkSurfaceFormatKHR& theFormat) +{ + if (myVkSurface == NULL) + { + return false; + } + + uint32_t aNbSurfFormats = 0; + VkResult aRes = vkGetPhysicalDeviceSurfaceFormatsKHR (theDevice->PhysicalDevice(), myVkSurface, &aNbSurfFormats, NULL); + if (aRes != VkResult::VK_SUCCESS + || aNbSurfFormats == 0) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, failed to get surface formats count: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + std::vector aVkSurfFormats (aNbSurfFormats); + aRes = vkGetPhysicalDeviceSurfaceFormatsKHR (theDevice->PhysicalDevice(), myVkSurface, &aNbSurfFormats, aVkSurfFormats.data()); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, failed to get surface formats: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + theFormat = aVkSurfFormats[0]; + return true; +} + +// ======================================================================= +// function : CurrentSize +// purpose : +// ======================================================================= +Graphic3d_Vec2u Vulkan_Surface::CurrentSize (const Handle(Vulkan_Device)& theDevice) +{ + if (myVkSurface == NULL) + { + return Graphic3d_Vec2u (0, 0); + } + + VkSurfaceCapabilitiesKHR aVkSurfCaps; + VkResult aRes = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (theDevice->PhysicalDevice(), myVkSurface, &aVkSurfCaps); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Window, failed to get surface capabilities: ") + Vulkan_Device::FormatVkError (aRes)); + return Graphic3d_Vec2u (0, 0); + } + + return Graphic3d_Vec2u (aVkSurfCaps.currentExtent.width, aVkSurfCaps.currentExtent.height); +} + +// ======================================================================= +// function : AcquireNextImage +// purpose : +// ======================================================================= +bool Vulkan_Surface::AcquireNextImage (const Handle(Vulkan_Device)& theDevice, + uint32_t& theSwapChainIndex) +{ + theSwapChainIndex = 0; + VkResult aRes = vkAcquireNextImageKHR (theDevice->Device(), myVkSwapChain, UINT64_MAX, VK_NULL_HANDLE, mySwapFence->Fence(), &theSwapChainIndex); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Surface, failed to get next swapchain image: ") + Vulkan_Device::FormatVkError (aRes)); + return false; + } + + return mySwapFence->Wait (theDevice) + && mySwapFence->Reset(theDevice); +} diff --git a/src/Vulkan/Vulkan_Surface.hxx b/src/Vulkan/Vulkan_Surface.hxx new file mode 100644 index 0000000000..b02c5e416a --- /dev/null +++ b/src/Vulkan/Vulkan_Surface.hxx @@ -0,0 +1,90 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_Surface_HeaderFile +#define _Vulkan_Surface_HeaderFile + +#include +#include +#include +#include + +#include +#include + +class Aspect_Window; +class Vulkan_Device; +class Vulkan_Fence; + +//! This class defines an Vulkan surface. +class Vulkan_Surface : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_Surface, Standard_Transient) +public: + + //! Constructor. + Standard_EXPORT Vulkan_Surface(); + + //! Destructor. + Standard_EXPORT virtual ~Vulkan_Surface(); + + //! Release default context. + Standard_EXPORT void Release (const Handle(Vulkan_Device)& theDevice); + + //! Perform initialization of default context. + Standard_EXPORT bool Init (const Handle(Vulkan_Device)& theDevice, + const Handle(Aspect_Window)& theWindow); + + //! Return surface. + VkSurfaceKHR Surface() const { return myVkSurface; } + + //! Return swap chain. + VkSwapchainKHR SwapChain() const { return myVkSwapChain; } + + //! Return the swap chain length. + uint32_t SwapChainSize() const { return (uint32_t )myVkImageViews.size(); } + + //! Return images within swap chain. + const std::vector& Images() const { return myVkImages; } + + //! Return image views within swap chain. + const std::vector& ImageViews() const { return myVkImageViews; } + + //! Return surface format. + const VkSurfaceFormatKHR& SurfaceFormat() const { return *myVkFormat; } + + //! Fetch actual surface size. + Graphic3d_Vec2u CurrentSize (const Handle(Vulkan_Device)& theDevice); + + //! Acquire next image from swap chain, @sa vkAcquireNextImageKHR(). + Standard_EXPORT bool AcquireNextImage (const Handle(Vulkan_Device)& theDevice, + uint32_t& theSwapChainIndex); + +protected: + + //! Find supported format. + Standard_EXPORT bool findFormat (const Handle(Vulkan_Device)& theDevice, + VkSurfaceFormatKHR& theFormat); + +protected: + + Handle(Vulkan_Fence) mySwapFence; + VkSurfaceKHR myVkSurface; + VkSwapchainKHR myVkSwapChain; + std::vector myVkImages; + std::vector myVkImageViews; + std::shared_ptr myVkFormat; + +}; + +#endif // _Vulkan_Surface_HeaderFile diff --git a/src/Vulkan/Vulkan_TestShader_fs_spv.pxx b/src/Vulkan/Vulkan_TestShader_fs_spv.pxx new file mode 100644 index 0000000000..7e2ba8baa1 --- /dev/null +++ b/src/Vulkan/Vulkan_TestShader_fs_spv.pxx @@ -0,0 +1,30 @@ + // 7.11.3113 + #pragma once +const uint32_t Vulkan_TestShader_fs_spv[] = { + 0x07230203,0x00010000,0x00080007,0x00000013,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0006000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x00030010,0x00000004, + 0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,0x00000000, + 0x00060005,0x00000009,0x4663636f,0x43676172,0x726f6c6f,0x00000030,0x00040005,0x0000000b, + 0x6f6c6f43,0x00007372,0x00080006,0x0000000b,0x00000000,0x5763636f,0x646c726f,0x77656956, + 0x7274614d,0x00007869,0x00080006,0x0000000b,0x00000001,0x5063636f,0x656a6f72,0x6f697463, + 0x74614d6e,0x00786972,0x00080006,0x0000000b,0x00000002,0x4d63636f,0x6c65646f,0x6c726f57, + 0x74614d64,0x00786972,0x00050006,0x0000000b,0x00000003,0x6c6f4375,0x0000726f,0x00030005, + 0x0000000d,0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040048,0x0000000b, + 0x00000000,0x00000005,0x00050048,0x0000000b,0x00000000,0x00000023,0x00000000,0x00050048, + 0x0000000b,0x00000000,0x00000007,0x00000010,0x00040048,0x0000000b,0x00000001,0x00000005, + 0x00050048,0x0000000b,0x00000001,0x00000023,0x00000040,0x00050048,0x0000000b,0x00000001, + 0x00000007,0x00000010,0x00040048,0x0000000b,0x00000002,0x00000005,0x00050048,0x0000000b, + 0x00000002,0x00000023,0x00000080,0x00050048,0x0000000b,0x00000002,0x00000007,0x00000010, + 0x00050048,0x0000000b,0x00000003,0x00000023,0x000000c0,0x00030047,0x0000000b,0x00000002, + 0x00040047,0x0000000d,0x00000022,0x00000000,0x00040047,0x0000000d,0x00000021,0x00000000, + 0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020, + 0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,0x00000007, + 0x0004003b,0x00000008,0x00000009,0x00000003,0x00040018,0x0000000a,0x00000007,0x00000004, + 0x0006001e,0x0000000b,0x0000000a,0x0000000a,0x0000000a,0x00000007,0x00040020,0x0000000c, + 0x00000002,0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000002,0x00040015,0x0000000e, + 0x00000020,0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000003,0x00040020,0x00000010, + 0x00000002,0x00000007,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8, + 0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,0x0000000f,0x0004003d,0x00000007, + 0x00000012,0x00000011,0x0003003e,0x00000009,0x00000012,0x000100fd,0x00010038 +}; \ No newline at end of file diff --git a/src/Vulkan/Vulkan_TestShader_vs_spv.pxx b/src/Vulkan/Vulkan_TestShader_vs_spv.pxx new file mode 100644 index 0000000000..96fb034790 --- /dev/null +++ b/src/Vulkan/Vulkan_TestShader_vs_spv.pxx @@ -0,0 +1,47 @@ + // 7.11.3113 + #pragma once +const uint32_t Vulkan_TestShader_vs_spv[] = { + 0x07230203,0x00010000,0x00080007,0x00000025,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0007000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000d,0x00000020,0x00030003, + 0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,0x00000000,0x00060005,0x0000000b, + 0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x0000000b,0x00000000,0x505f6c67, + 0x7469736f,0x006e6f69,0x00070006,0x0000000b,0x00000001,0x505f6c67,0x746e696f,0x657a6953, + 0x00000000,0x00070006,0x0000000b,0x00000002,0x435f6c67,0x4470696c,0x61747369,0x0065636e, + 0x00070006,0x0000000b,0x00000003,0x435f6c67,0x446c6c75,0x61747369,0x0065636e,0x00030005, + 0x0000000d,0x00000000,0x00040005,0x00000011,0x6f6c6f43,0x00007372,0x00080006,0x00000011, + 0x00000000,0x5763636f,0x646c726f,0x77656956,0x7274614d,0x00007869,0x00080006,0x00000011, + 0x00000001,0x5063636f,0x656a6f72,0x6f697463,0x74614d6e,0x00786972,0x00080006,0x00000011, + 0x00000002,0x4d63636f,0x6c65646f,0x6c726f57,0x74614d64,0x00786972,0x00050006,0x00000011, + 0x00000003,0x6c6f4375,0x0000726f,0x00030005,0x00000013,0x00000000,0x00050005,0x00000020, + 0x5663636f,0x65747265,0x00000078,0x00050048,0x0000000b,0x00000000,0x0000000b,0x00000000, + 0x00050048,0x0000000b,0x00000001,0x0000000b,0x00000001,0x00050048,0x0000000b,0x00000002, + 0x0000000b,0x00000003,0x00050048,0x0000000b,0x00000003,0x0000000b,0x00000004,0x00030047, + 0x0000000b,0x00000002,0x00040048,0x00000011,0x00000000,0x00000005,0x00050048,0x00000011, + 0x00000000,0x00000023,0x00000000,0x00050048,0x00000011,0x00000000,0x00000007,0x00000010, + 0x00040048,0x00000011,0x00000001,0x00000005,0x00050048,0x00000011,0x00000001,0x00000023, + 0x00000040,0x00050048,0x00000011,0x00000001,0x00000007,0x00000010,0x00040048,0x00000011, + 0x00000002,0x00000005,0x00050048,0x00000011,0x00000002,0x00000023,0x00000080,0x00050048, + 0x00000011,0x00000002,0x00000007,0x00000010,0x00050048,0x00000011,0x00000003,0x00000023, + 0x000000c0,0x00030047,0x00000011,0x00000002,0x00040047,0x00000013,0x00000022,0x00000000, + 0x00040047,0x00000013,0x00000021,0x00000000,0x00040047,0x00000020,0x0000001e,0x00000000, + 0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020, + 0x00040017,0x00000007,0x00000006,0x00000004,0x00040015,0x00000008,0x00000020,0x00000000, + 0x0004002b,0x00000008,0x00000009,0x00000001,0x0004001c,0x0000000a,0x00000006,0x00000009, + 0x0006001e,0x0000000b,0x00000007,0x00000006,0x0000000a,0x0000000a,0x00040020,0x0000000c, + 0x00000003,0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000003,0x00040015,0x0000000e, + 0x00000020,0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040018,0x00000010, + 0x00000007,0x00000004,0x0006001e,0x00000011,0x00000010,0x00000010,0x00000010,0x00000007, + 0x00040020,0x00000012,0x00000002,0x00000011,0x0004003b,0x00000012,0x00000013,0x00000002, + 0x0004002b,0x0000000e,0x00000014,0x00000001,0x00040020,0x00000015,0x00000002,0x00000010, + 0x0004002b,0x0000000e,0x0000001b,0x00000002,0x00040020,0x0000001f,0x00000001,0x00000007, + 0x0004003b,0x0000001f,0x00000020,0x00000001,0x00040020,0x00000023,0x00000003,0x00000007, + 0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041, + 0x00000015,0x00000016,0x00000013,0x00000014,0x0004003d,0x00000010,0x00000017,0x00000016, + 0x00050041,0x00000015,0x00000018,0x00000013,0x0000000f,0x0004003d,0x00000010,0x00000019, + 0x00000018,0x00050092,0x00000010,0x0000001a,0x00000017,0x00000019,0x00050041,0x00000015, + 0x0000001c,0x00000013,0x0000001b,0x0004003d,0x00000010,0x0000001d,0x0000001c,0x00050092, + 0x00000010,0x0000001e,0x0000001a,0x0000001d,0x0004003d,0x00000007,0x00000021,0x00000020, + 0x00050091,0x00000007,0x00000022,0x0000001e,0x00000021,0x00050041,0x00000023,0x00000024, + 0x0000000d,0x0000000f,0x0003003e,0x00000024,0x00000022,0x000100fd,0x00010038 +}; \ No newline at end of file diff --git a/src/Vulkan/Vulkan_View.cxx b/src/Vulkan/Vulkan_View.cxx new file mode 100644 index 0000000000..ba1e7bbdf2 --- /dev/null +++ b/src/Vulkan/Vulkan_View.cxx @@ -0,0 +1,1050 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../Graphic3d/Graphic3d_Structure.pxx" + +#include "Vulkan_TestShader_fs_spv.pxx" +#include "Vulkan_TestShader_vs_spv.pxx" + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Vulkan_View, Graphic3d_CView) + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +Vulkan_View::Vulkan_View (const Handle(Graphic3d_StructureManager)& theMgr, + const Handle(Vulkan_GraphicDriver)& theDriver) +: Graphic3d_CView (theMgr), + myDriver (theDriver.get()), + myWasRedrawnGL (Standard_False), + myBackfacing (Graphic3d_TOBM_AUTOMATIC), + myLayer (Structure_MAX_PRIORITY - Structure_MIN_PRIORITY + 1, new BVH_LinearBuilder (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth)), + mySwapInterval (0), + ///myZLayers (Structure_MAX_PRIORITY - Structure_MIN_PRIORITY + 1), + //myFboColorFormat (GL_RGBA8), + //myFboDepthFormat (GL_DEPTH24_STENCIL8), + myFrameCounter (0), + myHasFboBlit (Standard_True), + myToDisableOIT (Standard_False), + myToDisableOITMSAA (Standard_False), + myToDisableMSAA (Standard_False), + myTransientDrawToFront (Standard_True), + myBackBufferRestored (Standard_False), + myIsImmediateDrawn (Standard_False) + //myTextureParams (new OpenGl_Aspects()), + //myBgGradientArray (new OpenGl_BackgroundArray (Graphic3d_TOB_GRADIENT)), + //myBgTextureArray (new OpenGl_BackgroundArray (Graphic3d_TOB_TEXTURE)), +{ + Handle(Graphic3d_CLight) aLight = new Graphic3d_CLight (Graphic3d_TOLS_AMBIENT); + aLight->SetHeadlight (false); + aLight->SetColor (Quantity_NOC_WHITE); + myNoShadingLight = new Graphic3d_LightSet(); + myNoShadingLight->Add (aLight); + + /*myMainSceneFbos[0] = new OpenGl_FrameBuffer(); + myMainSceneFbos[1] = new OpenGl_FrameBuffer(); + myMainSceneFbosOit[0] = new OpenGl_FrameBuffer(); + myMainSceneFbosOit[1] = new OpenGl_FrameBuffer(); + myImmediateSceneFbos[0] = new OpenGl_FrameBuffer(); + myImmediateSceneFbos[1] = new OpenGl_FrameBuffer(); + myImmediateSceneFbosOit[0] = new OpenGl_FrameBuffer(); + myImmediateSceneFbosOit[1] = new OpenGl_FrameBuffer(); + myOpenGlFBO = new OpenGl_FrameBuffer(); + myOpenGlFBO2 = new OpenGl_FrameBuffer(); + myRaytraceFBO1[0] = new OpenGl_FrameBuffer(); + myRaytraceFBO1[1] = new OpenGl_FrameBuffer(); + myRaytraceFBO2[0] = new OpenGl_FrameBuffer(); + myRaytraceFBO2[1] = new OpenGl_FrameBuffer();*/ +} + +// ======================================================================= +// function : Destructor +// purpose : +// ======================================================================= +Vulkan_View::~Vulkan_View() +{ + ///ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context + ///OpenGl_Element::Destroy (NULL, myBgGradientArray); + ///OpenGl_Element::Destroy (NULL, myBgTextureArray); + ///OpenGl_Element::Destroy (NULL, myTextureParams); +} + +// ======================================================================= +// function : ReleaseGlResources +// purpose : +// ======================================================================= +/*void Vulkan_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx) +{ + myGraduatedTrihedron.Release (theCtx.get()); + myFrameStatsPrs.Release (theCtx.get()); + + if (!myTextureEnv.IsNull()) + { + if (!theCtx.IsNull()) + { + for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next()) + { + theCtx->DelayedRelease (aTextureIter.ChangeValue()); + aTextureIter.ChangeValue().Nullify(); + } + } + myTextureEnv.Nullify(); + } + + if (myTextureParams != NULL) + { + myTextureParams->Release (theCtx.get()); + } + if (myBgGradientArray != NULL) + { + myBgGradientArray->Release (theCtx.get()); + } + if (myBgTextureArray != NULL) + { + myBgTextureArray->Release (theCtx.get()); + } + + myMainSceneFbos[0] ->Release (theCtx.get()); + myMainSceneFbos[1] ->Release (theCtx.get()); + myMainSceneFbosOit[0] ->Release (theCtx.get()); + myMainSceneFbosOit[1] ->Release (theCtx.get()); + myImmediateSceneFbos[0] ->Release (theCtx.get()); + myImmediateSceneFbos[1] ->Release (theCtx.get()); + myImmediateSceneFbosOit[0]->Release (theCtx.get()); + myImmediateSceneFbosOit[1]->Release (theCtx.get()); + myOpenGlFBO ->Release (theCtx.get()); + myOpenGlFBO2 ->Release (theCtx.get()); + myFullScreenQuad .Release (theCtx.get()); + myFullScreenQuadFlip .Release (theCtx.get()); + + releaseRaytraceResources (theCtx); +}*/ + +// ======================================================================= +// function : Remove +// purpose : +// ======================================================================= +void Vulkan_View::Remove() +{ + if (IsRemoved()) + { + return; + } + + myDriver->RemoveView (this); + /// TODO + myPlatformWindow.Nullify(); + + Graphic3d_CView::Remove(); +} + +// ======================================================================= +// function : SetLocalOrigin +// purpose : +// ======================================================================= +void Vulkan_View::SetLocalOrigin (const gp_XYZ& theOrigin) +{ + myLocalOrigin = theOrigin; + /**const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); + if (!aCtx.IsNull()) + { + aCtx->ShaderManager()->SetLocalOrigin (theOrigin); + }*/ +} + +// ======================================================================= +// function : SetTextureEnv +// purpose : +// ======================================================================= +void Vulkan_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& ) +{ + // +} + +// ======================================================================= +// function : SetImmediateModeDrawToFront +// purpose : +// ======================================================================= +Standard_Boolean Vulkan_View::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) +{ + const Standard_Boolean aPrevMode = myTransientDrawToFront; + myTransientDrawToFront = theDrawToFrontBuffer; + return aPrevMode; +} + + +// ======================================================================= +// function : initSwapChain +// purpose : +// ======================================================================= +bool Vulkan_View::initSwapChain (const Handle(Aspect_Window)& theWindow, + const Aspect_RenderingContext theContext) +{ + (void )theContext; + myPlatformWindow = theWindow; + mySwapInterval = myDriver->Options()->swapInterval; + const Handle(Vulkan_Device)& aDevice = myDriver->Device(); + if (aDevice->Device() == NULL + && !aDevice->Init (myDriver->Options())) + { + return false; + } + + if (!mySurface.IsNull()) + { + mySurface->Release (aDevice); + } + + mySurface = new Vulkan_Surface(); + return mySurface->Init (aDevice, theWindow); +} + +// ======================================================================= +// function : SetWindow +// purpose : +// ======================================================================= +void Vulkan_View::SetWindow (const Handle(Aspect_Window)& theWindow, + const Aspect_RenderingContext theContext) +{ + if (!initSwapChain (theWindow, theContext)) + { + throw Standard_ProgramError ("Vulkan_View::SetWindow() failed"); + } + + myHasFboBlit = Standard_True; + Invalidate(); +} + +// ======================================================================= +// function : Resized +// purpose : +// ======================================================================= +void Vulkan_View::Resized() +{ + if (myPlatformWindow.IsNull()) + { + return; + } + + /// TODO + ///myWindow->Resize(); +} + +// ======================================================================= +// function : BufferDump +// purpose : +// ======================================================================= +Standard_Boolean Vulkan_View::BufferDump (Image_PixMap& theImage, const Graphic3d_BufferType& theBufferType) +{ + (void )theImage; + (void )theBufferType; + return false; +} + +//======================================================================= +//function : AddZLayer +//purpose : +//======================================================================= +void Vulkan_View::AddZLayer (const Graphic3d_ZLayerId theLayerId) +{ + ///myZLayers.AddLayer (theLayerId); +} + +//======================================================================= +//function : RemoveZLayer +//purpose : +//======================================================================= +void Vulkan_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId) +{ + ///myZLayers.RemoveLayer (theLayerId); +} + +//======================================================================= +//function : SetZLayerSettings +//purpose : +//======================================================================= +void Vulkan_View::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, + const Graphic3d_ZLayerSettings& theSettings) +{ + ///myZLayers.SetLayerSettings (theLayerId, theSettings); +} + +//======================================================================= +//function : ZLayerMax +//purpose : +//======================================================================= +Standard_Integer Vulkan_View::ZLayerMax() const +{ + Standard_Integer aLayerMax = Graphic3d_ZLayerId_Default; + /*for (OpenGl_LayerSeqIds::Iterator aMapIt(myZLayers.LayerIDs()); aMapIt.More(); aMapIt.Next()) + { + aLayerMax = Max (aLayerMax, aMapIt.Value()); + }*/ + + return aLayerMax; +} + +//======================================================================= +//function : InvalidateZLayerBoundingBox +//purpose : +//======================================================================= +void Vulkan_View::InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const +{ + myLayer.InvalidateBoundingBox(); + /*if (myZLayers.LayerIDs().IsBound (theLayerId)) + { + myZLayers.Layer (theLayerId).InvalidateBoundingBox(); + } + else + { + const Standard_Integer aLayerMax = ZLayerMax(); + for (Standard_Integer aLayerId = Graphic3d_ZLayerId_Default; aLayerId < aLayerMax; ++aLayerId) + { + if (myZLayers.LayerIDs().IsBound (aLayerId)) + { + const OpenGl_Layer& aLayer = myZLayers.Layer (aLayerId); + if (aLayer.NbOfTransformPersistenceObjects() > 0) + { + aLayer.InvalidateBoundingBox(); + } + } + } + }*/ +} + +//======================================================================= +//function : ZLayerBoundingBox +//purpose : +//======================================================================= +Bnd_Box Vulkan_View::ZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId, + const Handle(Graphic3d_Camera)& theCamera, + const Standard_Integer theWindowWidth, + const Standard_Integer theWindowHeight, + const Standard_Boolean theToIncludeAuxiliary) const +{ + Bnd_Box aBox; + aBox = myLayer.BoundingBox (Identification(), + theCamera, + theWindowWidth, + theWindowHeight, + theToIncludeAuxiliary); + /*if (myZLayers.LayerIDs().IsBound (theLayerId)) + { + aBox = myZLayers.Layer (theLayerId).BoundingBox (Identification(), + theCamera, + theWindowWidth, + theWindowHeight, + theToIncludeAuxiliary); + } + + // add bounding box of gradient/texture background for proper Z-fit + if (theToIncludeAuxiliary + && theLayerId == Graphic3d_ZLayerId_BotOSD + && (myBgTextureArray->IsDefined() + || myBgGradientArray->IsDefined())) + { + // Background is drawn using 2D transformation persistence + // (e.g. it is actually placed in 3D coordinates within active camera position). + // We add here full-screen plane with 2D transformation persistence + // for simplicity (myBgTextureArray might define a little bit different options + // but it is updated within ::Render()) + const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldViewMat = theCamera->OrientationMatrix(); + Graphic3d_BndBox3d aBox2d (Graphic3d_Vec3d (0.0, 0.0, 0.0), + Graphic3d_Vec3d (double(theWindowWidth), double(theWindowHeight), 0.0)); + + Graphic3d_TransformPers aTrsfPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER); + aTrsfPers.Apply (theCamera, + aProjectionMat, + aWorldViewMat, + theWindowWidth, + theWindowHeight, + aBox2d); + aBox.Add (gp_Pnt (aBox2d.CornerMin().x(), aBox2d.CornerMin().y(), aBox2d.CornerMin().z())); + aBox.Add (gp_Pnt (aBox2d.CornerMax().x(), aBox2d.CornerMax().y(), aBox2d.CornerMax().z())); + }*/ + + return aBox; +} + +//======================================================================= +//function : considerZoomPersistenceObjects +//purpose : +//======================================================================= +void Vulkan_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId) +{ + myLayer.InvalidateBVHData(); + // +} + +//======================================================================= +//function : considerZoomPersistenceObjects +//purpose : +//======================================================================= +Standard_Real Vulkan_View::considerZoomPersistenceObjects (const Graphic3d_ZLayerId theLayerId, + const Handle(Graphic3d_Camera)& theCamera, + const Standard_Integer theWindowWidth, + const Standard_Integer theWindowHeight) const +{ + /*if (myZLayers.LayerIDs().IsBound (theLayerId)) + { + return myZLayers.Layer (theLayerId).considerZoomPersistenceObjects (Identification(), + theCamera, + theWindowWidth, + theWindowHeight); + }*/ + + return 1.0; +} + +//======================================================================= +//function : FBO +//purpose : +//======================================================================= +Handle(Standard_Transient) Vulkan_View::FBO() const +{ + return NULL; ///Handle(Standard_Transient)(myFBO); +} + +//======================================================================= +//function : SetFBO +//purpose : +//======================================================================= +void Vulkan_View::SetFBO (const Handle(Standard_Transient)& theFbo) +{ + ///myFBO = Handle(OpenGl_FrameBuffer)::DownCast (theFbo); +} + +//======================================================================= +//function : FBOCreate +//purpose : +//======================================================================= +Handle(Standard_Transient) Vulkan_View::FBOCreate (const Standard_Integer theWidth, + const Standard_Integer theHeight) +{ + return NULL;//return myWorkspace->FBOCreate (theWidth, theHeight); +} + +//======================================================================= +//function : FBORelease +//purpose : +//======================================================================= +void Vulkan_View::FBORelease (Handle(Standard_Transient)& theFbo) +{ + /*Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo); + if (aFrameBuffer.IsNull()) + { + return; + } + + myWorkspace->FBORelease (aFrameBuffer); + theFbo.Nullify();*/ +} + +//======================================================================= +//function : FBOGetDimensions +//purpose : +//======================================================================= +void Vulkan_View::FBOGetDimensions (const Handle(Standard_Transient)& theFbo, + Standard_Integer& theWidth, + Standard_Integer& theHeight, + Standard_Integer& theWidthMax, + Standard_Integer& theHeightMax) +{ + /*const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo); + if (aFrameBuffer.IsNull()) + { + return; + } + + theWidth = aFrameBuffer->GetVPSizeX(); // current viewport size + theHeight = aFrameBuffer->GetVPSizeY(); + theWidthMax = aFrameBuffer->GetSizeX(); // texture size + theHeightMax = aFrameBuffer->GetSizeY();*/ +} + +//======================================================================= +//function : FBOChangeViewport +//purpose : +//======================================================================= +void Vulkan_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo, + const Standard_Integer theWidth, + const Standard_Integer theHeight) +{ + /*const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo); + if (aFrameBuffer.IsNull()) + { + return; + } + + aFrameBuffer->ChangeViewport (theWidth, theHeight);*/ +} + +//======================================================================= +//function : displayStructure +//purpose : +//======================================================================= +void Vulkan_View::displayStructure (const Handle(Graphic3d_CStructure)& theStructure, + const Standard_Integer thePriority) +{ + const Graphic3d_ZLayerId aZLayer = theStructure->ZLayer(); + myLayer.Add (theStructure.get(), thePriority); + ///myZLayers.AddStructure (aStruct, aZLayer, thePriority); +} + +//======================================================================= +//function : eraseStructure +//purpose : +//======================================================================= +void Vulkan_View::eraseStructure (const Handle(Graphic3d_CStructure)& theStructure) +{ + int aPrior = 0; + myLayer.Remove (theStructure.get(), aPrior); + ///const OpenGl_Structure* aStruct = reinterpret_cast (theStructure.operator->()); + ///myZLayers.RemoveStructure (aStruct); +} + +//======================================================================= +//function : changeZLayer +//purpose : +//======================================================================= +void Vulkan_View::changeZLayer (const Handle(Graphic3d_CStructure)& theStructure, + const Graphic3d_ZLayerId theNewLayerId) +{ + const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer(); + ///const OpenGl_Structure* aStruct = reinterpret_cast (theStructure.operator->()); + ///myZLayers.ChangeLayer (aStruct, anOldLayer, theNewLayerId); + Update (anOldLayer); + Update (theNewLayerId); +} + +//======================================================================= +//function : changePriority +//purpose : +//======================================================================= +void Vulkan_View::changePriority (const Handle(Graphic3d_CStructure)& theStructure, + const Standard_Integer theNewPriority) +{ + const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer(); + ///const OpenGl_Structure* aStruct = reinterpret_cast (theStructure.operator->()); + ///myZLayers.ChangePriority (aStruct, aLayerId, theNewPriority); +} + +//======================================================================= +//function : DiagnosticInformation +//purpose : +//======================================================================= +void Vulkan_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const +{ + const Handle(Vulkan_Device)& aDevice = myDriver->Device(); + if (aDevice.IsNull()) + { + return; + } + + aDevice->DiagnosticInformation (theDict, theFlags); + if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0) + { + if (!mySurface.IsNull()) + { + Graphic3d_Vec2u aSize = mySurface->CurrentSize (aDevice); + TCollection_AsciiString aViewport = TCollection_AsciiString() + int(aSize.x()) + "x" + int(aSize.y()); + theDict.ChangeFromIndex (theDict.Add ("Viewport", aViewport)) = aViewport; + } + TCollection_AsciiString aResRatio (myRenderParams.ResolutionRatio()); + theDict.ChangeFromIndex (theDict.Add ("ResolutionRatio", aResRatio)) = aResRatio; + } +} + +//======================================================================= +//function : StatisticInformation +//purpose : +//======================================================================= +void Vulkan_View::StatisticInformation (TColStd_IndexedDataMapOfStringString& theDict) const +{ + if (const Handle(Vulkan_Device)& aDevice = myDriver->Device()) + { + const Handle(Vulkan_FrameStats)& aStats = aDevice->FrameStats(); + aStats->FormatStats (theDict, myRenderParams.CollectedStats); + } +} + +//======================================================================= +//function : StatisticInformation +//purpose : +//======================================================================= +TCollection_AsciiString Vulkan_View::StatisticInformation() const +{ + if (const Handle(Vulkan_Device)& aDevice = myDriver->Device()) + { + const Handle(Vulkan_FrameStats)& aStats = aDevice->FrameStats(); + return aStats->FormatStats (myRenderParams.CollectedStats); + } + return TCollection_AsciiString(); +} + +//======================================================================= +//function : Redraw +//purpose : +//======================================================================= +void Vulkan_View::Redraw() +{ + const Handle(Vulkan_Device)& aDevice = myDriver->Device(); + if (aDevice->Device() == NULL + || mySurface.IsNull() + || mySurface->Surface() == NULL) + { + return; + } + + Graphic3d_Vec2u aSurfSize = mySurface->CurrentSize (aDevice); + if (aSurfSize.x() == 0 + || aSurfSize.y() == 0) + { + return; + } + + static Handle(Vulkan_RenderPass) aRenderPass; + if (aRenderPass.IsNull()) + { + aRenderPass = new Vulkan_RenderPass(); + if (!aRenderPass->Create (aDevice, mySurface)) + { + return; + } + } + + static Handle(Vulkan_Shader) aShaderVert, aShaderFrag; + static Handle(Vulkan_Buffer) aShaderUniformBuffer; + struct UniformsColors + { + Graphic3d_Mat4 occWorldViewMatrix; + Graphic3d_Mat4 occProjectionMatrix; + Graphic3d_Mat4 occModelWorldMatrix; + Graphic3d_Vec4 uColor; + } aUniformsColors; + aUniformsColors.occProjectionMatrix = myCamera->ProjectionMatrixF(); + aUniformsColors.occWorldViewMatrix = myCamera->OrientationMatrixF(); + + aUniformsColors.uColor.SetValues (1.0f, 0.0f, 0.0f, 1.0f); + if (aShaderVert.IsNull()) + { + aUniformsColors.uColor.SetValues (1.0f, 1.0f, 1.0f, 1.0f); + + aShaderVert = new Vulkan_Shader(); + aShaderFrag = new Vulkan_Shader(); + aShaderUniformBuffer = new Vulkan_Buffer(); + aShaderVert->Create (aDevice, Vulkan_TestShader_vs_spv, sizeof(Vulkan_TestShader_vs_spv)); + aShaderFrag->Create (aDevice, Vulkan_TestShader_fs_spv, sizeof(Vulkan_TestShader_fs_spv)); + + //aShaderVert->CreateFromFile (aDevice, "C:/work/test.vs.spv"); + //aShaderFrag->CreateFromFile (aDevice, "C:/work/test.fs.spv"); + } + aShaderUniformBuffer->init (aDevice, &aUniformsColors, sizeof(aUniformsColors), Vulkan_BufferType_Uniform); + + std::vector aVkFrameBuffers (mySurface->SwapChainSize()); + for (uint32_t anImgIter = 0; anImgIter < mySurface->SwapChainSize(); ++anImgIter) + { + VkFramebufferCreateInfo aVkFboInfo; + const VkImageView aVkImageView = mySurface->ImageViews()[anImgIter]; + aVkFboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + aVkFboInfo.pNext = NULL; + aVkFboInfo.flags = 0; + aVkFboInfo.renderPass = aRenderPass->RenderPass(); + aVkFboInfo.attachmentCount = 1; + aVkFboInfo.pAttachments = &aVkImageView; + aVkFboInfo.width = aSurfSize.x(); + aVkFboInfo.height = aSurfSize.y(); + aVkFboInfo.layers = 1; + + VkFramebuffer& aVkFrameBuffer = aVkFrameBuffers[anImgIter]; + VkResult aRes = vkCreateFramebuffer (aDevice->Device(), &aVkFboInfo, NULL, &aVkFrameBuffer); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Window, failed to create framebuffer: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + } + + VkQueue aVkQueue = NULL; + vkGetDeviceQueue (aDevice->Device(), 0, 0, &aVkQueue); + + VkCommandPool aVkCmdPool = NULL; + { + VkCommandPoolCreateInfo aVkCmdPoolInfo; + aVkCmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + aVkCmdPoolInfo.pNext = NULL; + aVkCmdPoolInfo.flags = VkCommandPoolCreateFlagBits::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + aVkCmdPoolInfo.queueFamilyIndex = 0; + + VkResult aRes = vkCreateCommandPool (aDevice->Device(), &aVkCmdPoolInfo, NULL, &aVkCmdPool); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Window, failed to create command pool: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + + aRes = vkResetCommandPool (aDevice->Device(), aVkCmdPool, VkCommandPoolResetFlagBits::VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_View, failed to reset command pool: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + } + + static VkDescriptorSetLayout aVkDesSetLayout = NULL; + if (aVkDesSetLayout == NULL) + { + VkDescriptorSetLayoutBinding aVkDescSetLayoutBinding = {}; + aVkDescSetLayoutBinding.binding = 0; + aVkDescSetLayoutBinding.descriptorCount = 1; + aVkDescSetLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + aVkDescSetLayoutBinding.pImmutableSamplers = NULL; + aVkDescSetLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + ///aVkDescSetLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + + VkDescriptorSetLayoutCreateInfo aVkDescLayoutInfo = {}; + aVkDescLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + aVkDescLayoutInfo.bindingCount = 1; + aVkDescLayoutInfo.pBindings = &aVkDescSetLayoutBinding; + VkResult aRes = vkCreateDescriptorSetLayout (aDevice->Device(), &aVkDescLayoutInfo, aDevice->HostAllocator(), &aVkDesSetLayout); + if (aRes != VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_View, failed to create descriptor set layout: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + } + + VkDescriptorPool aVkDescriptorPool = NULL; + std::vector aVkDescriptorSets (mySurface->SwapChainSize(), NULL); + { + VkDescriptorPoolSize aVkPoolSize = {}; + aVkPoolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + aVkPoolSize.descriptorCount = mySurface->SwapChainSize(); + + VkDescriptorPoolCreateInfo aVkPoolInfo = {}; + aVkPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + aVkPoolInfo.poolSizeCount = 1; + aVkPoolInfo.pPoolSizes = &aVkPoolSize; + aVkPoolInfo.maxSets = mySurface->SwapChainSize(); + VkResult aRes = vkCreateDescriptorPool (aDevice->Device(), &aVkPoolInfo, aDevice->HostAllocator(), &aVkDescriptorPool); + if (aRes != VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_View, failed to create descriptor pool: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + + std::vector aDescSetLayouts (mySurface->SwapChainSize(), aVkDesSetLayout); + VkDescriptorSetAllocateInfo aDescSetAllocInfo = {}; + aDescSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + aDescSetAllocInfo.descriptorPool = aVkDescriptorPool; + aDescSetAllocInfo.descriptorSetCount = mySurface->SwapChainSize(); + aDescSetAllocInfo.pSetLayouts = aDescSetLayouts.data(); + + aRes = vkAllocateDescriptorSets (aDevice->Device(), &aDescSetAllocInfo, aVkDescriptorSets.data()); + if (aRes != VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_View, failed to allocate descriptor sets: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + + for (uint32_t anImgIter = 0; anImgIter < mySurface->SwapChainSize(); ++anImgIter) + { + VkDescriptorBufferInfo aVkDescBuffInfo = {}; + aVkDescBuffInfo.buffer = aShaderUniformBuffer->Buffer(); + aVkDescBuffInfo.offset = 0; + aVkDescBuffInfo.range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet aVkWriteDescSet = {}; + aVkWriteDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + aVkWriteDescSet.dstSet = aVkDescriptorSets[anImgIter]; + aVkWriteDescSet.dstBinding = 0; + aVkWriteDescSet.dstArrayElement = 0; + aVkWriteDescSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + aVkWriteDescSet.descriptorCount = 1; + aVkWriteDescSet.pBufferInfo = &aVkDescBuffInfo; + aVkWriteDescSet.pImageInfo = NULL; + aVkWriteDescSet.pTexelBufferView = NULL; + vkUpdateDescriptorSets (aDevice->Device(), 1, &aVkWriteDescSet, 0, NULL); + } + } + + std::vector aVkCmdBuffers (mySurface->SwapChainSize(), NULL); + { + VkCommandBufferAllocateInfo aVkCmdBufferAllocInfo; + aVkCmdBufferAllocInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + aVkCmdBufferAllocInfo.pNext = NULL; + aVkCmdBufferAllocInfo.commandPool = aVkCmdPool; + aVkCmdBufferAllocInfo.level = VkCommandBufferLevel::VK_COMMAND_BUFFER_LEVEL_PRIMARY; + aVkCmdBufferAllocInfo.commandBufferCount = mySurface->SwapChainSize(); + + VkResult aRes = vkAllocateCommandBuffers (aDevice->Device(), &aVkCmdBufferAllocInfo, aVkCmdBuffers.data()); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Window, failed to allocate command buffers: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + + for (uint32_t anImgIter = 0; anImgIter < mySurface->SwapChainSize(); ++anImgIter) + { + VkCommandBuffer& aVkCmdBuffer = aVkCmdBuffers[anImgIter]; + const VkImage aVkImage = mySurface->Images()[anImgIter]; + const VkFramebuffer aVkFrameBuffer = aVkFrameBuffers[anImgIter]; + aRes = vkResetCommandBuffer (aVkCmdBuffer, VkCommandBufferResetFlagBits::VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Window, failed to reset command buffer: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + + VkCommandBufferInheritanceInfo aVkCmdBufferInherInfo; + aVkCmdBufferInherInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; + aVkCmdBufferInherInfo.pNext = NULL; + aVkCmdBufferInherInfo.renderPass = aRenderPass->RenderPass(); + aVkCmdBufferInherInfo.subpass = 0; + aVkCmdBufferInherInfo.framebuffer = aVkFrameBuffer; + aVkCmdBufferInherInfo.occlusionQueryEnable = VK_FALSE; + aVkCmdBufferInherInfo.queryFlags = 0; + aVkCmdBufferInherInfo.pipelineStatistics = 0; + + VkCommandBufferBeginInfo aVkCmdBufferBeginInfo; + aVkCmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + aVkCmdBufferBeginInfo.pNext = NULL; + aVkCmdBufferBeginInfo.flags = 0; + aVkCmdBufferBeginInfo.pInheritanceInfo = &aVkCmdBufferInherInfo; + + vkBeginCommandBuffer (aVkCmdBuffer, &aVkCmdBufferBeginInfo); + { + VkClearValue aClearValue; + const Graphic3d_Vec4& aBgColor = myBgColor; + aClearValue.color.float32[0] = aBgColor.r(); + aClearValue.color.float32[1] = aBgColor.g(); + aClearValue.color.float32[2] = aBgColor.b(); + aClearValue.color.float32[3] = aBgColor.a(); + + VkRenderPassBeginInfo aVkRenderPassBeginInfo; + aVkRenderPassBeginInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + aVkRenderPassBeginInfo.pNext = NULL; + aVkRenderPassBeginInfo.renderPass = aRenderPass->RenderPass(); + aVkRenderPassBeginInfo.framebuffer = aVkFrameBuffer; + aVkRenderPassBeginInfo.renderArea = VkRect2D{ + VkOffset2D{0, 0}, + VkExtent2D{aSurfSize.x(), aSurfSize.y()} + }; + aVkRenderPassBeginInfo.clearValueCount = 1; + aVkRenderPassBeginInfo.pClearValues = &aClearValue; + + vkCmdBeginRenderPass (aVkCmdBuffer, &aVkRenderPassBeginInfo, VkSubpassContents::VK_SUBPASS_CONTENTS_INLINE); + { + static Handle(Vulkan_Pipeline) aPipe; + static Handle(Vulkan_PipelineLayout) aPipeLayout; + if (aPipe.IsNull()) + { + aPipeLayout = new Vulkan_PipelineLayout(); + aPipeLayout->Create (aDevice, aVkDesSetLayout); + aPipe = new Vulkan_Pipeline(); + aPipe->Create (aDevice, aRenderPass, aPipeLayout, aShaderVert, aShaderFrag, aSurfSize); + } + vkCmdBindPipeline (aVkCmdBuffer, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS, aPipe->Pipeline()); + + vkCmdBindDescriptorSets (aVkCmdBuffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + aPipe->PipelineLayout()->PipelineLayout(), + 0, 1, &aVkDescriptorSets[anImgIter], 0, NULL); + + /**static Handle(Vulkan_Buffer) aVertBuffer; + if (aVertBuffer.IsNull()) + { + const Graphic3d_Vec3 aVertData[3*2] = + { + Graphic3d_Vec3 (-0.5f, 0.5f, 0.0f), Graphic3d_Vec3(), + Graphic3d_Vec3 ( 0.5f, 0.5f, 0.0f), Graphic3d_Vec3(), + Graphic3d_Vec3 ( 0.0f, -0.5f, 0.0f), Graphic3d_Vec3() + }; + + aVertBuffer = new Vulkan_Buffer(); + aVertBuffer->Init (aDevice, aVertData, 3); + } + + { + std::vector aVkVertBuffers = { aVertBuffer->Buffer() }; + std::vector aVkVertOffsets = {0}; + vkCmdBindVertexBuffers (aVkCmdBuffer, 0, 1, aVkVertBuffers.data(), aVkVertOffsets.data()); + vkCmdDraw (aVkCmdBuffer, 3, 1, 0, 0); + }*/ + + for (Graphic3d_ArrayOfIndexedMapOfStructure::Iterator aPriorIter (myLayer.ArrayOfStructures()); aPriorIter.More(); aPriorIter.Next()) + { + for (Vulkan_Structure::StructIterator aStructIter (aPriorIter.Value()); aStructIter.More(); aStructIter.Next()) + { + const Vulkan_Structure* aStruct = aStructIter.Value(); + for (Vulkan_Structure::GroupIterator aGroupIter (aStruct->Groups()); aGroupIter.More(); aGroupIter.Next()) + { + Vulkan_Group* aGroup = aGroupIter.ChangeValue(); + for (Vulkan_ListOfElements::Iterator aPrimIter (aGroup->myElements); aPrimIter.More(); aPrimIter.Next()) + { + Vulkan_PrimitiveArray& aPrim = aPrimIter.ChangeValue(); + if (aPrim.VboAttribs.IsNull() + && !aPrim.Attribs.IsNull()) + { + aPrim.VboAttribs = new Vulkan_Buffer(); + aPrim.VboAttribs->init (aDevice, aPrim.Attribs->Data(), aPrim.Attribs->Size(), Vulkan_BufferType_Vertex); + } + if (aPrim.VboIndices.IsNull() + && !aPrim.Indices.IsNull()) + { + aPrim.VboIndices = new Vulkan_Buffer(); + aPrim.VboIndices->init (aDevice, aPrim.Indices->Data(), aPrim.Indices->Size(), Vulkan_BufferType_Index); + } + if (!aPrim.VboAttribs.IsNull()) + { + VkBuffer aVkVertBuffers[1] = { aPrim.VboAttribs->Buffer() }; + VkDeviceSize aVkVertOffsets[1] = {0}; + vkCmdBindVertexBuffers (aVkCmdBuffer, 0, 1, aVkVertBuffers, aVkVertOffsets); + if (!aPrim.VboIndices.IsNull()) + { + vkCmdBindIndexBuffer (aVkCmdBuffer, aPrim.VboIndices->Buffer(), 0, aPrim.Indices->Stride == 4 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16); + vkCmdDrawIndexed (aVkCmdBuffer, aPrim.Indices->NbElements, 1, 0, 0, 0); + } + else + { + vkCmdDraw (aVkCmdBuffer, aPrim.Attribs->NbElements, 1, 0, 0); + } + } + } + } + } + } + } + vkCmdEndRenderPass (aVkCmdBuffer); + + VkImageMemoryBarrier aVkImgMemBarrier; + aVkImgMemBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + aVkImgMemBarrier.pNext = NULL; + aVkImgMemBarrier.srcAccessMask = 0; + aVkImgMemBarrier.dstAccessMask = VkAccessFlagBits::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VkAccessFlagBits::VK_ACCESS_MEMORY_READ_BIT; + aVkImgMemBarrier.oldLayout = VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED; + aVkImgMemBarrier.newLayout = VkImageLayout::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + aVkImgMemBarrier.srcQueueFamilyIndex = 0; + aVkImgMemBarrier.dstQueueFamilyIndex = 0; + aVkImgMemBarrier.image = aVkImage; + aVkImgMemBarrier.subresourceRange = {VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + + vkCmdPipelineBarrier (aVkCmdBuffer, + VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + 0, + 0, NULL, + 0, NULL, + 1, &aVkImgMemBarrier); + } + vkEndCommandBuffer (aVkCmdBuffer); + } + } + +/// + uint32_t aVKSwapChainIndex = 0; + if (!mySurface->AcquireNextImage (aDevice, aVKSwapChainIndex)) + { + return; + } + + const VkCommandBuffer aVkCmdBuffer = aVkCmdBuffers[aVKSwapChainIndex]; + const VkPipelineStageFlags aVkWaitMask = VkPipelineStageFlagBits::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + VkSubmitInfo aVkSubmitInfo; + aVkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + aVkSubmitInfo.pNext = NULL; + aVkSubmitInfo.waitSemaphoreCount = 0; + aVkSubmitInfo.pWaitSemaphores = NULL; + aVkSubmitInfo.pWaitDstStageMask = &aVkWaitMask; + aVkSubmitInfo.commandBufferCount = 1; + aVkSubmitInfo.pCommandBuffers = &aVkCmdBuffer; + aVkSubmitInfo.signalSemaphoreCount = 0; + aVkSubmitInfo.pSignalSemaphores = NULL; + + VkResult aRes = vkQueueSubmit (aVkQueue, 1, &aVkSubmitInfo, VK_NULL_HANDLE); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Window, failed to submit command buffer: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + + aRes = vkQueueWaitIdle (aVkQueue); + if (aRes != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Window, failed to wait for queuer: ") + Vulkan_Device::FormatVkError (aRes)); + return; + } + + const VkSwapchainKHR aSwapChain = mySurface->SwapChain(); + VkResult aResults = VkResult::VK_SUCCESS; + VkPresentInfoKHR aVkPresentInfo; + aVkPresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + aVkPresentInfo.pNext = NULL; + aVkPresentInfo.waitSemaphoreCount = 0; + aVkPresentInfo.pWaitSemaphores = NULL; + aVkPresentInfo.swapchainCount = 1; + aVkPresentInfo.pSwapchains = &aSwapChain; + aVkPresentInfo.pImageIndices = &aVKSwapChainIndex; + aVkPresentInfo.pResults = &aResults; + + aRes = vkQueuePresentKHR (aVkQueue, &aVkPresentInfo); + if (aRes != VkResult::VK_SUCCESS + || aResults != VkResult::VK_SUCCESS) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Vulkan_Window, failed to present swapchain: ") + + Vulkan_Device::FormatVkError (aRes != VkResult::VK_SUCCESS ? aRes : aResults)); + return; + } +} + +//======================================================================= +//function : RedrawImmediate +//purpose : +//======================================================================= +void Vulkan_View::RedrawImmediate() +{ + Redraw(); +} + +//======================================================================= +//function : Invalidate +//purpose : +//======================================================================= +void Vulkan_View::Invalidate() +{ + // +} diff --git a/src/Vulkan/Vulkan_View.hxx b/src/Vulkan/Vulkan_View.hxx new file mode 100644 index 0000000000..c7b784836d --- /dev/null +++ b/src/Vulkan/Vulkan_View.hxx @@ -0,0 +1,439 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Vulkan_View_HeaderFile +#define _Vulkan_View_HeaderFile + +#include +#include + +class Vulkan_Caps; +class Vulkan_Fence; +class Vulkan_GraphicDriver; +class Vulkan_Surface; + +//! Implementation of Vulkan view. +class Vulkan_View : public Graphic3d_CView +{ + DEFINE_STANDARD_RTTIEXT(Vulkan_View, Graphic3d_CView) +public: + + //! Constructor. + Standard_EXPORT Vulkan_View (const Handle(Graphic3d_StructureManager)& theMgr, + const Handle(Vulkan_GraphicDriver)& theDriver); + + //! Default destructor. + Standard_EXPORT virtual ~Vulkan_View(); + + ///Standard_EXPORT void ReleaseGlResources (const Handle(OpenGl_Context)& theCtx); + + //! Deletes and erases the view. + Standard_EXPORT virtual void Remove() Standard_OVERRIDE; + + //! @param theDrawToFrontBuffer Advanced option to modify rendering mode: + //! 1. TRUE. Drawing immediate mode structures directly to the front buffer over the scene image. + //! Fast, so preferred for interactive work (used by default). + //! However these extra drawings will be missed in image dump since it is performed from back buffer. + //! Notice that since no pre-buffering used the V-Sync will be ignored and rendering could be seen + //! in run-time (in case of slow hardware) and/or tearing may appear. + //! So this is strongly recommended to draw only simple (fast) structures. + //! 2. FALSE. Drawing immediate mode structures to the back buffer. + //! The complete scene is redrawn first, so this mode is slower if scene contains complex data and/or V-Sync + //! is turned on. But it works in any case and is especially useful for view dump because the dump image is read + //! from the back buffer. + //! @return previous mode. + Standard_EXPORT virtual Standard_Boolean SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) Standard_OVERRIDE; + + //! Creates and maps rendering window to the view. + //! @param theWindow [in] the window. + //! @param theContext [in] the rendering context. If NULL the context will be created internally. + Standard_EXPORT virtual void SetWindow (const Handle(Aspect_Window)& theWindow, + const Aspect_RenderingContext theContext) Standard_OVERRIDE; + + //! Returns window associated with the view. + virtual Handle(Aspect_Window) Window() const Standard_OVERRIDE { return myPlatformWindow; } + + //! Returns True if the window associated to the view is defined. + virtual Standard_Boolean IsDefined() const Standard_OVERRIDE { return !myPlatformWindow.IsNull(); } + + //! Handle changing size of the rendering window. + Standard_EXPORT virtual void Resized() Standard_OVERRIDE; + + //! Redraw content of the view. + Standard_EXPORT virtual void Redraw() Standard_OVERRIDE; + + //! Redraw immediate content of the view. + Standard_EXPORT virtual void RedrawImmediate() Standard_OVERRIDE; + + //! Marks BVH tree for given priority list as dirty and marks primitive set for rebuild. + Standard_EXPORT virtual void Invalidate() Standard_OVERRIDE; + + //! Return true if view content cache has been invalidated. + virtual Standard_Boolean IsInvalidated() Standard_OVERRIDE { return !myBackBufferRestored; } + + //! Dump active rendering buffer into specified memory buffer. + //! In Ray-Tracing allow to get a raw HDR buffer using Graphic3d_BT_RGB_RayTraceHdrLeft buffer type, + //! only Left view will be dumped ignoring stereoscopic parameter. + Standard_EXPORT virtual Standard_Boolean BufferDump (Image_PixMap& theImage, + const Graphic3d_BufferType& theBufferType) Standard_OVERRIDE; + + //! Marks BVH tree and the set of BVH primitives of correspondent priority list with id theLayerId as outdated. + Standard_EXPORT virtual void InvalidateBVHData (const Graphic3d_ZLayerId theLayerId) Standard_OVERRIDE; + + //! Insert a new top-level z layer with the given ID. + Standard_EXPORT virtual void AddZLayer (const Graphic3d_ZLayerId theLayerId) Standard_OVERRIDE; + + //! Remove a z layer with the given ID. + Standard_EXPORT virtual void RemoveZLayer (const Graphic3d_ZLayerId theLayerId) Standard_OVERRIDE; + + //! Sets the settings for a single Z layer of specified view. + Standard_EXPORT virtual void SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, + const Graphic3d_ZLayerSettings& theSettings) Standard_OVERRIDE; + + //! Returns the maximum Z layer ID. + //! First layer ID is Graphic3d_ZLayerId_Default, last ID is ZLayerMax(). + Standard_EXPORT virtual Standard_Integer ZLayerMax() const Standard_OVERRIDE; + + //! Returns the bounding box of all structures displayed in the Z layer. + //! Never fails. If Z layer does not exist nothing happens. + Standard_EXPORT virtual void InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const Standard_OVERRIDE; + + //! Returns the bounding box of all structures displayed in the Z layer. + //! If Z layer does not exist the empty box is returned. + //! @param theLayerId layer identifier + //! @param theCamera camera definition + //! @param theWindowWidth viewport width (for applying transformation-persistence) + //! @param theWindowHeight viewport height (for applying transformation-persistence) + //! @param theToIncludeAuxiliary consider also auxiliary presentations (with infinite flag or with trihedron transformation persistence) + //! @return computed bounding box + Standard_EXPORT virtual Bnd_Box ZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId, + const Handle(Graphic3d_Camera)& theCamera, + const Standard_Integer theWindowWidth, + const Standard_Integer theWindowHeight, + const Standard_Boolean theToIncludeAuxiliary) const Standard_OVERRIDE; + + //! Returns pointer to an assigned framebuffer object. + Standard_EXPORT virtual Handle(Standard_Transient) FBO() const Standard_OVERRIDE; + + //! Sets framebuffer object for offscreen rendering. + Standard_EXPORT virtual void SetFBO (const Handle(Standard_Transient)& theFbo) Standard_OVERRIDE; + + //! Generate offscreen FBO in the graphic library. + //! If not supported on hardware returns NULL. + Standard_EXPORT virtual Handle(Standard_Transient) FBOCreate (const Standard_Integer theWidth, + const Standard_Integer theHeight) Standard_OVERRIDE; + + //! Remove offscreen FBO from the graphic library + Standard_EXPORT virtual void FBORelease (Handle(Standard_Transient)& theFbo) Standard_OVERRIDE; + + //! Read offscreen FBO configuration. + Standard_EXPORT virtual void FBOGetDimensions (const Handle(Standard_Transient)& theFbo, + Standard_Integer& theWidth, + Standard_Integer& theHeight, + Standard_Integer& theWidthMax, + Standard_Integer& theHeightMax) Standard_OVERRIDE; + + //! Change offscreen FBO viewport. + Standard_EXPORT virtual void FBOChangeViewport (const Handle(Standard_Transient)& theFbo, + const Standard_Integer theWidth, + const Standard_Integer theHeight) Standard_OVERRIDE; + +public: + + //! Returns gradient background fill colors. + virtual Aspect_GradientBackground GradientBackground() const { return Aspect_GradientBackground(); } + + //! Sets gradient background fill colors. + virtual void SetGradientBackground (const Aspect_GradientBackground& ) {} + + //! Returns background image texture file path. + virtual TCollection_AsciiString BackgroundImage() Standard_OVERRIDE { return myBackgroundImagePath; } + + //! Sets background image texture file path. + virtual void SetBackgroundImage (const TCollection_AsciiString& ) Standard_OVERRIDE {} + + //! Returns background image fill style. + virtual Aspect_FillMethod BackgroundImageStyle() const Standard_OVERRIDE { return Aspect_FM_NONE; } + + //! Sets background image fill style. + virtual void SetBackgroundImageStyle (const Aspect_FillMethod ) Standard_OVERRIDE {} + + //! Returns environment texture set for the view. + virtual Handle(Graphic3d_TextureEnv) TextureEnv() const Standard_OVERRIDE { return myTextureEnvData; } + + //! Sets environment texture for the view. + Standard_EXPORT virtual void SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTextureEnv) Standard_OVERRIDE; + + //! Return backfacing model used for the view. + virtual Graphic3d_TypeOfBackfacingModel BackfacingModel() const Standard_OVERRIDE { return myBackfacing; } + + //! Sets backfacing model for the view. + virtual void SetBackfacingModel (const Graphic3d_TypeOfBackfacingModel theModel) Standard_OVERRIDE { myBackfacing = theModel; } + + //! Returns local camera origin currently set for rendering, might be modified during rendering. + const gp_XYZ& LocalOrigin() const { return myLocalOrigin; } + + //! Setup local camera origin currently set for rendering. + Standard_EXPORT void SetLocalOrigin (const gp_XYZ& theOrigin); + + //! Returns list of lights of the view. + virtual const Handle(Graphic3d_LightSet)& Lights() const Standard_OVERRIDE { return myLights; } + + //! Sets list of lights for the view. + virtual void SetLights (const Handle(Graphic3d_LightSet)& theLights) Standard_OVERRIDE + { + myLights = theLights; + ///myCurrLightSourceState = myStateCounter->Increment(); + } + + //! Returns list of clip planes set for the view. + virtual const Handle(Graphic3d_SequenceOfHClipPlane)& ClipPlanes() const Standard_OVERRIDE { return myClipPlanes; } + + //! Sets list of clip planes for the view. + virtual void SetClipPlanes (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes) Standard_OVERRIDE { myClipPlanes = thePlanes; } + + //! Fill in the dictionary with diagnostic info. + //! Should be called within rendering thread. + //! + //! This API should be used only for user output or for creating automated reports. + //! The format of returned information (e.g. key-value layout) + //! is NOT part of this API and can be changed at any time. + //! Thus application should not parse returned information to weed out specific parameters. + Standard_EXPORT virtual void DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const Standard_OVERRIDE; + + //! Returns string with statistic performance info. + Standard_EXPORT virtual TCollection_AsciiString StatisticInformation() const Standard_OVERRIDE; + + //! Fills in the dictionary with statistic performance info. + Standard_EXPORT virtual void StatisticInformation (TColStd_IndexedDataMapOfStringString& theDict) const Standard_OVERRIDE; + +public: + + //! Returns background color. + /**const Quantity_ColorRGBA& BackgroundColor() const { return myBgColor; } + + void SetBackgroundTextureStyle (const Aspect_FillMethod FillStyle); + + void SetBackgroundGradient (const Quantity_Color& AColor1, const Quantity_Color& AColor2, const Aspect_GradientFillMethod AType); + + void SetBackgroundGradientType (const Aspect_GradientFillMethod AType); + + //! Returns list of OpenGL Z-layers. + const OpenGl_LayerList& LayerList() const { return myZLayers; } + + //! Returns OpenGL window implementation. + const Handle(OpenGl_Window)& GlWindow() const { return myWindow; } + + //! Returns OpenGL environment map. + const Handle(OpenGl_TextureSet)& GlTextureEnv() const { return myTextureEnv; } + + //! Returns selector for BVH tree, providing a possibility to store information + //! about current view volume and to detect which objects are overlapping it. + const OpenGl_BVHTreeSelector& BVHTreeSelector() const { return myBVHSelector; } + + //! Returns true if there are immediate structures to display + bool HasImmediateStructures() const + { + return myZLayers.NbImmediateStructures() != 0; + }*/ + +protected: //! @name low-level redrawing sub-routines + + //! Redraws view for the given monographic camera projection, or left/right eye. + /** Standard_EXPORT virtual void redraw (const Graphic3d_Camera::Projection theProjection, + OpenGl_FrameBuffer* theReadDrawFbo, + OpenGl_FrameBuffer* theOitAccumFbo); + + //! Redraws view for the given monographic camera projection, or left/right eye. + //! + //! Method will blit snapshot containing main scene (myMainSceneFbos or BackBuffer) + //! into presentation buffer (myMainSceneFbos -> offscreen FBO or + //! myMainSceneFbos -> BackBuffer or BackBuffer -> FrontBuffer), + //! and redraw immediate structures on top. + //! + //! When scene caching is disabled (myTransientDrawToFront, no double buffer in window, etc.), + //! the first step (blitting) will be skipped. + //! + //! @return false if immediate structures has been rendered directly into FrontBuffer + //! and Buffer Swap should not be called. + Standard_EXPORT virtual bool redrawImmediate (const Graphic3d_Camera::Projection theProjection, + OpenGl_FrameBuffer* theReadFbo, + OpenGl_FrameBuffer* theDrawFbo, + OpenGl_FrameBuffer* theOitAccumFbo, + const Standard_Boolean theIsPartialUpdate = Standard_False); + + //! Blit image from/to specified buffers. + Standard_EXPORT bool blitBuffers (OpenGl_FrameBuffer* theReadFbo, + OpenGl_FrameBuffer* theDrawFbo, + const Standard_Boolean theToFlip = Standard_False); + + //! Setup default FBO. + Standard_EXPORT void bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo = NULL);*/ + +protected: //! @name Rendering of GL graphics (with prepared drawing buffer). + + //! Renders the graphical contents of the view into the preprepared window or framebuffer. + //! @param theProjection [in] the projection that should be used for rendering. + //! @param theReadDrawFbo [in] the framebuffer for rendering graphics. + //! @param theOitAccumFbo [in] the framebuffer for accumulating color and coverage for OIT process. + //! @param theToDrawImmediate [in] the flag indicates whether the rendering performs in immediate mode. + /**Standard_EXPORT virtual void render (Graphic3d_Camera::Projection theProjection, + OpenGl_FrameBuffer* theReadDrawFbo, + OpenGl_FrameBuffer* theOitAccumFbo, + const Standard_Boolean theToDrawImmediate); + + //! Renders the graphical scene. + //! @param theProjection [in] the projection that is used for rendering. + //! @param theReadDrawFbo [in] the framebuffer for rendering graphics. + //! @param theOitAccumFbo [in] the framebuffer for accumulating color and coverage for OIT process. + //! @param theToDrawImmediate [in] the flag indicates whether the rendering performs in immediate mode. + Standard_EXPORT virtual void renderScene (Graphic3d_Camera::Projection theProjection, + OpenGl_FrameBuffer* theReadDrawFbo, + OpenGl_FrameBuffer* theOitAccumFbo, + const Standard_Boolean theToDrawImmediate); + + //! Draw background (gradient / image) + Standard_EXPORT virtual void drawBackground (const Handle(OpenGl_Workspace)& theWorkspace); + + //! Render set of structures presented in the view. + //! @param theProjection [in] the projection that is used for rendering. + //! @param theReadDrawFbo [in] the framebuffer for rendering graphics. + //! @param theOitAccumFbo [in] the framebuffer for accumulating color and coverage for OIT process. + //! @param theToDrawImmediate [in] the flag indicates whether the rendering performs in immediate mode. + Standard_EXPORT virtual void renderStructs (Graphic3d_Camera::Projection theProjection, + OpenGl_FrameBuffer* theReadDrawFbo, + OpenGl_FrameBuffer* theOitAccumFbo, + const Standard_Boolean theToDrawImmediate);*/ + +private: + + //! Initialize swapchain. + Standard_EXPORT bool initSwapChain (const Handle(Aspect_Window)& theWindow, + const Aspect_RenderingContext theContext); + + //! Adds the structure to display lists of the view. + Standard_EXPORT virtual void displayStructure (const Handle(Graphic3d_CStructure)& theStructure, + const Standard_Integer thePriority) Standard_OVERRIDE; + + //! Erases the structure from display lists of the view. + Standard_EXPORT virtual void eraseStructure (const Handle(Graphic3d_CStructure)& theStructure) Standard_OVERRIDE; + + //! Change Z layer of a structure already presented in view. + Standard_EXPORT virtual void changeZLayer (const Handle(Graphic3d_CStructure)& theCStructure, + const Graphic3d_ZLayerId theNewLayerId) Standard_OVERRIDE; + + //! Changes the priority of a structure within its Z layer in the specified view. + Standard_EXPORT virtual void changePriority (const Handle(Graphic3d_CStructure)& theCStructure, + const Standard_Integer theNewPriority) Standard_OVERRIDE; + + //! Returns zoom-scale factor. + Standard_EXPORT virtual Standard_Real considerZoomPersistenceObjects (const Graphic3d_ZLayerId theLayerId, + const Handle(Graphic3d_Camera)& theCamera, + const Standard_Integer theWindowWidth, + const Standard_Integer theWindowHeight) const Standard_OVERRIDE; + +private: + + //! Copy content of Back buffer to the Front buffer. + /**bool copyBackToFront(); + + //! Initialize blit quad. + OpenGl_VertexBuffer* initBlitQuad (const Standard_Boolean theToFlip); + + //! Blend together views pair into stereo image. + void drawStereoPair (OpenGl_FrameBuffer* theDrawFbo); + + //! Check and update OIT compatibility with current OpenGL context's state. + bool checkOitCompatibility (const Handle(OpenGl_Context)& theGlContext, + const Standard_Boolean theMSAA); + + //! Chooses compatible internal color format for OIT frame buffer. + bool chooseOitColorConfiguration (const Handle(OpenGl_Context)& theGlContext, + const Standard_Integer theConfigIndex, + OpenGl_ColorFormats& theFormats);*/ + +protected: + + Graphic3d_Layer myLayer; /// TODO + Standard_Integer mySwapInterval; //!< last assigned swap interval (VSync) for this window + + Vulkan_GraphicDriver* myDriver; + Handle(Vulkan_Surface) mySurface; + Handle(Aspect_Window) myPlatformWindow; //!< software platform window wrapper + Standard_Boolean myWasRedrawnGL; + + Graphic3d_TypeOfBackfacingModel myBackfacing; + Handle(Graphic3d_SequenceOfHClipPlane) myClipPlanes; + gp_XYZ myLocalOrigin; + //Handle(OpenGl_FrameBuffer) myFBO; + TCollection_AsciiString myBackgroundImagePath; + Handle(Graphic3d_TextureEnv) myTextureEnvData; + + Handle(Graphic3d_LightSet) myNoShadingLight; + Handle(Graphic3d_LightSet) myLights; + ///OpenGl_LayerList myZLayers; //!< main list of displayed structure, sorted by layers + + Graphic3d_WorldViewProjState myWorldViewProjState; //!< camera modification state + ///OpenGl_StateCounter* myStateCounter; + ///Standard_Size myCurrLightSourceState; + ///Standard_Size myLightsRevision; + + //typedef std::pair StateInfo; + //StateInfo myLastOrientationState; + //StateInfo myLastViewMappingState; + //StateInfo myLastLightSourceState; + + //! Is needed for selection of overlapping objects and storage of the current view volume + ///OpenGl_BVHTreeSelector myBVHSelector; + + ///OpenGl_FrameStatsPrs myFrameStatsPrs; + + ///Handle(OpenGl_TextureSet) myTextureEnv; + + //! Framebuffers for OpenGL output. + ///Handle(OpenGl_FrameBuffer) myOpenGlFBO; + ///Handle(OpenGl_FrameBuffer) myOpenGlFBO2; + +protected: //! @name Rendering properties + + //! Two framebuffers (left and right views) store cached main presentation + //! of the view (without presentation of immediate layers). + int myFboColorFormat; //!< sized format for color attachments + int myFboDepthFormat; //!< sized format for depth-stencil attachments + //OpenGl_ColorFormats myFboOitColorConfig; //!< selected color format configuration for OIT color attachments + //Handle(OpenGl_FrameBuffer) myMainSceneFbos[2]; + //Handle(OpenGl_FrameBuffer) myMainSceneFbosOit[2]; //!< Additional buffers for transparent draw of main layer. + //Handle(OpenGl_FrameBuffer) myImmediateSceneFbos[2]; //!< Additional buffers for immediate layer in stereo mode. + //Handle(OpenGl_FrameBuffer) myImmediateSceneFbosOit[2]; //!< Additional buffers for transparency draw of immediate layer. + ///OpenGl_VertexBuffer myFullScreenQuad; //!< Vertices for full-screen quad rendering. + ///OpenGl_VertexBuffer myFullScreenQuadFlip; + ///Standard_Boolean myToFlipOutput; //!< Flag to draw result image upside-down + unsigned int myFrameCounter; //!< redraw counter, for debugging + Standard_Boolean myHasFboBlit; //!< disable FBOs on failure + Standard_Boolean myToDisableOIT; //!< disable OIT on failure + Standard_Boolean myToDisableOITMSAA; //!< disable OIT with MSAA on failure + Standard_Boolean myToDisableMSAA; //!< disable MSAA after failure + Standard_Boolean myTransientDrawToFront; //!< optimization flag for immediate mode (to render directly to the front buffer) + Standard_Boolean myBackBufferRestored; + Standard_Boolean myIsImmediateDrawn; //!< flag indicates that immediate mode buffer contains some data + +protected: //! @name Background parameters + + ///OpenGl_Aspects* myTextureParams; //!< Stores texture and its parameters for textured background + ///OpenGl_BackgroundArray* myBgGradientArray; //!< Primitive array for gradient background + ///OpenGl_BackgroundArray* myBgTextureArray; //!< Primitive array for texture background + +}; + +#endif // _Vulkan_View_HeaderFile